proceeded with cleaning up, sorting functions, etc adaa28a6
Anselm R. Garbe · 2006-07-15 17:00 7 file(s) · +532 −543
client.c +206 −205
2 2
 * (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
3 3
 * See LICENSE file for license details.
4 4
 */
5 +
#include "dwm.h"
5 6
6 7
#include <stdlib.h>
7 -
#include <stdio.h>
8 8
#include <string.h>
9 9
#include <X11/Xatom.h>
10 10
#include <X11/Xutil.h>
11 11
12 -
#include "dwm.h"
13 -
14 -
void
15 -
ban(Client *c)
16 -
{
17 -
	XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
18 -
	XMoveWindow(dpy, c->title, c->tx + 2 * sw, c->ty);
19 -
}
12 +
/* static functions */
20 13
21 14
static void
22 15
resizetitle(Client *c)
35 28
	XMoveResizeWindow(dpy, c->title, c->tx, c->ty, c->tw, c->th);
36 29
}
37 30
31 +
static int
32 +
xerrordummy(Display *dsply, XErrorEvent *ee)
33 +
{
34 +
	return 0;
35 +
}
36 +
37 +
/* extern functions */
38 +
38 39
void
39 -
settitle(Client *c)
40 +
ban(Client *c)
40 41
{
41 -
	XTextProperty name;
42 -
	int n;
43 -
	char **list = NULL;
42 +
	XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
43 +
	XMoveWindow(dpy, c->title, c->tx + 2 * sw, c->ty);
44 +
}
45 +
46 +
void
47 +
focus(Client *c)
48 +
{
49 +
	Client *old = sel;
50 +
	XEvent ev;
44 51
45 -
	name.nitems = 0;
46 -
	c->name[0] = 0;
47 -
	XGetTextProperty(dpy, c->win, &name, net_atom[NetWMName]);
48 -
	if(!name.nitems)
49 -
		XGetWMName(dpy, c->win, &name);
50 -
	if(!name.nitems)
52 +
	XFlush(dpy);
53 +
	sel = c;
54 +
	if(old && old != c)
55 +
		drawtitle(old);
56 +
	drawtitle(c);
57 +
	XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime);
58 +
	XFlush(dpy);
59 +
	while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
60 +
}
61 +
62 +
void
63 +
focusnext(Arg *arg)
64 +
{
65 +
	Client *c;
66 +
   
67 +
	if(!sel)
51 68
		return;
52 -
	if(name.encoding == XA_STRING)
53 -
		strncpy(c->name, (char *)name.value, sizeof(c->name));
54 -
	else {
55 -
		if(XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success
56 -
				&& n > 0 && *list)
57 -
		{
58 -
			strncpy(c->name, *list, sizeof(c->name));
59 -
			XFreeStringList(list);
60 -
		}
69 +
70 +
	if(!(c = getnext(sel->next)))
71 +
		c = getnext(clients);
72 +
	if(c) {
73 +
		higher(c);
74 +
		c->revert = sel;
75 +
		focus(c);
61 76
	}
62 -
	XFree(name.value);
63 -
	resizetitle(c);
64 77
}
65 78
66 79
void
67 -
setsize(Client *c)
80 +
focusprev(Arg *arg)
68 81
{
69 -
	XSizeHints size;
70 -
	long msize;
71 -
	if(!XGetWMNormalHints(dpy, c->win, &size, &msize) || !size.flags)
72 -
		size.flags = PSize;
73 -
	c->flags = size.flags;
74 -
	if(c->flags & PBaseSize) {
75 -
		c->basew = size.base_width;
76 -
		c->baseh = size.base_height;
82 +
	Client *c;
83 +
84 +
	if(!sel)
85 +
		return;
86 +
87 +
	if((c = sel->revert && sel->revert->tags[tsel] ? sel->revert : NULL)) {
88 +
		higher(c);
89 +
		focus(c);
77 90
	}
78 -
	else
79 -
		c->basew = c->baseh = 0;
80 -
	if(c->flags & PResizeInc) {
81 -
		c->incw = size.width_inc;
82 -
		c->inch = size.height_inc;
91 +
}
92 +
93 +
Client *
94 +
getclient(Window w)
95 +
{
96 +
	Client *c;
97 +
	for(c = clients; c; c = c->next)
98 +
		if(c->win == w)
99 +
			return c;
100 +
	return NULL;
101 +
}
102 +
103 +
Client *
104 +
getctitle(Window w)
105 +
{
106 +
	Client *c;
107 +
	for(c = clients; c; c = c->next)
108 +
		if(c->title == w)
109 +
			return c;
110 +
	return NULL;
111 +
}
112 +
113 +
void
114 +
gravitate(Client *c, Bool invert)
115 +
{
116 +
	int dx = 0, dy = 0;
117 +
118 +
	switch(c->grav) {
119 +
	case StaticGravity:
120 +
	case NorthWestGravity:
121 +
	case NorthGravity:
122 +
	case NorthEastGravity:
123 +
		dy = c->border;
124 +
		break;
125 +
	case EastGravity:
126 +
	case CenterGravity:
127 +
	case WestGravity:
128 +
		dy = -(c->h / 2) + c->border;
129 +
		break;
130 +
	case SouthEastGravity:
131 +
	case SouthGravity:
132 +
	case SouthWestGravity:
133 +
		dy = -c->h;
134 +
		break;
135 +
	default:
136 +
		break;
83 137
	}
84 -
	else
85 -
		c->incw = c->inch = 0;
86 -
	if(c->flags & PMaxSize) {
87 -
		c->maxw = size.max_width;
88 -
		c->maxh = size.max_height;
138 +
139 +
	switch (c->grav) {
140 +
	case StaticGravity:
141 +
	case NorthWestGravity:
142 +
	case WestGravity:
143 +
	case SouthWestGravity:
144 +
		dx = c->border;
145 +
		break;
146 +
	case NorthGravity:
147 +
	case CenterGravity:
148 +
	case SouthGravity:
149 +
		dx = -(c->w / 2) + c->border;
150 +
		break;
151 +
	case NorthEastGravity:
152 +
	case EastGravity:
153 +
	case SouthEastGravity:
154 +
		dx = -(c->w + c->border);
155 +
		break;
156 +
	default:
157 +
		break;
89 158
	}
90 -
	else
91 -
		c->maxw = c->maxh = 0;
92 -
	if(c->flags & PMinSize) {
93 -
		c->minw = size.min_width;
94 -
		c->minh = size.min_height;
159 +
160 +
	if(invert) {
161 +
		dx = -dx;
162 +
		dy = -dy;
95 163
	}
96 -
	else
97 -
		c->minw = c->minh = 0;
98 -
	if(c->flags & PWinGravity)
99 -
		c->grav = size.win_gravity;
100 -
	else
101 -
		c->grav = NorthWestGravity;
164 +
	c->x += dx;
165 +
	c->y += dy;
102 166
}
103 167
104 168
void
109 173
}
110 174
111 175
void
112 -
lower(Client *c)
176 +
killclient(Arg *arg)
113 177
{
114 -
	XLowerWindow(dpy, c->title);
115 -
	XLowerWindow(dpy, c->win);
178 +
	if(!sel)
179 +
		return;
180 +
	if(sel->proto & WM_PROTOCOL_DELWIN)
181 +
		sendevent(sel->win, wm_atom[WMProtocols], wm_atom[WMDelete]);
182 +
	else
183 +
		XKillClient(dpy, sel->win);
116 184
}
117 185
118 186
void
119 -
focus(Client *c)
187 +
lower(Client *c)
120 188
{
121 -
	Client *old = sel;
122 -
	XEvent ev;
123 -
124 -
	XFlush(dpy);
125 -
	sel = c;
126 -
	if(old && old != c)
127 -
		drawtitle(old);
128 -
	drawtitle(c);
129 -
	XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime);
130 -
	XFlush(dpy);
131 -
	while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
189 +
	XLowerWindow(dpy, c->title);
190 +
	XLowerWindow(dpy, c->win);
132 191
}
133 192
134 193
void
195 254
}
196 255
197 256
void
198 -
gravitate(Client *c, Bool invert)
257 +
maximize(Arg *arg)
199 258
{
200 -
	int dx = 0, dy = 0;
201 -
202 -
	switch(c->grav) {
203 -
	case StaticGravity:
204 -
	case NorthWestGravity:
205 -
	case NorthGravity:
206 -
	case NorthEastGravity:
207 -
		dy = c->border;
208 -
		break;
209 -
	case EastGravity:
210 -
	case CenterGravity:
211 -
	case WestGravity:
212 -
		dy = -(c->h / 2) + c->border;
213 -
		break;
214 -
	case SouthEastGravity:
215 -
	case SouthGravity:
216 -
	case SouthWestGravity:
217 -
		dy = -c->h;
218 -
		break;
219 -
	default:
220 -
		break;
221 -
	}
222 -
223 -
	switch (c->grav) {
224 -
	case StaticGravity:
225 -
	case NorthWestGravity:
226 -
	case WestGravity:
227 -
	case SouthWestGravity:
228 -
		dx = c->border;
229 -
		break;
230 -
	case NorthGravity:
231 -
	case CenterGravity:
232 -
	case SouthGravity:
233 -
		dx = -(c->w / 2) + c->border;
234 -
		break;
235 -
	case NorthEastGravity:
236 -
	case EastGravity:
237 -
	case SouthEastGravity:
238 -
		dx = -(c->w + c->border);
239 -
		break;
240 -
	default:
241 -
		break;
242 -
	}
243 -
244 -
	if(invert) {
245 -
		dx = -dx;
246 -
		dy = -dy;
247 -
	}
248 -
	c->x += dx;
249 -
	c->y += dy;
259 +
	if(!sel)
260 +
		return;
261 +
	sel->x = sx;
262 +
	sel->y = sy + bh;
263 +
	sel->w = sw - 2 * sel->border;
264 +
	sel->h = sh - 2 * sel->border - bh;
265 +
	higher(sel);
266 +
	resize(sel, False);
250 267
}
251 -
252 268
253 269
void
254 270
resize(Client *c, Bool inc)
290 306
	XFlush(dpy);
291 307
}
292 308
293 -
static int
294 -
xerrordummy(Display *dsply, XErrorEvent *ee)
309 +
void
310 +
setsize(Client *c)
311 +
{
312 +
	XSizeHints size;
313 +
	long msize;
314 +
	if(!XGetWMNormalHints(dpy, c->win, &size, &msize) || !size.flags)
315 +
		size.flags = PSize;
316 +
	c->flags = size.flags;
317 +
	if(c->flags & PBaseSize) {
318 +
		c->basew = size.base_width;
319 +
		c->baseh = size.base_height;
320 +
	}
321 +
	else
322 +
		c->basew = c->baseh = 0;
323 +
	if(c->flags & PResizeInc) {
324 +
		c->incw = size.width_inc;
325 +
		c->inch = size.height_inc;
326 +
	}
327 +
	else
328 +
		c->incw = c->inch = 0;
329 +
	if(c->flags & PMaxSize) {
330 +
		c->maxw = size.max_width;
331 +
		c->maxh = size.max_height;
332 +
	}
333 +
	else
334 +
		c->maxw = c->maxh = 0;
335 +
	if(c->flags & PMinSize) {
336 +
		c->minw = size.min_width;
337 +
		c->minh = size.min_height;
338 +
	}
339 +
	else
340 +
		c->minw = c->minh = 0;
341 +
	if(c->flags & PWinGravity)
342 +
		c->grav = size.win_gravity;
343 +
	else
344 +
		c->grav = NorthWestGravity;
345 +
}
346 +
347 +
void
348 +
settitle(Client *c)
295 349
{
296 -
	return 0;
350 +
	XTextProperty name;
351 +
	int n;
352 +
	char **list = NULL;
353 +
354 +
	name.nitems = 0;
355 +
	c->name[0] = 0;
356 +
	XGetTextProperty(dpy, c->win, &name, net_atom[NetWMName]);
357 +
	if(!name.nitems)
358 +
		XGetWMName(dpy, c->win, &name);
359 +
	if(!name.nitems)
360 +
		return;
361 +
	if(name.encoding == XA_STRING)
362 +
		strncpy(c->name, (char *)name.value, sizeof(c->name));
363 +
	else {
364 +
		if(XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success
365 +
				&& n > 0 && *list)
366 +
		{
367 +
			strncpy(c->name, *list, sizeof(c->name));
368 +
			XFreeStringList(list);
369 +
		}
370 +
	}
371 +
	XFree(name.value);
372 +
	resizetitle(c);
297 373
}
298 374
299 375
void
325 401
		focus(sel);
326 402
}
327 403
328 -
Client *
329 -
getctitle(Window w)
330 -
{
331 -
	Client *c;
332 -
	for(c = clients; c; c = c->next)
333 -
		if(c->title == w)
334 -
			return c;
335 -
	return NULL;
336 -
}
337 -
338 -
Client *
339 -
getclient(Window w)
340 -
{
341 -
	Client *c;
342 -
	for(c = clients; c; c = c->next)
343 -
		if(c->win == w)
344 -
			return c;
345 -
	return NULL;
346 -
}
347 -
348 404
void
349 405
zoom(Arg *arg)
350 406
{
366 422
	arrange(NULL);
367 423
	focus(sel);
368 424
}
369 -
370 -
void
371 -
maximize(Arg *arg)
372 -
{
373 -
	if(!sel)
374 -
		return;
375 -
	sel->x = sx;
376 -
	sel->y = sy + bh;
377 -
	sel->w = sw - 2 * sel->border;
378 -
	sel->h = sh - 2 * sel->border - bh;
379 -
	higher(sel);
380 -
	resize(sel, False);
381 -
}
382 -
383 -
void
384 -
focusprev(Arg *arg)
385 -
{
386 -
	Client *c;
387 -
388 -
	if(!sel)
389 -
		return;
390 -
391 -
	if((c = sel->revert && sel->revert->tags[tsel] ? sel->revert : NULL)) {
392 -
		higher(c);
393 -
		focus(c);
394 -
	}
395 -
}
396 -
397 -
void
398 -
focusnext(Arg *arg)
399 -
{
400 -
	Client *c;
401 -
   
402 -
	if(!sel)
403 -
		return;
404 -
405 -
	if(!(c = getnext(sel->next)))
406 -
		c = getnext(clients);
407 -
	if(c) {
408 -
		higher(c);
409 -
		c->revert = sel;
410 -
		focus(c);
411 -
	}
412 -
}
413 -
414 -
void
415 -
killclient(Arg *arg)
416 -
{
417 -
	if(!sel)
418 -
		return;
419 -
	if(sel->proto & WM_PROTOCOL_DELWIN)
420 -
		sendevent(sel->win, wm_atom[WMProtocols], wm_atom[WMDelete]);
421 -
	else
422 -
		XKillClient(dpy, sel->win);
423 -
}
draw.c +74 −72
2 2
 * (C)opyright MMIV-MMVI Anselm R. Garbe <garbeam at gmail dot com>
3 3
 * See LICENSE file for license details.
4 4
 */
5 +
#include "dwm.h"
5 6
6 7
#include <stdio.h>
7 8
#include <string.h>
9 +
#include <X11/Xlocale.h>
10 +
11 +
/* static functions */
8 12
9 -
#include <X11/Xlocale.h>
13 +
static void
14 +
drawborder(void)
15 +
{
16 +
	XPoint points[5];
17 +
	XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter);
18 +
	XSetForeground(dpy, dc.gc, dc.border);
19 +
	points[0].x = dc.x;
20 +
	points[0].y = dc.y;
21 +
	points[1].x = dc.w - 1;
22 +
	points[1].y = 0;
23 +
	points[2].x = 0;
24 +
	points[2].y = dc.h - 1;
25 +
	points[3].x = -(dc.w - 1);
26 +
	points[3].y = 0;
27 +
	points[4].x = 0;
28 +
	points[4].y = -(dc.h - 1);
29 +
	XDrawLines(dpy, dc.drawable, dc.gc, points, 5, CoordModePrevious);
30 +
}
10 31
11 -
#include "dwm.h"
32 +
/* extern functions */
12 33
13 34
void
14 35
drawall()
53 74
}
54 75
55 76
void
56 -
drawtitle(Client *c)
57 -
{
58 -
	int i;
59 -
	Bool istile = arrange == dotile;
60 -
61 -
	if(c == sel) {
62 -
		drawstatus();
63 -
		XUnmapWindow(dpy, c->title);
64 -
		XSetWindowBorder(dpy, c->win, dc.fg);
65 -
		return;
66 -
	}
67 -
68 -
	XSetWindowBorder(dpy, c->win, dc.bg);
69 -
	XMapWindow(dpy, c->title);
70 -
71 -
	dc.x = dc.y = 0;
72 -
73 -
	dc.w = 0;
74 -
	for(i = 0; i < TLast; i++) {
75 -
		if(c->tags[i]) {
76 -
			dc.x += dc.w;
77 -
			dc.w = textw(c->tags[i]);
78 -
			drawtext(c->tags[i], !istile, True);
79 -
		}
80 -
	}
81 -
	dc.x += dc.w;
82 -
	dc.w = textw(c->name);
83 -
	drawtext(c->name, !istile, True);
84 -
	XCopyArea(dpy, dc.drawable, c->title, dc.gc,
85 -
			0, 0, c->tw, c->th, 0, 0);
86 -
	XFlush(dpy);
87 -
}
88 -
89 -
static void
90 -
drawborder(void)
91 -
{
92 -
	XPoint points[5];
93 -
	XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter);
94 -
	XSetForeground(dpy, dc.gc, dc.border);
95 -
	points[0].x = dc.x;
96 -
	points[0].y = dc.y;
97 -
	points[1].x = dc.w - 1;
98 -
	points[1].y = 0;
99 -
	points[2].x = 0;
100 -
	points[2].y = dc.h - 1;
101 -
	points[3].x = -(dc.w - 1);
102 -
	points[3].y = 0;
103 -
	points[4].x = 0;
104 -
	points[4].y = -(dc.h - 1);
105 -
	XDrawLines(dpy, dc.drawable, dc.gc, points, 5, CoordModePrevious);
106 -
}
107 -
108 -
void
109 77
drawtext(const char *text, Bool invert, Bool border)
110 78
{
111 79
	int x, y, w, h;
155 123
	}
156 124
}
157 125
126 +
void
127 +
drawtitle(Client *c)
128 +
{
129 +
	int i;
130 +
	Bool istile = arrange == dotile;
131 +
132 +
	if(c == sel) {
133 +
		drawstatus();
134 +
		XUnmapWindow(dpy, c->title);
135 +
		XSetWindowBorder(dpy, c->win, dc.fg);
136 +
		return;
137 +
	}
138 +
139 +
	XSetWindowBorder(dpy, c->win, dc.bg);
140 +
	XMapWindow(dpy, c->title);
141 +
142 +
	dc.x = dc.y = 0;
143 +
144 +
	dc.w = 0;
145 +
	for(i = 0; i < TLast; i++) {
146 +
		if(c->tags[i]) {
147 +
			dc.x += dc.w;
148 +
			dc.w = textw(c->tags[i]);
149 +
			drawtext(c->tags[i], !istile, True);
150 +
		}
151 +
	}
152 +
	dc.x += dc.w;
153 +
	dc.w = textw(c->name);
154 +
	drawtext(c->name, !istile, True);
155 +
	XCopyArea(dpy, dc.drawable, c->title, dc.gc,
156 +
			0, 0, c->tw, c->th, 0, 0);
157 +
	XFlush(dpy);
158 +
}
159 +
158 160
unsigned long
159 161
getcolor(const char *colstr)
160 162
{
163 165
164 166
	XAllocNamedColor(dpy, cmap, colstr, &color, &color);
165 167
	return color.pixel;
166 -
}
167 -
168 -
unsigned int
169 -
textnw(char *text, unsigned int len)
170 -
{
171 -
	XRectangle r;
172 -
	if(dc.font.set) {
173 -
		XmbTextExtents(dc.font.set, text, len, NULL, &r);
174 -
		return r.width;
175 -
	}
176 -
	return XTextWidth(dc.font.xfont, text, len);
177 -
}
178 -
179 -
unsigned int
180 -
textw(char *text)
181 -
{
182 -
	return textnw(text, strlen(text)) + dc.font.height;
183 168
}
184 169
185 170
void
232 217
	}
233 218
	dc.font.height = dc.font.ascent + dc.font.descent;
234 219
}
220 +
221 +
unsigned int
222 +
textnw(char *text, unsigned int len)
223 +
{
224 +
	XRectangle r;
225 +
	if(dc.font.set) {
226 +
		XmbTextExtents(dc.font.set, text, len, NULL, &r);
227 +
		return r.width;
228 +
	}
229 +
	return XTextWidth(dc.font.xfont, text, len);
230 +
}
231 +
232 +
unsigned int
233 +
textw(char *text)
234 +
{
235 +
	return textnw(text, strlen(text)) + dc.font.height;
236 +
}
dwm.h +19 −20
104 104
105 105
/* client.c */
106 106
extern void ban(Client *c);
107 -
extern void manage(Window w, XWindowAttributes *wa);
108 -
extern void unmanage(Client *c);
109 -
extern Client *getclient(Window w);
110 107
extern void focus(Client *c);
111 -
extern void settitle(Client *c);
112 -
extern void resize(Client *c, Bool inc);
113 -
extern void setsize(Client *c);
108 +
extern void focusnext(Arg *arg);
109 +
extern void focusprev(Arg *arg);
110 +
extern Client *getclient(Window w);
114 111
extern Client *getctitle(Window w);
112 +
extern void gravitate(Client *c, Bool invert);
115 113
extern void higher(Client *c);
114 +
extern void killclient(Arg *arg);
116 115
extern void lower(Client *c);
117 -
extern void gravitate(Client *c, Bool invert);
118 -
extern void zoom(Arg *arg);
116 +
extern void manage(Window w, XWindowAttributes *wa);
119 117
extern void maximize(Arg *arg);
120 -
extern void focusprev(Arg *arg);
121 -
extern void focusnext(Arg *arg);
122 -
extern void killclient(Arg *arg);
118 +
extern void resize(Client *c, Bool inc);
119 +
extern void setsize(Client *c);
120 +
extern void settitle(Client *c);
121 +
extern void unmanage(Client *c);
122 +
extern void zoom(Arg *arg);
123 123
124 124
/* draw.c */
125 125
extern void drawall();
126 126
extern void drawstatus();
127 +
extern void drawtext(const char *text, Bool invert, Bool border);
127 128
extern void drawtitle(Client *c);
128 -
extern void drawtext(const char *text, Bool invert, Bool border);
129 129
extern unsigned long getcolor(const char *colstr);
130 130
extern void setfont(const char *fontstr);
131 131
extern unsigned int textnw(char *text, unsigned int len);
132 132
extern unsigned int textw(char *text);
133 -
extern unsigned int texth(void);
134 133
135 134
/* event.c */
136 135
extern void grabkeys();
137 136
138 137
/* main.c */
138 +
extern int getproto(Window w);
139 139
extern void quit(Arg *arg);
140 +
extern void sendevent(Window w, Atom a, long value);
140 141
extern int xerror(Display *dsply, XErrorEvent *ee);
141 -
extern void sendevent(Window w, Atom a, long value);
142 -
extern int getproto(Window w);
143 142
144 143
/* tag.c */
144 +
extern void appendtag(Arg *arg);
145 +
extern void dofloat(Arg *arg);
146 +
extern void dotile(Arg *arg);
145 147
extern Client *getnext(Client *c);
148 +
extern void replacetag(Arg *arg);
146 149
extern void settags(Client *c);
147 -
extern void dofloat(Arg *arg);
148 -
extern void dotile(Arg *arg);
149 150
extern void view(Arg *arg);
150 -
extern void appendtag(Arg *arg);
151 -
extern void replacetag(Arg *arg);
152 151
153 152
/* util.c */
154 -
extern void eprint(const char *errstr, ...);
155 153
extern void *emallocz(unsigned int size);
154 +
extern void eprint(const char *errstr, ...);
156 155
extern void spawn(Arg *arg);
event.c +128 −138
2 2
 * (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
3 3
 * See LICENSE file for license details.
4 4
 */
5 +
#include "dwm.h"
5 6
6 -
#include <fcntl.h>
7 -
#include <stdio.h>
8 7
#include <stdlib.h>
9 -
#include <string.h>
10 -
#include <unistd.h>
11 8
#include <X11/keysym.h>
12 9
#include <X11/Xatom.h>
13 -
14 -
#include "dwm.h"
15 10
16 11
#define ButtonMask      (ButtonPressMask | ButtonReleaseMask)
17 12
#define MouseMask       (ButtonMask | PointerMotionMask)
54 49
55 50
/********** CUSTOMIZE **********/
56 51
57 -
/* local functions */
58 -
static void buttonpress(XEvent *e);
59 -
static void configurerequest(XEvent *e);
60 -
static void destroynotify(XEvent *e);
61 -
static void enternotify(XEvent *e);
62 -
static void leavenotify(XEvent *e);
63 -
static void expose(XEvent *e);
64 -
static void keypress(XEvent *e);
65 -
static void maprequest(XEvent *e);
66 -
static void propertynotify(XEvent *e);
67 -
static void unmapnotify(XEvent *e);
52 +
/* static functions */
68 53
69 -
void (*handler[LASTEvent]) (XEvent *) = {
70 -
	[ButtonPress] = buttonpress,
71 -
	[ConfigureRequest] = configurerequest,
72 -
	[DestroyNotify] = destroynotify,
73 -
	[EnterNotify] = enternotify,
74 -
	[LeaveNotify] = leavenotify,
75 -
	[Expose] = expose,
76 -
	[KeyPress] = keypress,
77 -
	[MapRequest] = maprequest,
78 -
	[PropertyNotify] = propertynotify,
79 -
	[UnmapNotify] = unmapnotify
80 -
};
81 -
82 -
void
83 -
grabkeys()
84 -
{
85 -
	static unsigned int len = key ? sizeof(key) / sizeof(key[0]) : 0;
86 -
	unsigned int i;
87 -
	KeyCode code;
88 -
89 -
	for(i = 0; i < len; i++) {
90 -
		code = XKeysymToKeycode(dpy, key[i].keysym);
91 -
		XUngrabKey(dpy, code, key[i].mod, root);
92 -
		XGrabKey(dpy, code, key[i].mod, root, True,
93 -
				GrabModeAsync, GrabModeAsync);
94 -
	}
95 -
}
96 -
97 -
static void
98 -
keypress(XEvent *e)
99 -
{
100 -
	XKeyEvent *ev = &e->xkey;
101 -
	static unsigned int len = key ? sizeof(key) / sizeof(key[0]) : 0;
102 -
	unsigned int i;
103 -
	KeySym keysym;
104 -
105 -
	keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0);
106 -
	for(i = 0; i < len; i++)
107 -
		if((keysym == key[i].keysym) && (key[i].mod == ev->state)) {
108 -
			if(key[i].func)
109 -
				key[i].func(&key[i].arg);
110 -
			return;
111 -
		}
112 -
}
113 -
114 -
static void
115 -
resizemouse(Client *c)
116 -
{
117 -
	XEvent ev;
118 -
	int ocx, ocy;
119 -
120 -
	ocx = c->x;
121 -
	ocy = c->y;
122 -
	if(XGrabPointer(dpy, root, False, MouseMask, GrabModeAsync, GrabModeAsync,
123 -
				None, cursor[CurResize], CurrentTime) != GrabSuccess)
124 -
		return;
125 -
	XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w, c->h);
126 -
	for(;;) {
127 -
		XMaskEvent(dpy, MouseMask | ExposureMask, &ev);
128 -
		switch(ev.type) {
129 -
		default: break;
130 -
		case Expose:
131 -
			handler[Expose](&ev);
132 -
			break;
133 -
		case MotionNotify:
134 -
			XFlush(dpy);
135 -
			c->w = abs(ocx - ev.xmotion.x);
136 -
			c->h = abs(ocy - ev.xmotion.y);
137 -
			c->x = (ocx <= ev.xmotion.x) ? ocx : ocx - c->w;
138 -
			c->y = (ocy <= ev.xmotion.y) ? ocy : ocy - c->h;
139 -
			resize(c, True);
140 -
			break;
141 -
		case ButtonRelease:
142 -
			XUngrabPointer(dpy, CurrentTime);
143 -
			return;
144 -
		}
145 -
	}
146 -
}
147 -
148 -
static void
149 -
movemouse(Client *c)
150 -
{
151 -
	XEvent ev;
152 -
	int x1, y1, ocx, ocy, di;
153 -
	unsigned int dui;
154 -
	Window dummy;
155 -
156 -
	ocx = c->x;
157 -
	ocy = c->y;
158 -
	if(XGrabPointer(dpy, root, False, MouseMask, GrabModeAsync, GrabModeAsync,
159 -
				None, cursor[CurMove], CurrentTime) != GrabSuccess)
160 -
		return;
161 -
	XQueryPointer(dpy, root, &dummy, &dummy, &x1, &y1, &di, &di, &dui);
162 -
	for(;;) {
163 -
		XMaskEvent(dpy, MouseMask | ExposureMask, &ev);
164 -
		switch (ev.type) {
165 -
		default: break;
166 -
		case Expose:
167 -
			handler[Expose](&ev);
168 -
			break;
169 -
		case MotionNotify:
170 -
			XFlush(dpy);
171 -
			c->x = ocx + (ev.xmotion.x - x1);
172 -
			c->y = ocy + (ev.xmotion.y - y1);
173 -
			resize(c, False);
174 -
			break;
175 -
		case ButtonRelease:
176 -
			XUngrabPointer(dpy, CurrentTime);
177 -
			return;
178 -
		}
179 -
	}
180 -
}
54 +
static void movemouse(Client *c);
55 +
static void resizemouse(Client *c);
181 56
182 57
static void
183 58
buttonpress(XEvent *e)
280 155
}
281 156
282 157
static void
283 -
leavenotify(XEvent *e)
284 -
{
285 -
	XCrossingEvent *ev = &e->xcrossing;
286 -
287 -
	if((ev->window == root) && !ev->same_screen)
288 -
		issel = True;
289 -
}
290 -
291 -
static void
292 158
expose(XEvent *e)
293 159
{
294 160
	XExposeEvent *ev = &e->xexpose;
303 169
}
304 170
305 171
static void
172 +
keypress(XEvent *e)
173 +
{
174 +
	XKeyEvent *ev = &e->xkey;
175 +
	static unsigned int len = key ? sizeof(key) / sizeof(key[0]) : 0;
176 +
	unsigned int i;
177 +
	KeySym keysym;
178 +
179 +
	keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0);
180 +
	for(i = 0; i < len; i++)
181 +
		if((keysym == key[i].keysym) && (key[i].mod == ev->state)) {
182 +
			if(key[i].func)
183 +
				key[i].func(&key[i].arg);
184 +
			return;
185 +
		}
186 +
}
187 +
188 +
static void
189 +
leavenotify(XEvent *e)
190 +
{
191 +
	XCrossingEvent *ev = &e->xcrossing;
192 +
193 +
	if((ev->window == root) && !ev->same_screen)
194 +
		issel = True;
195 +
}
196 +
197 +
static void
306 198
maprequest(XEvent *e)
307 199
{
308 200
	XMapRequestEvent *ev = &e->xmaprequest;
322 214
}
323 215
324 216
static void
217 +
movemouse(Client *c)
218 +
{
219 +
	XEvent ev;
220 +
	int x1, y1, ocx, ocy, di;
221 +
	unsigned int dui;
222 +
	Window dummy;
223 +
224 +
	ocx = c->x;
225 +
	ocy = c->y;
226 +
	if(XGrabPointer(dpy, root, False, MouseMask, GrabModeAsync, GrabModeAsync,
227 +
				None, cursor[CurMove], CurrentTime) != GrabSuccess)
228 +
		return;
229 +
	XQueryPointer(dpy, root, &dummy, &dummy, &x1, &y1, &di, &di, &dui);
230 +
	for(;;) {
231 +
		XMaskEvent(dpy, MouseMask | ExposureMask, &ev);
232 +
		switch (ev.type) {
233 +
		default: break;
234 +
		case Expose:
235 +
			handler[Expose](&ev);
236 +
			break;
237 +
		case MotionNotify:
238 +
			XFlush(dpy);
239 +
			c->x = ocx + (ev.xmotion.x - x1);
240 +
			c->y = ocy + (ev.xmotion.y - y1);
241 +
			resize(c, False);
242 +
			break;
243 +
		case ButtonRelease:
244 +
			XUngrabPointer(dpy, CurrentTime);
245 +
			return;
246 +
		}
247 +
	}
248 +
}
249 +
250 +
static void
325 251
propertynotify(XEvent *e)
326 252
{
327 253
	XPropertyEvent *ev = &e->xproperty;
355 281
}
356 282
357 283
static void
284 +
resizemouse(Client *c)
285 +
{
286 +
	XEvent ev;
287 +
	int ocx, ocy;
288 +
289 +
	ocx = c->x;
290 +
	ocy = c->y;
291 +
	if(XGrabPointer(dpy, root, False, MouseMask, GrabModeAsync, GrabModeAsync,
292 +
				None, cursor[CurResize], CurrentTime) != GrabSuccess)
293 +
		return;
294 +
	XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w, c->h);
295 +
	for(;;) {
296 +
		XMaskEvent(dpy, MouseMask | ExposureMask, &ev);
297 +
		switch(ev.type) {
298 +
		default: break;
299 +
		case Expose:
300 +
			handler[Expose](&ev);
301 +
			break;
302 +
		case MotionNotify:
303 +
			XFlush(dpy);
304 +
			c->w = abs(ocx - ev.xmotion.x);
305 +
			c->h = abs(ocy - ev.xmotion.y);
306 +
			c->x = (ocx <= ev.xmotion.x) ? ocx : ocx - c->w;
307 +
			c->y = (ocy <= ev.xmotion.y) ? ocy : ocy - c->h;
308 +
			resize(c, True);
309 +
			break;
310 +
		case ButtonRelease:
311 +
			XUngrabPointer(dpy, CurrentTime);
312 +
			return;
313 +
		}
314 +
	}
315 +
}
316 +
317 +
static void
358 318
unmapnotify(XEvent *e)
359 319
{
360 320
	Client *c;
363 323
	if((c = getclient(ev->window)))
364 324
		unmanage(c);
365 325
}
326 +
327 +
/* extern functions */
328 +
329 +
void (*handler[LASTEvent]) (XEvent *) = {
330 +
	[ButtonPress] = buttonpress,
331 +
	[ConfigureRequest] = configurerequest,
332 +
	[DestroyNotify] = destroynotify,
333 +
	[EnterNotify] = enternotify,
334 +
	[LeaveNotify] = leavenotify,
335 +
	[Expose] = expose,
336 +
	[KeyPress] = keypress,
337 +
	[MapRequest] = maprequest,
338 +
	[PropertyNotify] = propertynotify,
339 +
	[UnmapNotify] = unmapnotify
340 +
};
341 +
342 +
void
343 +
grabkeys()
344 +
{
345 +
	static unsigned int len = key ? sizeof(key) / sizeof(key[0]) : 0;
346 +
	unsigned int i;
347 +
	KeyCode code;
348 +
349 +
	for(i = 0; i < len; i++) {
350 +
		code = XKeysymToKeycode(dpy, key[i].keysym);
351 +
		XUngrabKey(dpy, code, key[i].mod, root);
352 +
		XGrabKey(dpy, code, key[i].mod, root, True,
353 +
				GrabModeAsync, GrabModeAsync);
354 +
	}
355 +
}
main.c +29 −42
3 3
 * See LICENSE file for license details.
4 4
 */
5 5
6 +
#include "dwm.h"
7 +
6 8
#include <errno.h>
7 -
#include <stdarg.h>
8 9
#include <stdio.h>
9 10
#include <stdlib.h>
10 11
#include <string.h>
11 12
#include <unistd.h>
12 -
13 13
#include <X11/cursorfont.h>
14 14
#include <X11/Xatom.h>
15 15
#include <X11/Xproto.h>
16 16
17 -
#include "dwm.h"
18 -
19 -
/********** CUSTOMIZE **********/
20 -
21 -
char *tags[TLast] = {
22 -
	[Tscratch] = "scratch",
23 -
	[Tdev] = "dev",
24 -
	[Twww] = "www",
25 -
	[Twork] = "work",
26 -
};
27 -
28 -
/********** CUSTOMIZE **********/
29 -
30 -
/* X structs */
31 17
Display *dpy;
32 18
Window root, barwin;
33 19
Atom wm_atom[WMLast], net_atom[NetLast];
48 34
	"dwm-" VERSION ", (C)opyright MMVI Anselm R. Garbe\n";
49 35
static int (*xerrorxlib)(Display *, XErrorEvent *);
50 36
37 +
/* static functions */
38 +
51 39
static void
52 -
usage() {	eprint("usage: dwm [-v]\n"); }
40 +
cleanup()
41 +
{
42 +
	while(sel) {
43 +
		resize(sel, True);
44 +
		unmanage(sel);
45 +
	}
46 +
	XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
47 +
}
53 48
54 49
static void
55 50
scan()
73 68
		XFree(wins);
74 69
}
75 70
76 -
static void
77 -
cleanup()
78 -
{
79 -
	while(sel) {
80 -
		resize(sel, True);
81 -
		unmanage(sel);
82 -
	}
83 -
	XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
84 -
}
85 -
86 -
void
87 -
quit(Arg *arg)
88 -
{
89 -
	running = False;
90 -
}
91 -
92 71
static int
93 72
win_property(Window w, Atom a, Atom t, long l, unsigned char **prop)
94 73
{
109 88
	return res;
110 89
}
111 90
91 +
/*
92 +
 * Startup Error handler to check if another window manager
93 +
 * is already running.
94 +
 */
95 +
static int
96 +
xerrorstart(Display *dsply, XErrorEvent *ee)
97 +
{
98 +
	otherwm = True;
99 +
	return -1;
100 +
}
101 +
102 +
/* extern functions */
103 +
112 104
int
113 105
getproto(Window w)
114 106
{
144 136
	XFlush(dpy);
145 137
}
146 138
147 -
/*
148 -
 * Startup Error handler to check if another window manager
149 -
 * is already running.
150 -
 */
151 -
static int
152 -
xerrorstart(Display *dsply, XErrorEvent *ee)
139 +
void
140 +
quit(Arg *arg)
153 141
{
154 -
	otherwm = True;
155 -
	return -1;
142 +
	running = False;
156 143
}
157 144
158 145
/*
201 188
			exit(0);
202 189
			break;
203 190
		default:
204 -
			usage();
191 +
			eprint("usage: dwm [-v]\n");
205 192
			break;
206 193
		}
207 194
	}
tag.c +63 −55
2 2
 * (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
3 3
 * See LICENSE file for license details.
4 4
 */
5 +
#include "dwm.h"
5 6
6 -
#include <stdlib.h>
7 -
#include <stdio.h>
8 7
#include <string.h>
9 -
#include <X11/Xatom.h>
10 8
#include <X11/Xutil.h>
11 9
12 -
#include "dwm.h"
10 +
/********** CUSTOMIZE **********/
11 +
12 +
char *tags[TLast] = {
13 +
	[Tscratch] = "scratch",
14 +
	[Tdev] = "dev",
15 +
	[Twww] = "www",
16 +
	[Twork] = "work",
17 +
};
13 18
14 19
static Rule rule[] = {
15 20
	/* class			instance	tags						dofloat */
16 21
	{ "Firefox-bin",	"Gecko",	{ [Twww] = "www" },			False },
17 22
};
18 23
19 -
void (*arrange)(Arg *) = dotile;
24 +
/********** CUSTOMIZE **********/
20 25
21 -
Client *
22 -
getnext(Client *c)
23 -
{
24 -
	for(; c && !c->tags[tsel]; c = c->next);
25 -
	return c;
26 -
}
26 +
/* extern functions */
27 +
28 +
void (*arrange)(Arg *) = dotile;
27 29
28 30
void
29 -
settags(Client *c)
31 +
appendtag(Arg *arg)
30 32
{
31 -
	XClassHint ch;
32 -
	static unsigned int len = rule ? sizeof(rule) / sizeof(rule[0]) : 0;
33 -
	unsigned int i, j;
34 -
	Bool matched = False;
35 -
36 -
	if(!len) {
37 -
		c->tags[tsel] = tags[tsel];
33 +
	if(!sel)
38 34
		return;
39 -
	}
40 35
41 -
	if(XGetClassHint(dpy, c->win, &ch)) {
42 -
		if(ch.res_class && ch.res_name) {
43 -
			for(i = 0; i < len; i++)
44 -
				if(!strncmp(rule[i].class, ch.res_class, sizeof(rule[i].class))
45 -
					&& !strncmp(rule[i].instance, ch.res_name, sizeof(rule[i].instance)))
46 -
				{
47 -
					for(j = 0; j < TLast; j++)
48 -
						c->tags[j] = rule[i].tags[j];
49 -
					c->dofloat = rule[i].dofloat;
50 -
					matched = True;
51 -
					break;
52 -
				}
53 -
		}
54 -
		if(ch.res_class)
55 -
			XFree(ch.res_class);
56 -
		if(ch.res_name)
57 -
			XFree(ch.res_name);
58 -
	}
59 -
60 -
	if(!matched)
61 -
		c->tags[tsel] = tags[tsel];
62 -
}
63 -
64 -
void
65 -
view(Arg *arg)
66 -
{
67 -
	tsel = arg->i;
36 +
	sel->tags[arg->i] = tags[arg->i];
68 37
	arrange(NULL);
69 -
	drawall();
70 38
}
71 39
72 40
void
147 115
	drawall();
148 116
}
149 117
150 -
void
151 -
appendtag(Arg *arg)
118 +
Client *
119 +
getnext(Client *c)
152 120
{
153 -
	if(!sel)
154 -
		return;
155 -
156 -
	sel->tags[arg->i] = tags[arg->i];
157 -
	arrange(NULL);
121 +
	for(; c && !c->tags[tsel]; c = c->next);
122 +
	return c;
158 123
}
159 124
160 125
void
169 134
	appendtag(arg);
170 135
}
171 136
137 +
void
138 +
settags(Client *c)
139 +
{
140 +
	XClassHint ch;
141 +
	static unsigned int len = rule ? sizeof(rule) / sizeof(rule[0]) : 0;
142 +
	unsigned int i, j;
143 +
	Bool matched = False;
144 +
145 +
	if(!len) {
146 +
		c->tags[tsel] = tags[tsel];
147 +
		return;
148 +
	}
149 +
150 +
	if(XGetClassHint(dpy, c->win, &ch)) {
151 +
		if(ch.res_class && ch.res_name) {
152 +
			for(i = 0; i < len; i++)
153 +
				if(!strncmp(rule[i].class, ch.res_class, sizeof(rule[i].class))
154 +
					&& !strncmp(rule[i].instance, ch.res_name, sizeof(rule[i].instance)))
155 +
				{
156 +
					for(j = 0; j < TLast; j++)
157 +
						c->tags[j] = rule[i].tags[j];
158 +
					c->dofloat = rule[i].dofloat;
159 +
					matched = True;
160 +
					break;
161 +
				}
162 +
		}
163 +
		if(ch.res_class)
164 +
			XFree(ch.res_class);
165 +
		if(ch.res_name)
166 +
			XFree(ch.res_name);
167 +
	}
168 +
169 +
	if(!matched)
170 +
		c->tags[tsel] = tags[tsel];
171 +
}
172 +
173 +
void
174 +
view(Arg *arg)
175 +
{
176 +
	tsel = arg->i;
177 +
	arrange(NULL);
178 +
	drawall();
179 +
}
util.c +13 −11
2 2
 * (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
3 3
 * See LICENSE file for license details.
4 4
 */
5 +
#include "dwm.h"
5 6
6 7
#include <stdarg.h>
7 8
#include <stdio.h>
8 9
#include <stdlib.h>
9 -
#include <sys/types.h>
10 10
#include <sys/wait.h>
11 11
#include <unistd.h>
12 12
13 -
#include "dwm.h"
14 -
15 -
void
16 -
eprint(const char *errstr, ...) {
17 -
	va_list ap;
18 -
	va_start(ap, errstr);
19 -
	vfprintf(stderr, errstr, ap);
20 -
	va_end(ap);
21 -
	exit(1);
22 -
}
13 +
/* static functions */
23 14
24 15
static void
25 16
bad_malloc(unsigned int size)
28 19
			(int) size);
29 20
	exit(1);
30 21
}
22 +
23 +
/* extern functions */
31 24
32 25
void *
33 26
emallocz(unsigned int size)
36 29
	if(!res)
37 30
		bad_malloc(size);
38 31
	return res;
32 +
}
33 +
34 +
void
35 +
eprint(const char *errstr, ...) {
36 +
	va_list ap;
37 +
	va_start(ap, errstr);
38 +
	vfprintf(stderr, errstr, ap);
39 +
	va_end(ap);
40 +
	exit(1);
39 41
}
40 42
41 43
void