several other additions/fixes, dwm is quite usable already efa7e514
Anselm R. Garbe · 2006-07-13 18:21 4 file(s) · +164 −110
client.c +139 −94
13 13
14 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 22
static Client *
17 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 26
	return c;
21 27
}
22 28
23 -
static Client *
24 -
prev(Client *c)
29 +
void
30 +
zoom(Arg *arg)
25 31
{
26 -
	for(c = c->prev; c && !c->tags[tsel]; c = c->prev);
27 -
	return c;
32 +
	Client **l;
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 47
void
31 48
max(Arg *arg)
32 49
{
33 -
	if(!csel)
50 +
	if(!sel)
34 51
		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);
52 +
	sel->x = sx;
53 +
	sel->y = sy;
54 +
	sel->w = sw - 2 * sel->border;
55 +
	sel->h = sh - 2 * sel->border;
56 +
	craise(sel);
57 +
	resize(sel);
41 58
	discard_events(EnterWindowMask);
42 59
}
43 60
44 61
void
62 +
view(Arg *arg)
63 +
{
64 +
	tsel = arg->i;
65 +
	arrange(NULL);
66 +
}
67 +
68 +
void
45 69
tag(Arg *arg)
46 70
{
47 -
	if(!csel)
71 +
	int i, n;
72 +
	if(!sel)
48 73
		return;
49 74
50 -
	if(arg->i == tsel)
51 -
		return;
75 +
	if(arg->i == tsel) {
76 +
		for(n = i = 0; i < TLast; i++)
77 +
			if(sel->tags[i])
78 +
				n++;
79 +
		if(n < 2)
80 +
			return;
81 +
	}
52 82
53 -
	if(csel->tags[arg->i])
54 -
		csel->tags[arg->i] = NULL; /* toggle tag */
83 +
	if(sel->tags[arg->i])
84 +
		sel->tags[arg->i] = NULL; /* toggle tag */
55 85
	else
56 -
		csel->tags[arg->i] = tags[arg->i];
86 +
		sel->tags[arg->i] = tags[arg->i];
57 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 97
void
61 98
floating(Arg *arg)
62 99
{
63 100
	Client *c;
64 101
65 102
	arrange = floating;
66 -
	if(!csel)
67 -
		return;
68 -
	for(c = csel; c; c = next(c))
69 -
		resize(c);
103 +
	for(c = clients; c; c = c->next) {
104 +
		if(c->tags[tsel])
105 +
			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 115
	discard_events(EnterWindowMask);
71 116
}
72 117
78 123
    float rt, fd;
79 124
80 125
	arrange = tiling;
81 -
	if(!csel)
82 -
		return;
83 -
	for(n = 0, c = csel; c; c = next(c), n++);
84 -
	rt = sqrt(n);
85 -
	if(modff(rt, &fd) < 0.5)
86 -
		rows = floor(rt);
87 -
	else
88 -
		rows = ceil(rt);
89 -
	if(rows * rows < n)
90 -
		cols = rows + 1;
126 +
	for(n = 0, c = clients; c; c = next(c->next), n++);
127 +
	if(n) {
128 +
		rt = sqrt(n);
129 +
		if(modff(rt, &fd) < 0.5)
130 +
			rows = floor(rt);
131 +
		else
132 +
			rows = ceil(rt);
133 +
		if(rows * rows < n)
134 +
			cols = rows + 1;
135 +
		else
136 +
			cols = rows;
137 +
138 +
		gw = (sw - 2)  / cols;
139 +
		gh = (sh - 2) / rows;
140 +
	}
91 141
	else
92 -
		cols = rows;
142 +
		cols = rows = gw = gh = 0;
93 143
94 -
	gw = (sw - 2)  / cols;
95 -
	gh = (sh - 2) / rows;
96 -
97 -
	for(i = j = 0, c = csel; c; c = next(c)) {
98 -
		c->x = i * gw;
99 -
		c->y = j * gh;
100 -
		c->w = gw;
101 -
		c->h = gh;
102 -
		resize(c);
103 -
		if(++i == cols) {
104 -
			j++;
105 -
			i = 0;
144 +
	for(i = j = 0, c = clients; c; c = c->next) {
145 +
		if(c->tags[tsel]) {
146 +
			c->x = i * gw;
147 +
			c->y = j * gh;
148 +
			c->w = gw;
149 +
			c->h = gh;
150 +
			resize(c);
151 +
			if(++i == cols) {
152 +
				j++;
153 +
				i = 0;
154 +
			}
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);
106 163
		}
107 164
	}
108 165
	discard_events(EnterWindowMask);
113 170
{
114 171
	Client *c;
115 172
116 -
	if(!csel)
173 +
	if(!sel)
117 174
		return;
118 175
119 -
	if(!(c = prev(csel)))
120 -
		c = prev(cend);
121 -
	if(c) {
176 +
	if((c = sel->revert && sel->revert->tags[tsel] ? sel->revert : NULL)) {
122 177
		craise(c);
123 -
		XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w / 2, c->h / 2);
178 +
		center(c);
124 179
		focus(c);
125 180
	}
126 181
}
130 185
{
131 186
	Client *c;
132 187
   
133 -
	if(!csel)
188 +
	if(!sel)
134 189
		return;
135 190
136 -
	if(!(c = next(csel)))
137 -
		c = next(cstart);
138 -
191 +
	if(!(c = next(sel->next)))
192 +
		c = next(clients);
139 193
	if(c) {
140 194
		craise(c);
141 -
		XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w / 2, c->h / 2);
195 +
		center(c);
196 +
		c->revert = sel;
142 197
		focus(c);
143 198
	}
144 199
}
146 201
void
147 202
ckill(Arg *arg)
148 203
{
149 -
	Client *c = csel;
150 -
151 -
	if(!c)
204 +
	if(!sel)
152 205
		return;
153 -
	if(c->proto & WM_PROTOCOL_DELWIN)
154 -
		send_message(c->win, wm_atom[WMProtocols], wm_atom[WMDelete]);
206 +
	if(sel->proto & WM_PROTOCOL_DELWIN)
207 +
		send_message(sel->win, wm_atom[WMProtocols], wm_atom[WMDelete]);
155 208
	else
156 -
		XKillClient(dpy, c->win);
209 +
		XKillClient(dpy, sel->win);
157 210
}
158 211
159 212
static void
256 309
void
257 310
focus(Client *c)
258 311
{
259 -
	if(csel && csel != c) {
260 -
		XSetWindowBorder(dpy, csel->win, dc.bg);
261 -
		XMapWindow(dpy, csel->title);
262 -
		draw_client(csel);
312 +
	if(sel && sel != c) {
313 +
		XSetWindowBorder(dpy, sel->win, dc.bg);
314 +
		XMapWindow(dpy, sel->title);
315 +
		draw_client(sel);
263 316
	}
264 -
	csel = c;
317 +
	sel = c;
265 318
	XUnmapWindow(dpy, c->title);
266 319
	XSetWindowBorder(dpy, c->win, dc.fg);
267 320
	draw_client(c);
273 326
void
274 327
manage(Window w, XWindowAttributes *wa)
275 328
{
276 -
	Client *c;
329 +
	Client *c, **l;
277 330
	XSetWindowAttributes twa;
278 331
279 332
	c = emallocz(sizeof(Client));
284 337
	c->h = wa->height;
285 338
	c->th = th;
286 339
	c->border = 1;
340 +
	c->proto = win_proto(c->win);
287 341
	update_size(c);
288 342
	XSelectInput(dpy, c->win,
289 343
			StructureNotifyMask | PropertyChangeMask | EnterWindowMask);
300 354
301 355
	update_name(c);
302 356
303 -
	if(!cstart)
304 -
		cstart = cend = c;
305 -
	else {
306 -
		cend->next = c;
307 -
		c->prev = cend;
308 -
		cend = c;
309 -
	}
357 +
	for(l = &clients; *l; l = &(*l)->next);
358 +
	c->next = *l; /* *l == nil */
359 +
	*l = c;
310 360
311 361
	XSetWindowBorderWidth(dpy, c->win, 1);
312 362
	XMapRaised(dpy, c->win);
318 368
	XGrabButton(dpy, Button3, Mod1Mask, c->win, False, ButtonPressMask,
319 369
			GrabModeAsync, GrabModeSync, None, None);
320 370
	arrange(NULL);
321 -
	XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w / 2, c->h / 2);
371 +
	center(c);
322 372
	focus(c);
323 373
}
324 374
420 470
void
421 471
unmanage(Client *c)
422 472
{
473 +
	Client **l;
474 +
423 475
	XGrabServer(dpy);
424 476
	XSetErrorHandler(dummy_error_handler);
425 477
426 478
	XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
427 479
	XDestroyWindow(dpy, c->title);
428 480
429 -
	if(c->prev) {
430 -
		c->prev->next = c->next;
431 -
		if(csel == c)
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;
481 +
	for(l = &clients; *l && *l != c; l = &(*l)->next);
482 +
	*l = c->next;
483 +
	for(l = &clients; *l; l = &(*l)->next)
484 +
		if((*l)->revert == c)
485 +
			(*l)->revert = NULL;
486 +
	if(sel == c)
487 +
		sel = sel->revert ? sel->revert : clients;
443 488
444 489
	free(c);
445 490
447 492
	XSetErrorHandler(error_handler);
448 493
	XUngrabServer(dpy);
449 494
	arrange(NULL);
450 -
	if(csel)
451 -
		focus(csel);
495 +
	if(sel)
496 +
		focus(sel);
452 497
}
453 498
454 499
Client *
455 500
gettitle(Window w)
456 501
{
457 502
	Client *c;
458 -
	for(c = cstart; c; c = c->next)
503 +
	for(c = clients; c; c = c->next)
459 504
		if(c->title == w)
460 505
			return c;
461 506
	return NULL;
465 510
getclient(Window w)
466 511
{
467 512
	Client *c;
468 -
	for(c = cstart; c; c = c->next)
513 +
	for(c = clients; c; c = c->next)
469 514
		if(c->win == w)
470 515
			return c;
471 516
	return NULL;
475 520
draw_client(Client *c)
476 521
{
477 522
	int i;
478 -
	if(c == csel)
523 +
	if(c == sel)
479 524
		return;
480 525
481 526
	dc.x = dc.y = 0;
dev.c +14 −8
20 20
const char *xlock[] = { "xlock", NULL };
21 21
22 22
static Key key[] = {
23 -
	{ Mod1Mask, XK_Return, spawn, { .argv = term } },
23 +
	{ Mod1Mask, XK_Return, zoom, { 0 } },
24 +
	{ Mod1Mask, XK_t, spawn, { .argv = term } },
24 25
	{ Mod1Mask, XK_w, spawn, { .argv = browse } },
25 26
	{ Mod1Mask, XK_l, spawn, { .argv = xlock } },
26 27
	{ Mod1Mask, XK_k, prevc, { 0 } },
27 28
	{ Mod1Mask, XK_j, nextc, { 0 } }, 
28 -
	{ Mod1Mask, XK_t, tiling, { 0 } }, 
29 -
	{ Mod1Mask, XK_f, floating, { 0 } }, 
30 29
	{ Mod1Mask, XK_m, max, { 0 } }, 
31 -
	{ Mod1Mask, XK_0, tag, { .i = Tscratch } }, 
32 -
	{ Mod1Mask, XK_1, tag, { .i = Tdev } }, 
33 -
	{ Mod1Mask, XK_2, tag, { .i = Tirc } }, 
34 -
	{ Mod1Mask, XK_3, tag, { .i = Twww } }, 
35 -
	{ Mod1Mask, XK_4, tag, { .i = Twork } }, 
30 +
	{ Mod1Mask, XK_0, view, { .i = Tscratch } }, 
31 +
	{ Mod1Mask, XK_1, view, { .i = Tdev } }, 
32 +
	{ Mod1Mask, XK_2, view, { .i = Tirc } }, 
33 +
	{ Mod1Mask, XK_3, view, { .i = Twww } }, 
34 +
	{ Mod1Mask, XK_4, view, { .i = Twork } }, 
35 +
	{ Mod1Mask, XK_space, tiling, { 0 } }, 
36 +
	{ Mod1Mask | ShiftMask, XK_space, floating, { 0 } }, 
37 +
	{ Mod1Mask | ShiftMask, XK_0, tag, { .i = Tscratch } }, 
38 +
	{ Mod1Mask | ShiftMask, XK_1, tag, { .i = Tdev } }, 
39 +
	{ Mod1Mask | ShiftMask, XK_2, tag, { .i = Tirc } }, 
40 +
	{ Mod1Mask | ShiftMask, XK_3, tag, { .i = Twww } }, 
41 +
	{ Mod1Mask | ShiftMask, XK_4, tag, { .i = Twork } }, 
36 42
	{ Mod1Mask | ShiftMask, XK_c, ckill, { 0 } }, 
37 43
	{ Mod1Mask | ShiftMask, XK_q, quit, { 0 } },
38 44
};
dwm.h +5 −3
68 68
	Window trans;
69 69
	Window title;
70 70
	Client *next;
71 -
	Client *prev;
71 +
	Client *revert;
72 72
};
73 73
74 74
struct Key {
89 89
extern char stext[1024], *tags[TLast];
90 90
91 91
extern DC dc;
92 -
extern Client *cstart, *cend, *csel;
92 +
extern Client *clients, *sel;
93 93
94 94
/* client.c */
95 95
extern void manage(Window w, XWindowAttributes *wa);
109 109
extern void max(Arg *arg);
110 110
extern void floating(Arg *arg);
111 111
extern void tiling(Arg *arg);
112 -
void tag(Arg *arg);
112 +
extern void tag(Arg *arg);
113 +
extern void view(Arg *arg);
114 +
extern void zoom(Arg *arg);
113 115
extern void gravitate(Client *c, Bool invert);
114 116
115 117
/* draw.c */
main.c +6 −5
38 38
int screen, sx, sy, sw, sh, th;
39 39
40 40
DC dc = {0};
41 -
Client *cstart = NULL;
42 -
Client *cend = NULL;
43 -
Client *csel = NULL;
41 +
Client *clients = NULL;
42 +
Client *sel = NULL;
44 43
45 44
static Bool other_wm_running;
46 45
static const char version[] =
169 168
static void
170 169
cleanup()
171 170
{
172 -
	while(csel)
173 -
		unmanage(csel);
171 +
	while(sel) {
172 +
		resize(sel);
173 +
		unmanage(sel);
174 +
	}
174 175
	XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
175 176
}
176 177