38 #include <X11/keysym.h> |
38 #include <X11/keysym.h> |
39 #include <X11/Xatom.h> |
39 #include <X11/Xatom.h> |
40 #include <X11/Xlib.h> |
40 #include <X11/Xlib.h> |
41 #include <X11/Xproto.h> |
41 #include <X11/Xproto.h> |
42 #include <X11/Xutil.h> |
42 #include <X11/Xutil.h> |
43 /* |
|
44 * TODO: Idea: |
|
45 * I intend to not provide real Xinerama support, but instead having a Column |
|
46 * tilecols[] array which is used by tile(), and a Column maxcols[] arrays which is used by |
|
47 * monocle(). Those arrays should be initialized in config.h. For simplicity |
|
48 * reasons mwfact should be replaced with a more advanced method which |
|
49 * implements the same, but using the boundary between tilecols[0] and |
|
50 * tilecols[1] instead. Besides this, get rid of BARPOS and use instead the |
|
51 * following mechanism: |
|
52 * |
|
53 * #define BX 0 |
|
54 * #define BY 0 |
|
55 * #define BW sw |
|
56 * bh is calculated automatically and should be used for the |
|
57 */ |
|
58 //#ifdef XINERAMA |
|
59 #include <X11/extensions/Xinerama.h> |
|
60 //#endif |
|
61 |
43 |
62 /* macros */ |
44 /* macros */ |
63 #define BUTTONMASK (ButtonPressMask|ButtonReleaseMask) |
45 #define BUTTONMASK (ButtonPressMask|ButtonReleaseMask) |
64 #define CLEANMASK(mask) (mask & ~(numlockmask|LockMask)) |
46 #define CLEANMASK(mask) (mask & ~(numlockmask|LockMask)) |
65 #define LENGTH(x) (sizeof x / sizeof x[0]) |
47 #define LENGTH(x) (sizeof x / sizeof x[0]) |
66 #define MAXTAGLEN 16 |
48 #define MAXTAGLEN 16 |
67 #define MOUSEMASK (BUTTONMASK|PointerMotionMask) |
49 #define MOUSEMASK (BUTTONMASK|PointerMotionMask) |
68 |
50 |
69 |
|
70 /* enums */ |
51 /* enums */ |
71 enum { BarTop, BarBot, BarOff }; /* bar position */ |
|
72 enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ |
52 enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ |
73 enum { ColBorder, ColFG, ColBG, ColLast }; /* color */ |
53 enum { ColBorder, ColFG, ColBG, ColLast }; /* color */ |
74 enum { NetSupported, NetWMName, NetLast }; /* EWMH atoms */ |
54 enum { NetSupported, NetWMName, NetLast }; /* EWMH atoms */ |
75 enum { WMProtocols, WMDelete, WMName, WMState, WMLast };/* default atoms */ |
55 enum { WMProtocols, WMDelete, WMName, WMState, WMLast };/* default atoms */ |
76 |
56 |
77 /* typedefs */ |
57 /* typedefs */ |
78 typedef struct Client Client; |
58 typedef struct Client Client; |
79 struct Client { |
59 struct Client { |
80 char name[256]; |
60 char name[256]; |
81 int x, y, w, h; |
61 int x, y, w, h; |
|
62 int rx, ry, rw, rh; |
82 int basew, baseh, incw, inch, maxw, maxh, minw, minh; |
63 int basew, baseh, incw, inch, maxw, maxh, minw, minh; |
83 int minax, maxax, minay, maxay; |
64 int minax, maxax, minay, maxay; |
84 long flags; |
65 long flags; |
85 unsigned int border, oldborder; |
66 unsigned int border, oldborder; |
86 Bool isbanned, isfixed, isfloating, isurgent; |
67 Bool isbanned, isfixed, isfloating, isurgent; |
183 void restack(void); |
160 void restack(void); |
184 void run(void); |
161 void run(void); |
185 void scan(void); |
162 void scan(void); |
186 void setclientstate(Client *c, long state); |
163 void setclientstate(Client *c, long state); |
187 void setlayout(const char *arg); |
164 void setlayout(const char *arg); |
188 void setmwfact(const char *arg); |
|
189 void setup(void); |
165 void setup(void); |
190 void spawn(const char *arg); |
166 void spawn(const char *arg); |
191 void tag(const char *arg); |
167 void tag(const char *arg); |
192 unsigned int textnw(const char *text, unsigned int len); |
168 unsigned int textnw(const char *text, unsigned int len); |
193 unsigned int textw(const char *text); |
169 unsigned int textw(const char *text); |
194 void tile(void); |
170 void tile(void); |
195 void togglebar(const char *arg); |
|
196 void togglefloating(const char *arg); |
171 void togglefloating(const char *arg); |
197 void toggletag(const char *arg); |
172 void toggletag(const char *arg); |
198 void toggleview(const char *arg); |
173 void toggleview(const char *arg); |
199 void unban(Client *c); |
174 void unban(Client *c); |
200 void unmanage(Client *c); |
175 void unmanage(Client *c); |
201 void unmapnotify(XEvent *e); |
176 void unmapnotify(XEvent *e); |
202 void updatebarpos(void); |
|
203 void updatesizehints(Client *c); |
177 void updatesizehints(Client *c); |
204 void updatetitle(Client *c); |
178 void updatetitle(Client *c); |
205 void updatewmhints(Client *c); |
179 void updatewmhints(Client *c); |
206 void view(const char *arg); |
180 void view(const char *arg); |
207 void viewprevtag(const char *arg); /* views previous selected tags */ |
181 void viewprevtag(const char *arg); /* views previous selected tags */ |
212 void selectview(const char *arg); |
186 void selectview(const char *arg); |
213 |
187 |
214 /* variables */ |
188 /* variables */ |
215 char stext[256], buf[256]; |
189 char stext[256], buf[256]; |
216 double mwfact; |
190 double mwfact; |
217 int screen, sx, sy, sw, sh, wax, way, waw, wah, ncols; |
191 int screen, sx, sy, sw, sh; |
218 int (*xerrorxlib)(Display *, XErrorEvent *); |
192 int (*xerrorxlib)(Display *, XErrorEvent *); |
219 unsigned int bh, bpos; |
193 unsigned int bh, bpos; |
220 unsigned int blw = 0; |
194 unsigned int blw = 0; |
221 unsigned int numlockmask = 0; |
195 unsigned int numlockmask = 0; |
222 void (*handler[LASTEvent]) (XEvent *) = { |
196 void (*handler[LASTEvent]) (XEvent *) = { |
232 [MapRequest] = maprequest, |
206 [MapRequest] = maprequest, |
233 [PropertyNotify] = propertynotify, |
207 [PropertyNotify] = propertynotify, |
234 [UnmapNotify] = unmapnotify |
208 [UnmapNotify] = unmapnotify |
235 }; |
209 }; |
236 Atom wmatom[WMLast], netatom[NetLast]; |
210 Atom wmatom[WMLast], netatom[NetLast]; |
237 Bool domwfact = True; |
|
238 Bool dozoom = True; |
211 Bool dozoom = True; |
239 Bool otherwm, readin; |
212 Bool otherwm, readin; |
240 Bool running = True; |
213 Bool running = True; |
241 Bool *prevtags; |
214 Bool *prevtags; |
242 Bool *seltags; |
215 Bool *seltags; |
243 Client *clients = NULL; |
216 Client *clients = NULL; |
244 Client *sel = NULL; |
217 Client *sel = NULL; |
245 Client *stack = NULL; |
218 Client *stack = NULL; |
246 Column *cols = NULL; |
|
247 Cursor cursor[CurLast]; |
219 Cursor cursor[CurLast]; |
248 Display *dpy; |
220 Display *dpy; |
249 DC dc = {0}; |
221 DC dc = {0}; |
250 Layout *lt; |
222 Layout *lt; |
251 Window root, barwin; |
223 Window root, barwin; |
435 void |
405 void |
436 configurenotify(XEvent *e) { |
406 configurenotify(XEvent *e) { |
437 XConfigureEvent *ev = &e->xconfigure; |
407 XConfigureEvent *ev = &e->xconfigure; |
438 |
408 |
439 if(ev->window == root && (ev->width != sw || ev->height != sh)) { |
409 if(ev->window == root && (ev->width != sw || ev->height != sh)) { |
440 /* TODO -- use Xinerama dimensions here ? */ |
|
441 sw = ev->width; |
410 sw = ev->width; |
442 sh = ev->height; |
411 sh = ev->height; |
443 XFreePixmap(dpy, dc.drawable); |
412 XFreePixmap(dpy, dc.drawable); |
444 dc.drawable = XCreatePixmap(dpy, root, DisplayWidth(root, screen), bh, DefaultDepth(dpy, screen)); |
413 dc.drawable = XCreatePixmap(dpy, root, BW, bh, DefaultDepth(dpy, screen)); |
445 XResizeWindow(dpy, barwin, sw, bh); |
414 XMoveResizeWindow(dpy, barwin, BX, BY, BW, bh); |
446 updatebarpos(); |
|
447 arrange(); |
415 arrange(); |
448 } |
416 } |
449 } |
417 } |
450 |
418 |
451 void |
419 void |
452 configurerequest(XEvent *e) { |
420 configurerequest(XEvent *e) { |
453 Client *c; |
421 Client *c; |
454 XConfigureRequestEvent *ev = &e->xconfigurerequest; |
422 XConfigureRequestEvent *ev = &e->xconfigurerequest; |
455 XWindowChanges wc; |
423 XWindowChanges wc; |
456 |
424 |
457 /* TODO -- consider Xinerama if necessary when centering */ |
|
458 if((c = getclient(ev->window))) { |
425 if((c = getclient(ev->window))) { |
459 if(ev->value_mask & CWBorderWidth) |
426 if(ev->value_mask & CWBorderWidth) |
460 c->border = ev->border_width; |
427 c->border = ev->border_width; |
461 if(c->isfixed || c->isfloating || (floating == lt->arrange)) { |
428 if(c->isfixed || c->isfloating || (floating == lt->arrange)) { |
462 if(ev->value_mask & CWX) |
429 if(ev->value_mask & CWX) |
567 drawsquare(False, c->isfloating, False, dc.sel); |
524 drawsquare(False, c->isfloating, False, dc.sel); |
568 } |
525 } |
569 else |
526 else |
570 drawtext(NULL, dc.norm, False); |
527 drawtext(NULL, dc.norm, False); |
571 } |
528 } |
572 XCopyArea(dpy, dc.drawable, barwin, dc.gc, 0, 0, sw, bh, 0, 0); |
529 XCopyArea(dpy, dc.drawable, barwin, dc.gc, 0, 0, BW, bh, 0, 0); |
573 XSync(dpy, False); |
530 XSync(dpy, False); |
574 } |
531 } |
575 |
532 |
576 void |
533 void |
577 drawsquare(Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]) { |
534 drawsquare(Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]) { |
688 if(!c || (c && !isvisible(c))) |
645 if(!c || (c && !isvisible(c))) |
689 for(c = stack; c && !isvisible(c); c = c->snext); |
646 for(c = stack; c && !isvisible(c); c = c->snext); |
690 if(sel && sel != c) { |
647 if(sel && sel != c) { |
691 grabbuttons(sel, False); |
648 grabbuttons(sel, False); |
692 XSetWindowBorder(dpy, sel->win, dc.norm[ColBorder]); |
649 XSetWindowBorder(dpy, sel->win, dc.norm[ColBorder]); |
|
650 if(lt->arrange == monocle) |
|
651 resize(sel, sel->rx, sel->ry, sel->rw, sel->rh, True); |
693 } |
652 } |
694 if(c) { |
653 if(c) { |
695 detachstack(c); |
654 detachstack(c); |
696 attachstack(c); |
655 attachstack(c); |
697 grabbuttons(c, True); |
656 grabbuttons(c, True); |
|
657 if(lt->arrange == monocle) { |
|
658 if(sel != c) { |
|
659 c->rx = c->x; |
|
660 c->ry = c->y; |
|
661 c->rw = c->w; |
|
662 c->rh = c->h; |
|
663 } |
|
664 resize(c, MOX, MOY, MOW, MOH, RESIZEHINTS); |
|
665 } |
698 } |
666 } |
699 sel = c; |
667 sel = c; |
700 if(c) { |
668 if(c) { |
701 XSetWindowBorder(dpy, c->win, dc.sel[ColBorder]); |
669 XSetWindowBorder(dpy, c->win, dc.sel[ColBorder]); |
702 XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); |
670 XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); |
1014 |
982 |
1015 c = emallocz(sizeof(Client)); |
983 c = emallocz(sizeof(Client)); |
1016 c->tags = emallocz(TAGSZ); |
984 c->tags = emallocz(TAGSZ); |
1017 c->win = w; |
985 c->win = w; |
1018 |
986 |
1019 c->x = wa->x + sx; |
987 c->x = c->rx = wa->x + sx; |
1020 c->y = wa->y + sy; |
988 c->y = c->ry = wa->y + sy; |
1021 c->w = wa->width; |
989 c->w = c->rw = wa->width; |
1022 c->h = wa->height; |
990 c->h = c->rh = wa->height; |
1023 c->oldborder = wa->border_width; |
991 c->oldborder = wa->border_width; |
1024 |
992 |
1025 if(c->w == sw && c->h == sh) { |
993 if(c->w == sw && c->h == sh) { |
1026 c->x = sx; |
994 c->x = sx; |
1027 c->y = sy; |
995 c->y = sy; |
1028 c->border = wa->border_width; |
996 c->border = wa->border_width; |
1029 } |
997 } |
1030 else { |
998 else { |
1031 if(c->x + c->w + 2 * c->border > wax + waw) |
999 if(c->x + c->w + 2 * c->border > sx + sw) |
1032 c->x = wax + waw - c->w - 2 * c->border; |
1000 c->x = sx + sw - c->w - 2 * c->border; |
1033 if(c->y + c->h + 2 * c->border > way + wah) |
1001 if(c->y + c->h + 2 * c->border > sy + sh) |
1034 c->y = way + wah - c->h - 2 * c->border; |
1002 c->y = sy + sh - c->h - 2 * c->border; |
1035 if(c->x < wax) |
1003 if(c->x < sx) |
1036 c->x = wax; |
1004 c->x = sx; |
1037 if(c->y < way) |
1005 if(c->y < sy) |
1038 c->y = way; |
1006 c->y = sy; |
1039 c->border = BORDERPX; |
1007 c->border = BORDERPX; |
1040 } |
1008 } |
1041 wc.border_width = c->border; |
1009 wc.border_width = c->border; |
1042 XConfigureWindow(dpy, w, CWBorderWidth, &wc); |
1010 XConfigureWindow(dpy, w, CWBorderWidth, &wc); |
1043 XSetWindowBorder(dpy, w, dc.norm[ColBorder]); |
1011 XSetWindowBorder(dpy, w, dc.norm[ColBorder]); |
1085 manage(ev->window, &wa); |
1053 manage(ev->window, &wa); |
1086 } |
1054 } |
1087 |
1055 |
1088 void |
1056 void |
1089 monocle(void) { |
1057 monocle(void) { |
1090 Client *c; |
1058 dozoom = False; |
1091 |
|
1092 domwfact = dozoom = False; |
|
1093 for(c = nexttiled(clients); c; c = nexttiled(c->next)) |
|
1094 resize(c, wax, way, waw - 2 * c->border, wah - 2 * c->border, RESIZEHINTS); |
|
1095 } |
1059 } |
1096 |
1060 |
1097 void |
1061 void |
1098 movemouse(Client *c) { |
1062 movemouse(Client *c) { |
1099 int x1, y1, ocx, ocy, di, nx, ny; |
1063 int x1, y1, ocx, ocy, di, nx, ny; |
1120 break; |
1084 break; |
1121 case MotionNotify: |
1085 case MotionNotify: |
1122 XSync(dpy, False); |
1086 XSync(dpy, False); |
1123 nx = ocx + (ev.xmotion.x - x1); |
1087 nx = ocx + (ev.xmotion.x - x1); |
1124 ny = ocy + (ev.xmotion.y - y1); |
1088 ny = ocy + (ev.xmotion.y - y1); |
1125 if(abs(wax - nx) < SNAP) |
1089 if(abs(sx - nx) < SNAP) |
1126 nx = wax; |
1090 nx = sx; |
1127 else if(abs((wax + waw) - (nx + c->w + 2 * c->border)) < SNAP) |
1091 else if(abs((sx + sw) - (nx + c->w + 2 * c->border)) < SNAP) |
1128 nx = wax + waw - c->w - 2 * c->border; |
1092 nx = sx + sw - c->w - 2 * c->border; |
1129 if(abs(way - ny) < SNAP) |
1093 if(abs(sy - ny) < SNAP) |
1130 ny = way; |
1094 ny = sy; |
1131 else if(abs((way + wah) - (ny + c->h + 2 * c->border)) < SNAP) |
1095 else if(abs((sy + sh) - (ny + c->h + 2 * c->border)) < SNAP) |
1132 ny = way + wah - c->h - 2 * c->border; |
1096 ny = sy + sh - c->h - 2 * c->border; |
1133 if(!c->isfloating && (lt->arrange != floating) && (abs(nx - c->x) > SNAP || abs(ny - c->y) > SNAP)) |
1097 if(!c->isfloating && (lt->arrange != floating) && (abs(nx - c->x) > SNAP || abs(ny - c->y) > SNAP)) |
1134 togglefloating(NULL); |
1098 togglefloating(NULL); |
1135 if((lt->arrange == floating) || c->isfloating) |
1099 if((lt->arrange == floating) || c->isfloating) |
1136 resize(c, nx, ny, c->w, c->h, False); |
1100 resize(c, nx, ny, c->w, c->h, False); |
1137 break; |
1101 break; |
1426 |
1390 |
1427 void |
1391 void |
1428 setlayout(const char *arg) { |
1392 setlayout(const char *arg) { |
1429 unsigned int i; |
1393 unsigned int i; |
1430 |
1394 |
1431 if(!arg) { |
1395 if(!arg) |
1432 lt++; |
1396 return; |
1433 if(lt == &layouts[LENGTH(layouts)]) |
1397 for(i = 0; i < LENGTH(layouts); i++) |
1434 lt = &layouts[0]; |
1398 if(!strcmp(arg, layouts[i].symbol)) |
1435 } |
1399 break; |
1436 else { |
1400 if(i == LENGTH(layouts)) |
1437 for(i = 0; i < LENGTH(layouts); i++) |
1401 return; |
1438 if(!strcmp(arg, layouts[i].symbol)) |
1402 lt = &layouts[i]; |
1439 break; |
|
1440 if(i == LENGTH(layouts)) |
|
1441 return; |
|
1442 lt = &layouts[i]; |
|
1443 } |
|
1444 if(sel) |
1403 if(sel) |
1445 arrange(); |
1404 arrange(); |
1446 else |
1405 else |
1447 drawbar(); |
1406 drawbar(); |
1448 } |
1407 } |
1449 |
1408 |
1450 void |
1409 void |
1451 setmwfact(const char *arg) { |
|
1452 double delta; |
|
1453 |
|
1454 if(!domwfact) |
|
1455 return; |
|
1456 /* arg handling, manipulate mwfact */ |
|
1457 if(arg == NULL) |
|
1458 mwfact = MWFACT; |
|
1459 else if(sscanf(arg, "%lf", &delta) == 1) { |
|
1460 if(arg[0] == '+' || arg[0] == '-') |
|
1461 mwfact += delta; |
|
1462 else |
|
1463 mwfact = delta; |
|
1464 if(mwfact < 0.1) |
|
1465 mwfact = 0.1; |
|
1466 else if(mwfact > 0.9) |
|
1467 mwfact = 0.9; |
|
1468 } |
|
1469 arrange(); |
|
1470 } |
|
1471 |
|
1472 void |
|
1473 setup(void) { |
1410 setup(void) { |
1474 int screens = 1; |
|
1475 unsigned int i; |
1411 unsigned int i; |
1476 XSetWindowAttributes wa; |
1412 XSetWindowAttributes wa; |
1477 //#ifdef XINERAMA |
|
1478 XineramaScreenInfo *info; |
|
1479 //#endif |
|
1480 |
1413 |
1481 /* init screen */ |
1414 /* init screen */ |
1482 screen = DefaultScreen(dpy); |
1415 screen = DefaultScreen(dpy); |
1483 root = RootWindow(dpy, screen); |
1416 root = RootWindow(dpy, screen); |
1484 sx = 0; |
1417 sx = 0; |
1485 sy = 0; |
1418 sy = 0; |
1486 sw = DisplayWidth(dpy, screen); |
1419 sw = DisplayWidth(dpy, screen); |
1487 sh = DisplayHeight(dpy, screen); |
1420 sh = DisplayHeight(dpy, screen); |
1488 if(XineramaIsActive(dpy)) { |
|
1489 if((info = XineramaQueryScreens(dpy, &screens))) { |
|
1490 sx = info[0].x_org; |
|
1491 sy = info[0].y_org; |
|
1492 sw = info[0].width; |
|
1493 sh = info[0].height; |
|
1494 } |
|
1495 } |
|
1496 |
1421 |
1497 /* init atoms */ |
1422 /* init atoms */ |
1498 wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False); |
1423 wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False); |
1499 wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False); |
1424 wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False); |
1500 wmatom[WMName] = XInternAtom(dpy, "WM_NAME", False); |
1425 wmatom[WMName] = XInternAtom(dpy, "WM_NAME", False); |
1505 /* init cursors */ |
1430 /* init cursors */ |
1506 wa.cursor = cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr); |
1431 wa.cursor = cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr); |
1507 cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing); |
1432 cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing); |
1508 cursor[CurMove] = XCreateFontCursor(dpy, XC_fleur); |
1433 cursor[CurMove] = XCreateFontCursor(dpy, XC_fleur); |
1509 |
1434 |
1510 ncols = 2; |
|
1511 #if 0 |
|
1512 if(XineramaIsActive(dpy)) { |
|
1513 if((info = XineramaQueryScreens(dpy, &screens))) { |
|
1514 if(screens >= 1) { |
|
1515 sx = info[0].x_org; |
|
1516 sy = info[0].y_org; |
|
1517 sw = info[0].width; |
|
1518 sh = info[0].height; |
|
1519 } |
|
1520 else { |
|
1521 ncols = screens; |
|
1522 cols = emallocz(ncols * sizeof(Column)); |
|
1523 for(i = 0; i < ncols; i++) { |
|
1524 cols[i].x = info[i].x_org; |
|
1525 cols[i].y = info[i].y_org; |
|
1526 cols[i].w = info[i].width; |
|
1527 cols[i].h = info[i].height; |
|
1528 } |
|
1529 } |
|
1530 XFree(info); |
|
1531 } |
|
1532 } |
|
1533 else |
|
1534 { |
|
1535 cols = emallocz(ncols * sizeof(Column)); |
|
1536 cols[0].x = sx; |
|
1537 cols[0].y = sy; |
|
1538 } |
|
1539 #endif |
|
1540 /* init appearance */ |
1435 /* init appearance */ |
1541 dc.norm[ColBorder] = getcolor(NORMBORDERCOLOR); |
1436 dc.norm[ColBorder] = getcolor(NORMBORDERCOLOR); |
1542 dc.norm[ColBG] = getcolor(NORMBGCOLOR); |
1437 dc.norm[ColBG] = getcolor(NORMBGCOLOR); |
1543 dc.norm[ColFG] = getcolor(NORMFGCOLOR); |
1438 dc.norm[ColFG] = getcolor(NORMFGCOLOR); |
1544 dc.sel[ColBorder] = getcolor(SELBORDERCOLOR); |
1439 dc.sel[ColBorder] = getcolor(SELBORDERCOLOR); |
1556 seltags = emallocz(TAGSZ); |
1451 seltags = emallocz(TAGSZ); |
1557 prevtags = emallocz(TAGSZ); |
1452 prevtags = emallocz(TAGSZ); |
1558 seltags[0] = prevtags[0] = True; |
1453 seltags[0] = prevtags[0] = True; |
1559 |
1454 |
1560 /* init layouts */ |
1455 /* init layouts */ |
1561 mwfact = MWFACT; |
|
1562 lt = &layouts[0]; |
1456 lt = &layouts[0]; |
1563 |
1457 |
1564 /* TODO: Xinerama hints ? */ |
|
1565 /* init bar */ |
1458 /* init bar */ |
1566 for(blw = i = 0; i < LENGTH(layouts); i++) { |
1459 for(blw = i = 0; i < LENGTH(layouts); i++) { |
1567 i = textw(layouts[i].symbol); |
1460 i = textw(layouts[i].symbol); |
1568 if(i > blw) |
1461 if(i > blw) |
1569 blw = i; |
1462 blw = i; |
1570 } |
1463 } |
1571 |
1464 |
1572 bpos = BARPOS; |
|
1573 wa.override_redirect = 1; |
1465 wa.override_redirect = 1; |
1574 wa.background_pixmap = ParentRelative; |
1466 wa.background_pixmap = ParentRelative; |
1575 wa.event_mask = ButtonPressMask|ExposureMask; |
1467 wa.event_mask = ButtonPressMask|ExposureMask; |
1576 |
1468 |
1577 barwin = XCreateWindow(dpy, root, sx, sy, sw, bh, 0, DefaultDepth(dpy, screen), |
1469 barwin = XCreateWindow(dpy, root, BX, BY, BW, bh, 0, DefaultDepth(dpy, screen), |
1578 CopyFromParent, DefaultVisual(dpy, screen), |
1470 CopyFromParent, DefaultVisual(dpy, screen), |
1579 CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); |
1471 CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); |
1580 XDefineCursor(dpy, barwin, cursor[CurNormal]); |
1472 XDefineCursor(dpy, barwin, cursor[CurNormal]); |
1581 updatebarpos(); |
|
1582 XMapRaised(dpy, barwin); |
1473 XMapRaised(dpy, barwin); |
1583 strcpy(stext, "dwm-"VERSION); |
1474 strcpy(stext, "dwm-"VERSION); |
1584 drawbar(); |
1475 drawbar(); |
1585 |
1476 |
1586 /* EWMH support per view */ |
1477 /* EWMH support per view */ |
1653 void |
1544 void |
1654 tile(void) { |
1545 tile(void) { |
1655 unsigned int i, n, nx, ny, nw, nh, mw, th; |
1546 unsigned int i, n, nx, ny, nw, nh, mw, th; |
1656 Client *c, *mc; |
1547 Client *c, *mc; |
1657 |
1548 |
1658 domwfact = dozoom = True; |
1549 dozoom = True; |
1659 nx = wax; |
1550 nx = MX; |
1660 ny = way; |
1551 ny = MY; |
1661 nw = 0; |
1552 nw = 0; |
1662 for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next)) |
1553 for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next)) |
1663 n++; |
1554 n++; |
1664 |
1555 |
1665 /* window geoms */ |
1556 /* window geoms */ |
1666 mw = (n == 1) ? waw : mwfact * waw; |
1557 mw = (n == 1) ? MOW : MW; |
1667 th = (n > 1) ? wah / (n - 1) : 0; |
1558 th = (n > 1) ? TH / (n - 1) : 0; |
1668 if(n > 1 && th < bh) |
1559 if(n > 1 && th < bh) |
1669 th = wah; |
1560 th = TH; |
1670 |
1561 |
1671 for(i = 0, c = mc = nexttiled(clients); c; c = nexttiled(c->next)) { |
1562 for(i = 0, c = mc = nexttiled(clients); c; c = nexttiled(c->next)) { |
1672 if(i == 0) { /* master */ |
1563 if(i == 0) { /* master */ |
1673 nw = mw - 2 * c->border; |
1564 nw = mw - 2 * c->border; |
1674 nh = wah - 2 * c->border; |
1565 nh = MH - 2 * c->border; |
1675 } |
1566 } |
1676 else { /* tile window */ |
1567 else { /* tile window */ |
1677 if(i == 1) { |
1568 if(i == 1) { |
1678 ny = way; |
1569 ny = TY; |
1679 nx += mc->w + 2 * mc->border; |
1570 nx = TX; |
1680 nw = waw - mw - 2 * c->border; |
1571 nw = TW - 2 * c->border; |
1681 } |
1572 } |
1682 if(i + 1 == n) /* remainder */ |
1573 if(i + 1 == n) /* remainder */ |
1683 nh = (way + wah) - ny - 2 * c->border; |
1574 nh = (TY + TH) - ny - 2 * c->border; |
1684 else |
1575 else |
1685 nh = th - 2 * c->border; |
1576 nh = th - 2 * c->border; |
1686 } |
1577 } |
1687 resize(c, nx, ny, nw, nh, RESIZEHINTS); |
1578 resize(c, nx, ny, nw, nh, RESIZEHINTS); |
1688 if((RESIZEHINTS) && ((c->h < bh) || (c->h > nh) || (c->w < bh) || (c->w > nw))) |
1579 if((RESIZEHINTS) && ((c->h < bh) || (c->h > nh) || (c->w < bh) || (c->w > nw))) |
1689 /* client doesn't accept size constraints */ |
1580 /* client doesn't accept size constraints */ |
1690 resize(c, nx, ny, nw, nh, False); |
1581 resize(c, nx, ny, nw, nh, False); |
1691 if(n > 1 && th != wah) |
1582 if(n > 1 && th != TH) |
1692 ny = c->y + c->h + 2 * c->border; |
1583 ny = c->y + c->h + 2 * c->border; |
1693 i++; |
1584 i++; |
1694 } |
1585 } |
1695 } |
|
1696 |
|
1697 void |
|
1698 togglebar(const char *arg) { |
|
1699 if(bpos == BarOff) |
|
1700 bpos = (BARPOS == BarOff) ? BarTop : BARPOS; |
|
1701 else |
|
1702 bpos = BarOff; |
|
1703 updatebarpos(); |
|
1704 arrange(); |
|
1705 } |
1586 } |
1706 |
1587 |
1707 void |
1588 void |
1708 togglefloating(const char *arg) { |
1589 togglefloating(const char *arg) { |
1709 if(!sel) |
1590 if(!sel) |
1781 if((c = getclient(ev->window))) |
1660 if((c = getclient(ev->window))) |
1782 unmanage(c); |
1661 unmanage(c); |
1783 } |
1662 } |
1784 |
1663 |
1785 void |
1664 void |
1786 updatebarpos(void) { |
|
1787 XEvent ev; |
|
1788 |
|
1789 wax = sx; |
|
1790 way = sy; |
|
1791 wah = sh; |
|
1792 waw = sw; |
|
1793 switch(bpos) { |
|
1794 default: |
|
1795 wah -= bh; |
|
1796 way += bh; |
|
1797 XMoveWindow(dpy, barwin, sx, sy); |
|
1798 break; |
|
1799 case BarBot: |
|
1800 wah -= bh; |
|
1801 XMoveWindow(dpy, barwin, sx, sy + wah); |
|
1802 break; |
|
1803 case BarOff: |
|
1804 XMoveWindow(dpy, barwin, sx, sy - bh); |
|
1805 break; |
|
1806 } |
|
1807 XSync(dpy, False); |
|
1808 while(XCheckMaskEvent(dpy, EnterWindowMask, &ev)); |
|
1809 } |
|
1810 |
|
1811 void |
|
1812 updatesizehints(Client *c) { |
1665 updatesizehints(Client *c) { |
1813 long msize; |
1666 long msize; |
1814 XSizeHints size; |
1667 XSizeHints size; |
1815 |
1668 |
1816 if(!XGetWMNormalHints(dpy, c->win, &size, &msize) || !size.flags) |
1669 if(!XGetWMNormalHints(dpy, c->win, &size, &msize) || !size.flags) |