65 /* typedefs */ |
60 /* typedefs */ |
66 typedef struct Client Client; |
61 typedef struct Client Client; |
67 struct Client { |
62 struct Client { |
68 char name[256]; |
63 char name[256]; |
69 int x, y, w, h; |
64 int x, y, w, h; |
70 int rx, ry, rw, rh; |
|
71 int basew, baseh, incw, inch, maxw, maxh, minw, minh; |
65 int basew, baseh, incw, inch, maxw, maxh, minw, minh; |
72 int minax, maxax, minay, maxay; |
66 int minax, maxax, minay, maxay; |
73 long flags; |
67 long flags; |
74 unsigned int border, oldborder; |
68 unsigned int border, oldborder; |
75 Bool isbanned, isfixed, isfloating, isurgent; |
69 Bool isbanned, isfixed, isfloating, isurgent; |
174 void spawn(const char *arg); |
169 void spawn(const char *arg); |
175 void tag(const char *arg); |
170 void tag(const char *arg); |
176 unsigned int textnw(const char *text, unsigned int len); |
171 unsigned int textnw(const char *text, unsigned int len); |
177 unsigned int textw(const char *text); |
172 unsigned int textw(const char *text); |
178 void tile(void); |
173 void tile(void); |
|
174 unsigned int tilemaster(void); |
|
175 void tilevstack(unsigned int n); |
179 void togglefloating(const char *arg); |
176 void togglefloating(const char *arg); |
180 void toggletag(const char *arg); |
177 void toggletag(const char *arg); |
181 void toggleview(const char *arg); |
178 void toggleview(const char *arg); |
182 void unban(Client *c); |
179 void unban(Client *c); |
183 void unmanage(Client *c); |
180 void unmanage(Client *c); |
211 [MapRequest] = maprequest, |
208 [MapRequest] = maprequest, |
212 [PropertyNotify] = propertynotify, |
209 [PropertyNotify] = propertynotify, |
213 [UnmapNotify] = unmapnotify |
210 [UnmapNotify] = unmapnotify |
214 }; |
211 }; |
215 Atom wmatom[WMLast], netatom[NetLast]; |
212 Atom wmatom[WMLast], netatom[NetLast]; |
216 Bool dozoom = True; |
|
217 Bool otherwm, readin; |
213 Bool otherwm, readin; |
218 Bool running = True; |
214 Bool running = True; |
219 Bool *prevtags; |
215 Bool *prevtags; |
220 Bool *seltags; |
216 Bool *seltags; |
221 Client *clients = NULL; |
217 Client *clients = NULL; |
426 XWindowChanges wc; |
422 XWindowChanges wc; |
427 |
423 |
428 if((c = getclient(ev->window))) { |
424 if((c = getclient(ev->window))) { |
429 if(ev->value_mask & CWBorderWidth) |
425 if(ev->value_mask & CWBorderWidth) |
430 c->border = ev->border_width; |
426 c->border = ev->border_width; |
431 if(c->isfixed || c->isfloating || (floating == lt->arrange)) { |
427 if(c->isfixed || c->isfloating || lt->isfloating) { |
432 if(ev->value_mask & CWX) |
428 if(ev->value_mask & CWX) |
433 c->x = sx + ev->x; |
429 c->x = sx + ev->x; |
434 if(ev->value_mask & CWY) |
430 if(ev->value_mask & CWY) |
435 c->y = sy + ev->y; |
431 c->y = sy + ev->y; |
436 if(ev->value_mask & CWWidth) |
432 if(ev->value_mask & CWWidth) |
648 if(!c || (c && !isvisible(c))) |
643 if(!c || (c && !isvisible(c))) |
649 for(c = stack; c && !isvisible(c); c = c->snext); |
644 for(c = stack; c && !isvisible(c); c = c->snext); |
650 if(sel && sel != c) { |
645 if(sel && sel != c) { |
651 grabbuttons(sel, False); |
646 grabbuttons(sel, False); |
652 XSetWindowBorder(dpy, sel->win, dc.norm[ColBorder]); |
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 if(c) { |
649 if(c) { |
657 detachstack(c); |
650 detachstack(c); |
658 attachstack(c); |
651 attachstack(c); |
659 grabbuttons(c, True); |
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 sel = c; |
654 sel = c; |
671 if(c) { |
655 if(c) { |
672 XSetWindowBorder(dpy, c->win, dc.sel[ColBorder]); |
656 XSetWindowBorder(dpy, c->win, dc.sel[ColBorder]); |
673 XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); |
657 XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); |
985 |
969 |
986 c = emallocz(sizeof(Client)); |
970 c = emallocz(sizeof(Client)); |
987 c->tags = emallocz(TAGSZ); |
971 c->tags = emallocz(TAGSZ); |
988 c->win = w; |
972 c->win = w; |
989 |
973 |
990 c->x = c->rx = wa->x + sx; |
974 /* geometry */ |
991 c->y = c->ry = wa->y + sy; |
975 c->x = wa->x; |
992 c->w = c->rw = wa->width; |
976 c->y = wa->y; |
993 c->h = c->rh = wa->height; |
977 c->w = wa->width; |
|
978 c->h = wa->height; |
994 c->oldborder = wa->border_width; |
979 c->oldborder = wa->border_width; |
995 |
|
996 if(c->w == sw && c->h == sh) { |
980 if(c->w == sw && c->h == sh) { |
997 c->x = sx; |
981 c->x = sx; |
998 c->y = sy; |
982 c->y = sy; |
999 c->border = wa->border_width; |
983 c->border = wa->border_width; |
1000 } |
984 } |
1001 else { |
985 else { |
1002 if(c->x + c->w + 2 * c->border > sx + sw) |
986 if(c->x + c->w + 2 * c->border > WX + WW) |
1003 c->x = sx + sw - c->w - 2 * c->border; |
987 c->x = WX + WW - c->w - 2 * c->border; |
1004 if(c->y + c->h + 2 * c->border > sy + sh) |
988 if(c->y + c->h + 2 * c->border > WY + WH) |
1005 c->y = sy + sh - c->h - 2 * c->border; |
989 c->y = WY + WH - c->h - 2 * c->border; |
1006 if(c->x < sx) |
990 if(c->x < WX) |
1007 c->x = sx; |
991 c->x = WX; |
1008 if(c->y < sy) |
992 if(c->y < WY) |
1009 c->y = sy; |
993 c->y = WY; |
1010 c->border = BORDERPX; |
994 c->border = BORDERPX; |
1011 } |
995 } |
|
996 |
1012 wc.border_width = c->border; |
997 wc.border_width = c->border; |
1013 XConfigureWindow(dpy, w, CWBorderWidth, &wc); |
998 XConfigureWindow(dpy, w, CWBorderWidth, &wc); |
1014 XSetWindowBorder(dpy, w, dc.norm[ColBorder]); |
999 XSetWindowBorder(dpy, w, dc.norm[ColBorder]); |
1015 configure(c); /* propagates border_width, if size doesn't change */ |
1000 configure(c); /* propagates border_width, if size doesn't change */ |
1016 updatesizehints(c); |
1001 updatesizehints(c); |
1055 if(!getclient(ev->window)) |
1040 if(!getclient(ev->window)) |
1056 manage(ev->window, &wa); |
1041 manage(ev->window, &wa); |
1057 } |
1042 } |
1058 |
1043 |
1059 void |
1044 void |
1060 monocle(void) { |
1045 monocle(void) { |
1061 dozoom = False; |
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 void |
1053 void |
1065 movemouse(Client *c) { |
1054 movemouse(Client *c) { |
1066 int x1, y1, ocx, ocy, di, nx, ny; |
1055 int x1, y1, ocx, ocy, di, nx, ny; |
1087 break; |
1076 break; |
1088 case MotionNotify: |
1077 case MotionNotify: |
1089 XSync(dpy, False); |
1078 XSync(dpy, False); |
1090 nx = ocx + (ev.xmotion.x - x1); |
1079 nx = ocx + (ev.xmotion.x - x1); |
1091 ny = ocy + (ev.xmotion.y - y1); |
1080 ny = ocy + (ev.xmotion.y - y1); |
1092 if(abs(sx - nx) < SNAP) |
1081 if(abs(WX - nx) < SNAP) |
1093 nx = sx; |
1082 nx = WX; |
1094 else if(abs((sx + sw) - (nx + c->w + 2 * c->border)) < SNAP) |
1083 else if(abs((WX + WW) - (nx + c->w + 2 * c->border)) < SNAP) |
1095 nx = sx + sw - c->w - 2 * c->border; |
1084 nx = WX + WW - c->w - 2 * c->border; |
1096 if(abs(sy - ny) < SNAP) |
1085 if(abs(WY - ny) < SNAP) |
1097 ny = sy; |
1086 ny = WY; |
1098 else if(abs((sy + sh) - (ny + c->h + 2 * c->border)) < SNAP) |
1087 else if(abs((WY + WH) - (ny + c->h + 2 * c->border)) < SNAP) |
1099 ny = sy + sh - c->h - 2 * c->border; |
1088 ny = WY + WH - c->h - 2 * c->border; |
1100 if(!c->isfloating && (lt->arrange != floating) && (abs(nx - c->x) > SNAP || abs(ny - c->y) > SNAP)) |
1089 if(!c->isfloating && !lt->isfloating && (abs(nx - c->x) > SNAP || abs(ny - c->y) > SNAP)) |
1101 togglefloating(NULL); |
1090 togglefloating(NULL); |
1102 if((lt->arrange == floating) || c->isfloating) |
1091 if((lt->isfloating) || c->isfloating) |
1103 resize(c, nx, ny, c->w, c->h, False); |
1092 resize(c, nx, ny, c->w, c->h, False); |
1104 break; |
1093 break; |
1105 } |
1094 } |
1106 } |
1095 } |
1107 } |
1096 } |
1256 XSync(dpy, False); |
1245 XSync(dpy, False); |
1257 if((nw = ev.xmotion.x - ocx - 2 * c->border + 1) <= 0) |
1246 if((nw = ev.xmotion.x - ocx - 2 * c->border + 1) <= 0) |
1258 nw = 1; |
1247 nw = 1; |
1259 if((nh = ev.xmotion.y - ocy - 2 * c->border + 1) <= 0) |
1248 if((nh = ev.xmotion.y - ocy - 2 * c->border + 1) <= 0) |
1260 nh = 1; |
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 togglefloating(NULL); |
1251 togglefloating(NULL); |
1263 if((lt->arrange == floating) || c->isfloating) |
1252 if((lt->isfloating) || c->isfloating) |
1264 resize(c, c->x, c->y, nw, nh, True); |
1253 resize(c, c->x, c->y, nw, nh, True); |
1265 break; |
1254 break; |
1266 } |
1255 } |
1267 } |
1256 } |
1268 } |
1257 } |
1274 XWindowChanges wc; |
1263 XWindowChanges wc; |
1275 |
1264 |
1276 drawbar(); |
1265 drawbar(); |
1277 if(!sel) |
1266 if(!sel) |
1278 return; |
1267 return; |
1279 if(sel->isfloating || (lt->arrange == floating)) |
1268 if(sel->isfloating || lt->isfloating) |
1280 XRaiseWindow(dpy, sel->win); |
1269 XRaiseWindow(dpy, sel->win); |
1281 if(lt->arrange != floating) { |
1270 if(!lt->isfloating) { |
1282 wc.stack_mode = Below; |
1271 wc.stack_mode = Below; |
1283 wc.sibling = barwin; |
1272 wc.sibling = barwin; |
1284 if(!sel->isfloating) { |
1273 if(!sel->isfloating) { |
1285 XConfigureWindow(dpy, sel->win, CWSibling|CWStackMode, &wc); |
1274 XConfigureWindow(dpy, sel->win, CWSibling|CWStackMode, &wc); |
1286 wc.sibling = sel->win; |
1275 wc.sibling = sel->win; |
1391 PropModeReplace, (unsigned char *)data, 2); |
1380 PropModeReplace, (unsigned char *)data, 2); |
1392 } |
1381 } |
1393 |
1382 |
1394 void |
1383 void |
1395 setlayout(const char *arg) { |
1384 setlayout(const char *arg) { |
|
1385 static Layout *revert = 0; |
1396 unsigned int i; |
1386 unsigned int i; |
1397 |
1387 |
1398 if(!arg) |
1388 if(!arg) |
1399 return; |
1389 return; |
1400 for(i = 0; i < LENGTH(layouts); i++) |
1390 for(i = 0; i < LENGTH(layouts); i++) |
1401 if(!strcmp(arg, layouts[i].symbol)) |
1391 if(!strcmp(arg, layouts[i].symbol)) |
1402 break; |
1392 break; |
1403 if(i == LENGTH(layouts)) |
1393 if(i == LENGTH(layouts)) |
1404 return; |
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 if(sel) |
1401 if(sel) |
1407 arrange(); |
1402 arrange(); |
1408 else |
1403 else |
1409 drawbar(); |
1404 drawbar(); |
1410 } |
1405 } |
1543 textw(const char *text) { |
1538 textw(const char *text) { |
1544 return textnw(text, strlen(text)) + dc.font.height; |
1539 return textnw(text, strlen(text)) + dc.font.height; |
1545 } |
1540 } |
1546 |
1541 |
1547 void |
1542 void |
|
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; |
|
1553 Client *c, *mc; |
|
1554 |
|
1555 for(n = 0, mc = c = nexttiled(clients); c; c = nexttiled(c->next)) |
|
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 } |
|
1565 |
|
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; |
|
1578 |
|
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); |
|
1584 else |
|
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; |
|
1589 } |
|
1590 } |
|
1591 |
|
1592 void |
1548 tile(void) { |
1593 tile(void) { |
1549 unsigned int i, n, nx, ny, nw, nh, mw, th; |
1594 tilevstack(tilemaster()); |
1550 Client *c, *mc; |
|
1551 |
|
1552 dozoom = True; |
|
1553 nx = MX; |
|
1554 ny = MY; |
|
1555 nw = 0; |
|
1556 for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next)) |
|
1557 n++; |
|
1558 |
|
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; |
|
1564 |
|
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; |
|
1578 else |
|
1579 nh = th - 2 * c->border; |
|
1580 } |
|
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 } |
|
1589 } |
1595 } |
1590 |
1596 |
1591 void |
1597 void |
1592 togglefloating(const char *arg) { |
1598 togglefloating(const char *arg) { |
1593 if(!sel) |
1599 if(!sel) |