changeset 1001 | 2477f818215c |
parent 1000 | 55e4d698f53a |
child 1002 | 5cc2be8efeb4 |
1000:55e4d698f53a | 1001:2477f818215c |
---|---|
19 * stack list. Each client contains an array of Bools of the same size as the |
19 * stack list. Each client contains an array of Bools of the same size as the |
20 * global tags array to indicate the tags of a client. For each client dwm |
20 * global tags array to indicate the tags of a client. For each client dwm |
21 * creates a small title window, which is resized whenever the (_NET_)WM_NAME |
21 * creates a small title window, which is resized whenever the (_NET_)WM_NAME |
22 * properties are updated or the client is moved/resized. |
22 * properties are updated or the client is moved/resized. |
23 * |
23 * |
24 * Keys and tagging rules are organized as arrays and defined in the config.h |
24 * Keys and tagging rules are organized as arrays and defined in config.h. |
25 * file. These arrays are kept static in event.o and tag.o respectively, |
|
26 * because no other part of dwm needs access to them. The current layout is |
|
27 * represented by the lt pointer. |
|
28 * |
25 * |
29 * To understand everything else, start reading main(). |
26 * To understand everything else, start reading main(). |
30 */ |
27 */ |
31 #include <errno.h> |
28 #include <errno.h> |
32 #include <locale.h> |
29 #include <locale.h> |
112 regex_t *propregex; |
109 regex_t *propregex; |
113 regex_t *tagregex; |
110 regex_t *tagregex; |
114 } Regs; |
111 } Regs; |
115 |
112 |
116 /* forward declarations */ |
113 /* forward declarations */ |
117 static void applyrules(Client *c); |
114 void applyrules(Client *c); |
118 static void arrange(void); |
115 void arrange(void); |
119 static void attach(Client *c); |
116 void attach(Client *c); |
120 static void attachstack(Client *c); |
117 void attachstack(Client *c); |
121 static void ban(Client *c); |
118 void ban(Client *c); |
122 static void buttonpress(XEvent *e); |
119 void buttonpress(XEvent *e); |
123 static void checkotherwm(void); |
120 void checkotherwm(void); |
124 static void cleanup(void); |
121 void cleanup(void); |
125 static void compileregs(void); |
122 void compileregs(void); |
126 static void configure(Client *c); |
123 void configure(Client *c); |
127 static void configurenotify(XEvent *e); |
124 void configurenotify(XEvent *e); |
128 static void configurerequest(XEvent *e); |
125 void configurerequest(XEvent *e); |
129 static void destroynotify(XEvent *e); |
126 void destroynotify(XEvent *e); |
130 static void detach(Client *c); |
127 void detach(Client *c); |
131 static void detachstack(Client *c); |
128 void detachstack(Client *c); |
132 static void drawbar(void); |
129 void drawbar(void); |
133 static void drawsquare(Bool filled, Bool empty, unsigned long col[ColLast]); |
130 void drawsquare(Bool filled, Bool empty, unsigned long col[ColLast]); |
134 static void drawtext(const char *text, unsigned long col[ColLast]); |
131 void drawtext(const char *text, unsigned long col[ColLast]); |
135 static void *emallocz(unsigned int size); |
132 void *emallocz(unsigned int size); |
136 static void enternotify(XEvent *e); |
133 void enternotify(XEvent *e); |
137 static void eprint(const char *errstr, ...); |
134 void eprint(const char *errstr, ...); |
138 static void expose(XEvent *e); |
135 void expose(XEvent *e); |
139 static void floating(void); /* default floating layout */ |
136 void floating(void); /* default floating layout */ |
140 static void focus(Client *c); |
137 void focus(Client *c); |
141 static void focusnext(const char *arg); |
138 void focusnext(const char *arg); |
142 static void focusprev(const char *arg); |
139 void focusprev(const char *arg); |
143 static Client *getclient(Window w); |
140 Client *getclient(Window w); |
144 static unsigned long getcolor(const char *colstr); |
141 unsigned long getcolor(const char *colstr); |
145 static long getstate(Window w); |
142 long getstate(Window w); |
146 static Bool gettextprop(Window w, Atom atom, char *text, unsigned int size); |
143 Bool gettextprop(Window w, Atom atom, char *text, unsigned int size); |
147 static void grabbuttons(Client *c, Bool focused); |
144 void grabbuttons(Client *c, Bool focused); |
148 static unsigned int idxoftag(const char *tag); |
145 unsigned int idxoftag(const char *tag); |
149 static void initfont(const char *fontstr); |
146 void initfont(const char *fontstr); |
150 static Bool isarrange(void (*func)()); |
147 Bool isarrange(void (*func)()); |
151 static Bool isoccupied(unsigned int t); |
148 Bool isoccupied(unsigned int t); |
152 static Bool isprotodel(Client *c); |
149 Bool isprotodel(Client *c); |
153 static Bool isvisible(Client *c); |
150 Bool isvisible(Client *c); |
154 static void keypress(XEvent *e); |
151 void keypress(XEvent *e); |
155 static void killclient(const char *arg); |
152 void killclient(const char *arg); |
156 static void leavenotify(XEvent *e); |
153 void leavenotify(XEvent *e); |
157 static void manage(Window w, XWindowAttributes *wa); |
154 void manage(Window w, XWindowAttributes *wa); |
158 static void mappingnotify(XEvent *e); |
155 void mappingnotify(XEvent *e); |
159 static void maprequest(XEvent *e); |
156 void maprequest(XEvent *e); |
160 static void movemouse(Client *c); |
157 void movemouse(Client *c); |
161 static Client *nexttiled(Client *c); |
158 Client *nexttiled(Client *c); |
162 static void propertynotify(XEvent *e); |
159 void propertynotify(XEvent *e); |
163 static void quit(const char *arg); |
160 void quit(const char *arg); |
164 static void resize(Client *c, int x, int y, int w, int h, Bool sizehints); |
161 void resize(Client *c, int x, int y, int w, int h, Bool sizehints); |
165 static void resizemouse(Client *c); |
162 void resizemouse(Client *c); |
166 static void restack(void); |
163 void restack(void); |
167 static void run(void); |
164 void run(void); |
168 static void scan(void); |
165 void scan(void); |
169 static void setclientstate(Client *c, long state); |
166 void setclientstate(Client *c, long state); |
170 static void setlayout(const char *arg); |
167 void setlayout(const char *arg); |
171 static void setmwfact(const char *arg); |
168 void setmwfact(const char *arg); |
172 static void setup(void); |
169 void setup(void); |
173 static void spawn(const char *arg); |
170 void spawn(const char *arg); |
174 static void tag(const char *arg); |
171 void tag(const char *arg); |
175 static unsigned int textnw(const char *text, unsigned int len); |
172 unsigned int textnw(const char *text, unsigned int len); |
176 static unsigned int textw(const char *text); |
173 unsigned int textw(const char *text); |
177 static void tile(void); |
174 void tile(void); |
178 static void togglebar(const char *arg); |
175 void togglebar(const char *arg); |
179 static void togglefloating(const char *arg); |
176 void togglefloating(const char *arg); |
180 static void togglemax(const char *arg); |
177 void togglemax(const char *arg); |
181 static void toggletag(const char *arg); |
178 void toggletag(const char *arg); |
182 static void toggleview(const char *arg); |
179 void toggleview(const char *arg); |
183 static void unban(Client *c); |
180 void unban(Client *c); |
184 static void unmanage(Client *c); |
181 void unmanage(Client *c); |
185 static void unmapnotify(XEvent *e); |
182 void unmapnotify(XEvent *e); |
186 static void updatebarpos(void); |
183 void updatebarpos(void); |
187 static void updatesizehints(Client *c); |
184 void updatesizehints(Client *c); |
188 static void updatetitle(Client *c); |
185 void updatetitle(Client *c); |
189 static void view(const char *arg); |
186 void view(const char *arg); |
190 static int xerror(Display *dpy, XErrorEvent *ee); |
187 int xerror(Display *dpy, XErrorEvent *ee); |
191 static int xerrordummy(Display *dsply, XErrorEvent *ee); |
188 int xerrordummy(Display *dsply, XErrorEvent *ee); |
192 static int xerrorstart(Display *dsply, XErrorEvent *ee); |
189 int xerrorstart(Display *dsply, XErrorEvent *ee); |
193 static void zoom(const char *arg); |
190 void zoom(const char *arg); |
194 |
191 |
195 /* variables */ |
192 /* variables */ |
196 static char stext[256]; |
193 char stext[256]; |
197 static double mwfact; |
194 double mwfact; |
198 static int screen, sx, sy, sw, sh, wax, way, waw, wah; |
195 int screen, sx, sy, sw, sh, wax, way, waw, wah; |
199 static int (*xerrorxlib)(Display *, XErrorEvent *); |
196 int (*xerrorxlib)(Display *, XErrorEvent *); |
200 static unsigned int bh, bpos, ntags; |
197 unsigned int bh, bpos, ntags; |
201 static unsigned int blw = 0; |
198 unsigned int blw = 0; |
202 static unsigned int ltidx = 0; /* default */ |
199 unsigned int ltidx = 0; /* default */ |
203 static unsigned int nlayouts = 0; |
200 unsigned int nlayouts = 0; |
204 static unsigned int nrules = 0; |
201 unsigned int nrules = 0; |
205 static unsigned int numlockmask = 0; |
202 unsigned int numlockmask = 0; |
206 static void (*handler[LASTEvent]) (XEvent *) = { |
203 void (*handler[LASTEvent]) (XEvent *) = { |
207 [ButtonPress] = buttonpress, |
204 [ButtonPress] = buttonpress, |
208 [ConfigureRequest] = configurerequest, |
205 [ConfigureRequest] = configurerequest, |
209 [ConfigureNotify] = configurenotify, |
206 [ConfigureNotify] = configurenotify, |
210 [DestroyNotify] = destroynotify, |
207 [DestroyNotify] = destroynotify, |
211 [EnterNotify] = enternotify, |
208 [EnterNotify] = enternotify, |
215 [MappingNotify] = mappingnotify, |
212 [MappingNotify] = mappingnotify, |
216 [MapRequest] = maprequest, |
213 [MapRequest] = maprequest, |
217 [PropertyNotify] = propertynotify, |
214 [PropertyNotify] = propertynotify, |
218 [UnmapNotify] = unmapnotify |
215 [UnmapNotify] = unmapnotify |
219 }; |
216 }; |
220 static Atom wmatom[WMLast], netatom[NetLast]; |
217 Atom wmatom[WMLast], netatom[NetLast]; |
221 static Bool otherwm, readin; |
218 Bool otherwm, readin; |
222 static Bool running = True; |
219 Bool running = True; |
223 static Bool *seltags; |
220 Bool *seltags; |
224 static Bool selscreen = True; |
221 Bool selscreen = True; |
225 static Client *clients = NULL; |
222 Client *clients = NULL; |
226 static Client *sel = NULL; |
223 Client *sel = NULL; |
227 static Client *stack = NULL; |
224 Client *stack = NULL; |
228 static Cursor cursor[CurLast]; |
225 Cursor cursor[CurLast]; |
229 static Display *dpy; |
226 Display *dpy; |
230 static DC dc = {0}; |
227 DC dc = {0}; |
231 static Window barwin, root; |
228 Window barwin, root; |
232 static Regs *regs = NULL; |
229 Regs *regs = NULL; |
233 |
230 |
234 /* configuration, allows nested code to access above variables */ |
231 /* configuration, allows nested code to access above variables */ |
235 #include "config.h" |
232 #include "config.h" |
236 |
233 |
237 /* functions*/ |
234 /* functions*/ |
238 static void |
235 void |
239 applyrules(Client *c) { |
236 applyrules(Client *c) { |
240 static char buf[512]; |
237 static char buf[512]; |
241 unsigned int i, j; |
238 unsigned int i, j; |
242 regmatch_t tmp; |
239 regmatch_t tmp; |
243 Bool matched = False; |
240 Bool matched = False; |
265 if(!matched) |
262 if(!matched) |
266 for(i = 0; i < ntags; i++) |
263 for(i = 0; i < ntags; i++) |
267 c->tags[i] = seltags[i]; |
264 c->tags[i] = seltags[i]; |
268 } |
265 } |
269 |
266 |
270 static void |
267 void |
271 arrange(void) { |
268 arrange(void) { |
272 Client *c; |
269 Client *c; |
273 |
270 |
274 for(c = clients; c; c = c->next) |
271 for(c = clients; c; c = c->next) |
275 if(isvisible(c)) |
272 if(isvisible(c)) |
279 layouts[ltidx].arrange(); |
276 layouts[ltidx].arrange(); |
280 focus(NULL); |
277 focus(NULL); |
281 restack(); |
278 restack(); |
282 } |
279 } |
283 |
280 |
284 static void |
281 void |
285 attach(Client *c) { |
282 attach(Client *c) { |
286 if(clients) |
283 if(clients) |
287 clients->prev = c; |
284 clients->prev = c; |
288 c->next = clients; |
285 c->next = clients; |
289 clients = c; |
286 clients = c; |
290 } |
287 } |
291 |
288 |
292 static void |
289 void |
293 attachstack(Client *c) { |
290 attachstack(Client *c) { |
294 c->snext = stack; |
291 c->snext = stack; |
295 stack = c; |
292 stack = c; |
296 } |
293 } |
297 |
294 |
298 static void |
295 void |
299 ban(Client *c) { |
296 ban(Client *c) { |
300 if(c->isbanned) |
297 if(c->isbanned) |
301 return; |
298 return; |
302 XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y); |
299 XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y); |
303 c->isbanned = True; |
300 c->isbanned = True; |
304 } |
301 } |
305 |
302 |
306 static void |
303 void |
307 buttonpress(XEvent *e) { |
304 buttonpress(XEvent *e) { |
308 unsigned int i, x; |
305 unsigned int i, x; |
309 Client *c; |
306 Client *c; |
310 XButtonPressedEvent *ev = &e->xbutton; |
307 XButtonPressedEvent *ev = &e->xbutton; |
311 |
308 |
357 resizemouse(c); |
354 resizemouse(c); |
358 } |
355 } |
359 } |
356 } |
360 } |
357 } |
361 |
358 |
362 static void |
359 void |
363 checkotherwm(void) { |
360 checkotherwm(void) { |
364 otherwm = False; |
361 otherwm = False; |
365 XSetErrorHandler(xerrorstart); |
362 XSetErrorHandler(xerrorstart); |
366 |
363 |
367 /* this causes an error if some other window manager is running */ |
364 /* this causes an error if some other window manager is running */ |
373 XSetErrorHandler(NULL); |
370 XSetErrorHandler(NULL); |
374 xerrorxlib = XSetErrorHandler(xerror); |
371 xerrorxlib = XSetErrorHandler(xerror); |
375 XSync(dpy, False); |
372 XSync(dpy, False); |
376 } |
373 } |
377 |
374 |
378 static void |
375 void |
379 cleanup(void) { |
376 cleanup(void) { |
380 close(STDIN_FILENO); |
377 close(STDIN_FILENO); |
381 while(stack) { |
378 while(stack) { |
382 unban(stack); |
379 unban(stack); |
383 unmanage(stack); |
380 unmanage(stack); |
396 XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); |
393 XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); |
397 XSync(dpy, False); |
394 XSync(dpy, False); |
398 free(seltags); |
395 free(seltags); |
399 } |
396 } |
400 |
397 |
401 static void |
398 void |
402 compileregs(void) { |
399 compileregs(void) { |
403 unsigned int i; |
400 unsigned int i; |
404 regex_t *reg; |
401 regex_t *reg; |
405 |
402 |
406 if(regs) |
403 if(regs) |
423 regs[i].tagregex = reg; |
420 regs[i].tagregex = reg; |
424 } |
421 } |
425 } |
422 } |
426 } |
423 } |
427 |
424 |
428 static void |
425 void |
429 configure(Client *c) { |
426 configure(Client *c) { |
430 XConfigureEvent ce; |
427 XConfigureEvent ce; |
431 |
428 |
432 ce.type = ConfigureNotify; |
429 ce.type = ConfigureNotify; |
433 ce.display = dpy; |
430 ce.display = dpy; |
441 ce.above = None; |
438 ce.above = None; |
442 ce.override_redirect = False; |
439 ce.override_redirect = False; |
443 XSendEvent(dpy, c->win, False, StructureNotifyMask, (XEvent *)&ce); |
440 XSendEvent(dpy, c->win, False, StructureNotifyMask, (XEvent *)&ce); |
444 } |
441 } |
445 |
442 |
446 static void |
443 void |
447 configurenotify(XEvent *e) { |
444 configurenotify(XEvent *e) { |
448 XConfigureEvent *ev = &e->xconfigure; |
445 XConfigureEvent *ev = &e->xconfigure; |
449 |
446 |
450 if (ev->window == root && (ev->width != sw || ev->height != sh)) { |
447 if (ev->window == root && (ev->width != sw || ev->height != sh)) { |
451 sw = ev->width; |
448 sw = ev->width; |
456 updatebarpos(); |
453 updatebarpos(); |
457 arrange(); |
454 arrange(); |
458 } |
455 } |
459 } |
456 } |
460 |
457 |
461 static void |
458 void |
462 configurerequest(XEvent *e) { |
459 configurerequest(XEvent *e) { |
463 Client *c; |
460 Client *c; |
464 XConfigureRequestEvent *ev = &e->xconfigurerequest; |
461 XConfigureRequestEvent *ev = &e->xconfigurerequest; |
465 XWindowChanges wc; |
462 XWindowChanges wc; |
466 |
463 |
501 XConfigureWindow(dpy, ev->window, ev->value_mask, &wc); |
498 XConfigureWindow(dpy, ev->window, ev->value_mask, &wc); |
502 } |
499 } |
503 XSync(dpy, False); |
500 XSync(dpy, False); |
504 } |
501 } |
505 |
502 |
506 static void |
503 void |
507 destroynotify(XEvent *e) { |
504 destroynotify(XEvent *e) { |
508 Client *c; |
505 Client *c; |
509 XDestroyWindowEvent *ev = &e->xdestroywindow; |
506 XDestroyWindowEvent *ev = &e->xdestroywindow; |
510 |
507 |
511 if((c = getclient(ev->window))) |
508 if((c = getclient(ev->window))) |
512 unmanage(c); |
509 unmanage(c); |
513 } |
510 } |
514 |
511 |
515 static void |
512 void |
516 detach(Client *c) { |
513 detach(Client *c) { |
517 if(c->prev) |
514 if(c->prev) |
518 c->prev->next = c->next; |
515 c->prev->next = c->next; |
519 if(c->next) |
516 if(c->next) |
520 c->next->prev = c->prev; |
517 c->next->prev = c->prev; |
521 if(c == clients) |
518 if(c == clients) |
522 clients = c->next; |
519 clients = c->next; |
523 c->next = c->prev = NULL; |
520 c->next = c->prev = NULL; |
524 } |
521 } |
525 |
522 |
526 static void |
523 void |
527 detachstack(Client *c) { |
524 detachstack(Client *c) { |
528 Client **tc; |
525 Client **tc; |
529 |
526 |
530 for(tc=&stack; *tc && *tc != c; tc=&(*tc)->snext); |
527 for(tc=&stack; *tc && *tc != c; tc=&(*tc)->snext); |
531 *tc = c->snext; |
528 *tc = c->snext; |
532 } |
529 } |
533 |
530 |
534 static void |
531 void |
535 drawbar(void) { |
532 drawbar(void) { |
536 int i, x; |
533 int i, x; |
537 |
534 |
538 dc.x = dc.y = 0; |
535 dc.x = dc.y = 0; |
539 for(i = 0; i < ntags; i++) { |
536 for(i = 0; i < ntags; i++) { |
569 } |
566 } |
570 XCopyArea(dpy, dc.drawable, barwin, dc.gc, 0, 0, sw, bh, 0, 0); |
567 XCopyArea(dpy, dc.drawable, barwin, dc.gc, 0, 0, sw, bh, 0, 0); |
571 XSync(dpy, False); |
568 XSync(dpy, False); |
572 } |
569 } |
573 |
570 |
574 static void |
571 void |
575 drawsquare(Bool filled, Bool empty, unsigned long col[ColLast]) { |
572 drawsquare(Bool filled, Bool empty, unsigned long col[ColLast]) { |
576 int x; |
573 int x; |
577 XGCValues gcv; |
574 XGCValues gcv; |
578 XRectangle r = { dc.x, dc.y, dc.w, dc.h }; |
575 XRectangle r = { dc.x, dc.y, dc.w, dc.h }; |
579 |
576 |
590 r.width = r.height = x; |
587 r.width = r.height = x; |
591 XDrawRectangles(dpy, dc.drawable, dc.gc, &r, 1); |
588 XDrawRectangles(dpy, dc.drawable, dc.gc, &r, 1); |
592 } |
589 } |
593 } |
590 } |
594 |
591 |
595 static void |
592 void |
596 drawtext(const char *text, unsigned long col[ColLast]) { |
593 drawtext(const char *text, unsigned long col[ColLast]) { |
597 int x, y, w, h; |
594 int x, y, w, h; |
598 static char buf[256]; |
595 static char buf[256]; |
599 unsigned int len, olen; |
596 unsigned int len, olen; |
600 XRectangle r = { dc.x, dc.y, dc.w, dc.h }; |
597 XRectangle r = { dc.x, dc.y, dc.w, dc.h }; |
630 XmbDrawString(dpy, dc.drawable, dc.font.set, dc.gc, x, y, buf, len); |
627 XmbDrawString(dpy, dc.drawable, dc.font.set, dc.gc, x, y, buf, len); |
631 else |
628 else |
632 XDrawString(dpy, dc.drawable, dc.gc, x, y, buf, len); |
629 XDrawString(dpy, dc.drawable, dc.gc, x, y, buf, len); |
633 } |
630 } |
634 |
631 |
635 static void * |
632 void * |
636 emallocz(unsigned int size) { |
633 emallocz(unsigned int size) { |
637 void *res = calloc(1, size); |
634 void *res = calloc(1, size); |
638 |
635 |
639 if(!res) |
636 if(!res) |
640 eprint("fatal: could not malloc() %u bytes\n", size); |
637 eprint("fatal: could not malloc() %u bytes\n", size); |
641 return res; |
638 return res; |
642 } |
639 } |
643 |
640 |
644 static void |
641 void |
645 enternotify(XEvent *e) { |
642 enternotify(XEvent *e) { |
646 Client *c; |
643 Client *c; |
647 XCrossingEvent *ev = &e->xcrossing; |
644 XCrossingEvent *ev = &e->xcrossing; |
648 |
645 |
649 if(ev->mode != NotifyNormal || ev->detail == NotifyInferior) |
646 if(ev->mode != NotifyNormal || ev->detail == NotifyInferior) |
654 selscreen = True; |
651 selscreen = True; |
655 focus(NULL); |
652 focus(NULL); |
656 } |
653 } |
657 } |
654 } |
658 |
655 |
659 static void |
656 void |
660 eprint(const char *errstr, ...) { |
657 eprint(const char *errstr, ...) { |
661 va_list ap; |
658 va_list ap; |
662 |
659 |
663 va_start(ap, errstr); |
660 va_start(ap, errstr); |
664 vfprintf(stderr, errstr, ap); |
661 vfprintf(stderr, errstr, ap); |
665 va_end(ap); |
662 va_end(ap); |
666 exit(EXIT_FAILURE); |
663 exit(EXIT_FAILURE); |
667 } |
664 } |
668 |
665 |
669 static void |
666 void |
670 expose(XEvent *e) { |
667 expose(XEvent *e) { |
671 XExposeEvent *ev = &e->xexpose; |
668 XExposeEvent *ev = &e->xexpose; |
672 |
669 |
673 if(ev->count == 0) { |
670 if(ev->count == 0) { |
674 if(barwin == ev->window) |
671 if(barwin == ev->window) |
675 drawbar(); |
672 drawbar(); |
676 } |
673 } |
677 } |
674 } |
678 |
675 |
679 static void |
676 void |
680 floating(void) { /* default floating layout */ |
677 floating(void) { /* default floating layout */ |
681 Client *c; |
678 Client *c; |
682 |
679 |
683 for(c = clients; c; c = c->next) |
680 for(c = clients; c; c = c->next) |
684 if(isvisible(c)) |
681 if(isvisible(c)) |
685 resize(c, c->x, c->y, c->w, c->h, True); |
682 resize(c, c->x, c->y, c->w, c->h, True); |
686 } |
683 } |
687 |
684 |
688 static void |
685 void |
689 focus(Client *c) { |
686 focus(Client *c) { |
690 if((!c && selscreen) || (c && !isvisible(c))) |
687 if((!c && selscreen) || (c && !isvisible(c))) |
691 for(c = stack; c && !isvisible(c); c = c->snext); |
688 for(c = stack; c && !isvisible(c); c = c->snext); |
692 if(sel && sel != c) { |
689 if(sel && sel != c) { |
693 grabbuttons(sel, False); |
690 grabbuttons(sel, False); |
708 } |
705 } |
709 else |
706 else |
710 XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); |
707 XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); |
711 } |
708 } |
712 |
709 |
713 static void |
710 void |
714 focusnext(const char *arg) { |
711 focusnext(const char *arg) { |
715 Client *c; |
712 Client *c; |
716 |
713 |
717 if(!sel) |
714 if(!sel) |
718 return; |
715 return; |
723 focus(c); |
720 focus(c); |
724 restack(); |
721 restack(); |
725 } |
722 } |
726 } |
723 } |
727 |
724 |
728 static void |
725 void |
729 focusprev(const char *arg) { |
726 focusprev(const char *arg) { |
730 Client *c; |
727 Client *c; |
731 |
728 |
732 if(!sel) |
729 if(!sel) |
733 return; |
730 return; |
740 focus(c); |
737 focus(c); |
741 restack(); |
738 restack(); |
742 } |
739 } |
743 } |
740 } |
744 |
741 |
745 static Client * |
742 Client * |
746 getclient(Window w) { |
743 getclient(Window w) { |
747 Client *c; |
744 Client *c; |
748 |
745 |
749 for(c = clients; c && c->win != w; c = c->next); |
746 for(c = clients; c && c->win != w; c = c->next); |
750 return c; |
747 return c; |
751 } |
748 } |
752 |
749 |
753 static unsigned long |
750 unsigned long |
754 getcolor(const char *colstr) { |
751 getcolor(const char *colstr) { |
755 Colormap cmap = DefaultColormap(dpy, screen); |
752 Colormap cmap = DefaultColormap(dpy, screen); |
756 XColor color; |
753 XColor color; |
757 |
754 |
758 if(!XAllocNamedColor(dpy, cmap, colstr, &color, &color)) |
755 if(!XAllocNamedColor(dpy, cmap, colstr, &color, &color)) |
759 eprint("error, cannot allocate color '%s'\n", colstr); |
756 eprint("error, cannot allocate color '%s'\n", colstr); |
760 return color.pixel; |
757 return color.pixel; |
761 } |
758 } |
762 |
759 |
763 static long |
760 long |
764 getstate(Window w) { |
761 getstate(Window w) { |
765 int format, status; |
762 int format, status; |
766 long result = -1; |
763 long result = -1; |
767 unsigned char *p = NULL; |
764 unsigned char *p = NULL; |
768 unsigned long n, extra; |
765 unsigned long n, extra; |
776 result = *p; |
773 result = *p; |
777 XFree(p); |
774 XFree(p); |
778 return result; |
775 return result; |
779 } |
776 } |
780 |
777 |
781 static Bool |
778 Bool |
782 gettextprop(Window w, Atom atom, char *text, unsigned int size) { |
779 gettextprop(Window w, Atom atom, char *text, unsigned int size) { |
783 char **list = NULL; |
780 char **list = NULL; |
784 int n; |
781 int n; |
785 XTextProperty name; |
782 XTextProperty name; |
786 |
783 |
803 text[size - 1] = '\0'; |
800 text[size - 1] = '\0'; |
804 XFree(name.value); |
801 XFree(name.value); |
805 return True; |
802 return True; |
806 } |
803 } |
807 |
804 |
808 static void |
805 void |
809 grabbuttons(Client *c, Bool focused) { |
806 grabbuttons(Client *c, Bool focused) { |
810 XUngrabButton(dpy, AnyButton, AnyModifier, c->win); |
807 XUngrabButton(dpy, AnyButton, AnyModifier, c->win); |
811 |
808 |
812 if(focused) { |
809 if(focused) { |
813 XGrabButton(dpy, Button1, MODKEY, c->win, False, BUTTONMASK, |
810 XGrabButton(dpy, Button1, MODKEY, c->win, False, BUTTONMASK, |
840 else |
837 else |
841 XGrabButton(dpy, AnyButton, AnyModifier, c->win, False, BUTTONMASK, |
838 XGrabButton(dpy, AnyButton, AnyModifier, c->win, False, BUTTONMASK, |
842 GrabModeAsync, GrabModeSync, None, None); |
839 GrabModeAsync, GrabModeSync, None, None); |
843 } |
840 } |
844 |
841 |
845 static unsigned int |
842 unsigned int |
846 idxoftag(const char *tag) { |
843 idxoftag(const char *tag) { |
847 unsigned int i; |
844 unsigned int i; |
848 |
845 |
849 for(i = 0; i < ntags; i++) |
846 for(i = 0; i < ntags; i++) |
850 if(tags[i] == tag) |
847 if(tags[i] == tag) |
851 return i; |
848 return i; |
852 return 0; |
849 return 0; |
853 } |
850 } |
854 |
851 |
855 static void |
852 void |
856 initfont(const char *fontstr) { |
853 initfont(const char *fontstr) { |
857 char *def, **missing; |
854 char *def, **missing; |
858 int i, n; |
855 int i, n; |
859 |
856 |
860 missing = NULL; |
857 missing = NULL; |
892 dc.font.descent = dc.font.xfont->descent; |
889 dc.font.descent = dc.font.xfont->descent; |
893 } |
890 } |
894 dc.font.height = dc.font.ascent + dc.font.descent; |
891 dc.font.height = dc.font.ascent + dc.font.descent; |
895 } |
892 } |
896 |
893 |
897 static Bool |
894 Bool |
898 isarrange(void (*func)()) |
895 isarrange(void (*func)()) |
899 { |
896 { |
900 return func == layouts[ltidx].arrange; |
897 return func == layouts[ltidx].arrange; |
901 } |
898 } |
902 |
899 |
903 static Bool |
900 Bool |
904 isoccupied(unsigned int t) { |
901 isoccupied(unsigned int t) { |
905 Client *c; |
902 Client *c; |
906 |
903 |
907 for(c = clients; c; c = c->next) |
904 for(c = clients; c; c = c->next) |
908 if(c->tags[t]) |
905 if(c->tags[t]) |
909 return True; |
906 return True; |
910 return False; |
907 return False; |
911 } |
908 } |
912 |
909 |
913 static Bool |
910 Bool |
914 isprotodel(Client *c) { |
911 isprotodel(Client *c) { |
915 int i, n; |
912 int i, n; |
916 Atom *protocols; |
913 Atom *protocols; |
917 Bool ret = False; |
914 Bool ret = False; |
918 |
915 |
923 XFree(protocols); |
920 XFree(protocols); |
924 } |
921 } |
925 return ret; |
922 return ret; |
926 } |
923 } |
927 |
924 |
928 static Bool |
925 Bool |
929 isvisible(Client *c) { |
926 isvisible(Client *c) { |
930 unsigned int i; |
927 unsigned int i; |
931 |
928 |
932 for(i = 0; i < ntags; i++) |
929 for(i = 0; i < ntags; i++) |
933 if(c->tags[i] && seltags[i]) |
930 if(c->tags[i] && seltags[i]) |
934 return True; |
931 return True; |
935 return False; |
932 return False; |
936 } |
933 } |
937 |
934 |
938 static void |
935 void |
939 keypress(XEvent *e) { |
936 keypress(XEvent *e) { |
940 KEYS |
937 KEYS |
941 unsigned int len = sizeof keys / sizeof keys[0]; |
938 unsigned int len = sizeof keys / sizeof keys[0]; |
942 unsigned int i; |
939 unsigned int i; |
943 KeyCode code; |
940 KeyCode code; |
968 if(keys[i].func) |
965 if(keys[i].func) |
969 keys[i].func(keys[i].arg); |
966 keys[i].func(keys[i].arg); |
970 } |
967 } |
971 } |
968 } |
972 |
969 |
973 static void |
970 void |
974 killclient(const char *arg) { |
971 killclient(const char *arg) { |
975 XEvent ev; |
972 XEvent ev; |
976 |
973 |
977 if(!sel) |
974 if(!sel) |
978 return; |
975 return; |
987 } |
984 } |
988 else |
985 else |
989 XKillClient(dpy, sel->win); |
986 XKillClient(dpy, sel->win); |
990 } |
987 } |
991 |
988 |
992 static void |
989 void |
993 leavenotify(XEvent *e) { |
990 leavenotify(XEvent *e) { |
994 XCrossingEvent *ev = &e->xcrossing; |
991 XCrossingEvent *ev = &e->xcrossing; |
995 |
992 |
996 if((ev->window == root) && !ev->same_screen) { |
993 if((ev->window == root) && !ev->same_screen) { |
997 selscreen = False; |
994 selscreen = False; |
998 focus(NULL); |
995 focus(NULL); |
999 } |
996 } |
1000 } |
997 } |
1001 |
998 |
1002 static void |
999 void |
1003 manage(Window w, XWindowAttributes *wa) { |
1000 manage(Window w, XWindowAttributes *wa) { |
1004 unsigned int i; |
1001 unsigned int i; |
1005 Client *c, *t = NULL; |
1002 Client *c, *t = NULL; |
1006 Window trans; |
1003 Window trans; |
1007 Status rettrans; |
1004 Status rettrans; |
1055 XMapWindow(dpy, c->win); |
1052 XMapWindow(dpy, c->win); |
1056 setclientstate(c, NormalState); |
1053 setclientstate(c, NormalState); |
1057 arrange(); |
1054 arrange(); |
1058 } |
1055 } |
1059 |
1056 |
1060 static void |
1057 void |
1061 mappingnotify(XEvent *e) { |
1058 mappingnotify(XEvent *e) { |
1062 XMappingEvent *ev = &e->xmapping; |
1059 XMappingEvent *ev = &e->xmapping; |
1063 |
1060 |
1064 XRefreshKeyboardMapping(ev); |
1061 XRefreshKeyboardMapping(ev); |
1065 if(ev->request == MappingKeyboard) |
1062 if(ev->request == MappingKeyboard) |
1066 keypress(NULL); |
1063 keypress(NULL); |
1067 } |
1064 } |
1068 |
1065 |
1069 static void |
1066 void |
1070 maprequest(XEvent *e) { |
1067 maprequest(XEvent *e) { |
1071 static XWindowAttributes wa; |
1068 static XWindowAttributes wa; |
1072 XMapRequestEvent *ev = &e->xmaprequest; |
1069 XMapRequestEvent *ev = &e->xmaprequest; |
1073 |
1070 |
1074 if(!XGetWindowAttributes(dpy, ev->window, &wa)) |
1071 if(!XGetWindowAttributes(dpy, ev->window, &wa)) |
1077 return; |
1074 return; |
1078 if(!getclient(ev->window)) |
1075 if(!getclient(ev->window)) |
1079 manage(ev->window, &wa); |
1076 manage(ev->window, &wa); |
1080 } |
1077 } |
1081 |
1078 |
1082 static void |
1079 void |
1083 movemouse(Client *c) { |
1080 movemouse(Client *c) { |
1084 int x1, y1, ocx, ocy, di, nx, ny; |
1081 int x1, y1, ocx, ocy, di, nx, ny; |
1085 unsigned int dui; |
1082 unsigned int dui; |
1086 Window dummy; |
1083 Window dummy; |
1087 XEvent ev; |
1084 XEvent ev; |
1120 break; |
1117 break; |
1121 } |
1118 } |
1122 } |
1119 } |
1123 } |
1120 } |
1124 |
1121 |
1125 static Client * |
1122 Client * |
1126 nexttiled(Client *c) { |
1123 nexttiled(Client *c) { |
1127 for(; c && (c->isfloating || !isvisible(c)); c = c->next); |
1124 for(; c && (c->isfloating || !isvisible(c)); c = c->next); |
1128 return c; |
1125 return c; |
1129 } |
1126 } |
1130 |
1127 |
1131 static void |
1128 void |
1132 propertynotify(XEvent *e) { |
1129 propertynotify(XEvent *e) { |
1133 Client *c; |
1130 Client *c; |
1134 Window trans; |
1131 Window trans; |
1135 XPropertyEvent *ev = &e->xproperty; |
1132 XPropertyEvent *ev = &e->xproperty; |
1136 |
1133 |
1154 drawbar(); |
1151 drawbar(); |
1155 } |
1152 } |
1156 } |
1153 } |
1157 } |
1154 } |
1158 |
1155 |
1159 static void |
1156 void |
1160 quit(const char *arg) { |
1157 quit(const char *arg) { |
1161 readin = running = False; |
1158 readin = running = False; |
1162 } |
1159 } |
1163 |
1160 |
1164 static void |
1161 void |
1165 resize(Client *c, int x, int y, int w, int h, Bool sizehints) { |
1162 resize(Client *c, int x, int y, int w, int h, Bool sizehints) { |
1166 double dx, dy, max, min, ratio; |
1163 double dx, dy, max, min, ratio; |
1167 XWindowChanges wc; |
1164 XWindowChanges wc; |
1168 |
1165 |
1169 if(sizehints) { |
1166 if(sizehints) { |
1222 configure(c); |
1219 configure(c); |
1223 XSync(dpy, False); |
1220 XSync(dpy, False); |
1224 } |
1221 } |
1225 } |
1222 } |
1226 |
1223 |
1227 static void |
1224 void |
1228 resizemouse(Client *c) { |
1225 resizemouse(Client *c) { |
1229 int ocx, ocy; |
1226 int ocx, ocy; |
1230 int nw, nh; |
1227 int nw, nh; |
1231 XEvent ev; |
1228 XEvent ev; |
1232 |
1229 |
1261 break; |
1258 break; |
1262 } |
1259 } |
1263 } |
1260 } |
1264 } |
1261 } |
1265 |
1262 |
1266 static void |
1263 void |
1267 restack(void) { |
1264 restack(void) { |
1268 Client *c; |
1265 Client *c; |
1269 XEvent ev; |
1266 XEvent ev; |
1270 XWindowChanges wc; |
1267 XWindowChanges wc; |
1271 |
1268 |
1290 } |
1287 } |
1291 XSync(dpy, False); |
1288 XSync(dpy, False); |
1292 while(XCheckMaskEvent(dpy, EnterWindowMask, &ev)); |
1289 while(XCheckMaskEvent(dpy, EnterWindowMask, &ev)); |
1293 } |
1290 } |
1294 |
1291 |
1295 static void |
1292 void |
1296 run(void) { |
1293 run(void) { |
1297 char *p; |
1294 char *p; |
1298 int r, xfd; |
1295 int r, xfd; |
1299 fd_set rd; |
1296 fd_set rd; |
1300 XEvent ev; |
1297 XEvent ev; |
1338 (handler[ev.type])(&ev); /* call handler */ |
1335 (handler[ev.type])(&ev); /* call handler */ |
1339 } |
1336 } |
1340 } |
1337 } |
1341 } |
1338 } |
1342 |
1339 |
1343 static void |
1340 void |
1344 scan(void) { |
1341 scan(void) { |
1345 unsigned int i, num; |
1342 unsigned int i, num; |
1346 Window *wins, d1, d2; |
1343 Window *wins, d1, d2; |
1347 XWindowAttributes wa; |
1344 XWindowAttributes wa; |
1348 |
1345 |
1365 } |
1362 } |
1366 if(wins) |
1363 if(wins) |
1367 XFree(wins); |
1364 XFree(wins); |
1368 } |
1365 } |
1369 |
1366 |
1370 static void |
1367 void |
1371 setclientstate(Client *c, long state) { |
1368 setclientstate(Client *c, long state) { |
1372 long data[] = {state, None}; |
1369 long data[] = {state, None}; |
1373 |
1370 |
1374 XChangeProperty(dpy, c->win, wmatom[WMState], wmatom[WMState], 32, |
1371 XChangeProperty(dpy, c->win, wmatom[WMState], wmatom[WMState], 32, |
1375 PropModeReplace, (unsigned char *)data, 2); |
1372 PropModeReplace, (unsigned char *)data, 2); |
1376 } |
1373 } |
1377 |
1374 |
1378 static void |
1375 void |
1379 setlayout(const char *arg) { |
1376 setlayout(const char *arg) { |
1380 unsigned int i; |
1377 unsigned int i; |
1381 |
1378 |
1382 if(!arg) { |
1379 if(!arg) { |
1383 if(++ltidx == nlayouts) |
1380 if(++ltidx == nlayouts) |
1395 arrange(); |
1392 arrange(); |
1396 else |
1393 else |
1397 drawbar(); |
1394 drawbar(); |
1398 } |
1395 } |
1399 |
1396 |
1400 static void |
1397 void |
1401 setmwfact(const char *arg) { |
1398 setmwfact(const char *arg) { |
1402 double delta; |
1399 double delta; |
1403 |
1400 |
1404 if(!isarrange(tile)) |
1401 if(!isarrange(tile)) |
1405 return; |
1402 return; |
1417 mwfact = 0.9; |
1414 mwfact = 0.9; |
1418 } |
1415 } |
1419 arrange(); |
1416 arrange(); |
1420 } |
1417 } |
1421 |
1418 |
1422 static void |
1419 void |
1423 setup(void) { |
1420 setup(void) { |
1424 unsigned int i, j, mask; |
1421 unsigned int i, j, mask; |
1425 Window w; |
1422 Window w; |
1426 XModifierKeymap *modmap; |
1423 XModifierKeymap *modmap; |
1427 XSetWindowAttributes wa; |
1424 XSetWindowAttributes wa; |
1511 |
1508 |
1512 /* multihead support */ |
1509 /* multihead support */ |
1513 selscreen = XQueryPointer(dpy, root, &w, &w, &i, &i, &i, &i, &mask); |
1510 selscreen = XQueryPointer(dpy, root, &w, &w, &i, &i, &i, &i, &mask); |
1514 } |
1511 } |
1515 |
1512 |
1516 static void |
1513 void |
1517 spawn(const char *arg) { |
1514 spawn(const char *arg) { |
1518 static char *shell = NULL; |
1515 static char *shell = NULL; |
1519 |
1516 |
1520 if(!shell && !(shell = getenv("SHELL"))) |
1517 if(!shell && !(shell = getenv("SHELL"))) |
1521 shell = "/bin/sh"; |
1518 shell = "/bin/sh"; |
1535 exit(0); |
1532 exit(0); |
1536 } |
1533 } |
1537 wait(0); |
1534 wait(0); |
1538 } |
1535 } |
1539 |
1536 |
1540 static void |
1537 void |
1541 tag(const char *arg) { |
1538 tag(const char *arg) { |
1542 unsigned int i; |
1539 unsigned int i; |
1543 |
1540 |
1544 if(!sel) |
1541 if(!sel) |
1545 return; |
1542 return; |
1549 if(i >= 0 && i < ntags) |
1546 if(i >= 0 && i < ntags) |
1550 sel->tags[i] = True; |
1547 sel->tags[i] = True; |
1551 arrange(); |
1548 arrange(); |
1552 } |
1549 } |
1553 |
1550 |
1554 static unsigned int |
1551 unsigned int |
1555 textnw(const char *text, unsigned int len) { |
1552 textnw(const char *text, unsigned int len) { |
1556 XRectangle r; |
1553 XRectangle r; |
1557 |
1554 |
1558 if(dc.font.set) { |
1555 if(dc.font.set) { |
1559 XmbTextExtents(dc.font.set, text, len, NULL, &r); |
1556 XmbTextExtents(dc.font.set, text, len, NULL, &r); |
1560 return r.width; |
1557 return r.width; |
1561 } |
1558 } |
1562 return XTextWidth(dc.font.xfont, text, len); |
1559 return XTextWidth(dc.font.xfont, text, len); |
1563 } |
1560 } |
1564 |
1561 |
1565 static unsigned int |
1562 unsigned int |
1566 textw(const char *text) { |
1563 textw(const char *text) { |
1567 return textnw(text, strlen(text)) + dc.font.height; |
1564 return textnw(text, strlen(text)) + dc.font.height; |
1568 } |
1565 } |
1569 |
1566 |
1570 static void |
1567 void |
1571 tile(void) { |
1568 tile(void) { |
1572 unsigned int i, n, nx, ny, nw, nh, mw, th; |
1569 unsigned int i, n, nx, ny, nw, nh, mw, th; |
1573 Client *c; |
1570 Client *c; |
1574 |
1571 |
1575 for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next)) |
1572 for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next)) |
1604 if(n > 1 && th != wah) |
1601 if(n > 1 && th != wah) |
1605 ny += nh + 2 * c->border; |
1602 ny += nh + 2 * c->border; |
1606 } |
1603 } |
1607 } |
1604 } |
1608 |
1605 |
1609 static void |
1606 void |
1610 togglebar(const char *arg) { |
1607 togglebar(const char *arg) { |
1611 if(bpos == BarOff) |
1608 if(bpos == BarOff) |
1612 bpos = (BARPOS == BarOff) ? BarTop : BARPOS; |
1609 bpos = (BARPOS == BarOff) ? BarTop : BARPOS; |
1613 else |
1610 else |
1614 bpos = BarOff; |
1611 bpos = BarOff; |
1615 updatebarpos(); |
1612 updatebarpos(); |
1616 arrange(); |
1613 arrange(); |
1617 } |
1614 } |
1618 |
1615 |
1619 static void |
1616 void |
1620 togglefloating(const char *arg) { |
1617 togglefloating(const char *arg) { |
1621 if(!sel) |
1618 if(!sel) |
1622 return; |
1619 return; |
1623 sel->isfloating = !sel->isfloating; |
1620 sel->isfloating = !sel->isfloating; |
1624 if(sel->isfloating) |
1621 if(sel->isfloating) |
1625 resize(sel, sel->x, sel->y, sel->w, sel->h, True); |
1622 resize(sel, sel->x, sel->y, sel->w, sel->h, True); |
1626 arrange(); |
1623 arrange(); |
1627 } |
1624 } |
1628 |
1625 |
1629 static void |
1626 void |
1630 togglemax(const char *arg) { |
1627 togglemax(const char *arg) { |
1631 XEvent ev; |
1628 XEvent ev; |
1632 |
1629 |
1633 if(!sel || (!isarrange(floating) && !sel->isfloating) || sel->isfixed) |
1630 if(!sel || (!isarrange(floating) && !sel->isfloating) || sel->isfixed) |
1634 return; |
1631 return; |
1643 resize(sel, sel->rx, sel->ry, sel->rw, sel->rh, True); |
1640 resize(sel, sel->rx, sel->ry, sel->rw, sel->rh, True); |
1644 drawbar(); |
1641 drawbar(); |
1645 while(XCheckMaskEvent(dpy, EnterWindowMask, &ev)); |
1642 while(XCheckMaskEvent(dpy, EnterWindowMask, &ev)); |
1646 } |
1643 } |
1647 |
1644 |
1648 static void |
1645 void |
1649 toggletag(const char *arg) { |
1646 toggletag(const char *arg) { |
1650 unsigned int i, j; |
1647 unsigned int i, j; |
1651 |
1648 |
1652 if(!sel) |
1649 if(!sel) |
1653 return; |
1650 return; |
1657 if(j == ntags) |
1654 if(j == ntags) |
1658 sel->tags[i] = True; |
1655 sel->tags[i] = True; |
1659 arrange(); |
1656 arrange(); |
1660 } |
1657 } |
1661 |
1658 |
1662 static void |
1659 void |
1663 toggleview(const char *arg) { |
1660 toggleview(const char *arg) { |
1664 unsigned int i, j; |
1661 unsigned int i, j; |
1665 |
1662 |
1666 i = idxoftag(arg); |
1663 i = idxoftag(arg); |
1667 seltags[i] = !seltags[i]; |
1664 seltags[i] = !seltags[i]; |
1669 if(j == ntags) |
1666 if(j == ntags) |
1670 seltags[i] = True; /* cannot toggle last view */ |
1667 seltags[i] = True; /* cannot toggle last view */ |
1671 arrange(); |
1668 arrange(); |
1672 } |
1669 } |
1673 |
1670 |
1674 static void |
1671 void |
1675 unban(Client *c) { |
1672 unban(Client *c) { |
1676 if(!c->isbanned) |
1673 if(!c->isbanned) |
1677 return; |
1674 return; |
1678 XMoveWindow(dpy, c->win, c->x, c->y); |
1675 XMoveWindow(dpy, c->win, c->x, c->y); |
1679 c->isbanned = False; |
1676 c->isbanned = False; |
1680 } |
1677 } |
1681 |
1678 |
1682 static void |
1679 void |
1683 unmanage(Client *c) { |
1680 unmanage(Client *c) { |
1684 XWindowChanges wc; |
1681 XWindowChanges wc; |
1685 |
1682 |
1686 wc.border_width = c->oldborder; |
1683 wc.border_width = c->oldborder; |
1687 /* The server grab construct avoids race conditions. */ |
1684 /* The server grab construct avoids race conditions. */ |
1700 XSetErrorHandler(xerror); |
1697 XSetErrorHandler(xerror); |
1701 XUngrabServer(dpy); |
1698 XUngrabServer(dpy); |
1702 arrange(); |
1699 arrange(); |
1703 } |
1700 } |
1704 |
1701 |
1705 static void |
1702 void |
1706 unmapnotify(XEvent *e) { |
1703 unmapnotify(XEvent *e) { |
1707 Client *c; |
1704 Client *c; |
1708 XUnmapEvent *ev = &e->xunmap; |
1705 XUnmapEvent *ev = &e->xunmap; |
1709 |
1706 |
1710 if((c = getclient(ev->window))) |
1707 if((c = getclient(ev->window))) |
1711 unmanage(c); |
1708 unmanage(c); |
1712 } |
1709 } |
1713 |
1710 |
1714 static void |
1711 void |
1715 updatebarpos(void) { |
1712 updatebarpos(void) { |
1716 XEvent ev; |
1713 XEvent ev; |
1717 |
1714 |
1718 wax = sx; |
1715 wax = sx; |
1719 way = sy; |
1716 way = sy; |
1735 } |
1732 } |
1736 XSync(dpy, False); |
1733 XSync(dpy, False); |
1737 while(XCheckMaskEvent(dpy, EnterWindowMask, &ev)); |
1734 while(XCheckMaskEvent(dpy, EnterWindowMask, &ev)); |
1738 } |
1735 } |
1739 |
1736 |
1740 static void |
1737 void |
1741 updatesizehints(Client *c) { |
1738 updatesizehints(Client *c) { |
1742 long msize; |
1739 long msize; |
1743 XSizeHints size; |
1740 XSizeHints size; |
1744 |
1741 |
1745 if(!XGetWMNormalHints(dpy, c->win, &size, &msize) || !size.flags) |
1742 if(!XGetWMNormalHints(dpy, c->win, &size, &msize) || !size.flags) |
1787 c->minax = c->maxax = c->minay = c->maxay = 0; |
1784 c->minax = c->maxax = c->minay = c->maxay = 0; |
1788 c->isfixed = (c->maxw && c->minw && c->maxh && c->minh |
1785 c->isfixed = (c->maxw && c->minw && c->maxh && c->minh |
1789 && c->maxw == c->minw && c->maxh == c->minh); |
1786 && c->maxw == c->minw && c->maxh == c->minh); |
1790 } |
1787 } |
1791 |
1788 |
1792 static void |
1789 void |
1793 updatetitle(Client *c) { |
1790 updatetitle(Client *c) { |
1794 if(!gettextprop(c->win, netatom[NetWMName], c->name, sizeof c->name)) |
1791 if(!gettextprop(c->win, netatom[NetWMName], c->name, sizeof c->name)) |
1795 gettextprop(c->win, wmatom[WMName], c->name, sizeof c->name); |
1792 gettextprop(c->win, wmatom[WMName], c->name, sizeof c->name); |
1796 } |
1793 } |
1797 |
1794 |
1798 /* There's no way to check accesses to destroyed windows, thus those cases are |
1795 /* There's no way to check accesses to destroyed windows, thus those cases are |
1799 * ignored (especially on UnmapNotify's). Other types of errors call Xlibs |
1796 * ignored (especially on UnmapNotify's). Other types of errors call Xlibs |
1800 * default error handler, which may call exit. */ |
1797 * default error handler, which may call exit. */ |
1801 static int |
1798 int |
1802 xerror(Display *dpy, XErrorEvent *ee) { |
1799 xerror(Display *dpy, XErrorEvent *ee) { |
1803 if(ee->error_code == BadWindow |
1800 if(ee->error_code == BadWindow |
1804 || (ee->request_code == X_SetInputFocus && ee->error_code == BadMatch) |
1801 || (ee->request_code == X_SetInputFocus && ee->error_code == BadMatch) |
1805 || (ee->request_code == X_PolyText8 && ee->error_code == BadDrawable) |
1802 || (ee->request_code == X_PolyText8 && ee->error_code == BadDrawable) |
1806 || (ee->request_code == X_PolyFillRectangle && ee->error_code == BadDrawable) |
1803 || (ee->request_code == X_PolyFillRectangle && ee->error_code == BadDrawable) |
1812 fprintf(stderr, "dwm: fatal error: request code=%d, error code=%d\n", |
1809 fprintf(stderr, "dwm: fatal error: request code=%d, error code=%d\n", |
1813 ee->request_code, ee->error_code); |
1810 ee->request_code, ee->error_code); |
1814 return xerrorxlib(dpy, ee); /* may call exit */ |
1811 return xerrorxlib(dpy, ee); /* may call exit */ |
1815 } |
1812 } |
1816 |
1813 |
1817 static int |
1814 int |
1818 xerrordummy(Display *dsply, XErrorEvent *ee) { |
1815 xerrordummy(Display *dsply, XErrorEvent *ee) { |
1819 return 0; |
1816 return 0; |
1820 } |
1817 } |
1821 |
1818 |
1822 /* Startup Error handler to check if another window manager |
1819 /* Startup Error handler to check if another window manager |
1823 * is already running. */ |
1820 * is already running. */ |
1824 static int |
1821 int |
1825 xerrorstart(Display *dsply, XErrorEvent *ee) { |
1822 xerrorstart(Display *dsply, XErrorEvent *ee) { |
1826 otherwm = True; |
1823 otherwm = True; |
1827 return -1; |
1824 return -1; |
1828 } |
1825 } |
1829 |
1826 |
1830 static void |
1827 void |
1831 view(const char *arg) { |
1828 view(const char *arg) { |
1832 unsigned int i; |
1829 unsigned int i; |
1833 |
1830 |
1834 for(i = 0; i < ntags; i++) |
1831 for(i = 0; i < ntags; i++) |
1835 seltags[i] = arg == NULL; |
1832 seltags[i] = arg == NULL; |
1837 if(i >= 0 && i < ntags) |
1834 if(i >= 0 && i < ntags) |
1838 seltags[i] = True; |
1835 seltags[i] = True; |
1839 arrange(); |
1836 arrange(); |
1840 } |
1837 } |
1841 |
1838 |
1842 static void |
1839 void |
1843 zoom(const char *arg) { |
1840 zoom(const char *arg) { |
1844 Client *c; |
1841 Client *c; |
1845 |
1842 |
1846 if(!sel || !isarrange(tile) || sel->isfloating) |
1843 if(!sel || !isarrange(tile) || sel->isfloating) |
1847 return; |
1844 return; |