Mercurial > aewl
comparison client.c @ 50:148f25ed0ad7
several other additions/fixes, dwm is quite usable already
author | Anselm R. Garbe <garbeam@wmii.de> |
---|---|
date | Thu, 13 Jul 2006 18:21:38 +0200 |
parents | 466591c2f967 |
children | 035617ee18d1 |
comparison
equal
deleted
inserted
replaced
49:466591c2f967 | 50:148f25ed0ad7 |
---|---|
11 | 11 |
12 #include "dwm.h" | 12 #include "dwm.h" |
13 | 13 |
14 static void (*arrange)(Arg *) = floating; | 14 static void (*arrange)(Arg *) = floating; |
15 | 15 |
16 static void | |
17 center(Client *c) | |
18 { | |
19 XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w / 2, c->h / 2); | |
20 } | |
21 | |
16 static Client * | 22 static Client * |
17 next(Client *c) | 23 next(Client *c) |
18 { | 24 { |
19 for(c = c->next; c && !c->tags[tsel]; c = c->next); | 25 for(; c && !c->tags[tsel]; c = c->next); |
20 return c; | 26 return c; |
21 } | 27 } |
22 | 28 |
23 static Client * | 29 void |
24 prev(Client *c) | 30 zoom(Arg *arg) |
25 { | 31 { |
26 for(c = c->prev; c && !c->tags[tsel]; c = c->prev); | 32 Client **l; |
27 return c; | 33 |
34 if(!sel) | |
35 return; | |
36 | |
37 for(l = &clients; *l && *l != sel; l = &(*l)->next); | |
38 *l = sel->next; | |
39 | |
40 sel->next = clients; /* pop */ | |
41 clients = sel; | |
42 arrange(NULL); | |
43 center(sel); | |
44 focus(sel); | |
28 } | 45 } |
29 | 46 |
30 void | 47 void |
31 max(Arg *arg) | 48 max(Arg *arg) |
32 { | 49 { |
33 if(!csel) | 50 if(!sel) |
34 return; | 51 return; |
35 csel->x = sx; | 52 sel->x = sx; |
36 csel->y = sy; | 53 sel->y = sy; |
37 csel->w = sw - 2 * csel->border; | 54 sel->w = sw - 2 * sel->border; |
38 csel->h = sh - 2 * csel->border; | 55 sel->h = sh - 2 * sel->border; |
39 craise(csel); | 56 craise(sel); |
40 resize(csel); | 57 resize(sel); |
41 discard_events(EnterWindowMask); | 58 discard_events(EnterWindowMask); |
42 } | 59 } |
43 | 60 |
44 void | 61 void |
62 view(Arg *arg) | |
63 { | |
64 tsel = arg->i; | |
65 arrange(NULL); | |
66 } | |
67 | |
68 void | |
45 tag(Arg *arg) | 69 tag(Arg *arg) |
46 { | 70 { |
47 if(!csel) | 71 int i, n; |
48 return; | 72 if(!sel) |
49 | 73 return; |
50 if(arg->i == tsel) | 74 |
51 return; | 75 if(arg->i == tsel) { |
52 | 76 for(n = i = 0; i < TLast; i++) |
53 if(csel->tags[arg->i]) | 77 if(sel->tags[i]) |
54 csel->tags[arg->i] = NULL; /* toggle tag */ | 78 n++; |
55 else | 79 if(n < 2) |
56 csel->tags[arg->i] = tags[arg->i]; | 80 return; |
81 } | |
82 | |
83 if(sel->tags[arg->i]) | |
84 sel->tags[arg->i] = NULL; /* toggle tag */ | |
85 else | |
86 sel->tags[arg->i] = tags[arg->i]; | |
57 arrange(NULL); | 87 arrange(NULL); |
58 } | 88 } |
59 | 89 |
90 static void | |
91 ban_client(Client *c) | |
92 { | |
93 XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y); | |
94 XMoveWindow(dpy, c->title, c->tx + 2 * sw, c->ty); | |
95 } | |
96 | |
60 void | 97 void |
61 floating(Arg *arg) | 98 floating(Arg *arg) |
62 { | 99 { |
63 Client *c; | 100 Client *c; |
64 | 101 |
65 arrange = floating; | 102 arrange = floating; |
66 if(!csel) | 103 for(c = clients; c; c = c->next) { |
67 return; | 104 if(c->tags[tsel]) |
68 for(c = csel; c; c = next(c)) | 105 resize(c); |
69 resize(c); | 106 else |
107 ban_client(c); | |
108 } | |
109 if(sel && !sel->tags[tsel]) { | |
110 if((sel = next(clients))) { | |
111 craise(sel); | |
112 focus(sel); | |
113 } | |
114 } | |
70 discard_events(EnterWindowMask); | 115 discard_events(EnterWindowMask); |
71 } | 116 } |
72 | 117 |
73 void | 118 void |
74 tiling(Arg *arg) | 119 tiling(Arg *arg) |
76 Client *c; | 121 Client *c; |
77 int n, cols, rows, gw, gh, i, j; | 122 int n, cols, rows, gw, gh, i, j; |
78 float rt, fd; | 123 float rt, fd; |
79 | 124 |
80 arrange = tiling; | 125 arrange = tiling; |
81 if(!csel) | 126 for(n = 0, c = clients; c; c = next(c->next), n++); |
82 return; | 127 if(n) { |
83 for(n = 0, c = csel; c; c = next(c), n++); | 128 rt = sqrt(n); |
84 rt = sqrt(n); | 129 if(modff(rt, &fd) < 0.5) |
85 if(modff(rt, &fd) < 0.5) | 130 rows = floor(rt); |
86 rows = floor(rt); | 131 else |
87 else | 132 rows = ceil(rt); |
88 rows = ceil(rt); | 133 if(rows * rows < n) |
89 if(rows * rows < n) | 134 cols = rows + 1; |
90 cols = rows + 1; | 135 else |
91 else | 136 cols = rows; |
92 cols = rows; | 137 |
93 | 138 gw = (sw - 2) / cols; |
94 gw = (sw - 2) / cols; | 139 gh = (sh - 2) / rows; |
95 gh = (sh - 2) / rows; | 140 } |
96 | 141 else |
97 for(i = j = 0, c = csel; c; c = next(c)) { | 142 cols = rows = gw = gh = 0; |
98 c->x = i * gw; | 143 |
99 c->y = j * gh; | 144 for(i = j = 0, c = clients; c; c = c->next) { |
100 c->w = gw; | 145 if(c->tags[tsel]) { |
101 c->h = gh; | 146 c->x = i * gw; |
102 resize(c); | 147 c->y = j * gh; |
103 if(++i == cols) { | 148 c->w = gw; |
104 j++; | 149 c->h = gh; |
105 i = 0; | 150 resize(c); |
151 if(++i == cols) { | |
152 j++; | |
153 i = 0; | |
154 } | |
106 } | 155 } |
156 else | |
157 ban_client(c); | |
158 } | |
159 if(sel && !sel->tags[tsel]) { | |
160 if((sel = next(clients))) { | |
161 craise(sel); | |
162 focus(sel); | |
163 } | |
107 } | 164 } |
108 discard_events(EnterWindowMask); | 165 discard_events(EnterWindowMask); |
109 } | 166 } |
110 | 167 |
111 void | 168 void |
112 prevc(Arg *arg) | 169 prevc(Arg *arg) |
113 { | 170 { |
114 Client *c; | 171 Client *c; |
115 | 172 |
116 if(!csel) | 173 if(!sel) |
117 return; | 174 return; |
118 | 175 |
119 if(!(c = prev(csel))) | 176 if((c = sel->revert && sel->revert->tags[tsel] ? sel->revert : NULL)) { |
120 c = prev(cend); | 177 craise(c); |
178 center(c); | |
179 focus(c); | |
180 } | |
181 } | |
182 | |
183 void | |
184 nextc(Arg *arg) | |
185 { | |
186 Client *c; | |
187 | |
188 if(!sel) | |
189 return; | |
190 | |
191 if(!(c = next(sel->next))) | |
192 c = next(clients); | |
121 if(c) { | 193 if(c) { |
122 craise(c); | 194 craise(c); |
123 XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w / 2, c->h / 2); | 195 center(c); |
196 c->revert = sel; | |
124 focus(c); | 197 focus(c); |
125 } | 198 } |
126 } | 199 } |
127 | 200 |
128 void | 201 void |
129 nextc(Arg *arg) | |
130 { | |
131 Client *c; | |
132 | |
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) | 202 ckill(Arg *arg) |
148 { | 203 { |
149 Client *c = csel; | 204 if(!sel) |
150 | 205 return; |
151 if(!c) | 206 if(sel->proto & WM_PROTOCOL_DELWIN) |
152 return; | 207 send_message(sel->win, wm_atom[WMProtocols], wm_atom[WMDelete]); |
153 if(c->proto & WM_PROTOCOL_DELWIN) | 208 else |
154 send_message(c->win, wm_atom[WMProtocols], wm_atom[WMDelete]); | 209 XKillClient(dpy, sel->win); |
155 else | |
156 XKillClient(dpy, c->win); | |
157 } | 210 } |
158 | 211 |
159 static void | 212 static void |
160 resize_title(Client *c) | 213 resize_title(Client *c) |
161 { | 214 { |
254 } | 307 } |
255 | 308 |
256 void | 309 void |
257 focus(Client *c) | 310 focus(Client *c) |
258 { | 311 { |
259 if(csel && csel != c) { | 312 if(sel && sel != c) { |
260 XSetWindowBorder(dpy, csel->win, dc.bg); | 313 XSetWindowBorder(dpy, sel->win, dc.bg); |
261 XMapWindow(dpy, csel->title); | 314 XMapWindow(dpy, sel->title); |
262 draw_client(csel); | 315 draw_client(sel); |
263 } | 316 } |
264 csel = c; | 317 sel = c; |
265 XUnmapWindow(dpy, c->title); | 318 XUnmapWindow(dpy, c->title); |
266 XSetWindowBorder(dpy, c->win, dc.fg); | 319 XSetWindowBorder(dpy, c->win, dc.fg); |
267 draw_client(c); | 320 draw_client(c); |
268 XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); | 321 XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); |
269 XFlush(dpy); | 322 XFlush(dpy); |
271 } | 324 } |
272 | 325 |
273 void | 326 void |
274 manage(Window w, XWindowAttributes *wa) | 327 manage(Window w, XWindowAttributes *wa) |
275 { | 328 { |
276 Client *c; | 329 Client *c, **l; |
277 XSetWindowAttributes twa; | 330 XSetWindowAttributes twa; |
278 | 331 |
279 c = emallocz(sizeof(Client)); | 332 c = emallocz(sizeof(Client)); |
280 c->win = w; | 333 c->win = w; |
281 c->tx = c->x = wa->x; | 334 c->tx = c->x = wa->x; |
282 c->ty = c->y = wa->y; | 335 c->ty = c->y = wa->y; |
283 c->tw = c->w = wa->width; | 336 c->tw = c->w = wa->width; |
284 c->h = wa->height; | 337 c->h = wa->height; |
285 c->th = th; | 338 c->th = th; |
286 c->border = 1; | 339 c->border = 1; |
340 c->proto = win_proto(c->win); | |
287 update_size(c); | 341 update_size(c); |
288 XSelectInput(dpy, c->win, | 342 XSelectInput(dpy, c->win, |
289 StructureNotifyMask | PropertyChangeMask | EnterWindowMask); | 343 StructureNotifyMask | PropertyChangeMask | EnterWindowMask); |
290 XGetTransientForHint(dpy, c->win, &c->trans); | 344 XGetTransientForHint(dpy, c->win, &c->trans); |
291 twa.override_redirect = 1; | 345 twa.override_redirect = 1; |
298 DefaultVisual(dpy, screen), | 352 DefaultVisual(dpy, screen), |
299 CWOverrideRedirect | CWBackPixmap | CWEventMask, &twa); | 353 CWOverrideRedirect | CWBackPixmap | CWEventMask, &twa); |
300 | 354 |
301 update_name(c); | 355 update_name(c); |
302 | 356 |
303 if(!cstart) | 357 for(l = &clients; *l; l = &(*l)->next); |
304 cstart = cend = c; | 358 c->next = *l; /* *l == nil */ |
305 else { | 359 *l = c; |
306 cend->next = c; | |
307 c->prev = cend; | |
308 cend = c; | |
309 } | |
310 | 360 |
311 XSetWindowBorderWidth(dpy, c->win, 1); | 361 XSetWindowBorderWidth(dpy, c->win, 1); |
312 XMapRaised(dpy, c->win); | 362 XMapRaised(dpy, c->win); |
313 XMapRaised(dpy, c->title); | 363 XMapRaised(dpy, c->title); |
314 XGrabButton(dpy, Button1, Mod1Mask, c->win, False, ButtonPressMask, | 364 XGrabButton(dpy, Button1, Mod1Mask, c->win, False, ButtonPressMask, |
316 XGrabButton(dpy, Button2, Mod1Mask, c->win, False, ButtonPressMask, | 366 XGrabButton(dpy, Button2, Mod1Mask, c->win, False, ButtonPressMask, |
317 GrabModeAsync, GrabModeSync, None, None); | 367 GrabModeAsync, GrabModeSync, None, None); |
318 XGrabButton(dpy, Button3, Mod1Mask, c->win, False, ButtonPressMask, | 368 XGrabButton(dpy, Button3, Mod1Mask, c->win, False, ButtonPressMask, |
319 GrabModeAsync, GrabModeSync, None, None); | 369 GrabModeAsync, GrabModeSync, None, None); |
320 arrange(NULL); | 370 arrange(NULL); |
321 XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w / 2, c->h / 2); | 371 center(c); |
322 focus(c); | 372 focus(c); |
323 } | 373 } |
324 | 374 |
325 void | 375 void |
326 gravitate(Client *c, Bool invert) | 376 gravitate(Client *c, Bool invert) |
418 } | 468 } |
419 | 469 |
420 void | 470 void |
421 unmanage(Client *c) | 471 unmanage(Client *c) |
422 { | 472 { |
473 Client **l; | |
474 | |
423 XGrabServer(dpy); | 475 XGrabServer(dpy); |
424 XSetErrorHandler(dummy_error_handler); | 476 XSetErrorHandler(dummy_error_handler); |
425 | 477 |
426 XUngrabButton(dpy, AnyButton, AnyModifier, c->win); | 478 XUngrabButton(dpy, AnyButton, AnyModifier, c->win); |
427 XDestroyWindow(dpy, c->title); | 479 XDestroyWindow(dpy, c->title); |
428 | 480 |
429 if(c->prev) { | 481 for(l = &clients; *l && *l != c; l = &(*l)->next); |
430 c->prev->next = c->next; | 482 *l = c->next; |
431 if(csel == c) | 483 for(l = &clients; *l; l = &(*l)->next) |
432 csel = c->prev; | 484 if((*l)->revert == c) |
433 } | 485 (*l)->revert = NULL; |
434 if(c->next) { | 486 if(sel == c) |
435 c->next->prev = c->prev; | 487 sel = sel->revert ? sel->revert : clients; |
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 | 488 |
444 free(c); | 489 free(c); |
445 | 490 |
446 XFlush(dpy); | 491 XFlush(dpy); |
447 XSetErrorHandler(error_handler); | 492 XSetErrorHandler(error_handler); |
448 XUngrabServer(dpy); | 493 XUngrabServer(dpy); |
449 arrange(NULL); | 494 arrange(NULL); |
450 if(csel) | 495 if(sel) |
451 focus(csel); | 496 focus(sel); |
452 } | 497 } |
453 | 498 |
454 Client * | 499 Client * |
455 gettitle(Window w) | 500 gettitle(Window w) |
456 { | 501 { |
457 Client *c; | 502 Client *c; |
458 for(c = cstart; c; c = c->next) | 503 for(c = clients; c; c = c->next) |
459 if(c->title == w) | 504 if(c->title == w) |
460 return c; | 505 return c; |
461 return NULL; | 506 return NULL; |
462 } | 507 } |
463 | 508 |
464 Client * | 509 Client * |
465 getclient(Window w) | 510 getclient(Window w) |
466 { | 511 { |
467 Client *c; | 512 Client *c; |
468 for(c = cstart; c; c = c->next) | 513 for(c = clients; c; c = c->next) |
469 if(c->win == w) | 514 if(c->win == w) |
470 return c; | 515 return c; |
471 return NULL; | 516 return NULL; |
472 } | 517 } |
473 | 518 |
474 void | 519 void |
475 draw_client(Client *c) | 520 draw_client(Client *c) |
476 { | 521 { |
477 int i; | 522 int i; |
478 if(c == csel) | 523 if(c == sel) |
479 return; | 524 return; |
480 | 525 |
481 dc.x = dc.y = 0; | 526 dc.x = dc.y = 0; |
482 dc.h = c->th; | 527 dc.h = c->th; |
483 | 528 |