introduced Layout struct cdbc84b9
Anselm R. Garbe · 2007-02-19 16:40 9 file(s) · +115 −82
client.c +4 −4
263 263
	setclientstate(c, NormalState);
264 264
	if(isvisible(c))
265 265
		focus(c);
266 -
	arrange();
266 +
	lt->arrange();
267 267
}
268 268
269 269
Client *
430 430
	XSync(dpy, False);
431 431
	XSetErrorHandler(xerror);
432 432
	XUngrabServer(dpy);
433 -
	arrange();
433 +
	lt->arrange();
434 434
}
435 435
436 436
void
440 440
441 441
	if(!sel)
442 442
		return;
443 -
	if(sel->isfloat || (arrange == dofloat)) {
443 +
	if(sel->isfloat || (lt->arrange == dofloat)) {
444 444
		togglemax(sel);
445 445
		return;
446 446
	}
452 452
	detach(c);
453 453
	attach(c);
454 454
	focus(c);
455 -
	arrange();
455 +
	lt->arrange();
456 456
}
config.arg.h +7 −4
5 5
#define TAGS \
6 6
const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9", NULL };
7 7
8 -
#define DEFMODE			dotile		/* dofloat */
9 -
#define FLOATSYMBOL		"><>"
10 -
#define TILESYMBOL		"[]="
8 +
#define LAYOUTS \
9 +
static Layout layout[] = { \
10 +
	/* symbol		function */ \
11 +
	{ "[]=",		dotile }, /* first entry is default */ \
12 +
	{ "><>",		dofloat }, \
13 +
};
11 14
12 15
#define BORDERPX		1
13 16
#define FONT			"-*-terminus-medium-r-*-*-14-*-*-*-*-*-*-*"
60 63
	{ MODKEY|ControlMask|ShiftMask,	XK_8,		toggletag,	{ .i = 7 } }, \
61 64
	{ MODKEY|ControlMask|ShiftMask,	XK_9,		toggletag,	{ .i = 8 } }, \
62 65
	{ MODKEY|ShiftMask,		XK_c,		killclient,	{ 0 } }, \
63 -
	{ MODKEY,			XK_space,	togglemode,	{ 0 } }, \
66 +
	{ MODKEY,			XK_space,	togglelayout,	{ 0 } }, \
64 67
	{ MODKEY|ShiftMask,		XK_space,	togglefloat,	{ 0 } }, \
65 68
	{ MODKEY,			XK_0,		view,		{ .i = -1 } }, \
66 69
	{ MODKEY,			XK_1,		view,		{ .i = 0 } }, \
config.default.h +7 −4
5 5
#define TAGS \
6 6
const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9", NULL };
7 7
8 -
#define DEFMODE			dotile		/* dofloat */
9 -
#define FLOATSYMBOL		"><>"
10 -
#define TILESYMBOL		"[]="
8 +
#define LAYOUTS \
9 +
Layout layout[] = { \
10 +
	/* symbol		function */ \
11 +
	{ "[]=",		dotile }, /* first entry is default */ \
12 +
	{ "><>",		dofloat }, \
13 +
};
11 14
12 15
#define BORDERPX		1
13 16
#define FONT			"-*-fixed-medium-r-normal-*-13-*-*-*-*-*-*-*"
55 58
	{ MODKEY|ControlMask|ShiftMask,	XK_8,		toggletag,	{ .i = 7 } }, \
56 59
	{ MODKEY|ControlMask|ShiftMask,	XK_9,		toggletag,	{ .i = 8 } }, \
57 60
	{ MODKEY|ShiftMask,		XK_c,		killclient,	{ 0 } }, \
58 -
	{ MODKEY,			XK_space,	togglemode,	{ 0 } }, \
61 +
	{ MODKEY,			XK_space,	togglelayout,	{ 0 } }, \
59 62
	{ MODKEY|ShiftMask,		XK_space,	togglefloat,	{ 0 } }, \
60 63
	{ MODKEY,			XK_0,		view,		{ .i = -1 } }, \
61 64
	{ MODKEY,			XK_1,		view,		{ .i = 0 } }, \
config.mk +2 −2
17 17
# flags
18 18
CFLAGS = -Os ${INCS} -DVERSION=\"${VERSION}\"
19 19
LDFLAGS = ${LIBS}
20 -
#CFLAGS = -g -Wall -O2 ${INCS} -DVERSION=\"${VERSION}\"
21 -
#LDFLAGS = -g ${LIBS}
20 +
CFLAGS = -g -Wall -O2 ${INCS} -DVERSION=\"${VERSION}\"
21 +
LDFLAGS = -g ${LIBS}
22 22
23 23
# Solaris
24 24
#CFLAGS = -fast ${INCS} -DVERSION=\"${VERSION}\"
dwm.1 +19 −19
6 6
.RB [ \-v ]
7 7
.SH DESCRIPTION
8 8
dwm is a dynamic window manager for X. It manages windows in tiling and
9 -
floating modes. Either mode can be applied dynamically, optimizing the
9 +
floating layouts. Either layout can be applied dynamically, optimizing the
10 10
environment for the application in use and the task performed.
11 11
.P
12 -
In tiling mode windows are managed in a master and stacking area. The master
12 +
In tiling layout windows are managed in a master and stacking area. The master
13 13
area contains the windows which currently need most attention, whereas the
14 -
stacking area contains all other windows. In floating mode windows can be
14 +
stacking area contains all other windows. In floating layout windows can be
15 15
resized and moved freely. Dialog windows are always managed floating,
16 -
regardless of the mode applied.
16 +
regardless of the layout applied.
17 17
.P
18 18
Windows are grouped by tags. Each window can be tagged with one or multiple
19 19
tags. Selecting certain tags displays all windows with these tags.
20 20
.P
21 -
dwm contains a small status bar which displays all available tags, the mode,
21 +
dwm contains a small status bar which displays all available tags, the layout,
22 22
the title of the focused window, and the text read from standard input. The
23 23
selected tags are indicated with a different color. The tags of the focused
24 24
window are indicated with a filled square in the top left corner.  The tags
37 37
is read and displayed in the status text area.
38 38
.TP
39 39
.B Button1
40 -
click on a tag label to display all windows with that tag, click on the mode
41 -
label toggles between tiling and floating mode.
40 +
click on a tag label to display all windows with that tag, click on the layout
41 +
label toggles between tiling and floating layout.
42 42
.TP
43 43
.B Button3
44 44
click on a tag label adds/removes all windows with that tag to/from the view.
45 45
.TP
46 46
.B Button4
47 -
click on the mode label increases the number of windows in the master area (tiling mode only).
47 +
click on the layout label increases the number of windows in the master area (tiling layout only).
48 48
.TP
49 49
.B Button5
50 -
click on the mode label decreases the number of windows in the master area (tiling mode only).
50 +
click on the layout label decreases the number of windows in the master area (tiling layout only).
51 51
.TP
52 52
.B Mod1-Button1
53 53
click on a tag label applies that tag to the focused window.
67 67
Focus previous window.
68 68
.TP
69 69
.B Mod1-Return
70 -
Zooms/cycles current window to/from master area (tiling mode), toggles maximization of current window (floating mode).
70 +
Zooms/cycles current window to/from master area (tiling layout), toggles maximization of current window (floating layout).
71 71
.TP
72 72
.B Mod1-g
73 -
Grow master area (tiling mode only).
73 +
Grow master area (tiling layout only).
74 74
.TP
75 75
.B Mod1-s
76 -
Shrink master area (tiling mode only).
76 +
Shrink master area (tiling layout only).
77 77
.TP
78 78
.B Mod1-i
79 -
Increase the number of windows in the master area (tiling mode only).
79 +
Increase the number of windows in the master area (tiling layout only).
80 80
.TP
81 81
.B Mod1-d
82 -
Decrease the number of windows in the master area (tiling mode only).
82 +
Decrease the number of windows in the master area (tiling layout only).
83 83
.TP
84 84
.B Mod1-Shift-[1..n]
85 85
Apply
98 98
Close focused window.
99 99
.TP
100 100
.B Mod1-space
101 -
Toggle between tiling and floating mode (affects all windows).
101 +
Toggle between tiling and floating layout (affects all windows).
102 102
.TP
103 103
.B Mod1-Shift-space
104 -
Toggle focused window between floating and non-floating state (tiling mode only).
104 +
Toggle focused window between floating and non-floating state (tiling layout only).
105 105
.TP
106 106
.B Mod1-[1..n]
107 107
View all windows with
121 121
.SS Mouse commands
122 122
.TP
123 123
.B Mod1-Button1
124 -
Move current window while dragging (floating mode only).
124 +
Move current window while dragging (floating layout only).
125 125
.TP
126 126
.B Mod1-Button2
127 -
Zooms/cycles current window to/from master area (tiling mode), toggles maximization of current window (floating mode).
127 +
Zooms/cycles current window to/from master area (tiling layout), toggles maximization of current window (floating layout).
128 128
.TP
129 129
.B Mod1-Button3
130 -
Resize current window while dragging (floating mode only).
130 +
Resize current window while dragging (floating layout only).
131 131
.SH CUSTOMIZATION
132 132
dwm is customized by creating a custom config.h and (re)compiling the source
133 133
code. This keeps it fast, secure and simple.
dwm.h +12 −7
24 24
 *
25 25
 * Keys and tagging rules are organized as arrays and defined in the config.h
26 26
 * file. These arrays are kept static in event.o and tag.o respectively,
27 -
 * because no other part of dwm needs access to them.  The current mode is
28 -
 * represented by the arrange() function pointer, which wether points to
29 -
 * dofloat() or dotile(). 
27 +
 * because no other part of dwm needs access to them.  The current layout is
28 +
 * represented by the lt pointer.
30 29
 *
31 30
 * To understand everything else, start reading main.c:main().
32 31
 */
80 79
	Client *snext;
81 80
	Window win;
82 81
};
82 +
83 +
typedef struct {
84 +
	const char *symbol;
85 +
	void (*arrange)(void);
86 +
} Layout;
83 87
84 88
extern const char *tags[];			/* all tags */
85 89
extern char stext[256];				/* status text */
86 -
extern int bh, bmw;				/* bar height, bar mode label width */
87 90
extern int screen, sx, sy, sw, sh;		/* screen geometry */
88 91
extern int wax, way, wah, waw;			/* windowarea geometry */
92 +
extern unsigned int bh, blw;			/* bar height, bar layout label width */
89 93
extern unsigned int master, nmaster;		/* master percent, number of master clients */
90 94
extern unsigned int ntags, numlockmask;		/* number of tags, dynamic lock mask */
91 95
extern void (*handler[LASTEvent])(XEvent *);	/* event handler */
92 -
extern void (*arrange)(void);			/* arrange function, indicates mode  */
93 96
extern Atom wmatom[WMLast], netatom[NetLast];
94 97
extern Bool running, selscreen, *seltag;	/* seltag is array of Bool */
95 98
extern Client *clients, *sel, *stack;		/* global client list and stack */
96 99
extern Cursor cursor[CurLast];
97 100
extern DC dc;					/* global draw context */
98 101
extern Display *dpy;
102 +
extern Layout *lt;
99 103
extern Window root, barwin;
100 104
101 105
/* client.c */
124 128
extern int xerror(Display *dsply, XErrorEvent *ee);	/* dwm's X error handler */
125 129
126 130
/* screen.c */
127 -
extern void compileregexps(void);		/* initialize regexps of rules defined in config.h */
131 +
extern void compileregs(void);			/* initialize regexps of rules defined in config.h */
128 132
extern void dofloat(void);			/* arranges all windows floating */
129 133
extern void dotile(void);			/* arranges all windows tiled */
130 134
extern void incnmaster(Arg *arg);		/* increments nmaster with arg's index value */
135 +
extern void initlayouts(void);			/* initialize layout array */
131 136
extern Bool isvisible(Client *c);		/* returns True if client is visible */
132 137
extern void resizemaster(Arg *arg);		/* resizes the master percent with arg's index value */
133 138
extern void restack(void);			/* restores z layers of all clients */
134 139
extern void settags(Client *c, Client *trans);	/* sets tags of c */
135 140
extern void tag(Arg *arg);			/* tags c with arg's index */
136 141
extern void togglefloat(Arg *arg);		/* toggles focusesd client between floating/non-floating state */
137 -
extern void togglemode(Arg *arg);		/* toggles global arrange function (dotile/dofloat) */
142 +
extern void togglelayout(Arg *arg);		/* toggles layout */
138 143
extern void toggletag(Arg *arg);		/* toggles c tags with arg's index */
139 144
extern void toggleview(Arg *arg);		/* toggles the tag with arg's index (in)visible */
140 145
extern void view(Arg *arg);			/* views the tag with arg's index */
event.c +6 −6
137 137
				return;
138 138
			}
139 139
		}
140 -
		if(ev->x < x + bmw)
140 +
		if(ev->x < x + blw)
141 141
			switch(ev->button) {
142 142
			case Button1:
143 -
				togglemode(NULL);
143 +
				togglelayout(NULL);
144 144
				break;
145 145
			case Button4:
146 146
				a.i = 1;
156 156
		focus(c);
157 157
		if(CLEANMASK(ev->state) != MODKEY)
158 158
			return;
159 -
		if(ev->button == Button1 && (arrange == dofloat || c->isfloat)) {
159 +
		if(ev->button == Button1 && (lt->arrange == dofloat || c->isfloat)) {
160 160
			restack();
161 161
			movemouse(c);
162 162
		}
163 163
		else if(ev->button == Button2)
164 164
			zoom(NULL);
165 165
		else if(ev->button == Button3
166 -
		&& (arrange == dofloat || c->isfloat) && !c->isfixed)
166 +
		&& (lt->arrange == dofloat || c->isfloat) && !c->isfixed)
167 167
		{
168 168
			restack();
169 169
			resizemouse(c);
181 181
		c->ismax = False;
182 182
		if(ev->value_mask & CWBorderWidth)
183 183
			c->border = ev->border_width;
184 -
		if(c->isfixed || c->isfloat || (arrange == dofloat)) {
184 +
		if(c->isfixed || c->isfloat || (lt->arrange == dofloat)) {
185 185
			if(ev->value_mask & CWX)
186 186
				c->x = ev->x;
187 187
			if(ev->value_mask & CWY)
310 310
			case XA_WM_TRANSIENT_FOR:
311 311
				XGetTransientForHint(dpy, c->win, &trans);
312 312
				if(!c->isfloat && (c->isfloat = (trans != 0)))
313 -
					arrange();
313 +
					lt->arrange();
314 314
				break;
315 315
			case XA_WM_NORMAL_HINTS:
316 316
				updatesizehints(c);
main.c +6 −6
18 18
/* extern */
19 19
20 20
char stext[256];
21 -
int bh, bmw, screen, sx, sy, sw, sh, wax, way, waw, wah;
22 -
unsigned int ntags, numlockmask;
21 +
int screen, sx, sy, sw, sh, wax, way, waw, wah;
22 +
unsigned int bh, ntags, numlockmask;
23 23
Atom wmatom[WMLast], netatom[NetLast];
24 24
Bool running = True;
25 25
Bool *seltag;
246 246
	wa.cursor = cursor[CurNormal];
247 247
	XChangeWindowAttributes(dpy, root, CWEventMask | CWCursor, &wa);
248 248
	grabkeys();
249 -
	compileregexps();
249 +
	compileregs();
250 250
	for(ntags = 0; tags[ntags]; ntags++);
251 251
	seltag = emallocz(sizeof(Bool) * ntags);
252 252
	seltag[0] = True;
262 262
	sx = sy = 0;
263 263
	sw = DisplayWidth(dpy, screen);
264 264
	sh = DisplayHeight(dpy, screen);
265 -
	bmw = textw(TILESYMBOL) > textw(FLOATSYMBOL) ? textw(TILESYMBOL) : textw(FLOATSYMBOL);
265 +
	initlayouts();
266 266
	/* bar */
267 267
	dc.h = bh = dc.font.height + 2;
268 268
	wa.override_redirect = 1;
312 312
			drawtext(tags[i], dc.norm, sel && sel->tags[i], isoccupied(i));
313 313
		dc.x += dc.w;
314 314
	}
315 -
	dc.w = bmw;
316 -
	drawtext(arrange == dofloat ? FLOATSYMBOL : TILESYMBOL, dc.norm, False, False);
315 +
	dc.w = blw;
316 +
	drawtext(lt->symbol, dc.norm, False, False);
317 317
	x = dc.x + dc.w;
318 318
	dc.w = textw(stext);
319 319
	dc.x = sw - dc.w;
screen.c +52 −30
9 9
#include <sys/types.h>
10 10
#include <X11/Xutil.h>
11 11
12 -
void (*arrange)(void) = DEFMODE;
13 12
unsigned int master = MASTER;
14 13
unsigned int nmaster = NMASTER;
14 +
unsigned int blw = 0;
15 +
Layout *lt = NULL;
15 16
16 17
/* static */
17 18
24 25
typedef struct {
25 26
	regex_t *propregex;
26 27
	regex_t *tagregex;
27 -
} Regexps;
28 +
} Regs;
28 29
30 +
LAYOUTS
29 31
TAGS
30 32
RULES
31 33
32 -
static Regexps *regexps = NULL;
33 -
static unsigned int len = 0;
34 +
static Regs *regs = NULL;
35 +
static unsigned int nrules = 0;
36 +
static unsigned int nlayouts = 0;
34 37
35 38
/* extern */
36 39
37 40
void
38 -
compileregexps(void) {
41 +
compileregs(void) {
39 42
	unsigned int i;
40 43
	regex_t *reg;
41 44
42 -
	if(regexps)
45 +
	if(regs)
43 46
		return;
44 -
	len = sizeof rule / sizeof rule[0];
45 -
	regexps = emallocz(len * sizeof(Regexps));
46 -
	for(i = 0; i < len; i++) {
47 +
	nrules = sizeof rule / sizeof rule[0];
48 +
	regs = emallocz(nrules * sizeof(Regs));
49 +
	for(i = 0; i < nrules; i++) {
47 50
		if(rule[i].prop) {
48 51
			reg = emallocz(sizeof(regex_t));
49 52
			if(regcomp(reg, rule[i].prop, REG_EXTENDED))
50 53
				free(reg);
51 54
			else
52 -
				regexps[i].propregex = reg;
55 +
				regs[i].propregex = reg;
53 56
		}
54 57
		if(rule[i].tags) {
55 58
			reg = emallocz(sizeof(regex_t));
56 59
			if(regcomp(reg, rule[i].tags, REG_EXTENDED))
57 60
				free(reg);
58 61
			else
59 -
				regexps[i].tagregex = reg;
62 +
				regs[i].tagregex = reg;
60 63
		}
61 64
	}
62 65
}
138 141
139 142
void
140 143
incnmaster(Arg *arg) {
141 -
	if((arrange == dofloat) || (nmaster + arg->i < 1)
144 +
	if((lt->arrange == dofloat) || (nmaster + arg->i < 1)
142 145
	|| (wah / (nmaster + arg->i) <= 2 * BORDERPX))
143 146
		return;
144 147
	nmaster += arg->i;
145 148
	if(sel)
146 -
		arrange();
149 +
		lt->arrange();
147 150
	else
148 151
		drawstatus();
149 152
}
150 153
154 +
void
155 +
initlayouts(void) {
156 +
	unsigned int i, w;
157 +
158 +
	lt = &layout[0];
159 +
	nlayouts = sizeof layout / sizeof layout[0];
160 +
	for(blw = i = 0; i < nlayouts; i++) {
161 +
		w = textw(layout[i].symbol);
162 +
		if(w > blw)
163 +
			blw = w;
164 +
	}
165 +
}
166 +
151 167
Bool
152 168
isvisible(Client *c) {
153 169
	unsigned int i;
160 176
161 177
void
162 178
resizemaster(Arg *arg) {
163 -
	if(arrange != dotile)
179 +
	if(lt->arrange != dotile)
164 180
		return;
165 181
	if(arg->i == 0)
166 182
		master = MASTER;
170 186
			return;
171 187
		master += arg->i;
172 188
	}
173 -
	arrange();
189 +
	lt->arrange();
174 190
}
175 191
176 192
void
181 197
	drawstatus();
182 198
	if(!sel)
183 199
		return;
184 -
	if(sel->isfloat || arrange == dofloat)
200 +
	if(sel->isfloat || lt->arrange == dofloat)
185 201
		XRaiseWindow(dpy, sel->win);
186 -
	if(arrange != dofloat) {
202 +
	if(lt->arrange != dofloat) {
187 203
		if(!sel->isfloat)
188 204
			XLowerWindow(dpy, sel->win);
189 205
		for(c = nexttiled(clients); c; c = nexttiled(c->next)) {
212 228
		snprintf(prop, sizeof prop, "%s:%s:%s",
213 229
				ch.res_class ? ch.res_class : "",
214 230
				ch.res_name ? ch.res_name : "", c->name);
215 -
		for(i = 0; i < len; i++)
216 -
			if(regexps[i].propregex && !regexec(regexps[i].propregex, prop, 1, &tmp, 0)) {
231 +
		for(i = 0; i < nrules; i++)
232 +
			if(regs[i].propregex && !regexec(regs[i].propregex, prop, 1, &tmp, 0)) {
217 233
				c->isfloat = rule[i].isfloat;
218 -
				for(j = 0; regexps[i].tagregex && j < ntags; j++) {
219 -
					if(!regexec(regexps[i].tagregex, tags[j], 1, &tmp, 0)) {
234 +
				for(j = 0; regs[i].tagregex && j < ntags; j++) {
235 +
					if(!regexec(regs[i].tagregex, tags[j], 1, &tmp, 0)) {
220 236
						matched = True;
221 237
						c->tags[j] = True;
222 238
					}
242 258
		sel->tags[i] = (arg->i == -1) ? True : False;
243 259
	if(arg->i >= 0 && arg->i < ntags)
244 260
		sel->tags[arg->i] = True;
245 -
	arrange();
261 +
	lt->arrange();
246 262
}
247 263
248 264
void
249 265
togglefloat(Arg *arg) {
250 -
	if(!sel || arrange == dofloat)
266 +
	if(!sel || lt->arrange == dofloat)
251 267
		return;
252 268
	sel->isfloat = !sel->isfloat;
253 -
	arrange();
269 +
	lt->arrange();
254 270
}
255 271
256 272
void
263 279
	for(i = 0; i < ntags && !sel->tags[i]; i++);
264 280
	if(i == ntags)
265 281
		sel->tags[arg->i] = True;
266 -
	arrange();
282 +
	lt->arrange();
267 283
}
268 284
269 285
void
270 -
togglemode(Arg *arg) {
271 -
	arrange = (arrange == dofloat) ? dotile : dofloat;
286 +
togglelayout(Arg *arg) {
287 +
	unsigned int i;
288 +
289 +
	for(i = 0; i < nlayouts && lt != &layout[i]; i++);
290 +
	if(i == nlayouts - 1)
291 +
		lt = &layout[0];
292 +
	else
293 +
		lt = &layout[++i];
272 294
	if(sel)
273 -
		arrange();
295 +
		lt->arrange();
274 296
	else
275 297
		drawstatus();
276 298
}
283 305
	for(i = 0; i < ntags && !seltag[i]; i++);
284 306
	if(i == ntags)
285 307
		seltag[arg->i] = True; /* cannot toggle last view */
286 -
	arrange();
308 +
	lt->arrange();
287 309
}
288 310
289 311
void
294 316
		seltag[i] = (arg->i == -1) ? True : False;
295 317
	if(arg->i >= 0 && arg->i < ntags)
296 318
		seltag[arg->i] = True;
297 -
	arrange();
319 +
	lt->arrange();
298 320
}