experimental xinerama support, two new actions, Mod1-w/e and Mod1-Shift-w/e 2ce37bc6
Anselm R Garbe · 2009-06-20 15:10 3 file(s) · +209 −121
config.def.h +9 −1
13 13
static Bool showbar                 = True;     /* False means no bar */
14 14
static Bool topbar                  = True;     /* False means bottom bar */
15 15
16 +
16 17
/* tagging */
17 18
static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
18 19
static unsigned int tagset[] = {1, 1}; /* after start, first tag is selected */
20 21
static Rule rules[] = {
21 22
	/* class      instance    title       tags mask     isfloating */
22 23
	{ "Gimp",     NULL,       NULL,       0,            True },
23 -
	{ "Firefox",  NULL,       NULL,       1 << 8,       True },
24 +
	{ "Firefox",  NULL,       NULL,       1 << 8,       False },
25 +
24 26
};
25 27
26 28
/* layout(s) */
68 70
	{ MODKEY|ShiftMask,             XK_space,  togglefloating, {0} },
69 71
	{ MODKEY,                       XK_0,      view,           {.ui = ~0 } },
70 72
	{ MODKEY|ShiftMask,             XK_0,      tag,            {.ui = ~0 } },
73 +
#ifdef XINERAMA
74 +
	{ MODKEY,                       XK_w,      focusmon,       {.ui = 0 } },
75 +
	{ MODKEY,                       XK_e,      focusmon,       {.ui = 1 } },
76 +
	{ MODKEY|ShiftMask,             XK_w,      tagmon,         {.ui = 0 } },
77 +
	{ MODKEY|ShiftMask,             XK_e,      tagmon,         {.ui = 1 } },
78 +
#endif /* XINERAMA */
71 79
	TAGKEYS(                        XK_1,                      0)
72 80
	TAGKEYS(                        XK_2,                      1)
73 81
	TAGKEYS(                        XK_3,                      2)
config.mk +6 −4
11 11
X11LIB = /usr/X11R6/lib
12 12
13 13
# Xinerama, un-comment if you want it
14 -
#XINERAMALIBS = -L${X11LIB} -lXinerama
15 -
#XINERAMAFLAGS = -DXINERAMA
14 +
XINERAMALIBS = -L${X11LIB} -lXinerama
15 +
XINERAMAFLAGS = -DXINERAMA
16 16
17 17
# includes and libs
18 18
INCS = -I. -I/usr/include -I${X11INC}
20 20
21 21
# flags
22 22
CPPFLAGS = -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS}
23 -
CFLAGS = -std=c99 -pedantic -Wall -Os ${INCS} ${CPPFLAGS}
24 -
LDFLAGS = -s ${LIBS}
23 +
CFLAGS = -g -std=c99 -pedantic -Wall -O0 ${INCS} ${CPPFLAGS}
24 +
#CFLAGS = -std=c99 -pedantic -Wall -Os ${INCS} ${CPPFLAGS}
25 +
LDFLAGS = -g ${LIBS}
26 +
#LDFLAGS = -s ${LIBS}
25 27
26 28
# Solaris
27 29
#CFLAGS = -fast ${INCS} -DVERSION=\"${VERSION}\"
dwm.c +194 −116
38 38
#include <X11/Xutil.h>
39 39
#ifdef XINERAMA
40 40
#include <X11/extensions/Xinerama.h>
41 -
#endif
41 +
#endif /* XINERAMA */
42 42
43 43
/* macros */
44 44
#define BUTTONMASK              (ButtonPressMask|ButtonReleaseMask)
45 45
#define CLEANMASK(mask)         (mask & ~(numlockmask|LockMask))
46 46
#define INRECT(X,Y,RX,RY,RW,RH) ((X) >= (RX) && (X) < (RX) + (RW) && (Y) >= (RY) && (Y) < (RY) + (RH))
47 -
#define ISVISIBLE(x)            (x->tags & tagset[selmon->seltags])
47 +
#define ISVISIBLE(x)            (x->tags & tagset[mon[x->mon].seltags])
48 48
#define LENGTH(x)               (sizeof x / sizeof x[0])
49 49
#define MAX(a, b)               ((a) > (b) ? (a) : (b))
50 50
#define MIN(a, b)               ((a) < (b) ? (a) : (b))
115 115
} Key;
116 116
117 117
typedef struct {
118 -
	const char *symbol;
119 -
	void (*arrange)(void);
120 -
} Layout;
121 -
122 -
typedef struct {
123 -
	int wx, wy, ww, wh;
118 +
	char symbol[4];
119 +
	int by, btx;          /* bar geometry */
120 +
	int wx, wy, ww, wh;   /* window area  */
124 121
	unsigned int seltags;
125 122
	unsigned int sellt;
123 +
	Bool showbar;
124 +
	Bool topbar;
125 +
	Window barwin;
126 126
} Monitor;
127 127
128 128
typedef struct {
129 +
	const char *symbol;
130 +
	void (*arrange)(Monitor *);
131 +
} Layout;
132 +
133 +
typedef struct {
129 134
	const char *class;
130 135
	const char *instance;
131 136
	const char *title;
150 155
static void detach(Client *c);
151 156
static void detachstack(Client *c);
152 157
static void die(const char *errstr, ...);
153 -
static void drawbar(void);
158 +
static void drawbar(Monitor *m);
159 +
static void drawbars();
154 160
static void drawsquare(Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]);
155 161
static void drawtext(const char *text, unsigned long col[ColLast], Bool invert);
156 162
static void enternotify(XEvent *e);
171 177
static void manage(Window w, XWindowAttributes *wa);
172 178
static void mappingnotify(XEvent *e);
173 179
static void maprequest(XEvent *e);
174 -
static void monocle(void);
180 +
static void monocle(Monitor *m);
175 181
static void movemouse(const Arg *arg);
176 -
static Client *nexttiled(Client *c);
182 +
static Client *nexttiled(Monitor *m, Client *c);
177 183
static void propertynotify(XEvent *e);
178 184
static void quit(const Arg *arg);
179 185
static void resize(Client *c, int x, int y, int w, int h);
180 186
static void resizemouse(const Arg *arg);
181 -
static void restack(void);
187 +
static void restack(Monitor *m);
182 188
static void run(void);
183 189
static void scan(void);
184 190
static void setclientstate(Client *c, long state);
190 196
static void spawn(const Arg *arg);
191 197
static void tag(const Arg *arg);
192 198
static int textnw(const char *text, unsigned int len);
193 -
static void tile(void);
199 +
static void tile(Monitor *);
194 200
static void togglebar(const Arg *arg);
195 201
static void togglefloating(const Arg *arg);
196 202
static void toggletag(const Arg *arg);
197 203
static void toggleview(const Arg *arg);
198 204
static void unmanage(Client *c);
199 205
static void unmapnotify(XEvent *e);
200 -
static void updatebar(void);
201 206
static void updategeom(void);
202 207
static void updatenumlockmask(void);
203 208
static void updatesizehints(Client *c);
209 214
static int xerrordummy(Display *dpy, XErrorEvent *ee);
210 215
static int xerrorstart(Display *dpy, XErrorEvent *ee);
211 216
static void zoom(const Arg *arg);
217 +
#ifdef XINERAMA
218 +
static void focusmon(const Arg *arg);
219 +
static void tagmon(const Arg *arg);
220 +
#endif /* XINERAMA */
212 221
213 222
/* variables */
214 223
static char stext[256];
215 224
static int screen;
216 -
static int sx, sy, sw, sh; /* X display screen geometry x, y, width, height */ 
217 -
static int by, bh, blw;    /* bar geometry y, height and layout symbol width */
225 +
static int sx, sy, sw, sh;   /* X display screen geometry x, y, width, height */
226 +
static int bh, blw = 0;      /* bar geometry */
218 227
static int (*xerrorxlib)(Display *, XErrorEvent *);
219 228
static unsigned int numlockmask = 0;
220 229
static void (*handler[LASTEvent]) (XEvent *) = {
243 252
static Layout *lt[] = { NULL, NULL };
244 253
static Monitor *mon = NULL, *selmon = NULL;
245 254
static unsigned int nmons;
246 -
static Window root, barwin;
255 +
static Window root;
247 256
/* configuration, allows nested code to access above variables */
248 257
#include "config.h"
249 258
266 275
			&& (!r->class || (ch.res_class && strstr(ch.res_class, r->class)))
267 276
			&& (!r->instance || (ch.res_name && strstr(ch.res_name, r->instance)))) {
268 277
				c->isfloating = r->isfloating;
269 -
				c->tags |= r->tags; 
278 +
				c->tags |= r->tags;
270 279
			}
271 280
		}
272 281
		if(ch.res_class)
344 353
345 354
void
346 355
arrange(void) {
356 +
	unsigned int i;
347 357
	showhide(stack);
348 358
	focus(NULL);
349 -
	if(lt[selmon->sellt]->arrange)
350 -
		lt[selmon->sellt]->arrange();
351 -
	restack();
359 +
	for(i = 0; i < nmons; i++) {
360 +
		if(lt[mon[i].sellt]->arrange)
361 +
			lt[mon[i].sellt]->arrange(&mon[i]);
362 +
		restack(&mon[i]);
363 +
	}
352 364
}
353 365
354 366
void
371 383
	XButtonPressedEvent *ev = &e->xbutton;
372 384
373 385
	click = ClkRootWin;
374 -
	if(ev->window == barwin) {
375 -
		i = x = 0;
376 -
		do x += TEXTW(tags[i]); while(ev->x >= x && ++i < LENGTH(tags));
386 +
	if(ev->window == selmon->barwin) {
387 +
		i = 0;
388 +
		x = selmon->btx;
389 +
		do
390 +
			x += TEXTW(tags[i]);
391 +
		while(ev->x >= x && ++i < LENGTH(tags));
377 392
		if(i < LENGTH(tags)) {
378 393
			click = ClkTagBar;
379 394
			arg.ui = 1 << i;
412 427
413 428
void
414 429
cleanup(void) {
430 +
	unsigned int i;
415 431
	Arg a = {.ui = ~0};
416 432
	Layout foo = { "", NULL };
417 433
429 445
	XFreeCursor(dpy, cursor[CurNormal]);
430 446
	XFreeCursor(dpy, cursor[CurResize]);
431 447
	XFreeCursor(dpy, cursor[CurMove]);
432 -
	XDestroyWindow(dpy, barwin);
448 +
	for(i = 0; i < nmons; i++)
449 +
		XDestroyWindow(dpy, mon[i].barwin);
450 +
	free(mon);
433 451
	XSync(dpy, False);
434 452
	XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
435 453
}
466 484
467 485
void
468 486
configurenotify(XEvent *e) {
487 +
	unsigned int i;
469 488
	XConfigureEvent *ev = &e->xconfigure;
470 489
471 490
	if(ev->window == root && (ev->width != sw || ev->height != sh)) {
472 491
		sw = ev->width;
473 492
		sh = ev->height;
474 493
		updategeom();
475 -
		updatebar();
494 +
		if(dc.drawable != 0)
495 +
			XFreePixmap(dpy, dc.drawable);
496 +
		dc.drawable = XCreatePixmap(dpy, root, DisplayWidth(dpy, screen), bh, DefaultDepth(dpy, screen));
497 +
		for(i = 0; i < nmons; i++)
498 +
			XMoveResizeWindow(dpy, mon[i].barwin, mon[i].wx, mon[i].by, mon[i].ww, bh);
476 499
		arrange();
477 500
	}
478 501
}
556 579
}
557 580
558 581
void
559 -
drawbar(void) {
582 +
drawbar(Monitor *m) {
560 583
	int x;
561 584
	unsigned int i, occ = 0, urg = 0;
562 585
	unsigned long *col;
563 586
	Client *c;
564 587
565 588
	for(c = clients; c; c = c->next) {
566 -
		occ |= c->tags;
567 -
		if(c->isurgent)
568 -
			urg |= c->tags;
589 +
		if(m == &mon[c->mon]) {
590 +
			occ |= c->tags;
591 +
			if(c->isurgent)
592 +
				urg |= c->tags;
593 +
		}
569 594
	}
570 595
571 596
	dc.x = 0;
597 +
#ifdef XINERAMA
598 +
	{
599 +
		dc.w = TEXTW(m->symbol);
600 +
		drawtext(m->symbol, selmon == m ? dc.sel : dc.norm, False);
601 +
		dc.x += dc.w;
602 +
	}
603 +
#endif /* XINERAMA */
604 +
	m->btx = dc.x;
572 605
	for(i = 0; i < LENGTH(tags); i++) {
573 606
		dc.w = TEXTW(tags[i]);
574 -
		col = tagset[selmon->seltags] & 1 << i ? dc.sel : dc.norm;
607 +
		col = tagset[m->seltags] & 1 << i ? dc.sel : dc.norm;
575 608
		drawtext(tags[i], col, urg & 1 << i);
576 -
		drawsquare(sel && sel->tags & 1 << i, occ & 1 << i, urg & 1 << i, col);
609 +
		drawsquare(m == selmon && sel && sel->tags & 1 << i,
610 +
		           occ & 1 << i, urg & 1 << i, col);
577 611
		dc.x += dc.w;
578 612
	}
579 613
	if(blw > 0) {
580 614
		dc.w = blw;
581 -
		drawtext(lt[selmon->sellt]->symbol, dc.norm, False);
615 +
		drawtext(lt[m->sellt]->symbol, dc.norm, False);
582 616
		x = dc.x + dc.w;
583 617
	}
584 618
	else
585 619
		x = dc.x;
586 -
	dc.w = TEXTW(stext);
587 -
	dc.x = selmon->ww - dc.w;
588 -
	if(dc.x < x) {
589 -
		dc.x = x;
590 -
		dc.w = selmon->ww - x;
620 +
	if(m == selmon) {
621 +
		dc.w = TEXTW(stext);
622 +
		dc.x = m->ww - dc.w;
623 +
		if(dc.x < x) {
624 +
			dc.x = x;
625 +
			dc.w = m->ww - x;
626 +
		}
627 +
		drawtext(stext, dc.norm, False);
628 +
		if((dc.w = dc.x - x) > bh) {
629 +
			dc.x = x;
630 +
			if(sel) {
631 +
				drawtext(sel->name, dc.sel, False);
632 +
				drawsquare(sel->isfixed, sel->isfloating, False, dc.sel);
633 +
			}
634 +
			else
635 +
				drawtext(NULL, dc.norm, False);
636 +
		}
591 637
	}
592 -
	drawtext(stext, dc.norm, False);
593 -
	if((dc.w = dc.x - x) > bh) {
594 -
		dc.x = x;
595 -
		if(sel) {
596 -
			drawtext(sel->name, dc.sel, False);
597 -
			drawsquare(sel->isfixed, sel->isfloating, False, dc.sel);
598 -
		}
599 -
		else
600 -
			drawtext(NULL, dc.norm, False);
638 +
	else {
639 +
		dc.w = m->ww - x;
640 +
		drawtext(NULL, dc.norm, False);
601 641
	}
602 -
	XCopyArea(dpy, dc.drawable, barwin, dc.gc, 0, 0, selmon->ww, bh, 0, 0);
642 +
	XCopyArea(dpy, dc.drawable, m->barwin, dc.gc, 0, 0, m->ww, bh, 0, 0);
603 643
	XSync(dpy, False);
644 +
}
645 +
646 +
void
647 +
drawbars() {
648 +
	unsigned int i;
649 +
650 +
	for(i = 0; i < nmons; i++)
651 +
		drawbar(&mon[i]);
604 652
}
605 653
606 654
void
667 715
668 716
void
669 717
expose(XEvent *e) {
718 +
	unsigned int i;
670 719
	XExposeEvent *ev = &e->xexpose;
671 720
672 -
	if(ev->count == 0 && (ev->window == barwin))
673 -
		drawbar();
721 +
	for(i = 0; i < nmons; i++)
722 +
		if(ev->count == 0 && (ev->window == mon[i].barwin)) {
723 +
			drawbar(&mon[i]);
724 +
			break;
725 +
		}
674 726
}
675 727
676 728
void
693 745
	else
694 746
		XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
695 747
	sel = c;
696 -
	drawbar();
748 +
	if(c)
749 +
		selmon = &mon[c->mon];
750 +
	drawbars();
697 751
}
698 752
699 753
void
704 758
		XSetInputFocus(dpy, sel->win, RevertToPointerRoot, CurrentTime);
705 759
}
706 760
761 +
#ifdef XINERAMA
762 +
void
763 +
focusmon(const Arg *arg) {
764 +
	if(arg->ui >= nmons)
765 +
		return;
766 +
	selmon = &mon[arg->ui];
767 +
	focus(NULL);
768 +
	drawbars();
769 +
}
770 +
#endif /* XINERAMA */
771 +
707 772
void
708 773
focusstack(const Arg *arg) {
709 774
	Client *c = NULL, *i;
710 775
711 776
	if(!sel)
712 777
		return;
713 -
	if (arg->i > 0) {
778 +
	if(arg->i > 0) {
714 779
		for(c = sel->next; c && !ISVISIBLE(c); c = c->next);
715 780
		if(!c)
716 781
			for(c = clients; c && !ISVISIBLE(c); c = c->next);
726 791
	}
727 792
	if(c) {
728 793
		focus(c);
729 -
		restack();
794 +
		restack(selmon);
730 795
	}
731 796
}
732 797
946 1011
			c->y = sy + sh - HEIGHT(c);
947 1012
		c->x = MAX(c->x, sx);
948 1013
		/* only fix client y-offset, if the client center might cover the bar */
949 -
		/* TODO: is c always attached to selmon? */
950 -
		c->y = MAX(c->y, ((by == 0) && (c->x + (c->w / 2) >= selmon->wx)
951 -
		                            && (c->x + (c->w / 2) < selmon->wx + selmon->ww)) ? bh : sy);
1014 +
		c->y = MAX(c->y, ((selmon->by == 0) && (c->x + (c->w / 2) >= selmon->wx)
1015 +
		           && (c->x + (c->w / 2) < selmon->wx + selmon->ww)) ? bh : sy);
952 1016
		c->bw = borderpx;
953 1017
	}
954 1018
1001 1065
}
1002 1066
1003 1067
void
1004 -
monocle(void) {
1068 +
monocle(Monitor *m) {
1005 1069
	Client *c;
1006 -
	Monitor *m;
1007 1070
1008 -
	for(c = nexttiled(clients); c; c = nexttiled(c->next)) {
1009 -
		m = &mon[c->mon];
1071 +
	for(c = nexttiled(m, clients); c; c = nexttiled(m, c->next))
1010 1072
		resize(c, m->wx, m->wy, m->ww - 2 * c->bw, m->wh - 2 * c->bw);
1011 -
	}
1012 1073
}
1013 1074
1014 1075
void
1021 1082
1022 1083
	if(!(c = sel))
1023 1084
		return;
1024 -
	restack();
1085 +
	restack(selmon);
1025 1086
	ocx = c->x;
1026 1087
	ocy = c->y;
1027 1088
	if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
1063 1124
}
1064 1125
1065 1126
Client *
1066 -
nexttiled(Client *c) {
1067 -
	for(; c && (c->isfloating || !ISVISIBLE(c)); c = c->next);
1127 +
nexttiled(Monitor *m, Client *c) {
1128 +
	// TODO: m handling
1129 +
	for(; c && (c->isfloating || m != &mon[c->mon] || !ISVISIBLE(c)); c = c->next);
1068 1130
	return c;
1069 1131
}
1070 1132
1091 1153
			break;
1092 1154
		case XA_WM_HINTS:
1093 1155
			updatewmhints(c);
1094 -
			drawbar();
1156 +
			drawbars();
1095 1157
			break;
1096 1158
		}
1097 1159
		if(ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) {
1098 1160
			updatetitle(c);
1099 1161
			if(c == sel)
1100 -
				drawbar();
1162 +
				drawbars();
1101 1163
		}
1102 1164
	}
1103 1165
}
1133 1195
1134 1196
	if(!(c = sel))
1135 1197
		return;
1136 -
	restack();
1198 +
	restack(selmon);
1137 1199
	ocx = c->x;
1138 1200
	ocy = c->y;
1139 1201
	if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
1170 1232
}
1171 1233
1172 1234
void
1173 -
restack(void) {
1235 +
restack(Monitor *m) {
1174 1236
	Client *c;
1175 1237
	XEvent ev;
1176 1238
	XWindowChanges wc;
1177 1239
1178 -
	drawbar();
1240 +
	drawbars();
1179 1241
	if(!sel)
1180 1242
		return;
1181 -
	if(sel->isfloating || !lt[selmon->sellt]->arrange)
1243 +
	if(m == selmon && (sel->isfloating || !lt[m->sellt]->arrange))
1182 1244
		XRaiseWindow(dpy, sel->win);
1183 -
	if(lt[selmon->sellt]->arrange) {
1245 +
	if(lt[m->sellt]->arrange) {
1184 1246
		wc.stack_mode = Below;
1185 -
		wc.sibling = barwin;
1247 +
		wc.sibling = m->barwin;
1186 1248
		for(c = stack; c; c = c->snext)
1187 -
			if(!c->isfloating && ISVISIBLE(c)) {
1249 +
			if(!c->isfloating && m == &mon[c->mon] && ISVISIBLE(c)) {
1188 1250
				XConfigureWindow(dpy, c->win, CWSibling|CWStackMode, &wc);
1189 1251
				wc.sibling = c->win;
1190 1252
			}
1248 1310
	if(sel)
1249 1311
		arrange();
1250 1312
	else
1251 -
		drawbar();
1313 +
		drawbars();
1252 1314
}
1253 1315
1254 1316
/* arg > 1.0 will set mfact absolutly */
1309 1371
	if(!dc.font.set)
1310 1372
		XSetFont(dpy, dc.gc, dc.font.xfont->fid);
1311 1373
1312 -
	/* init bar */
1374 +
	/* init bars */
1375 +
	wa.override_redirect = True;
1376 +
	wa.background_pixmap = ParentRelative;
1377 +
	wa.event_mask = ButtonPressMask|ExposureMask;
1313 1378
	for(blw = i = 0; LENGTH(layouts) > 1 && i < LENGTH(layouts); i++) {
1314 1379
		w = TEXTW(layouts[i].symbol);
1315 1380
		blw = MAX(blw, w);
1316 1381
	}
1317 1382
1318 -
	wa.override_redirect = True;
1319 -
	wa.background_pixmap = ParentRelative;
1320 -
	wa.event_mask = ButtonPressMask|ExposureMask;
1383 +
	for(i = 0; i < nmons; i++) {
1384 +
		mon[i].barwin = XCreateWindow(dpy, root, mon[i].wx, mon[i].by, mon[i].ww, bh, 0, DefaultDepth(dpy, screen),
1321 1385
1322 -
	barwin = XCreateWindow(dpy, root, selmon->wx, by, selmon->ww, bh, 0, DefaultDepth(dpy, screen),
1323 -
			CopyFromParent, DefaultVisual(dpy, screen),
1324 -
			CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa);
1325 -
	XDefineCursor(dpy, barwin, cursor[CurNormal]);
1326 -
	XMapRaised(dpy, barwin);
1386 +
		                              CopyFromParent, DefaultVisual(dpy, screen),
1387 +
		                              CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa);
1388 +
		XDefineCursor(dpy, mon[i].barwin, cursor[CurNormal]);
1389 +
		XMapRaised(dpy, mon[i].barwin);
1390 +
	}
1327 1391
	updatestatus();
1328 1392
1329 1393
	/* EWMH support per view */
1384 1448
	}
1385 1449
}
1386 1450
1451 +
#ifdef XINERAMA
1452 +
void
1453 +
tagmon(const Arg *arg) {
1454 +
	if(!sel || arg->ui >= nmons)
1455 +
		return;
1456 +
	sel->mon = arg->ui;
1457 +
	arrange();
1458 +
}
1459 +
#endif /* XINERAMA */
1460 +
1387 1461
int
1388 1462
textnw(const char *text, unsigned int len) {
1389 1463
	XRectangle r;
1396 1470
}
1397 1471
1398 1472
void
1399 -
tile(void) {
1473 +
tile(Monitor *m) {
1400 1474
	int x, y, h, w, mw;
1401 1475
	unsigned int i, n;
1402 1476
	Client *c;
1403 -
	Monitor *m;
1404 1477
1405 -
	for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next), n++);
1478 +
	for(n = 0, c = nexttiled(m, clients); c; c = nexttiled(m, c->next), n++);
1406 1479
	if(n == 0)
1407 1480
		return;
1408 1481
1409 1482
	/* master */
1410 -
	c = nexttiled(clients);
1411 -
	m = &mon[c->mon];
1483 +
	c = nexttiled(m, clients);
1412 1484
	mw = mfact * m->ww;
1413 1485
	resize(c, m->wx, m->wy, (n == 1 ? m->ww : mw) - 2 * c->bw, m->wh - 2 * c->bw);
1414 1486
1423 1495
	if(h < bh)
1424 1496
		h = m->wh;
1425 1497
1426 -
	for(i = 0, c = nexttiled(c->next); c; c = nexttiled(c->next), i++) {
1498 +
	for(i = 0, c = nexttiled(m, c->next); c; c = nexttiled(m, c->next), i++) {
1427 1499
		resize(c, x, y, w - 2 * c->bw, /* remainder */ ((i + 1 == n)
1428 1500
		       ? m->wy + m->wh - y - 2 * c->bw : h - 2 * c->bw));
1429 1501
		if(h != m->wh)
1433 1505
1434 1506
void
1435 1507
togglebar(const Arg *arg) {
1436 -
	showbar = !showbar;
1508 +
	selmon->showbar = !selmon->showbar;
1437 1509
	updategeom();
1438 -
	updatebar();
1510 +
	XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh);
1439 1511
	arrange();
1440 1512
}
1441 1513
1453 1525
toggletag(const Arg *arg) {
1454 1526
	unsigned int mask;
1455 1527
1456 -
	if (!sel)
1528 +
	if(!sel)
1457 1529
		return;
1458 1530
	
1459 1531
	mask = sel->tags ^ (arg->ui & TAGMASK);
1505 1577
}
1506 1578
1507 1579
void
1508 -
updatebar(void) {
1509 -
	if(dc.drawable != 0)
1510 -
		XFreePixmap(dpy, dc.drawable);
1511 -
	dc.drawable = XCreatePixmap(dpy, root, selmon->ww, bh, DefaultDepth(dpy, screen));
1512 -
	XMoveResizeWindow(dpy, barwin, selmon->wx, by, selmon->ww, bh);
1513 -
}
1514 -
1515 -
void
1516 1580
updategeom(void) {
1517 1581
#ifdef XINERAMA
1518 1582
	int di, x, y, n;
1523 1587
	XineramaScreenInfo *info = NULL;
1524 1588
1525 1589
	/* window area geometry */
1526 -
	if(XineramaIsActive(dpy) && (info = XineramaQueryScreens(dpy, &n))) { 
1590 +
	if(XineramaIsActive(dpy) && (info = XineramaQueryScreens(dpy, &n))) {
1527 1591
		nmons = (unsigned int)n;
1528 1592
		for(c = clients; c; c = c->next)
1529 1593
			if(c->mon >= nmons)
1533 1597
		pquery = XQueryPointer(dpy, root, &dummy, &dummy, &x, &y, &di, &di, &dui);
1534 1598
		for(i = 0; i < nmons; i++) {
1535 1599
			/* TODO: consider re-using XineramaScreenInfo */
1600 +
			mon[i].symbol[0] = '[';
1601 +
			mon[i].symbol[1] = '0' + info[i].screen_number;
1602 +
			mon[i].symbol[2] = ']';
1603 +
			mon[i].symbol[3] = 0;
1604 +
			mon[i].showbar = showbar;
1605 +
			mon[i].topbar = topbar;
1536 1606
			mon[i].wx = info[i].x_org;
1537 -
			mon[i].wy = info[i].y_org;
1607 +
			mon[i].wy = mon[i].showbar && mon[i].topbar ? info[i].y_org + bh : info[i].y_org;
1538 1608
			mon[i].ww = info[i].width;
1539 -
			mon[i].wh = info[i].height;
1609 +
			mon[i].wh = mon[i].showbar ? info[i].height - bh : info[i].height;
1540 1610
			mon[i].seltags = 0;
1541 1611
			mon[i].sellt = 0;
1612 +
			if(mon[i].showbar)
1613 +
				mon[i].by = mon[i].topbar ? info[i].y_org : mon[i].wy + mon[i].wh;
1614 +
			else
1615 +
				mon[i].by = -bh;
1542 1616
			if(pquery && INRECT(x, y, info[i].x_org, info[i].y_org, info[i].width, info[i].height))
1543 1617
				selmon = &mon[i];
1544 1618
		}
1545 -
		/* bar adjustments of selmon */
1546 -
		selmon->wy = showbar && topbar ?  selmon->wy + bh : selmon->wy;
1547 -
		selmon->wh = showbar ? selmon->wh - bh : selmon->wh;
1548 1619
		XFree(info);
1549 1620
	}
1550 1621
	else
1551 -
#endif
1622 +
#endif /* XINERAMA */
1552 1623
	{
1553 1624
		nmons = 1;
1554 1625
		if(!(mon = (Monitor *)realloc(mon, sizeof(Monitor))))
1555 1626
			die("fatal: could not realloc() %u bytes\n", sizeof(Monitor));
1556 1627
		selmon = &mon[0];
1628 +
		mon[0].symbol[0] = '[';
1629 +
		mon[0].symbol[1] = '0';
1630 +
		mon[0].symbol[2] = ']';
1631 +
		mon[0].symbol[3] = 0;
1632 +
		mon[0].showbar = showbar;
1633 +
		mon[0].topbar = topbar;
1557 1634
		mon[0].wx = sx;
1558 -
		mon[0].wy = showbar && topbar ? sy + bh : sy;
1635 +
		mon[0].wy = mon[0].showbar && mon[0].topbar ? sy + bh : sy;
1559 1636
		mon[0].ww = sw;
1560 -
		mon[0].wh = showbar ? sh - bh : sh;
1637 +
		mon[0].wh = mon[0].showbar ? sh - bh : sh;
1561 1638
		mon[0].seltags = 0;
1562 1639
		mon[0].sellt = 0;
1640 +
		if(mon[0].showbar)
1641 +
			mon[0].by = mon[0].topbar ? sy : mon[0].wy + mon[0].wh;
1642 +
		else
1643 +
			mon[0].by = -bh;
1563 1644
	}
1564 -
1565 -
	/* bar position */
1566 -
	by = showbar ? (topbar ? selmon->wy - bh : selmon->wy + selmon->wh) : -bh;
1567 1645
}
1568 1646
1569 1647
void
1588 1666
1589 1667
	if(!XGetWMNormalHints(dpy, c->win, &size, &msize))
1590 1668
		/* size is uninitialized, ensure that size.flags aren't used */
1591 -
		size.flags = PSize; 
1669 +
		size.flags = PSize;
1592 1670
	if(size.flags & PBaseSize) {
1593 1671
		c->basew = size.base_width;
1594 1672
		c->baseh = size.base_height;
1641 1719
updatestatus() {
1642 1720
	if(!gettextprop(root, XA_WM_NAME, stext, sizeof(stext)))
1643 1721
		strcpy(stext, "dwm-"VERSION);
1644 -
	drawbar();
1722 +
	drawbar(selmon);
1645 1723
}
1646 1724
1647 1725
void
1709 1787
1710 1788
	if(!lt[selmon->sellt]->arrange || lt[selmon->sellt]->arrange == monocle || (sel && sel->isfloating))
1711 1789
		return;
1712 -
	if(c == nexttiled(clients))
1713 -
		if(!c || !(c = nexttiled(c->next)))
1790 +
	if(c == nexttiled(selmon, clients))
1791 +
		if(!c || !(c = nexttiled(selmon, c->next)))
1714 1792
			return;
1715 1793
	detach(c);
1716 1794
	attach(c);