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