changeset 1077 | 51b8e0c21bcb |
parent 1076 | 591632523d96 |
child 1078 | 5cfd3c602ede |
1076:591632523d96 | 1077:51b8e0c21bcb |
---|---|
115 regex_t *propregex; |
115 regex_t *propregex; |
116 regex_t *tagregex; |
116 regex_t *tagregex; |
117 } Regs; |
117 } Regs; |
118 |
118 |
119 typedef struct { |
119 typedef struct { |
120 int id; |
120 int screen; |
121 Window root; |
|
121 Window barwin; |
122 Window barwin; |
122 //TODO: Window root; |
|
123 //TODO: int screen; |
|
124 int sx, sy, sw, sh, wax, way, wah, waw; |
123 int sx, sy, sw, sh, wax, way, wah, waw; |
125 DC dc; |
124 DC dc; |
126 Bool *seltags; |
125 Bool *seltags; |
127 Bool *prevtags; |
126 Bool *prevtags; |
128 Layout *layout; |
127 Layout *layout; |
156 void focus(Client *c); |
155 void focus(Client *c); |
157 void focusin(XEvent *e); |
156 void focusin(XEvent *e); |
158 void focusnext(const char *arg); |
157 void focusnext(const char *arg); |
159 void focusprev(const char *arg); |
158 void focusprev(const char *arg); |
160 Client *getclient(Window w); |
159 Client *getclient(Window w); |
161 unsigned long getcolor(const char *colstr); |
160 unsigned long getcolor(const char *colstr, int screen); |
162 long getstate(Window w); |
161 long getstate(Window w); |
163 Bool gettextprop(Window w, Atom atom, char *text, unsigned int size); |
162 Bool gettextprop(Window w, Atom atom, char *text, unsigned int size); |
164 void grabbuttons(Client *c, Bool focused); |
163 void grabbuttons(Client *c, Bool focused); |
165 void grabkeys(void); |
164 void grabkeys(void); |
166 unsigned int idxoftag(const char *tag); |
165 unsigned int idxoftag(const char *tag); |
168 Bool isoccupied(Monitor *m, unsigned int t); |
167 Bool isoccupied(Monitor *m, unsigned int t); |
169 Bool isprotodel(Client *c); |
168 Bool isprotodel(Client *c); |
170 Bool isvisible(Client *c, Monitor *m); |
169 Bool isvisible(Client *c, Monitor *m); |
171 void keypress(XEvent *e); |
170 void keypress(XEvent *e); |
172 void killclient(const char *arg); |
171 void killclient(const char *arg); |
173 void leavenotify(XEvent *e); |
|
174 void manage(Window w, XWindowAttributes *wa); |
172 void manage(Window w, XWindowAttributes *wa); |
175 void mappingnotify(XEvent *e); |
173 void mappingnotify(XEvent *e); |
176 void maprequest(XEvent *e); |
174 void maprequest(XEvent *e); |
177 void movemouse(Client *c); |
175 void movemouse(Client *c); |
178 Client *nexttiled(Client *c, Monitor *m); |
176 Client *nexttiled(Client *c, Monitor *m); |
213 void movetomonitor(const char *arg); |
211 void movetomonitor(const char *arg); |
214 void selectmonitor(const char *arg); |
212 void selectmonitor(const char *arg); |
215 |
213 |
216 /* variables */ |
214 /* variables */ |
217 char stext[256]; |
215 char stext[256]; |
218 int mcount, screen; |
216 int mcount = 1; |
219 //double mwfact; |
217 //double mwfact; |
220 //int screen, sx, sy, sw, sh, wax, way, waw, wah; |
|
221 int (*xerrorxlib)(Display *, XErrorEvent *); |
218 int (*xerrorxlib)(Display *, XErrorEvent *); |
222 unsigned int bh, bpos; |
219 unsigned int bh, bpos; |
223 unsigned int blw = 0; |
220 unsigned int blw = 0; |
224 unsigned int numlockmask = 0; |
221 unsigned int numlockmask = 0; |
225 void (*handler[LASTEvent]) (XEvent *) = { |
222 void (*handler[LASTEvent]) (XEvent *) = { |
229 [DestroyNotify] = destroynotify, |
226 [DestroyNotify] = destroynotify, |
230 [EnterNotify] = enternotify, |
227 [EnterNotify] = enternotify, |
231 [Expose] = expose, |
228 [Expose] = expose, |
232 [FocusIn] = focusin, |
229 [FocusIn] = focusin, |
233 [KeyPress] = keypress, |
230 [KeyPress] = keypress, |
234 [LeaveNotify] = leavenotify, |
|
235 [MappingNotify] = mappingnotify, |
231 [MappingNotify] = mappingnotify, |
236 [MapRequest] = maprequest, |
232 [MapRequest] = maprequest, |
237 [PropertyNotify] = propertynotify, |
233 [PropertyNotify] = propertynotify, |
238 [UnmapNotify] = unmapnotify |
234 [UnmapNotify] = unmapnotify |
239 }; |
235 }; |
240 Atom wmatom[WMLast], netatom[NetLast]; |
236 Atom wmatom[WMLast], netatom[NetLast]; |
241 Bool domwfact = True; |
237 Bool domwfact = True; |
242 Bool dozoom = True; |
238 Bool dozoom = True; |
243 Bool otherwm, readin; |
239 Bool otherwm, readin; |
244 Bool running = True; |
240 Bool running = True; |
245 //Bool selscreen = True; |
|
246 Client *clients = NULL; |
241 Client *clients = NULL; |
247 Client *sel = NULL; |
242 Client *sel = NULL; |
248 Client *stack = NULL; |
243 Client *stack = NULL; |
249 Cursor cursor[CurLast]; |
244 Cursor cursor[CurLast]; |
250 Display *dpy; |
245 Display *dpy; |
251 DC dc = {0}; |
246 DC dc = {0}; |
252 Window root; |
|
253 //Layout *layout = NULL; |
|
254 //Window barwin, root; |
|
255 Regs *regs = NULL; |
247 Regs *regs = NULL; |
256 Monitor *monitors; |
248 Monitor *monitors; |
257 int selmonitor = 0; |
249 int selmonitor = 0; |
258 |
250 |
259 /* configuration, allows nested code to access above variables */ |
251 /* configuration, allows nested code to access above variables */ |
400 checkotherwm(void) { |
392 checkotherwm(void) { |
401 otherwm = False; |
393 otherwm = False; |
402 XSetErrorHandler(xerrorstart); |
394 XSetErrorHandler(xerrorstart); |
403 |
395 |
404 /* this causes an error if some other window manager is running */ |
396 /* this causes an error if some other window manager is running */ |
405 XSelectInput(dpy, root, SubstructureRedirectMask); |
397 XSelectInput(dpy, DefaultRootWindow(dpy), SubstructureRedirectMask); |
406 XSync(dpy, False); |
398 XSync(dpy, False); |
407 if(otherwm) |
399 if(otherwm) |
408 eprint("dwm: another window manager is already running\n"); |
400 eprint("dwm: another window manager is already running\n"); |
409 XSync(dpy, False); |
401 XSync(dpy, False); |
410 XSetErrorHandler(NULL); |
402 XSetErrorHandler(NULL); |
424 Monitor *m = &monitors[i]; |
416 Monitor *m = &monitors[i]; |
425 if(m->dc.font.set) |
417 if(m->dc.font.set) |
426 XFreeFontSet(dpy, m->dc.font.set); |
418 XFreeFontSet(dpy, m->dc.font.set); |
427 else |
419 else |
428 XFreeFont(dpy, m->dc.font.xfont); |
420 XFreeFont(dpy, m->dc.font.xfont); |
429 XUngrabKey(dpy, AnyKey, AnyModifier, root); |
421 XUngrabKey(dpy, AnyKey, AnyModifier, m->root); |
430 XFreePixmap(dpy, m->dc.drawable); |
422 XFreePixmap(dpy, m->dc.drawable); |
431 XFreeGC(dpy, m->dc.gc); |
423 XFreeGC(dpy, m->dc.gc); |
432 XDestroyWindow(dpy, m->barwin); |
424 XDestroyWindow(dpy, m->barwin); |
433 XFreeCursor(dpy, cursor[CurNormal]); |
425 XFreeCursor(dpy, cursor[CurNormal]); |
434 XFreeCursor(dpy, cursor[CurResize]); |
426 XFreeCursor(dpy, cursor[CurResize]); |
485 void |
477 void |
486 configurenotify(XEvent *e) { |
478 configurenotify(XEvent *e) { |
487 XConfigureEvent *ev = &e->xconfigure; |
479 XConfigureEvent *ev = &e->xconfigure; |
488 Monitor *m = &monitors[selmonitor]; |
480 Monitor *m = &monitors[selmonitor]; |
489 |
481 |
490 if(ev->window == root && (ev->width != m->sw || ev->height != m->sh)) { |
482 if(ev->window == m->root && (ev->width != m->sw || ev->height != m->sh)) { |
491 m->sw = ev->width; |
483 m->sw = ev->width; |
492 m->sh = ev->height; |
484 m->sh = ev->height; |
493 XFreePixmap(dpy, dc.drawable); |
485 XFreePixmap(dpy, dc.drawable); |
494 dc.drawable = XCreatePixmap(dpy, root, m->sw, bh, DefaultDepth(dpy, screen)); |
486 dc.drawable = XCreatePixmap(dpy, m->root, m->sw, bh, DefaultDepth(dpy, m->screen)); |
495 XResizeWindow(dpy, m->barwin, m->sw, bh); |
487 XResizeWindow(dpy, m->barwin, m->sw, bh); |
496 updatebarpos(m); |
488 updatebarpos(m); |
497 arrange(); |
489 arrange(); |
498 } |
490 } |
499 } |
491 } |
580 m->dc.x = 0; |
572 m->dc.x = 0; |
581 for(i = 0; i < LENGTH(tags); i++) { |
573 for(i = 0; i < LENGTH(tags); i++) { |
582 m->dc.w = textw(m, tags[i]); |
574 m->dc.w = textw(m, tags[i]); |
583 if(m->seltags[i]) { |
575 if(m->seltags[i]) { |
584 drawtext(m, tags[i], m->dc.sel); |
576 drawtext(m, tags[i], m->dc.sel); |
585 drawsquare(m, sel && sel->tags[i] && sel->monitor == m->id, isoccupied(m, i), m->dc.sel); |
577 drawsquare(m, sel && sel->tags[i] && sel->monitor == selmonitor, isoccupied(m, i), m->dc.sel); |
586 } |
578 } |
587 else { |
579 else { |
588 drawtext(m, tags[i], m->dc.norm); |
580 drawtext(m, tags[i], m->dc.norm); |
589 drawsquare(m, sel && sel->tags[i] && sel->monitor == m->id, isoccupied(m, i), m->dc.norm); |
581 drawsquare(m, sel && sel->tags[i] && sel->monitor == selmonitor, isoccupied(m, i), m->dc.norm); |
590 } |
582 } |
591 m->dc.x += m->dc.w; |
583 m->dc.x += m->dc.w; |
592 } |
584 } |
593 m->dc.w = blw; |
585 m->dc.w = blw; |
594 drawtext(m, m->layout->symbol, m->dc.norm); |
586 drawtext(m, m->layout->symbol, m->dc.norm); |
600 m->dc.w = m->sw - x; |
592 m->dc.w = m->sw - x; |
601 } |
593 } |
602 drawtext(m, stext, m->dc.norm); |
594 drawtext(m, stext, m->dc.norm); |
603 if((m->dc.w = m->dc.x - x) > bh) { |
595 if((m->dc.w = m->dc.x - x) > bh) { |
604 m->dc.x = x; |
596 m->dc.x = x; |
605 if(sel && sel->monitor == m->id) { |
597 if(sel && sel->monitor == selmonitor) { |
606 drawtext(m, sel->name, m->dc.sel); |
598 drawtext(m, sel->name, m->dc.sel); |
607 drawsquare(m, False, sel->isfloating, m->dc.sel); |
599 drawsquare(m, False, sel->isfloating, m->dc.sel); |
608 } |
600 } |
609 else |
601 else |
610 drawtext(m, NULL, m->dc.norm); |
602 drawtext(m, NULL, m->dc.norm); |
684 return res; |
676 return res; |
685 } |
677 } |
686 |
678 |
687 void |
679 void |
688 enternotify(XEvent *e) { |
680 enternotify(XEvent *e) { |
681 unsigned int i; |
|
689 Client *c; |
682 Client *c; |
690 XCrossingEvent *ev = &e->xcrossing; |
683 XCrossingEvent *ev = &e->xcrossing; |
691 |
684 |
692 if(ev->mode != NotifyNormal || ev->detail == NotifyInferior) |
685 if(ev->mode != NotifyNormal || ev->detail == NotifyInferior) |
693 return; |
686 return; |
694 if((c = getclient(ev->window))) |
687 if((c = getclient(ev->window))) |
695 focus(c); |
688 focus(c); |
696 else if(ev->window == root) { |
689 else { |
697 selmonitor = True; |
690 for(i = 0; i < mcount; i++) |
698 focus(NULL); |
691 if(ev->window == monitors[i].root) { |
692 selmonitor = i; |
|
693 focus(NULL); |
|
694 break; |
|
695 } |
|
699 } |
696 } |
700 } |
697 } |
701 |
698 |
702 void |
699 void |
703 eprint(const char *errstr, ...) { |
700 eprint(const char *errstr, ...) { |
729 resize(c, c->x, c->y, c->w, c->h, True); |
726 resize(c, c->x, c->y, c->w, c->h, True); |
730 } |
727 } |
731 |
728 |
732 void |
729 void |
733 focus(Client *c) { |
730 focus(Client *c) { |
734 Monitor *m = &monitors[monitorat(-1, -1)]; |
731 Monitor *m = &monitors[c ? c->monitor : selmonitor]; |
735 if(!c || (c && !isvisible(c, m))) |
732 if(!c || (c && !isvisible(c, m))) |
736 for(c = stack; c && !isvisible(c, m); c = c->snext); |
733 for(c = stack; c && !isvisible(c, m); c = c->snext); |
737 if(sel && sel != c) { |
734 if(sel && sel != c) { |
738 grabbuttons(sel, False); |
735 grabbuttons(sel, False); |
739 XSetWindowBorder(dpy, sel->win, monitors[sel->monitor].dc.norm[ColBorder]); |
736 XSetWindowBorder(dpy, sel->win, monitors[sel->monitor].dc.norm[ColBorder]); |
744 grabbuttons(c, True); |
741 grabbuttons(c, True); |
745 } |
742 } |
746 sel = c; |
743 sel = c; |
747 drawbar(); |
744 drawbar(); |
748 if(c) { |
745 if(c) { |
749 XSetWindowBorder(dpy, c->win, monitors[c->monitor].dc.sel[ColBorder]); |
746 XSetWindowBorder(dpy, c->win, m->dc.sel[ColBorder]); |
750 XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); |
747 XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); |
751 selmonitor = monitorat(c->x, c->y); |
748 selmonitor = c->monitor; |
752 } |
749 } |
753 else { |
750 else { |
754 XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); |
751 XSetInputFocus(dpy, m->root, RevertToPointerRoot, CurrentTime); |
755 selmonitor = monitorat(-1, -1); |
|
756 } |
752 } |
757 } |
753 } |
758 |
754 |
759 void |
755 void |
760 focusin(XEvent *e) { /* there are some broken focus acquiring clients */ |
756 focusin(XEvent *e) { /* there are some broken focus acquiring clients */ |
805 for(c = clients; c && c->win != w; c = c->next); |
801 for(c = clients; c && c->win != w; c = c->next); |
806 return c; |
802 return c; |
807 } |
803 } |
808 |
804 |
809 unsigned long |
805 unsigned long |
810 getcolor(const char *colstr) { |
806 getcolor(const char *colstr, int screen) { |
811 Colormap cmap = DefaultColormap(dpy, screen); |
807 Colormap cmap = DefaultColormap(dpy, screen); |
812 XColor color; |
808 XColor color; |
813 |
809 |
814 if(!XAllocNamedColor(dpy, cmap, colstr, &color, &color)) |
810 if(!XAllocNamedColor(dpy, cmap, colstr, &color, &color)) |
815 eprint("error, cannot allocate color '%s'\n", colstr); |
811 eprint("error, cannot allocate color '%s'\n", colstr); |
897 GrabModeAsync, GrabModeSync, None, None); |
893 GrabModeAsync, GrabModeSync, None, None); |
898 } |
894 } |
899 |
895 |
900 void |
896 void |
901 grabkeys(void) { |
897 grabkeys(void) { |
902 unsigned int i; |
898 unsigned int i, j; |
903 KeyCode code; |
899 KeyCode code; |
904 |
900 XModifierKeymap *modmap; |
905 XUngrabKey(dpy, AnyKey, AnyModifier, root); |
901 |
906 for(i = 0; i < LENGTH(keys); i++) { |
902 /* init modifier map */ |
907 code = XKeysymToKeycode(dpy, keys[i].keysym); |
903 modmap = XGetModifierMapping(dpy); |
908 XGrabKey(dpy, code, keys[i].mod, root, True, |
904 for(i = 0; i < 8; i++) |
909 GrabModeAsync, GrabModeAsync); |
905 for(j = 0; j < modmap->max_keypermod; j++) { |
910 XGrabKey(dpy, code, keys[i].mod | LockMask, root, True, |
906 if(modmap->modifiermap[i * modmap->max_keypermod + j] == XKeysymToKeycode(dpy, XK_Num_Lock)) |
911 GrabModeAsync, GrabModeAsync); |
907 numlockmask = (1 << i); |
912 XGrabKey(dpy, code, keys[i].mod | numlockmask, root, True, |
908 } |
913 GrabModeAsync, GrabModeAsync); |
909 XFreeModifiermap(modmap); |
914 XGrabKey(dpy, code, keys[i].mod | numlockmask | LockMask, root, True, |
910 |
915 GrabModeAsync, GrabModeAsync); |
911 for(i = 0; i < mcount; i++) { |
912 Monitor *m = &monitors[i]; |
|
913 XUngrabKey(dpy, AnyKey, AnyModifier, m->root); |
|
914 for(j = 0; j < LENGTH(keys); j++) { |
|
915 code = XKeysymToKeycode(dpy, keys[j].keysym); |
|
916 XGrabKey(dpy, code, keys[j].mod, m->root, True, |
|
917 GrabModeAsync, GrabModeAsync); |
|
918 XGrabKey(dpy, code, keys[j].mod | LockMask, m->root, True, |
|
919 GrabModeAsync, GrabModeAsync); |
|
920 XGrabKey(dpy, code, keys[j].mod | numlockmask, m->root, True, |
|
921 GrabModeAsync, GrabModeAsync); |
|
922 XGrabKey(dpy, code, keys[j].mod | numlockmask | LockMask, m->root, True, |
|
923 GrabModeAsync, GrabModeAsync); |
|
924 } |
|
916 } |
925 } |
917 } |
926 } |
918 |
927 |
919 unsigned int |
928 unsigned int |
920 idxoftag(const char *tag) { |
929 idxoftag(const char *tag) { |
969 Bool |
978 Bool |
970 isoccupied(Monitor *m, unsigned int t) { |
979 isoccupied(Monitor *m, unsigned int t) { |
971 Client *c; |
980 Client *c; |
972 |
981 |
973 for(c = clients; c; c = c->next) |
982 for(c = clients; c; c = c->next) |
974 if(c->tags[t] && c->monitor == m->id) |
983 if(c->tags[t] && c->monitor == selmonitor) |
975 return True; |
984 return True; |
976 return False; |
985 return False; |
977 } |
986 } |
978 |
987 |
979 Bool |
988 Bool |
994 Bool |
1003 Bool |
995 isvisible(Client *c, Monitor *m) { |
1004 isvisible(Client *c, Monitor *m) { |
996 unsigned int i; |
1005 unsigned int i; |
997 |
1006 |
998 for(i = 0; i < LENGTH(tags); i++) |
1007 for(i = 0; i < LENGTH(tags); i++) |
999 if(c->tags[i] && monitors[c->monitor].seltags[i] && m->id == c->monitor) |
1008 if(c->tags[i] && monitors[c->monitor].seltags[i] && c->monitor == selmonitor) |
1000 return True; |
1009 return True; |
1001 return False; |
1010 return False; |
1002 } |
1011 } |
1003 |
1012 |
1004 void |
1013 void |
1036 else |
1045 else |
1037 XKillClient(dpy, sel->win); |
1046 XKillClient(dpy, sel->win); |
1038 } |
1047 } |
1039 |
1048 |
1040 void |
1049 void |
1041 leavenotify(XEvent *e) { |
|
1042 XCrossingEvent *ev = &e->xcrossing; |
|
1043 |
|
1044 if((ev->window == root) && !ev->same_screen) { |
|
1045 selmonitor = False; |
|
1046 focus(NULL); |
|
1047 } |
|
1048 } |
|
1049 |
|
1050 void |
|
1051 manage(Window w, XWindowAttributes *wa) { |
1050 manage(Window w, XWindowAttributes *wa) { |
1052 Client *c, *t = NULL; |
1051 Client *c, *t = NULL; |
1052 Monitor *m = &monitors[selmonitor]; |
|
1053 Status rettrans; |
|
1053 Window trans; |
1054 Window trans; |
1054 Status rettrans; |
|
1055 XWindowChanges wc; |
1055 XWindowChanges wc; |
1056 |
1056 |
1057 c = emallocz(sizeof(Client)); |
1057 c = emallocz(sizeof(Client)); |
1058 c->tags = emallocz(sizeof initags); |
1058 c->tags = emallocz(sizeof initags); |
1059 c->win = w; |
1059 c->win = w; |
1060 |
1060 |
1061 applyrules(c); |
1061 applyrules(c); |
1062 Monitor *m = &monitors[c->monitor]; |
1062 |
1063 |
1063 c->x = wa->x + m->sx; |
1064 c->x = wa->x+m->sx; |
1064 c->y = wa->y + m->sy; |
1065 c->y = wa->y+m->sy; |
|
1066 c->w = wa->width; |
1065 c->w = wa->width; |
1067 c->h = wa->height; |
1066 c->h = wa->height; |
1068 c->oldborder = wa->border_width; |
1067 c->oldborder = wa->border_width; |
1069 |
1068 |
1070 if (monitorat(c->x, c->y) != c->monitor) { |
1069 if (monitorat(c->x, c->y) != c->monitor) { |
1140 Window dummy; |
1139 Window dummy; |
1141 XEvent ev; |
1140 XEvent ev; |
1142 |
1141 |
1143 ocx = nx = c->x; |
1142 ocx = nx = c->x; |
1144 ocy = ny = c->y; |
1143 ocy = ny = c->y; |
1145 if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, |
1144 if(XGrabPointer(dpy, monitors[selmonitor].root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, |
1146 None, cursor[CurMove], CurrentTime) != GrabSuccess) |
1145 None, cursor[CurMove], CurrentTime) != GrabSuccess) |
1147 return; |
1146 return; |
1148 XQueryPointer(dpy, root, &dummy, &dummy, &x1, &y1, &di, &di, &dui); |
1147 XQueryPointer(dpy, monitors[selmonitor].root, &dummy, &dummy, &x1, &y1, &di, &di, &dui); |
1149 for(;;) { |
1148 for(;;) { |
1150 XMaskEvent(dpy, MOUSEMASK | ExposureMask | SubstructureRedirectMask, &ev); |
1149 XMaskEvent(dpy, MOUSEMASK | ExposureMask | SubstructureRedirectMask, &ev); |
1151 switch (ev.type) { |
1150 switch (ev.type) { |
1152 case ButtonRelease: |
1151 case ButtonRelease: |
1153 XUngrabPointer(dpy, CurrentTime); |
1152 XUngrabPointer(dpy, CurrentTime); |
1230 |
1229 |
1231 void |
1230 void |
1232 resize(Client *c, int x, int y, int w, int h, Bool sizehints) { |
1231 resize(Client *c, int x, int y, int w, int h, Bool sizehints) { |
1233 XWindowChanges wc; |
1232 XWindowChanges wc; |
1234 Monitor scr = monitors[monitorat(x, y)]; |
1233 Monitor scr = monitors[monitorat(x, y)]; |
1235 c->monitor = scr.id; |
1234 c->monitor = monitorat(x, y); |
1236 |
1235 |
1237 if(sizehints) { |
1236 if(sizehints) { |
1238 /* set minimum possible */ |
1237 /* set minimum possible */ |
1239 if (w < 1) |
1238 if (w < 1) |
1240 w = 1; |
1239 w = 1; |
1303 int nw, nh; |
1302 int nw, nh; |
1304 XEvent ev; |
1303 XEvent ev; |
1305 |
1304 |
1306 ocx = c->x; |
1305 ocx = c->x; |
1307 ocy = c->y; |
1306 ocy = c->y; |
1308 if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, |
1307 if(XGrabPointer(dpy, monitors[selmonitor].root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, |
1309 None, cursor[CurResize], CurrentTime) != GrabSuccess) |
1308 None, cursor[CurResize], CurrentTime) != GrabSuccess) |
1310 return; |
1309 return; |
1311 XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->border - 1, c->h + c->border - 1); |
1310 XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->border - 1, c->h + c->border - 1); |
1312 for(;;) { |
1311 for(;;) { |
1313 XMaskEvent(dpy, MOUSEMASK | ExposureMask | SubstructureRedirectMask , &ev); |
1312 XMaskEvent(dpy, MOUSEMASK | ExposureMask | SubstructureRedirectMask , &ev); |
1427 } |
1426 } |
1428 } |
1427 } |
1429 |
1428 |
1430 void |
1429 void |
1431 scan(void) { |
1430 scan(void) { |
1432 unsigned int i, num; |
1431 unsigned int i, j, num; |
1433 Window *wins, d1, d2; |
1432 Window *wins, d1, d2; |
1434 XWindowAttributes wa; |
1433 XWindowAttributes wa; |
1435 |
1434 |
1436 wins = NULL; |
1435 for(i = 0; i < mcount; i++) { |
1437 if(XQueryTree(dpy, root, &d1, &d2, &wins, &num)) { |
1436 Monitor *m = &monitors[i]; |
1438 for(i = 0; i < num; i++) { |
1437 wins = NULL; |
1439 if(!XGetWindowAttributes(dpy, wins[i], &wa) |
1438 if(XQueryTree(dpy, m->root, &d1, &d2, &wins, &num)) { |
1440 || wa.override_redirect || XGetTransientForHint(dpy, wins[i], &d1)) |
1439 for(j = 0; j < num; j++) { |
1441 continue; |
1440 if(!XGetWindowAttributes(dpy, wins[j], &wa) |
1442 if(wa.map_state == IsViewable || getstate(wins[i]) == IconicState) |
1441 || wa.override_redirect || XGetTransientForHint(dpy, wins[j], &d1)) |
1443 manage(wins[i], &wa); |
1442 continue; |
1444 } |
1443 if(wa.map_state == IsViewable || getstate(wins[j]) == IconicState) |
1445 for(i = 0; i < num; i++) { /* now the transients */ |
1444 manage(wins[j], &wa); |
1446 if(!XGetWindowAttributes(dpy, wins[i], &wa)) |
1445 } |
1447 continue; |
1446 for(j = 0; j < num; j++) { /* now the transients */ |
1448 if(XGetTransientForHint(dpy, wins[i], &d1) |
1447 if(!XGetWindowAttributes(dpy, wins[j], &wa)) |
1449 && (wa.map_state == IsViewable || getstate(wins[i]) == IconicState)) |
1448 continue; |
1450 manage(wins[i], &wa); |
1449 if(XGetTransientForHint(dpy, wins[j], &d1) |
1451 } |
1450 && (wa.map_state == IsViewable || getstate(wins[j]) == IconicState)) |
1452 } |
1451 manage(wins[j], &wa); |
1453 if(wins) |
1452 } |
1454 XFree(wins); |
1453 } |
1454 if(wins) |
|
1455 XFree(wins); |
|
1456 } |
|
1455 } |
1457 } |
1456 |
1458 |
1457 void |
1459 void |
1458 setclientstate(Client *c, long state) { |
1460 setclientstate(Client *c, long state) { |
1459 long data[] = {state, None}; |
1461 long data[] = {state, None}; |
1511 } |
1513 } |
1512 |
1514 |
1513 void |
1515 void |
1514 setup(void) { |
1516 setup(void) { |
1515 unsigned int i, j, k; |
1517 unsigned int i, j, k; |
1516 XModifierKeymap *modmap; |
1518 Monitor *m; |
1517 XSetWindowAttributes wa; |
1519 XSetWindowAttributes wa; |
1518 int s = 1; |
|
1519 GC g; |
|
1520 XineramaScreenInfo *info = NULL; |
1520 XineramaScreenInfo *info = NULL; |
1521 |
1521 |
1522 /* init atoms */ |
1522 /* init atoms */ |
1523 wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False); |
1523 wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False); |
1524 wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False); |
1524 wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False); |
1525 wmatom[WMName] = XInternAtom(dpy, "WM_NAME", False); |
1525 wmatom[WMName] = XInternAtom(dpy, "WM_NAME", False); |
1526 wmatom[WMState] = XInternAtom(dpy, "WM_STATE", False); |
1526 wmatom[WMState] = XInternAtom(dpy, "WM_STATE", False); |
1527 netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False); |
1527 netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False); |
1528 netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False); |
1528 netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False); |
1529 XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32, |
|
1530 PropModeReplace, (unsigned char *) netatom, NetLast); |
|
1531 |
1529 |
1532 /* init cursors */ |
1530 /* init cursors */ |
1533 cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr); |
1531 wa.cursor = cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr); |
1534 cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing); |
1532 cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing); |
1535 cursor[CurMove] = XCreateFontCursor(dpy, XC_fleur); |
1533 cursor[CurMove] = XCreateFontCursor(dpy, XC_fleur); |
1536 |
1534 |
1537 |
1535 // init screens/monitors first |
1538 /* init modifier map */ |
|
1539 modmap = XGetModifierMapping(dpy); |
|
1540 for(i = 0; i < 8; i++) |
|
1541 for(j = 0; j < modmap->max_keypermod; j++) { |
|
1542 if(modmap->modifiermap[i * modmap->max_keypermod + j] |
|
1543 == XKeysymToKeycode(dpy, XK_Num_Lock)) |
|
1544 numlockmask = (1 << i); |
|
1545 } |
|
1546 XFreeModifiermap(modmap); |
|
1547 |
|
1548 /* select for events */ |
|
1549 wa.event_mask = SubstructureRedirectMask | SubstructureNotifyMask |
|
1550 | EnterWindowMask | LeaveWindowMask | StructureNotifyMask; |
|
1551 wa.cursor = cursor[CurNormal]; |
|
1552 XChangeWindowAttributes(dpy, root, CWEventMask | CWCursor, &wa); |
|
1553 XSelectInput(dpy, root, wa.event_mask); |
|
1554 |
|
1555 /* grab keys */ |
|
1556 grabkeys(); |
|
1557 |
|
1558 /* init tags */ |
|
1559 compileregs(); |
|
1560 |
|
1561 if (XineramaIsActive(dpy)) { |
1536 if (XineramaIsActive(dpy)) { |
1562 info = XineramaQueryScreens(dpy, &s); |
1537 info = XineramaQueryScreens(dpy, &mcount); |
1563 } |
1538 } |
1564 |
1539 mcount = 1; |
1565 monitors = emallocz(s*sizeof(Monitor)); |
1540 monitors = emallocz(mcount * sizeof(Monitor)); |
1566 mcount = s; |
1541 |
1567 |
1542 for(i = 0; i < mcount; i++) { |
1568 for(i = 0; i < s; i++) { |
|
1569 /* init geometry */ |
1543 /* init geometry */ |
1570 if (mcount != 1) { |
1544 m = &monitors[i]; |
1571 monitors[i].sx = info[i].x_org; |
1545 |
1572 monitors[i].sy = info[i].y_org; |
1546 m->screen = i; |
1573 monitors[i].sw = info[i].width; |
1547 m->root = RootWindow(dpy, i); |
1574 monitors[i].sh = info[i].height; |
1548 |
1549 if (mcount != 1) { // TODO: Xinerama |
|
1550 m->sx = info[i].x_org; |
|
1551 m->sy = info[i].y_org; |
|
1552 m->sw = info[i].width; |
|
1553 m->sh = info[i].height; |
|
1575 } |
1554 } |
1576 else { |
1555 else { |
1577 monitors[i].sx = 0; |
1556 m->sx = 0; |
1578 monitors[i].sy = 0; |
1557 m->sy = 0; |
1579 monitors[i].sw = DisplayWidth(dpy, screen); |
1558 m->sw = DisplayWidth(dpy, m->screen); |
1580 monitors[i].sh = DisplayHeight(dpy, screen); |
1559 m->sh = DisplayHeight(dpy, m->screen); |
1581 } |
1560 } |
1582 |
1561 |
1583 monitors[i].id = i; |
1562 m->seltags = emallocz(sizeof initags); |
1584 monitors[i].seltags = emallocz(sizeof initags); |
1563 m->prevtags = emallocz(sizeof initags); |
1585 monitors[i].prevtags = emallocz(sizeof initags); |
1564 |
1586 |
1565 memcpy(m->seltags, initags, sizeof initags); |
1587 memcpy(monitors[i].seltags, initags, sizeof initags); |
1566 memcpy(m->prevtags, initags, sizeof initags); |
1588 memcpy(monitors[i].prevtags, initags, sizeof initags); |
|
1589 |
1567 |
1590 /* init appearance */ |
1568 /* init appearance */ |
1591 monitors[i].dc.norm[ColBorder] = getcolor(NORMBORDERCOLOR); |
1569 m->dc.norm[ColBorder] = getcolor(NORMBORDERCOLOR, i); |
1592 monitors[i].dc.norm[ColBG] = getcolor(NORMBGCOLOR); |
1570 m->dc.norm[ColBG] = getcolor(NORMBGCOLOR, i); |
1593 monitors[i].dc.norm[ColFG] = getcolor(NORMFGCOLOR); |
1571 m->dc.norm[ColFG] = getcolor(NORMFGCOLOR, i); |
1594 monitors[i].dc.sel[ColBorder] = getcolor(SELBORDERCOLOR); |
1572 m->dc.sel[ColBorder] = getcolor(SELBORDERCOLOR, i); |
1595 monitors[i].dc.sel[ColBG] = getcolor(SELBGCOLOR); |
1573 m->dc.sel[ColBG] = getcolor(SELBGCOLOR, i); |
1596 monitors[i].dc.sel[ColFG] = getcolor(SELFGCOLOR); |
1574 m->dc.sel[ColFG] = getcolor(SELFGCOLOR, i); |
1597 initfont(&(monitors[i]), FONT); |
1575 initfont(m, FONT); |
1598 monitors[i].dc.h = bh = monitors[i].dc.font.height + 2; |
1576 m->dc.h = bh = m->dc.font.height + 2; |
1599 |
1577 |
1600 /* init layouts */ |
1578 /* init layouts */ |
1601 monitors[i].mwfact = MWFACT; |
1579 m->mwfact = MWFACT; |
1602 monitors[i].layout = &layouts[0]; |
1580 m->layout = &layouts[0]; |
1603 for(blw = k = 0; k < LENGTH(layouts); k++) { |
1581 for(blw = k = 0; k < LENGTH(layouts); k++) { |
1604 j = textw(&monitors[i], layouts[k].symbol); |
1582 j = textw(m, layouts[k].symbol); |
1605 if(j > blw) |
1583 if(j > blw) |
1606 blw = j; |
1584 blw = j; |
1607 } |
1585 } |
1608 |
1586 |
1587 // TODO: bpos per screen? |
|
1609 bpos = BARPOS; |
1588 bpos = BARPOS; |
1610 wa.override_redirect = 1; |
1589 wa.override_redirect = 1; |
1611 wa.background_pixmap = ParentRelative; |
1590 wa.background_pixmap = ParentRelative; |
1612 wa.event_mask = ButtonPressMask | ExposureMask; |
1591 wa.event_mask = ButtonPressMask | ExposureMask; |
1613 |
1592 |
1614 /* init bars */ |
1593 /* init bars */ |
1615 monitors[i].barwin = XCreateWindow(dpy, root, monitors[i].sx, monitors[i].sy, monitors[i].sw, bh, 0, |
1594 m->barwin = XCreateWindow(dpy, m->root, m->sx, m->sy, m->sw, bh, 0, |
1616 DefaultDepth(dpy, screen), CopyFromParent, DefaultVisual(dpy, screen), |
1595 DefaultDepth(dpy, m->screen), CopyFromParent, DefaultVisual(dpy, m->screen), |
1617 CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa); |
1596 CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa); |
1618 XDefineCursor(dpy, monitors[i].barwin, cursor[CurNormal]); |
1597 XDefineCursor(dpy, m->barwin, cursor[CurNormal]); |
1619 updatebarpos(&monitors[i]); |
1598 updatebarpos(m); |
1620 XMapRaised(dpy, monitors[i].barwin); |
1599 XMapRaised(dpy, m->barwin); |
1621 strcpy(stext, "dwm-"VERSION); |
1600 strcpy(stext, "dwm-"VERSION); |
1622 monitors[i].dc.drawable = XCreatePixmap(dpy, root, monitors[i].sw, bh, DefaultDepth(dpy, screen)); |
1601 m->dc.drawable = XCreatePixmap(dpy, m->root, m->sw, bh, DefaultDepth(dpy, m->screen)); |
1623 g = XCreateGC(dpy, root, 0, 0); |
1602 m->dc.gc = XCreateGC(dpy, m->root, 0, 0); |
1624 monitors[i].dc.gc = XCreateGC(dpy, root, 0, 0); |
1603 XSetLineAttributes(dpy, m->dc.gc, 1, LineSolid, CapButt, JoinMiter); |
1625 XSetLineAttributes(dpy, monitors[i].dc.gc, 1, LineSolid, CapButt, JoinMiter); |
1604 if(!m->dc.font.set) |
1626 if(!monitors[i].dc.font.set) |
1605 XSetFont(dpy, m->dc.gc, m->dc.font.xfont->fid); |
1627 XSetFont(dpy, monitors[i].dc.gc, monitors[i].dc.font.xfont->fid); |
1606 |
1628 } |
1607 /* EWMH support per monitor */ |
1608 XChangeProperty(dpy, m->root, netatom[NetSupported], XA_ATOM, 32, |
|
1609 PropModeReplace, (unsigned char *) netatom, NetLast); |
|
1610 |
|
1611 /* select for events */ |
|
1612 wa.event_mask = SubstructureRedirectMask | SubstructureNotifyMask |
|
1613 | EnterWindowMask | LeaveWindowMask | StructureNotifyMask; |
|
1614 XChangeWindowAttributes(dpy, m->root, CWEventMask | CWCursor, &wa); |
|
1615 XSelectInput(dpy, m->root, wa.event_mask); |
|
1616 } |
|
1617 |
|
1618 /* grab keys */ |
|
1619 grabkeys(); |
|
1620 |
|
1621 /* init tags */ |
|
1622 compileregs(); |
|
1629 } |
1623 } |
1630 |
1624 |
1631 void |
1625 void |
1632 spawn(const char *arg) { |
1626 spawn(const char *arg) { |
1633 static char *shell = NULL; |
1627 static char *shell = NULL; |
1976 |
1970 |
1977 int |
1971 int |
1978 monitorat(int x, int y) { |
1972 monitorat(int x, int y) { |
1979 int i; |
1973 int i; |
1980 |
1974 |
1975 return 0; |
|
1981 if(!XineramaIsActive(dpy)) |
1976 if(!XineramaIsActive(dpy)) |
1982 return 0; |
1977 return 0; |
1983 |
1978 |
1984 if (x < 0 || y < 0) { |
1979 if (x < 0 || y < 0) { |
1985 Window win; |
1980 Window win; |
1986 unsigned int mask; |
1981 unsigned int mask; |
1987 XQueryPointer(dpy, root, &win, &win, &x, &y, &i, &i, &mask); |
1982 XQueryPointer(dpy, DefaultRootWindow(dpy), &win, &win, &x, &y, &i, &i, &mask); |
1988 } |
1983 } |
1989 |
1984 |
1990 for(i = 0; i < mcount; i++) |
1985 for(i = 0; i < mcount; i++) { |
1991 if((x < 0 || (x >= monitors[i].sx && x < monitors[i].sx + monitors[i].sw)) |
1986 Monitor *m = &monitors[i]; |
1992 && (y < 0 || (y >= monitors[i].sy && y < monitors[i].sy + monitors[i].sh))) |
1987 if((x < 0 || (x >= m->sx && x < m->sx + m->sw)) |
1988 && (y < 0 || (y >= m->sy && y < m->sy + m->sh))) |
|
1993 { |
1989 { |
1994 return i; |
1990 return i; |
1995 } |
1991 } |
1992 } |
|
1996 return 0; |
1993 return 0; |
1997 } |
1994 } |
1998 |
1995 |
1999 void |
1996 void |
2000 movetomonitor(const char *arg) { |
1997 movetomonitor(const char *arg) { |
2009 |
2006 |
2010 void |
2007 void |
2011 selectmonitor(const char *arg) { |
2008 selectmonitor(const char *arg) { |
2012 Monitor *m = &monitors[arg ? atoi(arg) : (monitorat(-1, -1)+1) % mcount]; |
2009 Monitor *m = &monitors[arg ? atoi(arg) : (monitorat(-1, -1)+1) % mcount]; |
2013 |
2010 |
2014 XWarpPointer(dpy, None, root, 0, 0, 0, 0, m->wax+m->waw/2, m->way+m->wah/2); |
2011 XWarpPointer(dpy, None, m->root, 0, 0, 0, 0, m->wax+m->waw/2, m->way+m->wah/2); |
2015 focus(NULL); |
2012 focus(NULL); |
2016 } |
2013 } |
2017 |
2014 |
2018 |
2015 |
2019 int |
2016 int |
2020 main(int argc, char *argv[]) { |
2017 main(int argc, char *argv[]) { |
2021 if(argc == 2 && !strcmp("-v", argv[1])) |
2018 if(argc == 2 && !strcmp("-v", argv[1])) |
2022 eprint("dwm-"VERSION", © 2006-2007 Anselm R. Garbe, Sander van Dijk, " |
2019 eprint("dwm-"VERSION", © 2006-2007 Anselm R. Garbe, Sander van Dijk, " |
2023 "Jukka Salmi, Premysl Hruby, Szabolcs Nagy\n"); |
2020 "Jukka Salmi, Premysl Hruby, Szabolcs Nagy, Christof Musik\n"); |
2024 else if(argc != 1) |
2021 else if(argc != 1) |
2025 eprint("usage: dwm [-v]\n"); |
2022 eprint("usage: dwm [-v]\n"); |
2026 |
2023 |
2027 setlocale(LC_CTYPE, ""); |
2024 setlocale(LC_CTYPE, ""); |
2028 if(!(dpy = XOpenDisplay(0))) |
2025 if(!(dpy = XOpenDisplay(0))) |
2029 eprint("dwm: cannot open display\n"); |
2026 eprint("dwm: cannot open display\n"); |
2030 screen = DefaultScreen(dpy); |
|
2031 root = RootWindow(dpy, screen); |
|
2032 |
2027 |
2033 checkotherwm(); |
2028 checkotherwm(); |
2034 setup(); |
2029 setup(); |
2035 drawbar(); |
2030 drawbar(); |
2036 scan(); |
2031 scan(); |