36 #include <X11/Xlib.h> |
36 #include <X11/Xlib.h> |
37 #include <X11/Xproto.h> |
37 #include <X11/Xproto.h> |
38 #include <X11/Xutil.h> |
38 #include <X11/Xutil.h> |
39 #ifdef XINERAMA |
39 #ifdef XINERAMA |
40 #include <X11/extensions/Xinerama.h> |
40 #include <X11/extensions/Xinerama.h> |
41 #endif |
41 #endif /* XINERAMA */ |
42 |
42 |
43 /* macros */ |
43 /* macros */ |
44 #define BUTTONMASK (ButtonPressMask|ButtonReleaseMask) |
44 #define BUTTONMASK (ButtonPressMask|ButtonReleaseMask) |
45 #define CLEANMASK(mask) (mask & ~(numlockmask|LockMask)) |
45 #define CLEANMASK(mask) (mask & ~(numlockmask|LockMask)) |
46 #define INRECT(X,Y,RX,RY,RW,RH) ((X) >= (RX) && (X) < (RX) + (RW) && (Y) >= (RY) && (Y) < (RY) + (RH)) |
46 #define INRECT(X,Y,RX,RY,RW,RH) ((X) >= (RX) && (X) < (RX) + (RW) && (Y) >= (RY) && (Y) < (RY) + (RH)) |
47 #define ISVISIBLE(x) (x->tags & tagset[selmon->seltags]) |
47 #define ISVISIBLE(x) (x->tags & tagset[mon[x->mon].seltags]) |
48 #define LENGTH(x) (sizeof x / sizeof x[0]) |
48 #define LENGTH(x) (sizeof x / sizeof x[0]) |
49 #define MAX(a, b) ((a) > (b) ? (a) : (b)) |
49 #define MAX(a, b) ((a) > (b) ? (a) : (b)) |
50 #define MIN(a, b) ((a) < (b) ? (a) : (b)) |
50 #define MIN(a, b) ((a) < (b) ? (a) : (b)) |
51 #define MOUSEMASK (BUTTONMASK|PointerMotionMask) |
51 #define MOUSEMASK (BUTTONMASK|PointerMotionMask) |
52 #define WIDTH(x) ((x)->w + 2 * (x)->bw) |
52 #define WIDTH(x) ((x)->w + 2 * (x)->bw) |
148 static void configurerequest(XEvent *e); |
153 static void configurerequest(XEvent *e); |
149 static void destroynotify(XEvent *e); |
154 static void destroynotify(XEvent *e); |
150 static void detach(Client *c); |
155 static void detach(Client *c); |
151 static void detachstack(Client *c); |
156 static void detachstack(Client *c); |
152 static void die(const char *errstr, ...); |
157 static void die(const char *errstr, ...); |
153 static void drawbar(void); |
158 static void drawbar(Monitor *m); |
|
159 static void drawbars(); |
154 static void drawsquare(Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]); |
160 static void drawsquare(Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]); |
155 static void drawtext(const char *text, unsigned long col[ColLast], Bool invert); |
161 static void drawtext(const char *text, unsigned long col[ColLast], Bool invert); |
156 static void enternotify(XEvent *e); |
162 static void enternotify(XEvent *e); |
157 static void expose(XEvent *e); |
163 static void expose(XEvent *e); |
158 static void focus(Client *c); |
164 static void focus(Client *c); |
169 static void keypress(XEvent *e); |
175 static void keypress(XEvent *e); |
170 static void killclient(const Arg *arg); |
176 static void killclient(const Arg *arg); |
171 static void manage(Window w, XWindowAttributes *wa); |
177 static void manage(Window w, XWindowAttributes *wa); |
172 static void mappingnotify(XEvent *e); |
178 static void mappingnotify(XEvent *e); |
173 static void maprequest(XEvent *e); |
179 static void maprequest(XEvent *e); |
174 static void monocle(void); |
180 static void monocle(Monitor *m); |
175 static void movemouse(const Arg *arg); |
181 static void movemouse(const Arg *arg); |
176 static Client *nexttiled(Client *c); |
182 static Client *nexttiled(Monitor *m, Client *c); |
177 static void propertynotify(XEvent *e); |
183 static void propertynotify(XEvent *e); |
178 static void quit(const Arg *arg); |
184 static void quit(const Arg *arg); |
179 static void resize(Client *c, int x, int y, int w, int h); |
185 static void resize(Client *c, int x, int y, int w, int h); |
180 static void resizemouse(const Arg *arg); |
186 static void resizemouse(const Arg *arg); |
181 static void restack(void); |
187 static void restack(Monitor *m); |
182 static void run(void); |
188 static void run(void); |
183 static void scan(void); |
189 static void scan(void); |
184 static void setclientstate(Client *c, long state); |
190 static void setclientstate(Client *c, long state); |
185 static void setlayout(const Arg *arg); |
191 static void setlayout(const Arg *arg); |
186 static void setmfact(const Arg *arg); |
192 static void setmfact(const Arg *arg); |
188 static void showhide(Client *c); |
194 static void showhide(Client *c); |
189 static void sigchld(int signal); |
195 static void sigchld(int signal); |
190 static void spawn(const Arg *arg); |
196 static void spawn(const Arg *arg); |
191 static void tag(const Arg *arg); |
197 static void tag(const Arg *arg); |
192 static int textnw(const char *text, unsigned int len); |
198 static int textnw(const char *text, unsigned int len); |
193 static void tile(void); |
199 static void tile(Monitor *); |
194 static void togglebar(const Arg *arg); |
200 static void togglebar(const Arg *arg); |
195 static void togglefloating(const Arg *arg); |
201 static void togglefloating(const Arg *arg); |
196 static void toggletag(const Arg *arg); |
202 static void toggletag(const Arg *arg); |
197 static void toggleview(const Arg *arg); |
203 static void toggleview(const Arg *arg); |
198 static void unmanage(Client *c); |
204 static void unmanage(Client *c); |
199 static void unmapnotify(XEvent *e); |
205 static void unmapnotify(XEvent *e); |
200 static void updatebar(void); |
|
201 static void updategeom(void); |
206 static void updategeom(void); |
202 static void updatenumlockmask(void); |
207 static void updatenumlockmask(void); |
203 static void updatesizehints(Client *c); |
208 static void updatesizehints(Client *c); |
204 static void updatestatus(void); |
209 static void updatestatus(void); |
205 static void updatetitle(Client *c); |
210 static void updatetitle(Client *c); |
207 static void view(const Arg *arg); |
212 static void view(const Arg *arg); |
208 static int xerror(Display *dpy, XErrorEvent *ee); |
213 static int xerror(Display *dpy, XErrorEvent *ee); |
209 static int xerrordummy(Display *dpy, XErrorEvent *ee); |
214 static int xerrordummy(Display *dpy, XErrorEvent *ee); |
210 static int xerrorstart(Display *dpy, XErrorEvent *ee); |
215 static int xerrorstart(Display *dpy, XErrorEvent *ee); |
211 static void zoom(const Arg *arg); |
216 static void zoom(const Arg *arg); |
|
217 #ifdef XINERAMA |
|
218 static void focusmon(const Arg *arg); |
|
219 static void tagmon(const Arg *arg); |
|
220 #endif /* XINERAMA */ |
212 |
221 |
213 /* variables */ |
222 /* variables */ |
214 static char stext[256]; |
223 static char stext[256]; |
215 static int screen; |
224 static int screen; |
216 static int sx, sy, sw, sh; /* X display screen geometry x, y, width, height */ |
225 static int sx, sy, sw, sh; /* X display screen geometry x, y, width, height */ |
217 static int by, bh, blw; /* bar geometry y, height and layout symbol width */ |
226 static int bh, blw = 0; /* bar geometry */ |
218 static int (*xerrorxlib)(Display *, XErrorEvent *); |
227 static int (*xerrorxlib)(Display *, XErrorEvent *); |
219 static unsigned int numlockmask = 0; |
228 static unsigned int numlockmask = 0; |
220 static void (*handler[LASTEvent]) (XEvent *) = { |
229 static void (*handler[LASTEvent]) (XEvent *) = { |
221 [ButtonPress] = buttonpress, |
230 [ButtonPress] = buttonpress, |
222 [ConfigureRequest] = configurerequest, |
231 [ConfigureRequest] = configurerequest, |
241 static Display *dpy; |
250 static Display *dpy; |
242 static DC dc; |
251 static DC dc; |
243 static Layout *lt[] = { NULL, NULL }; |
252 static Layout *lt[] = { NULL, NULL }; |
244 static Monitor *mon = NULL, *selmon = NULL; |
253 static Monitor *mon = NULL, *selmon = NULL; |
245 static unsigned int nmons; |
254 static unsigned int nmons; |
246 static Window root, barwin; |
255 static Window root; |
247 /* configuration, allows nested code to access above variables */ |
256 /* configuration, allows nested code to access above variables */ |
248 #include "config.h" |
257 #include "config.h" |
249 |
258 |
250 /* compile-time check if all tags fit into an unsigned int bit array. */ |
259 /* compile-time check if all tags fit into an unsigned int bit array. */ |
251 struct NumTags { char limitexceeded[sizeof(unsigned int) * 8 < LENGTH(tags) ? -1 : 1]; }; |
260 struct NumTags { char limitexceeded[sizeof(unsigned int) * 8 < LENGTH(tags) ? -1 : 1]; }; |
427 XFreePixmap(dpy, dc.drawable); |
443 XFreePixmap(dpy, dc.drawable); |
428 XFreeGC(dpy, dc.gc); |
444 XFreeGC(dpy, dc.gc); |
429 XFreeCursor(dpy, cursor[CurNormal]); |
445 XFreeCursor(dpy, cursor[CurNormal]); |
430 XFreeCursor(dpy, cursor[CurResize]); |
446 XFreeCursor(dpy, cursor[CurResize]); |
431 XFreeCursor(dpy, cursor[CurMove]); |
447 XFreeCursor(dpy, cursor[CurMove]); |
432 XDestroyWindow(dpy, barwin); |
448 for(i = 0; i < nmons; i++) |
|
449 XDestroyWindow(dpy, mon[i].barwin); |
|
450 free(mon); |
433 XSync(dpy, False); |
451 XSync(dpy, False); |
434 XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); |
452 XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); |
435 } |
453 } |
436 |
454 |
437 void |
455 void |
464 XSendEvent(dpy, c->win, False, StructureNotifyMask, (XEvent *)&ce); |
482 XSendEvent(dpy, c->win, False, StructureNotifyMask, (XEvent *)&ce); |
465 } |
483 } |
466 |
484 |
467 void |
485 void |
468 configurenotify(XEvent *e) { |
486 configurenotify(XEvent *e) { |
|
487 unsigned int i; |
469 XConfigureEvent *ev = &e->xconfigure; |
488 XConfigureEvent *ev = &e->xconfigure; |
470 |
489 |
471 if(ev->window == root && (ev->width != sw || ev->height != sh)) { |
490 if(ev->window == root && (ev->width != sw || ev->height != sh)) { |
472 sw = ev->width; |
491 sw = ev->width; |
473 sh = ev->height; |
492 sh = ev->height; |
474 updategeom(); |
493 updategeom(); |
475 updatebar(); |
494 if(dc.drawable != 0) |
|
495 XFreePixmap(dpy, dc.drawable); |
|
496 dc.drawable = XCreatePixmap(dpy, root, DisplayWidth(dpy, screen), bh, DefaultDepth(dpy, screen)); |
|
497 for(i = 0; i < nmons; i++) |
|
498 XMoveResizeWindow(dpy, mon[i].barwin, mon[i].wx, mon[i].by, mon[i].ww, bh); |
476 arrange(); |
499 arrange(); |
477 } |
500 } |
478 } |
501 } |
479 |
502 |
480 void |
503 void |
554 va_end(ap); |
577 va_end(ap); |
555 exit(EXIT_FAILURE); |
578 exit(EXIT_FAILURE); |
556 } |
579 } |
557 |
580 |
558 void |
581 void |
559 drawbar(void) { |
582 drawbar(Monitor *m) { |
560 int x; |
583 int x; |
561 unsigned int i, occ = 0, urg = 0; |
584 unsigned int i, occ = 0, urg = 0; |
562 unsigned long *col; |
585 unsigned long *col; |
563 Client *c; |
586 Client *c; |
564 |
587 |
565 for(c = clients; c; c = c->next) { |
588 for(c = clients; c; c = c->next) { |
566 occ |= c->tags; |
589 if(m == &mon[c->mon]) { |
567 if(c->isurgent) |
590 occ |= c->tags; |
568 urg |= c->tags; |
591 if(c->isurgent) |
|
592 urg |= c->tags; |
|
593 } |
569 } |
594 } |
570 |
595 |
571 dc.x = 0; |
596 dc.x = 0; |
|
597 #ifdef XINERAMA |
|
598 { |
|
599 dc.w = TEXTW(m->symbol); |
|
600 drawtext(m->symbol, selmon == m ? dc.sel : dc.norm, False); |
|
601 dc.x += dc.w; |
|
602 } |
|
603 #endif /* XINERAMA */ |
|
604 m->btx = dc.x; |
572 for(i = 0; i < LENGTH(tags); i++) { |
605 for(i = 0; i < LENGTH(tags); i++) { |
573 dc.w = TEXTW(tags[i]); |
606 dc.w = TEXTW(tags[i]); |
574 col = tagset[selmon->seltags] & 1 << i ? dc.sel : dc.norm; |
607 col = tagset[m->seltags] & 1 << i ? dc.sel : dc.norm; |
575 drawtext(tags[i], col, urg & 1 << i); |
608 drawtext(tags[i], col, urg & 1 << i); |
576 drawsquare(sel && sel->tags & 1 << i, occ & 1 << i, urg & 1 << i, col); |
609 drawsquare(m == selmon && sel && sel->tags & 1 << i, |
|
610 occ & 1 << i, urg & 1 << i, col); |
577 dc.x += dc.w; |
611 dc.x += dc.w; |
578 } |
612 } |
579 if(blw > 0) { |
613 if(blw > 0) { |
580 dc.w = blw; |
614 dc.w = blw; |
581 drawtext(lt[selmon->sellt]->symbol, dc.norm, False); |
615 drawtext(lt[m->sellt]->symbol, dc.norm, False); |
582 x = dc.x + dc.w; |
616 x = dc.x + dc.w; |
583 } |
617 } |
584 else |
618 else |
585 x = dc.x; |
619 x = dc.x; |
586 dc.w = TEXTW(stext); |
620 if(m == selmon) { |
587 dc.x = selmon->ww - dc.w; |
621 dc.w = TEXTW(stext); |
588 if(dc.x < x) { |
622 dc.x = m->ww - dc.w; |
589 dc.x = x; |
623 if(dc.x < x) { |
590 dc.w = selmon->ww - x; |
624 dc.x = x; |
591 } |
625 dc.w = m->ww - x; |
592 drawtext(stext, dc.norm, False); |
626 } |
593 if((dc.w = dc.x - x) > bh) { |
627 drawtext(stext, dc.norm, False); |
594 dc.x = x; |
628 if((dc.w = dc.x - x) > bh) { |
595 if(sel) { |
629 dc.x = x; |
596 drawtext(sel->name, dc.sel, False); |
630 if(sel) { |
597 drawsquare(sel->isfixed, sel->isfloating, False, dc.sel); |
631 drawtext(sel->name, dc.sel, False); |
598 } |
632 drawsquare(sel->isfixed, sel->isfloating, False, dc.sel); |
599 else |
633 } |
600 drawtext(NULL, dc.norm, False); |
634 else |
601 } |
635 drawtext(NULL, dc.norm, False); |
602 XCopyArea(dpy, dc.drawable, barwin, dc.gc, 0, 0, selmon->ww, bh, 0, 0); |
636 } |
|
637 } |
|
638 else { |
|
639 dc.w = m->ww - x; |
|
640 drawtext(NULL, dc.norm, False); |
|
641 } |
|
642 XCopyArea(dpy, dc.drawable, m->barwin, dc.gc, 0, 0, m->ww, bh, 0, 0); |
603 XSync(dpy, False); |
643 XSync(dpy, False); |
|
644 } |
|
645 |
|
646 void |
|
647 drawbars() { |
|
648 unsigned int i; |
|
649 |
|
650 for(i = 0; i < nmons; i++) |
|
651 drawbar(&mon[i]); |
604 } |
652 } |
605 |
653 |
606 void |
654 void |
607 drawsquare(Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]) { |
655 drawsquare(Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]) { |
608 int x; |
656 int x; |
691 XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); |
743 XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); |
692 } |
744 } |
693 else |
745 else |
694 XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); |
746 XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); |
695 sel = c; |
747 sel = c; |
696 drawbar(); |
748 if(c) |
|
749 selmon = &mon[c->mon]; |
|
750 drawbars(); |
697 } |
751 } |
698 |
752 |
699 void |
753 void |
700 focusin(XEvent *e) { /* there are some broken focus acquiring clients */ |
754 focusin(XEvent *e) { /* there are some broken focus acquiring clients */ |
701 XFocusChangeEvent *ev = &e->xfocus; |
755 XFocusChangeEvent *ev = &e->xfocus; |
702 |
756 |
703 if(sel && ev->window != sel->win) |
757 if(sel && ev->window != sel->win) |
704 XSetInputFocus(dpy, sel->win, RevertToPointerRoot, CurrentTime); |
758 XSetInputFocus(dpy, sel->win, RevertToPointerRoot, CurrentTime); |
705 } |
759 } |
706 |
760 |
|
761 #ifdef XINERAMA |
|
762 void |
|
763 focusmon(const Arg *arg) { |
|
764 if(arg->ui >= nmons) |
|
765 return; |
|
766 selmon = &mon[arg->ui]; |
|
767 focus(NULL); |
|
768 drawbars(); |
|
769 } |
|
770 #endif /* XINERAMA */ |
|
771 |
707 void |
772 void |
708 focusstack(const Arg *arg) { |
773 focusstack(const Arg *arg) { |
709 Client *c = NULL, *i; |
774 Client *c = NULL, *i; |
710 |
775 |
711 if(!sel) |
776 if(!sel) |
712 return; |
777 return; |
713 if (arg->i > 0) { |
778 if(arg->i > 0) { |
714 for(c = sel->next; c && !ISVISIBLE(c); c = c->next); |
779 for(c = sel->next; c && !ISVISIBLE(c); c = c->next); |
715 if(!c) |
780 if(!c) |
716 for(c = clients; c && !ISVISIBLE(c); c = c->next); |
781 for(c = clients; c && !ISVISIBLE(c); c = c->next); |
717 } |
782 } |
718 else { |
783 else { |
944 c->x = sx + sw - WIDTH(c); |
1009 c->x = sx + sw - WIDTH(c); |
945 if(c->y + HEIGHT(c) > sy + sh) |
1010 if(c->y + HEIGHT(c) > sy + sh) |
946 c->y = sy + sh - HEIGHT(c); |
1011 c->y = sy + sh - HEIGHT(c); |
947 c->x = MAX(c->x, sx); |
1012 c->x = MAX(c->x, sx); |
948 /* only fix client y-offset, if the client center might cover the bar */ |
1013 /* only fix client y-offset, if the client center might cover the bar */ |
949 /* TODO: is c always attached to selmon? */ |
1014 c->y = MAX(c->y, ((selmon->by == 0) && (c->x + (c->w / 2) >= selmon->wx) |
950 c->y = MAX(c->y, ((by == 0) && (c->x + (c->w / 2) >= selmon->wx) |
1015 && (c->x + (c->w / 2) < selmon->wx + selmon->ww)) ? bh : sy); |
951 && (c->x + (c->w / 2) < selmon->wx + selmon->ww)) ? bh : sy); |
|
952 c->bw = borderpx; |
1016 c->bw = borderpx; |
953 } |
1017 } |
954 |
1018 |
955 wc.border_width = c->bw; |
1019 wc.border_width = c->bw; |
956 XConfigureWindow(dpy, w, CWBorderWidth, &wc); |
1020 XConfigureWindow(dpy, w, CWBorderWidth, &wc); |
999 if(!getclient(ev->window)) |
1063 if(!getclient(ev->window)) |
1000 manage(ev->window, &wa); |
1064 manage(ev->window, &wa); |
1001 } |
1065 } |
1002 |
1066 |
1003 void |
1067 void |
1004 monocle(void) { |
1068 monocle(Monitor *m) { |
1005 Client *c; |
1069 Client *c; |
1006 Monitor *m; |
1070 |
1007 |
1071 for(c = nexttiled(m, clients); c; c = nexttiled(m, c->next)) |
1008 for(c = nexttiled(clients); c; c = nexttiled(c->next)) { |
|
1009 m = &mon[c->mon]; |
|
1010 resize(c, m->wx, m->wy, m->ww - 2 * c->bw, m->wh - 2 * c->bw); |
1072 resize(c, m->wx, m->wy, m->ww - 2 * c->bw, m->wh - 2 * c->bw); |
1011 } |
|
1012 } |
1073 } |
1013 |
1074 |
1014 void |
1075 void |
1015 movemouse(const Arg *arg) { |
1076 movemouse(const Arg *arg) { |
1016 int x, y, ocx, ocy, di, nx, ny; |
1077 int x, y, ocx, ocy, di, nx, ny; |
1168 XUngrabPointer(dpy, CurrentTime); |
1230 XUngrabPointer(dpy, CurrentTime); |
1169 while(XCheckMaskEvent(dpy, EnterWindowMask, &ev)); |
1231 while(XCheckMaskEvent(dpy, EnterWindowMask, &ev)); |
1170 } |
1232 } |
1171 |
1233 |
1172 void |
1234 void |
1173 restack(void) { |
1235 restack(Monitor *m) { |
1174 Client *c; |
1236 Client *c; |
1175 XEvent ev; |
1237 XEvent ev; |
1176 XWindowChanges wc; |
1238 XWindowChanges wc; |
1177 |
1239 |
1178 drawbar(); |
1240 drawbars(); |
1179 if(!sel) |
1241 if(!sel) |
1180 return; |
1242 return; |
1181 if(sel->isfloating || !lt[selmon->sellt]->arrange) |
1243 if(m == selmon && (sel->isfloating || !lt[m->sellt]->arrange)) |
1182 XRaiseWindow(dpy, sel->win); |
1244 XRaiseWindow(dpy, sel->win); |
1183 if(lt[selmon->sellt]->arrange) { |
1245 if(lt[m->sellt]->arrange) { |
1184 wc.stack_mode = Below; |
1246 wc.stack_mode = Below; |
1185 wc.sibling = barwin; |
1247 wc.sibling = m->barwin; |
1186 for(c = stack; c; c = c->snext) |
1248 for(c = stack; c; c = c->snext) |
1187 if(!c->isfloating && ISVISIBLE(c)) { |
1249 if(!c->isfloating && m == &mon[c->mon] && ISVISIBLE(c)) { |
1188 XConfigureWindow(dpy, c->win, CWSibling|CWStackMode, &wc); |
1250 XConfigureWindow(dpy, c->win, CWSibling|CWStackMode, &wc); |
1189 wc.sibling = c->win; |
1251 wc.sibling = c->win; |
1190 } |
1252 } |
1191 } |
1253 } |
1192 XSync(dpy, False); |
1254 XSync(dpy, False); |
1307 dc.gc = XCreateGC(dpy, root, 0, NULL); |
1369 dc.gc = XCreateGC(dpy, root, 0, NULL); |
1308 XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter); |
1370 XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter); |
1309 if(!dc.font.set) |
1371 if(!dc.font.set) |
1310 XSetFont(dpy, dc.gc, dc.font.xfont->fid); |
1372 XSetFont(dpy, dc.gc, dc.font.xfont->fid); |
1311 |
1373 |
1312 /* init bar */ |
1374 /* init bars */ |
|
1375 wa.override_redirect = True; |
|
1376 wa.background_pixmap = ParentRelative; |
|
1377 wa.event_mask = ButtonPressMask|ExposureMask; |
1313 for(blw = i = 0; LENGTH(layouts) > 1 && i < LENGTH(layouts); i++) { |
1378 for(blw = i = 0; LENGTH(layouts) > 1 && i < LENGTH(layouts); i++) { |
1314 w = TEXTW(layouts[i].symbol); |
1379 w = TEXTW(layouts[i].symbol); |
1315 blw = MAX(blw, w); |
1380 blw = MAX(blw, w); |
1316 } |
1381 } |
1317 |
1382 |
1318 wa.override_redirect = True; |
1383 for(i = 0; i < nmons; i++) { |
1319 wa.background_pixmap = ParentRelative; |
1384 mon[i].barwin = XCreateWindow(dpy, root, mon[i].wx, mon[i].by, mon[i].ww, bh, 0, DefaultDepth(dpy, screen), |
1320 wa.event_mask = ButtonPressMask|ExposureMask; |
1385 |
1321 |
1386 CopyFromParent, DefaultVisual(dpy, screen), |
1322 barwin = XCreateWindow(dpy, root, selmon->wx, by, selmon->ww, bh, 0, DefaultDepth(dpy, screen), |
1387 CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); |
1323 CopyFromParent, DefaultVisual(dpy, screen), |
1388 XDefineCursor(dpy, mon[i].barwin, cursor[CurNormal]); |
1324 CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); |
1389 XMapRaised(dpy, mon[i].barwin); |
1325 XDefineCursor(dpy, barwin, cursor[CurNormal]); |
1390 } |
1326 XMapRaised(dpy, barwin); |
|
1327 updatestatus(); |
1391 updatestatus(); |
1328 |
1392 |
1329 /* EWMH support per view */ |
1393 /* EWMH support per view */ |
1330 XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32, |
1394 XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32, |
1331 PropModeReplace, (unsigned char *) netatom, NetLast); |
1395 PropModeReplace, (unsigned char *) netatom, NetLast); |
1421 w = (m->wx + mw > c->x + c->w) ? m->wx + m->ww - x : m->ww - mw; |
1493 w = (m->wx + mw > c->x + c->w) ? m->wx + m->ww - x : m->ww - mw; |
1422 h = m->wh / n; |
1494 h = m->wh / n; |
1423 if(h < bh) |
1495 if(h < bh) |
1424 h = m->wh; |
1496 h = m->wh; |
1425 |
1497 |
1426 for(i = 0, c = nexttiled(c->next); c; c = nexttiled(c->next), i++) { |
1498 for(i = 0, c = nexttiled(m, c->next); c; c = nexttiled(m, c->next), i++) { |
1427 resize(c, x, y, w - 2 * c->bw, /* remainder */ ((i + 1 == n) |
1499 resize(c, x, y, w - 2 * c->bw, /* remainder */ ((i + 1 == n) |
1428 ? m->wy + m->wh - y - 2 * c->bw : h - 2 * c->bw)); |
1500 ? m->wy + m->wh - y - 2 * c->bw : h - 2 * c->bw)); |
1429 if(h != m->wh) |
1501 if(h != m->wh) |
1430 y = c->y + HEIGHT(c); |
1502 y = c->y + HEIGHT(c); |
1431 } |
1503 } |
1432 } |
1504 } |
1433 |
1505 |
1434 void |
1506 void |
1435 togglebar(const Arg *arg) { |
1507 togglebar(const Arg *arg) { |
1436 showbar = !showbar; |
1508 selmon->showbar = !selmon->showbar; |
1437 updategeom(); |
1509 updategeom(); |
1438 updatebar(); |
1510 XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh); |
1439 arrange(); |
1511 arrange(); |
1440 } |
1512 } |
1441 |
1513 |
1442 void |
1514 void |
1443 togglefloating(const Arg *arg) { |
1515 togglefloating(const Arg *arg) { |
1503 if((c = getclient(ev->window))) |
1575 if((c = getclient(ev->window))) |
1504 unmanage(c); |
1576 unmanage(c); |
1505 } |
1577 } |
1506 |
1578 |
1507 void |
1579 void |
1508 updatebar(void) { |
|
1509 if(dc.drawable != 0) |
|
1510 XFreePixmap(dpy, dc.drawable); |
|
1511 dc.drawable = XCreatePixmap(dpy, root, selmon->ww, bh, DefaultDepth(dpy, screen)); |
|
1512 XMoveResizeWindow(dpy, barwin, selmon->wx, by, selmon->ww, bh); |
|
1513 } |
|
1514 |
|
1515 void |
|
1516 updategeom(void) { |
1580 updategeom(void) { |
1517 #ifdef XINERAMA |
1581 #ifdef XINERAMA |
1518 int di, x, y, n; |
1582 int di, x, y, n; |
1519 unsigned int dui, i = 0; |
1583 unsigned int dui, i = 0; |
1520 Bool pquery; |
1584 Bool pquery; |
1521 Client *c; |
1585 Client *c; |
1522 Window dummy; |
1586 Window dummy; |
1523 XineramaScreenInfo *info = NULL; |
1587 XineramaScreenInfo *info = NULL; |
1524 |
1588 |
1525 /* window area geometry */ |
1589 /* window area geometry */ |
1526 if(XineramaIsActive(dpy) && (info = XineramaQueryScreens(dpy, &n))) { |
1590 if(XineramaIsActive(dpy) && (info = XineramaQueryScreens(dpy, &n))) { |
1527 nmons = (unsigned int)n; |
1591 nmons = (unsigned int)n; |
1528 for(c = clients; c; c = c->next) |
1592 for(c = clients; c; c = c->next) |
1529 if(c->mon >= nmons) |
1593 if(c->mon >= nmons) |
1530 c->mon = nmons - 1; |
1594 c->mon = nmons - 1; |
1531 if(!(mon = (Monitor *)realloc(mon, sizeof(Monitor) * nmons))) |
1595 if(!(mon = (Monitor *)realloc(mon, sizeof(Monitor) * nmons))) |
1532 die("fatal: could not realloc() %u bytes\n", sizeof(Monitor) * nmons); |
1596 die("fatal: could not realloc() %u bytes\n", sizeof(Monitor) * nmons); |
1533 pquery = XQueryPointer(dpy, root, &dummy, &dummy, &x, &y, &di, &di, &dui); |
1597 pquery = XQueryPointer(dpy, root, &dummy, &dummy, &x, &y, &di, &di, &dui); |
1534 for(i = 0; i < nmons; i++) { |
1598 for(i = 0; i < nmons; i++) { |
1535 /* TODO: consider re-using XineramaScreenInfo */ |
1599 /* TODO: consider re-using XineramaScreenInfo */ |
|
1600 mon[i].symbol[0] = '['; |
|
1601 mon[i].symbol[1] = '0' + info[i].screen_number; |
|
1602 mon[i].symbol[2] = ']'; |
|
1603 mon[i].symbol[3] = 0; |
|
1604 mon[i].showbar = showbar; |
|
1605 mon[i].topbar = topbar; |
1536 mon[i].wx = info[i].x_org; |
1606 mon[i].wx = info[i].x_org; |
1537 mon[i].wy = info[i].y_org; |
1607 mon[i].wy = mon[i].showbar && mon[i].topbar ? info[i].y_org + bh : info[i].y_org; |
1538 mon[i].ww = info[i].width; |
1608 mon[i].ww = info[i].width; |
1539 mon[i].wh = info[i].height; |
1609 mon[i].wh = mon[i].showbar ? info[i].height - bh : info[i].height; |
1540 mon[i].seltags = 0; |
1610 mon[i].seltags = 0; |
1541 mon[i].sellt = 0; |
1611 mon[i].sellt = 0; |
|
1612 if(mon[i].showbar) |
|
1613 mon[i].by = mon[i].topbar ? info[i].y_org : mon[i].wy + mon[i].wh; |
|
1614 else |
|
1615 mon[i].by = -bh; |
1542 if(pquery && INRECT(x, y, info[i].x_org, info[i].y_org, info[i].width, info[i].height)) |
1616 if(pquery && INRECT(x, y, info[i].x_org, info[i].y_org, info[i].width, info[i].height)) |
1543 selmon = &mon[i]; |
1617 selmon = &mon[i]; |
1544 } |
1618 } |
1545 /* bar adjustments of selmon */ |
|
1546 selmon->wy = showbar && topbar ? selmon->wy + bh : selmon->wy; |
|
1547 selmon->wh = showbar ? selmon->wh - bh : selmon->wh; |
|
1548 XFree(info); |
1619 XFree(info); |
1549 } |
1620 } |
1550 else |
1621 else |
1551 #endif |
1622 #endif /* XINERAMA */ |
1552 { |
1623 { |
1553 nmons = 1; |
1624 nmons = 1; |
1554 if(!(mon = (Monitor *)realloc(mon, sizeof(Monitor)))) |
1625 if(!(mon = (Monitor *)realloc(mon, sizeof(Monitor)))) |
1555 die("fatal: could not realloc() %u bytes\n", sizeof(Monitor)); |
1626 die("fatal: could not realloc() %u bytes\n", sizeof(Monitor)); |
1556 selmon = &mon[0]; |
1627 selmon = &mon[0]; |
|
1628 mon[0].symbol[0] = '['; |
|
1629 mon[0].symbol[1] = '0'; |
|
1630 mon[0].symbol[2] = ']'; |
|
1631 mon[0].symbol[3] = 0; |
|
1632 mon[0].showbar = showbar; |
|
1633 mon[0].topbar = topbar; |
1557 mon[0].wx = sx; |
1634 mon[0].wx = sx; |
1558 mon[0].wy = showbar && topbar ? sy + bh : sy; |
1635 mon[0].wy = mon[0].showbar && mon[0].topbar ? sy + bh : sy; |
1559 mon[0].ww = sw; |
1636 mon[0].ww = sw; |
1560 mon[0].wh = showbar ? sh - bh : sh; |
1637 mon[0].wh = mon[0].showbar ? sh - bh : sh; |
1561 mon[0].seltags = 0; |
1638 mon[0].seltags = 0; |
1562 mon[0].sellt = 0; |
1639 mon[0].sellt = 0; |
1563 } |
1640 if(mon[0].showbar) |
1564 |
1641 mon[0].by = mon[0].topbar ? sy : mon[0].wy + mon[0].wh; |
1565 /* bar position */ |
1642 else |
1566 by = showbar ? (topbar ? selmon->wy - bh : selmon->wy + selmon->wh) : -bh; |
1643 mon[0].by = -bh; |
|
1644 } |
1567 } |
1645 } |
1568 |
1646 |
1569 void |
1647 void |
1570 updatenumlockmask(void) { |
1648 updatenumlockmask(void) { |
1571 unsigned int i, j; |
1649 unsigned int i, j; |