implemented setlayout in the way proposed on the ml, split tile() into two functions, a third will follow soon
c9170189
2 file(s) · +109 −103
| 13 | 13 | /* bar position */ |
|
| 14 | 14 | #define BX sx |
|
| 15 | 15 | #define BY sy |
|
| 16 | - | #define BW MW |
|
| 16 | + | #define BW sw |
|
| 17 | 17 | ||
| 18 | 18 | /* window area */ |
|
| 19 | 19 | #define WX 0 |
|
| 20 | 20 | #define WY bh |
|
| 21 | 21 | #define WW sw |
|
| 22 | - | #define WH sh |
|
| 22 | + | #define WH sh - bh |
|
| 23 | 23 | ||
| 24 | 24 | /* master area */ |
|
| 25 | - | #define MX sx |
|
| 26 | - | #define MY sy + bh |
|
| 25 | + | #define MX WX |
|
| 26 | + | #define MY WY |
|
| 27 | 27 | #define MW ((int)(((float)sw) * 0.6)) |
|
| 28 | - | #define MH sh - bh |
|
| 28 | + | #define MH WH |
|
| 29 | 29 | ||
| 30 | 30 | /* tile area, might be on a different screen */ |
|
| 31 | - | #define TX sx + MW |
|
| 32 | - | #define TY sy |
|
| 33 | - | #define TW sw - MW |
|
| 34 | - | #define TH sh |
|
| 31 | + | #define TX MX + MW |
|
| 32 | + | #define TY WY |
|
| 33 | + | #define TW WW - MW |
|
| 34 | + | #define TH WH |
|
| 35 | 35 | ||
| 36 | 36 | /* monocle area, might be restricted to a specific screen */ |
|
| 37 | - | #define MOX sx |
|
| 38 | - | #define MOY MY |
|
| 39 | - | #define MOW sw |
|
| 40 | - | #define MOH MH |
|
| 37 | + | #define MOX WX |
|
| 38 | + | #define MOY WY |
|
| 39 | + | #define MOW WW |
|
| 40 | + | #define MOH WH |
|
| 41 | 41 | ||
| 42 | 42 | /* tagging */ |
|
| 43 | 43 | const char tags[][MAXTAGLEN] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; |
|
| 55 | 55 | #define SNAP 32 /* snap pixel */ |
|
| 56 | 56 | ||
| 57 | 57 | Layout layouts[] = { |
|
| 58 | - | /* symbol function */ |
|
| 59 | - | { "[]=", tile }, /* first entry is default */ |
|
| 60 | - | { "><>", floating }, |
|
| 61 | - | { "[M]", monocle }, |
|
| 58 | + | /* symbol function isfloating */ |
|
| 59 | + | { "[]=", tile, False }, /* first entry is default */ |
|
| 60 | + | { "><>", floating True }, |
|
| 61 | + | { "[M]", monocle True }, |
|
| 62 | 62 | }; |
|
| 63 | 63 | ||
| 64 | 64 | /* key definitions */ |
|
| 1 | 1 | /** |
|
| 2 | - | * TODO |
|
| 3 | - | * - treat monocle as floating layout, actually otherwise certain monocled windows don't get raised |
|
| 4 | - | * - use WX, WY, WW, WH for window snapping/resizing/mouse |
|
| 5 | - | * - MOX, MOY, MOW, MOH should only be used in the case of monocle layout and of n==1 in tiled |
|
| 6 | - | * - simplify tile() |
|
| 7 | 2 | * - allow for vstack |
|
| 8 | 3 | */ |
|
| 9 | 4 | /* See LICENSE file for copyright and license details. |
|
| 67 | 62 | struct Client { |
|
| 68 | 63 | char name[256]; |
|
| 69 | 64 | int x, y, w, h; |
|
| 70 | - | int rx, ry, rw, rh; |
|
| 71 | 65 | int basew, baseh, incw, inch, maxw, maxh, minw, minh; |
|
| 72 | 66 | int minax, maxax, minay, maxay; |
|
| 73 | 67 | long flags; |
|
| 105 | 99 | typedef struct { |
|
| 106 | 100 | const char *symbol; |
|
| 107 | 101 | void (*arrange)(void); |
|
| 102 | + | Bool isfloating; |
|
| 108 | 103 | } Layout; |
|
| 109 | 104 | ||
| 110 | 105 | typedef struct { |
|
| 176 | 171 | unsigned int textnw(const char *text, unsigned int len); |
|
| 177 | 172 | unsigned int textw(const char *text); |
|
| 178 | 173 | void tile(void); |
|
| 174 | + | unsigned int tilemaster(void); |
|
| 175 | + | void tilevstack(unsigned int n); |
|
| 179 | 176 | void togglefloating(const char *arg); |
|
| 180 | 177 | void toggletag(const char *arg); |
|
| 181 | 178 | void toggleview(const char *arg); |
|
| 213 | 210 | [UnmapNotify] = unmapnotify |
|
| 214 | 211 | }; |
|
| 215 | 212 | Atom wmatom[WMLast], netatom[NetLast]; |
|
| 216 | - | Bool dozoom = True; |
|
| 217 | 213 | Bool otherwm, readin; |
|
| 218 | 214 | Bool running = True; |
|
| 219 | 215 | Bool *prevtags; |
|
| 297 | 293 | ban(Client *c) { |
|
| 298 | 294 | if(c->isbanned) |
|
| 299 | 295 | return; |
|
| 300 | - | XMoveWindow(dpy, c->win, c->x + 3 * sw, c->y); |
|
| 296 | + | XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y); |
|
| 301 | 297 | c->isbanned = True; |
|
| 302 | 298 | } |
|
| 303 | 299 | ||
| 428 | 424 | if((c = getclient(ev->window))) { |
|
| 429 | 425 | if(ev->value_mask & CWBorderWidth) |
|
| 430 | 426 | c->border = ev->border_width; |
|
| 431 | - | if(c->isfixed || c->isfloating || (floating == lt->arrange)) { |
|
| 427 | + | if(c->isfixed || c->isfloating || lt->isfloating) { |
|
| 432 | 428 | if(ev->value_mask & CWX) |
|
| 433 | 429 | c->x = sx + ev->x; |
|
| 434 | 430 | if(ev->value_mask & CWY) |
|
| 637 | 633 | floating(void) { /* default floating layout */ |
|
| 638 | 634 | Client *c; |
|
| 639 | 635 | ||
| 640 | - | dozoom = False; |
|
| 641 | 636 | for(c = clients; c; c = c->next) |
|
| 642 | 637 | if(isvisible(c)) |
|
| 643 | 638 | resize(c, c->x, c->y, c->w, c->h, True); |
|
| 650 | 645 | if(sel && sel != c) { |
|
| 651 | 646 | grabbuttons(sel, False); |
|
| 652 | 647 | XSetWindowBorder(dpy, sel->win, dc.norm[ColBorder]); |
|
| 653 | - | if(lt->arrange == monocle) |
|
| 654 | - | resize(sel, sel->rx, sel->ry, sel->rw, sel->rh, True); |
|
| 655 | 648 | } |
|
| 656 | 649 | if(c) { |
|
| 657 | 650 | detachstack(c); |
|
| 658 | 651 | attachstack(c); |
|
| 659 | 652 | grabbuttons(c, True); |
|
| 660 | - | if(lt->arrange == monocle) { |
|
| 661 | - | if(sel != c) { |
|
| 662 | - | c->rx = c->x; |
|
| 663 | - | c->ry = c->y; |
|
| 664 | - | c->rw = c->w; |
|
| 665 | - | c->rh = c->h; |
|
| 666 | - | } |
|
| 667 | - | resize(c, MOX, MOY, MOW, MOH, RESIZEHINTS); |
|
| 668 | - | } |
|
| 669 | 653 | } |
|
| 670 | 654 | sel = c; |
|
| 671 | 655 | if(c) { |
|
| 987 | 971 | c->tags = emallocz(TAGSZ); |
|
| 988 | 972 | c->win = w; |
|
| 989 | 973 | ||
| 990 | - | c->x = c->rx = wa->x + sx; |
|
| 991 | - | c->y = c->ry = wa->y + sy; |
|
| 992 | - | c->w = c->rw = wa->width; |
|
| 993 | - | c->h = c->rh = wa->height; |
|
| 974 | + | /* geometry */ |
|
| 975 | + | c->x = wa->x; |
|
| 976 | + | c->y = wa->y; |
|
| 977 | + | c->w = wa->width; |
|
| 978 | + | c->h = wa->height; |
|
| 994 | 979 | c->oldborder = wa->border_width; |
|
| 995 | - | ||
| 996 | 980 | if(c->w == sw && c->h == sh) { |
|
| 997 | 981 | c->x = sx; |
|
| 998 | 982 | c->y = sy; |
|
| 999 | 983 | c->border = wa->border_width; |
|
| 1000 | 984 | } |
|
| 1001 | 985 | else { |
|
| 1002 | - | if(c->x + c->w + 2 * c->border > sx + sw) |
|
| 1003 | - | c->x = sx + sw - c->w - 2 * c->border; |
|
| 1004 | - | if(c->y + c->h + 2 * c->border > sy + sh) |
|
| 1005 | - | c->y = sy + sh - c->h - 2 * c->border; |
|
| 1006 | - | if(c->x < sx) |
|
| 1007 | - | c->x = sx; |
|
| 1008 | - | if(c->y < sy) |
|
| 1009 | - | c->y = sy; |
|
| 986 | + | if(c->x + c->w + 2 * c->border > WX + WW) |
|
| 987 | + | c->x = WX + WW - c->w - 2 * c->border; |
|
| 988 | + | if(c->y + c->h + 2 * c->border > WY + WH) |
|
| 989 | + | c->y = WY + WH - c->h - 2 * c->border; |
|
| 990 | + | if(c->x < WX) |
|
| 991 | + | c->x = WX; |
|
| 992 | + | if(c->y < WY) |
|
| 993 | + | c->y = WY; |
|
| 1010 | 994 | c->border = BORDERPX; |
|
| 1011 | 995 | } |
|
| 996 | + | ||
| 1012 | 997 | wc.border_width = c->border; |
|
| 1013 | 998 | XConfigureWindow(dpy, w, CWBorderWidth, &wc); |
|
| 1014 | 999 | XSetWindowBorder(dpy, w, dc.norm[ColBorder]); |
|
| 1057 | 1042 | } |
|
| 1058 | 1043 | ||
| 1059 | 1044 | void |
|
| 1060 | - | monocle(void) { |
|
| 1061 | - | dozoom = False; |
|
| 1045 | + | monocle(void) { |
|
| 1046 | + | Client *c; |
|
| 1047 | + | ||
| 1048 | + | for(c = clients; c; c = c->next) |
|
| 1049 | + | if(isvisible(c)) |
|
| 1050 | + | resize(c, MOX, MOY, MOW, MOH, RESIZEHINTS); |
|
| 1062 | 1051 | } |
|
| 1063 | 1052 | ||
| 1064 | 1053 | void |
|
| 1089 | 1078 | XSync(dpy, False); |
|
| 1090 | 1079 | nx = ocx + (ev.xmotion.x - x1); |
|
| 1091 | 1080 | ny = ocy + (ev.xmotion.y - y1); |
|
| 1092 | - | if(abs(sx - nx) < SNAP) |
|
| 1093 | - | nx = sx; |
|
| 1094 | - | else if(abs((sx + sw) - (nx + c->w + 2 * c->border)) < SNAP) |
|
| 1095 | - | nx = sx + sw - c->w - 2 * c->border; |
|
| 1096 | - | if(abs(sy - ny) < SNAP) |
|
| 1097 | - | ny = sy; |
|
| 1098 | - | else if(abs((sy + sh) - (ny + c->h + 2 * c->border)) < SNAP) |
|
| 1099 | - | ny = sy + sh - c->h - 2 * c->border; |
|
| 1100 | - | if(!c->isfloating && (lt->arrange != floating) && (abs(nx - c->x) > SNAP || abs(ny - c->y) > SNAP)) |
|
| 1081 | + | if(abs(WX - nx) < SNAP) |
|
| 1082 | + | nx = WX; |
|
| 1083 | + | else if(abs((WX + WW) - (nx + c->w + 2 * c->border)) < SNAP) |
|
| 1084 | + | nx = WX + WW - c->w - 2 * c->border; |
|
| 1085 | + | if(abs(WY - ny) < SNAP) |
|
| 1086 | + | ny = WY; |
|
| 1087 | + | else if(abs((WY + WH) - (ny + c->h + 2 * c->border)) < SNAP) |
|
| 1088 | + | ny = WY + WH - c->h - 2 * c->border; |
|
| 1089 | + | if(!c->isfloating && !lt->isfloating && (abs(nx - c->x) > SNAP || abs(ny - c->y) > SNAP)) |
|
| 1101 | 1090 | togglefloating(NULL); |
|
| 1102 | - | if((lt->arrange == floating) || c->isfloating) |
|
| 1091 | + | if((lt->isfloating) || c->isfloating) |
|
| 1103 | 1092 | resize(c, nx, ny, c->w, c->h, False); |
|
| 1104 | 1093 | break; |
|
| 1105 | 1094 | } |
|
| 1258 | 1247 | nw = 1; |
|
| 1259 | 1248 | if((nh = ev.xmotion.y - ocy - 2 * c->border + 1) <= 0) |
|
| 1260 | 1249 | nh = 1; |
|
| 1261 | - | if(!c->isfloating && (lt->arrange != floating) && (abs(nw - c->w) > SNAP || abs(nh - c->h) > SNAP)) |
|
| 1250 | + | if(!c->isfloating && !lt->isfloating && (abs(nw - c->w) > SNAP || abs(nh - c->h) > SNAP)) |
|
| 1262 | 1251 | togglefloating(NULL); |
|
| 1263 | - | if((lt->arrange == floating) || c->isfloating) |
|
| 1252 | + | if((lt->isfloating) || c->isfloating) |
|
| 1264 | 1253 | resize(c, c->x, c->y, nw, nh, True); |
|
| 1265 | 1254 | break; |
|
| 1266 | 1255 | } |
|
| 1276 | 1265 | drawbar(); |
|
| 1277 | 1266 | if(!sel) |
|
| 1278 | 1267 | return; |
|
| 1279 | - | if(sel->isfloating || (lt->arrange == floating)) |
|
| 1268 | + | if(sel->isfloating || lt->isfloating) |
|
| 1280 | 1269 | XRaiseWindow(dpy, sel->win); |
|
| 1281 | - | if(lt->arrange != floating) { |
|
| 1270 | + | if(!lt->isfloating) { |
|
| 1282 | 1271 | wc.stack_mode = Below; |
|
| 1283 | 1272 | wc.sibling = barwin; |
|
| 1284 | 1273 | if(!sel->isfloating) { |
|
| 1393 | 1382 | ||
| 1394 | 1383 | void |
|
| 1395 | 1384 | setlayout(const char *arg) { |
|
| 1385 | + | static Layout *revert = 0; |
|
| 1396 | 1386 | unsigned int i; |
|
| 1397 | 1387 | ||
| 1398 | 1388 | if(!arg) |
|
| 1402 | 1392 | break; |
|
| 1403 | 1393 | if(i == LENGTH(layouts)) |
|
| 1404 | 1394 | return; |
|
| 1405 | - | lt = &layouts[i]; |
|
| 1395 | + | if(revert && &layouts[i] == lt) |
|
| 1396 | + | lt = revert; |
|
| 1397 | + | else { |
|
| 1398 | + | revert = lt; |
|
| 1399 | + | lt = &layouts[i]; |
|
| 1400 | + | } |
|
| 1406 | 1401 | if(sel) |
|
| 1407 | 1402 | arrange(); |
|
| 1408 | 1403 | else |
|
| 1545 | 1540 | } |
|
| 1546 | 1541 | ||
| 1547 | 1542 | void |
|
| 1548 | - | tile(void) { |
|
| 1549 | - | unsigned int i, n, nx, ny, nw, nh, mw, th; |
|
| 1543 | + | tileresize(Client *c, int x, int y, int w, int h) { |
|
| 1544 | + | resize(c, x, y, w, h, RESIZEHINTS); |
|
| 1545 | + | if((RESIZEHINTS) && ((c->h < bh) || (c->h > h) || (c->w < bh) || (c->w > w))) |
|
| 1546 | + | /* client doesn't accept size constraints */ |
|
| 1547 | + | resize(c, x, y, w, h, False); |
|
| 1548 | + | } |
|
| 1549 | + | ||
| 1550 | + | unsigned int |
|
| 1551 | + | tilemaster(void) { |
|
| 1552 | + | unsigned int n; |
|
| 1550 | 1553 | Client *c, *mc; |
|
| 1551 | 1554 | ||
| 1552 | - | dozoom = True; |
|
| 1553 | - | nx = MX; |
|
| 1554 | - | ny = MY; |
|
| 1555 | - | nw = 0; |
|
| 1556 | - | for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next)) |
|
| 1555 | + | for(n = 0, mc = c = nexttiled(clients); c; c = nexttiled(c->next)) |
|
| 1557 | 1556 | n++; |
|
| 1557 | + | if(n == 0) |
|
| 1558 | + | return 0; |
|
| 1559 | + | if(n == 1) |
|
| 1560 | + | tileresize(mc, MOX, MOY, (MOW) - 2 * mc->border, (MOH) - 2 * mc->border); |
|
| 1561 | + | else |
|
| 1562 | + | tileresize(mc, MX, MY, (MW) - 2 * mc->border, (MH) - 2 * mc->border); |
|
| 1563 | + | return n - 1; |
|
| 1564 | + | } |
|
| 1558 | 1565 | ||
| 1559 | - | /* window geoms */ |
|
| 1560 | - | mw = (n == 1) ? MOW : MW; |
|
| 1561 | - | th = (n > 1) ? TH / (n - 1) : 0; |
|
| 1562 | - | if(n > 1 && th < bh) |
|
| 1563 | - | th = TH; |
|
| 1566 | + | void |
|
| 1567 | + | tilevstack(unsigned int n) { |
|
| 1568 | + | int i, y, h; |
|
| 1569 | + | Client *c; |
|
| 1570 | + | ||
| 1571 | + | if(n == 0) |
|
| 1572 | + | return; |
|
| 1573 | + | ||
| 1574 | + | y = TY; |
|
| 1575 | + | h = (TH) / n; |
|
| 1576 | + | if(h < bh) |
|
| 1577 | + | h = TH; |
|
| 1564 | 1578 | ||
| 1565 | - | for(i = 0, c = mc = nexttiled(clients); c; c = nexttiled(c->next)) { |
|
| 1566 | - | if(i == 0) { /* master */ |
|
| 1567 | - | nw = mw - 2 * c->border; |
|
| 1568 | - | nh = MH - 2 * c->border; |
|
| 1569 | - | } |
|
| 1570 | - | else { /* tile window */ |
|
| 1571 | - | if(i == 1) { |
|
| 1572 | - | ny = TY; |
|
| 1573 | - | nx = TX; |
|
| 1574 | - | nw = TW - 2 * c->border; |
|
| 1575 | - | } |
|
| 1576 | - | if(i + 1 == n) /* remainder */ |
|
| 1577 | - | nh = (TY + TH) - ny - 2 * c->border; |
|
| 1579 | + | for(i = 0, c = nexttiled(clients); c; c = nexttiled(c->next), i++) |
|
| 1580 | + | if(i > 0) { |
|
| 1581 | + | if(i > 1 && i == n) /* remainder */ |
|
| 1582 | + | tileresize(c, TX, y, (TW) - 2 * c->border, |
|
| 1583 | + | ((TY) + (TH)) - y - 2 * c->border); |
|
| 1578 | 1584 | else |
|
| 1579 | - | nh = th - 2 * c->border; |
|
| 1585 | + | tileresize(c, TX, y, (TW) - 2 * c->border, |
|
| 1586 | + | h - 2 * c->border); |
|
| 1587 | + | if(h != TH) |
|
| 1588 | + | y = c->y + c->h + 2 * c->border; |
|
| 1580 | 1589 | } |
|
| 1581 | - | resize(c, nx, ny, nw, nh, RESIZEHINTS); |
|
| 1582 | - | if((RESIZEHINTS) && ((c->h < bh) || (c->h > nh) || (c->w < bh) || (c->w > nw))) |
|
| 1583 | - | /* client doesn't accept size constraints */ |
|
| 1584 | - | resize(c, nx, ny, nw, nh, False); |
|
| 1585 | - | if(n > 1 && th != TH) |
|
| 1586 | - | ny = c->y + c->h + 2 * c->border; |
|
| 1587 | - | i++; |
|
| 1588 | - | } |
|
| 1590 | + | } |
|
| 1591 | + | ||
| 1592 | + | void |
|
| 1593 | + | tile(void) { |
|
| 1594 | + | tilevstack(tilemaster()); |
|
| 1589 | 1595 | } |
|
| 1590 | 1596 | ||
| 1591 | 1597 | void |
|
| 1796 | 1802 | zoom(const char *arg) { |
|
| 1797 | 1803 | Client *c = sel; |
|
| 1798 | 1804 | ||
| 1799 | - | if(!sel || !dozoom || sel->isfloating) |
|
| 1805 | + | if(!sel || lt->isfloating || sel->isfloating) |
|
| 1800 | 1806 | return; |
|
| 1801 | 1807 | if(c == nexttiled(clients)) |
|
| 1802 | 1808 | if(!(c = nexttiled(c->next))) |
|