9 #include <X11/Xatom.h> |
9 #include <X11/Xatom.h> |
10 #include <X11/Xutil.h> |
10 #include <X11/Xutil.h> |
11 |
11 |
12 #include "dwm.h" |
12 #include "dwm.h" |
13 |
13 |
14 static void (*arrange)(void *) = floating; |
14 static void (*arrange)(Arg *) = floating; |
15 |
15 |
16 void |
16 static Client * |
17 max(void *aux) |
17 next(Client *c) |
18 { |
18 { |
19 if(!stack) |
19 for(c = c->next; c && !c->tags[tsel]; c = c->next); |
20 return; |
20 return c; |
21 stack->x = sx; |
21 } |
22 stack->y = sy; |
22 |
23 stack->w = sw - 2 * stack->border; |
23 static Client * |
24 stack->h = sh - 2 * stack->border; |
24 prev(Client *c) |
25 craise(stack); |
25 { |
26 resize(stack); |
26 for(c = c->prev; c && !c->tags[tsel]; c = c->prev); |
|
27 return c; |
|
28 } |
|
29 |
|
30 void |
|
31 max(Arg *arg) |
|
32 { |
|
33 if(!csel) |
|
34 return; |
|
35 csel->x = sx; |
|
36 csel->y = sy; |
|
37 csel->w = sw - 2 * csel->border; |
|
38 csel->h = sh - 2 * csel->border; |
|
39 craise(csel); |
|
40 resize(csel); |
27 discard_events(EnterWindowMask); |
41 discard_events(EnterWindowMask); |
28 } |
42 } |
29 |
43 |
30 void |
44 void |
31 floating(void *aux) |
45 tag(Arg *arg) |
|
46 { |
|
47 if(!csel) |
|
48 return; |
|
49 |
|
50 if(arg->i == tsel) |
|
51 return; |
|
52 |
|
53 if(csel->tags[arg->i]) |
|
54 csel->tags[arg->i] = NULL; /* toggle tag */ |
|
55 else |
|
56 csel->tags[arg->i] = tags[arg->i]; |
|
57 arrange(NULL); |
|
58 } |
|
59 |
|
60 void |
|
61 floating(Arg *arg) |
32 { |
62 { |
33 Client *c; |
63 Client *c; |
34 |
64 |
35 arrange = floating; |
65 arrange = floating; |
36 for(c = stack; c; c = c->snext) |
66 if(!csel) |
|
67 return; |
|
68 for(c = csel; c; c = next(c)) |
37 resize(c); |
69 resize(c); |
38 discard_events(EnterWindowMask); |
70 discard_events(EnterWindowMask); |
39 } |
71 } |
40 |
72 |
41 void |
73 void |
42 tiling(void *aux) |
74 tiling(Arg *arg) |
43 { |
75 { |
44 Client *c; |
76 Client *c; |
45 int n, cols, rows, gw, gh, i, j; |
77 int n, cols, rows, gw, gh, i, j; |
46 float rt, fd; |
78 float rt, fd; |
47 |
79 |
48 arrange = tiling; |
80 arrange = tiling; |
49 if(!clients) |
81 if(!csel) |
50 return; |
82 return; |
51 for(n = 0, c = clients; c; c = c->next, n++); |
83 for(n = 0, c = csel; c; c = next(c), n++); |
52 rt = sqrt(n); |
84 rt = sqrt(n); |
53 if(modff(rt, &fd) < 0.5) |
85 if(modff(rt, &fd) < 0.5) |
54 rows = floor(rt); |
86 rows = floor(rt); |
55 else |
87 else |
56 rows = ceil(rt); |
88 rows = ceil(rt); |
75 } |
107 } |
76 discard_events(EnterWindowMask); |
108 discard_events(EnterWindowMask); |
77 } |
109 } |
78 |
110 |
79 void |
111 void |
80 sel(void *aux) |
112 prevc(Arg *arg) |
81 { |
113 { |
82 const char *arg = aux; |
114 Client *c; |
83 Client *c = NULL; |
115 |
84 |
116 if(!csel) |
85 if(!arg || !stack) |
117 return; |
86 return; |
118 |
87 if(!strncmp(arg, "next", 5)) |
119 if(!(c = prev(csel))) |
88 c = stack->snext ? stack->snext : stack; |
120 c = prev(cend); |
89 else if(!strncmp(arg, "prev", 5)) |
121 if(c) { |
90 for(c = stack; c && c->snext; c = c->snext); |
122 craise(c); |
91 if(!c) |
123 XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w / 2, c->h / 2); |
92 c = stack; |
124 focus(c); |
93 craise(c); |
125 } |
94 XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w / 2, c->h / 2); |
126 } |
95 focus(c); |
127 |
96 } |
128 void |
97 |
129 nextc(Arg *arg) |
98 void |
130 { |
99 ckill(void *aux) |
131 Client *c; |
100 { |
132 |
101 Client *c = stack; |
133 if(!csel) |
|
134 return; |
|
135 |
|
136 if(!(c = next(csel))) |
|
137 c = next(cstart); |
|
138 |
|
139 if(c) { |
|
140 craise(c); |
|
141 XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w / 2, c->h / 2); |
|
142 focus(c); |
|
143 } |
|
144 } |
|
145 |
|
146 void |
|
147 ckill(Arg *arg) |
|
148 { |
|
149 Client *c = csel; |
102 |
150 |
103 if(!c) |
151 if(!c) |
104 return; |
152 return; |
105 if(c->proto & WM_PROTOCOL_DELWIN) |
153 if(c->proto & WM_PROTOCOL_DELWIN) |
106 send_message(c->win, wm_atom[WMProtocols], wm_atom[WMDelete]); |
154 send_message(c->win, wm_atom[WMProtocols], wm_atom[WMDelete]); |
206 } |
254 } |
207 |
255 |
208 void |
256 void |
209 focus(Client *c) |
257 focus(Client *c) |
210 { |
258 { |
211 Client **l, *old; |
259 if(csel && csel != c) { |
212 |
260 XSetWindowBorder(dpy, csel->win, dc.bg); |
213 old = stack; |
261 XMapWindow(dpy, csel->title); |
214 for(l = &stack; *l && *l != c; l = &(*l)->snext); |
262 draw_client(csel); |
215 if(*l) |
263 } |
216 *l = c->snext; |
264 csel = c; |
217 c->snext = stack; |
|
218 stack = c; |
|
219 if(old && old != c) { |
|
220 XSetWindowBorder(dpy, old->win, dc.bg); |
|
221 XMapWindow(dpy, old->title); |
|
222 draw_client(old); |
|
223 } |
|
224 XUnmapWindow(dpy, c->title); |
265 XUnmapWindow(dpy, c->title); |
225 XSetWindowBorder(dpy, c->win, dc.fg); |
266 XSetWindowBorder(dpy, c->win, dc.fg); |
226 draw_client(c); |
267 draw_client(c); |
227 XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); |
268 XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); |
228 XFlush(dpy); |
269 XFlush(dpy); |
256 0, DefaultDepth(dpy, screen), CopyFromParent, |
297 0, DefaultDepth(dpy, screen), CopyFromParent, |
257 DefaultVisual(dpy, screen), |
298 DefaultVisual(dpy, screen), |
258 CWOverrideRedirect | CWBackPixmap | CWEventMask, &twa); |
299 CWOverrideRedirect | CWBackPixmap | CWEventMask, &twa); |
259 |
300 |
260 update_name(c); |
301 update_name(c); |
261 for(l=&clients; *l; l=&(*l)->next); |
302 |
262 c->next = *l; /* *l == nil */ |
303 if(!cstart) |
263 *l = c; |
304 cstart = cend = c; |
|
305 else { |
|
306 cend->next = c; |
|
307 c->prev = cend; |
|
308 cend = c; |
|
309 } |
|
310 |
264 XSetWindowBorderWidth(dpy, c->win, 1); |
311 XSetWindowBorderWidth(dpy, c->win, 1); |
265 XMapRaised(dpy, c->win); |
312 XMapRaised(dpy, c->win); |
266 XMapRaised(dpy, c->title); |
313 XMapRaised(dpy, c->title); |
267 XGrabButton(dpy, Button1, Mod1Mask, c->win, False, ButtonPressMask, |
314 XGrabButton(dpy, Button1, Mod1Mask, c->win, False, ButtonPressMask, |
268 GrabModeAsync, GrabModeSync, None, None); |
315 GrabModeAsync, GrabModeSync, None, None); |
371 } |
418 } |
372 |
419 |
373 void |
420 void |
374 unmanage(Client *c) |
421 unmanage(Client *c) |
375 { |
422 { |
376 Client **l; |
|
377 |
|
378 XGrabServer(dpy); |
423 XGrabServer(dpy); |
379 XSetErrorHandler(dummy_error_handler); |
424 XSetErrorHandler(dummy_error_handler); |
380 |
425 |
381 XUngrabButton(dpy, AnyButton, AnyModifier, c->win); |
426 XUngrabButton(dpy, AnyButton, AnyModifier, c->win); |
382 XDestroyWindow(dpy, c->title); |
427 XDestroyWindow(dpy, c->title); |
383 |
428 |
384 for(l=&clients; *l && *l != c; l=&(*l)->next); |
429 if(c->prev) { |
385 *l = c->next; |
430 c->prev->next = c->next; |
386 for(l=&stack; *l && *l != c; l=&(*l)->snext); |
431 if(csel == c) |
387 *l = c->snext; |
432 csel = c->prev; |
|
433 } |
|
434 if(c->next) { |
|
435 c->next->prev = c->prev; |
|
436 if(csel == c) |
|
437 csel = c->next; |
|
438 } |
|
439 if(cstart == c) |
|
440 cstart = c->next; |
|
441 if(cend == c) |
|
442 cend = c->prev; |
|
443 |
388 free(c); |
444 free(c); |
389 |
445 |
390 XFlush(dpy); |
446 XFlush(dpy); |
391 XSetErrorHandler(error_handler); |
447 XSetErrorHandler(error_handler); |
392 XUngrabServer(dpy); |
448 XUngrabServer(dpy); |
393 arrange(NULL); |
449 arrange(NULL); |
394 if(stack) |
450 if(csel) |
395 focus(stack); |
451 focus(csel); |
396 } |
452 } |
397 |
453 |
398 Client * |
454 Client * |
399 gettitle(Window w) |
455 gettitle(Window w) |
400 { |
456 { |
401 Client *c; |
457 Client *c; |
402 for(c = clients; c; c = c->next) |
458 for(c = cstart; c; c = c->next) |
403 if(c->title == w) |
459 if(c->title == w) |
404 return c; |
460 return c; |
405 return NULL; |
461 return NULL; |
406 } |
462 } |
407 |
463 |
408 Client * |
464 Client * |
409 getclient(Window w) |
465 getclient(Window w) |
410 { |
466 { |
411 Client *c; |
467 Client *c; |
412 for(c = clients; c; c = c->next) |
468 for(c = cstart; c; c = c->next) |
413 if(c->win == w) |
469 if(c->win == w) |
414 return c; |
470 return c; |
415 return NULL; |
471 return NULL; |
416 } |
472 } |
417 |
473 |
418 void |
474 void |
419 draw_client(Client *c) |
475 draw_client(Client *c) |
420 { |
476 { |
421 int i; |
477 int i; |
422 if(c == stack) |
478 if(c == csel) |
423 return; |
479 return; |
424 |
480 |
425 dc.x = dc.y = 0; |
481 dc.x = dc.y = 0; |
426 dc.h = c->th; |
482 dc.h = c->th; |
427 |
483 |