pushing my changes of tonight upstream (hg tip is NOW very UNSTABLE -- but those changes are necessary to get a decent multihead support) -- I renamed Monitor into View, to reflect in a better way the dwm terminology of the past a3d8c05a
anselm@anselm1 · 2008-02-23 23:11 2 file(s) · +344 −365
config.def.h +7 −7
3 3
/* appearance */
4 4
#define BARPOS			BarTop /* BarBot, BarOff */
5 5
#define BORDERPX		1
6 -
#define FONT			"-*-terminus-medium-r-normal-*-14-*-*-*-*-*-*-*"
6 +
#define FONT			"-*-terminus-medium-r-normal-*-12-*-*-*-*-*-*-*"
7 7
#define NORMBORDERCOLOR		"#cccccc"
8 8
#define NORMBGCOLOR		"#cccccc"
9 9
#define NORMFGCOLOR		"#000000"
13 13
14 14
/* tagging */
15 15
const char tags[][MAXTAGLEN] = { "1", "2", "3", "4", "5", "6", "7", "8", "www" };
16 -
Bool initags[LENGTH(tags)] = {[0] = True};
16 +
int initags[LENGTH(tags)]    = { [0] = 1 };
17 17
Rule rules[] = {
18 -
	/* class:instance:title regex	tags regex	isfloating */	/* monitor */
19 -
	{ "Firefox",			"www",		False,		-1 },
20 -
	{ "Gimp",			NULL,		True,		-1 },
21 -
	{ "MPlayer",			NULL,		True,		-1 },
22 -
	{ "Acroread",			NULL,		True,		-1 },
18 +
	/* class:instance:title regex	tags regex	isfloating */
19 +
	{ "Firefox",			"www",		False },
20 +
	{ "Gimp",			NULL,		True },
21 +
	{ "MPlayer",			NULL,		True },
22 +
	{ "Acroread",			NULL,		True },
23 23
};
24 24
25 25
/* layout(s) */
dwm.c +337 −358
17 17
 * set the override_redirect flag.  Clients are organized in a global
18 18
 * doubly-linked client list, the focus history is remembered through a global
19 19
 * stack list. Each client contains an array of Bools of the same size as the
20 -
 * global tags array to indicate the tags of a client.  
20 +
 * global tags array to indicate the tags of a client.
21 21
 *
22 22
 * Keys and tagging rules are organized as arrays and defined in config.h.
23 23
 *
45 45
//#endif
46 46
47 47
/* macros */
48 -
#define BUTTONMASK		(ButtonPressMask | ButtonReleaseMask)
49 -
#define CLEANMASK(mask)		(mask & ~(numlockmask | LockMask))
48 +
#define BUTTONMASK		(ButtonPressMask|ButtonReleaseMask)
49 +
#define CLEANMASK(mask)		(mask & ~(numlockmask|LockMask))
50 50
#define LENGTH(x)		(sizeof x / sizeof x[0])
51 51
#define MAXTAGLEN		16
52 -
#define MOUSEMASK		(BUTTONMASK | PointerMotionMask)
52 +
#define MOUSEMASK		(BUTTONMASK|PointerMotionMask)
53 53
54 54
55 55
/* enums */
60 60
enum { WMProtocols, WMDelete, WMName, WMState, WMLast };/* default atoms */
61 61
62 62
/* typedefs */
63 -
typedef struct Monitor Monitor;
63 +
typedef struct View View;
64 64
typedef struct Client Client;
65 65
struct Client {
66 66
	char name[256];
67 67
	int x, y, w, h;
68 68
	int basew, baseh, incw, inch, maxw, maxh, minw, minh;
69 69
	int minax, maxax, minay, maxay;
70 +
	int *tags;
70 71
	long flags;
71 72
	unsigned int border, oldborder;
72 73
	Bool isbanned, isfixed, isfloating, isurgent;
73 -
	Bool *tags;
74 74
	Client *next;
75 75
	Client *prev;
76 76
	Client *snext;
77 77
	Window win;
78 -
	Monitor *monitor;
79 78
};
80 79
81 80
typedef struct {
102 101
103 102
typedef struct {
104 103
	const char *symbol;
105 -
	void (*arrange)(Monitor *);
104 +
	void (*arrange)(View *);
106 105
} Layout;
107 106
108 107
typedef struct {
109 108
	const char *prop;
110 109
	const char *tags;
111 110
	Bool isfloating;
112 -
	int monitor;
113 111
} Rule;
114 112
115 113
typedef struct {
117 115
	regex_t *tagregex;
118 116
} Regs;
119 117
120 -
struct Monitor {
121 -
	int sx, sy, sw, sh, wax, way, wah, waw;
118 +
struct View {
119 +
	int id;
120 +
	int x, y, w, h, wax, way, wah, waw;
122 121
	double mwfact;
123 -
	Bool *seltags;
124 -
	Bool *prevtags;
125 122
	Layout *layout;
126 123
	Window barwin;
127 124
};
128 -
129 125
130 126
/* function declarations */
131 127
void applyrules(Client *c);
132 -
void arrange(Monitor *m);
128 +
void arrange(void);
133 129
void attach(Client *c);
134 130
void attachstack(Client *c);
135 131
void ban(Client *c);
143 139
void destroynotify(XEvent *e);
144 140
void detach(Client *c);
145 141
void detachstack(Client *c);
146 -
void drawbar(Monitor *m);
147 -
void drawsquare(Monitor *m, Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]);
148 -
void drawtext(Monitor *m, const char *text, unsigned long col[ColLast], Bool invert);
142 +
void drawbar(View *v);
143 +
void drawsquare(View *v, Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]);
144 +
void drawtext(View *v, const char *text, unsigned long col[ColLast], Bool invert);
149 145
void *emallocz(unsigned int size);
150 146
void enternotify(XEvent *e);
151 147
void eprint(const char *errstr, ...);
152 148
void expose(XEvent *e);
153 -
void floating(Monitor *m); /* default floating layout */
149 +
void floating(View *v); /* default floating layout */
154 150
void focus(Client *c);
155 151
void focusin(XEvent *e);
156 152
void focusnext(const char *arg);
157 153
void focusprev(const char *arg);
158 154
Client *getclient(Window w);
159 155
unsigned long getcolor(const char *colstr);
160 -
Monitor *getmonitor(Window barwin);
156 +
View *getviewbar(Window barwin);
157 +
View *getview(Client *c);
161 158
long getstate(Window w);
162 159
Bool gettextprop(Window w, Atom atom, char *text, unsigned int size);
163 160
void grabbuttons(Client *c, Bool focused);
164 161
void grabkeys(void);
165 162
unsigned int idxoftag(const char *tag);
166 163
void initfont(const char *fontstr);
167 -
Bool isoccupied(Monitor *monitor, unsigned int t);
164 +
Bool isoccupied(unsigned int t);
168 165
Bool isprotodel(Client *c);
169 -
Bool isurgent(Monitor *monitor, unsigned int t);
170 -
Bool isvisible(Client *c, Monitor *m);
166 +
Bool isurgent(unsigned int t);
167 +
Bool isvisible(Client *c);
171 168
void keypress(XEvent *e);
172 169
void killclient(const char *arg);
173 170
void manage(Window w, XWindowAttributes *wa);
174 171
void mappingnotify(XEvent *e);
175 172
void maprequest(XEvent *e);
176 -
Monitor *monitorat(void);
173 +
View *viewat(void);
177 174
void movemouse(Client *c);
178 -
Client *nexttiled(Client *c, Monitor *monitor);
175 +
Client *nexttiled(Client *c, View *v);
179 176
void propertynotify(XEvent *e);
180 177
void quit(const char *arg);
181 178
void reapply(const char *arg);
182 179
void resize(Client *c, int x, int y, int w, int h, Bool sizehints);
183 180
void resizemouse(Client *c);
184 -
void restack(Monitor *m);
181 +
void restack(View *v);
185 182
void run(void);
186 183
void scan(void);
187 184
void setclientstate(Client *c, long state);
192 189
void tag(const char *arg);
193 190
unsigned int textnw(const char *text, unsigned int len);
194 191
unsigned int textw(const char *text);
195 -
void tile(Monitor *m);
192 +
void tile(View *v);
196 193
void togglebar(const char *arg);
197 194
void togglefloating(const char *arg);
198 195
void toggletag(const char *arg);
200 197
void unban(Client *c);
201 198
void unmanage(Client *c);
202 199
void unmapnotify(XEvent *e);
203 -
void updatebarpos(Monitor *m);
200 +
void updatebarpos(View *v);
204 201
void updatesizehints(Client *c);
205 202
void updatetitle(Client *c);
206 203
void updatewmhints(Client *c);
207 204
void view(const char *arg);
208 205
void viewprevtag(const char *arg);	/* views previous selected tags */
209 206
int xerror(Display *dpy, XErrorEvent *ee);
210 -
int xerrordummy(Display *dsply, XErrorEvent *ee);
211 -
int xerrorstart(Display *dsply, XErrorEvent *ee);
207 +
int xerrordummy(Display *dpy, XErrorEvent *ee);
208 +
int xerrorstart(Display *dpy, XErrorEvent *ee);
212 209
void zoom(const char *arg);
213 -
void movetomonitor(const char *arg);
214 -
void selectmonitor(const char *arg);
210 +
void selectview(const char *arg);
215 211
216 212
/* variables */
217 213
char stext[256];
218 -
int mcount = 1;
219 -
Monitor *selmonitor;
214 +
int nviews = 1;
215 +
View *selview;
220 216
int screen;
217 +
int *seltags;
218 +
int *prevtags;
221 219
int (*xerrorxlib)(Display *, XErrorEvent *);
222 220
unsigned int bh, bpos;
223 221
unsigned int blw = 0;
249 247
Display *dpy;
250 248
DC dc = {0};
251 249
Regs *regs = NULL;
252 -
Monitor *monitors;
250 +
View *views;
253 251
Window root;
254 252
255 253
/* configuration, allows nested code to access above variables */
256 254
#include "config.h"
257 255
258 -
//Bool prevtags[LENGTH(tags)];
259 -
260 256
/* function implementations */
261 257
void
262 258
applyrules(Client *c) {
264 260
	unsigned int i, j;
265 261
	regmatch_t tmp;
266 262
	Bool matched_tag = False;
267 -
	Bool matched_monitor = False;
268 263
	XClassHint ch = { 0 };
269 264
270 265
	/* rule matching */
274 269
			ch.res_name ? ch.res_name : "", c->name);
275 270
	for(i = 0; i < LENGTH(rules); i++)
276 271
		if(regs[i].propregex && !regexec(regs[i].propregex, buf, 1, &tmp, 0)) {
277 -
			if (rules[i].monitor >= 0 && rules[i].monitor < mcount) {
278 -
				matched_monitor = True;
279 -
				c->monitor = &monitors[rules[i].monitor];
280 -
			}
281 -
282 272
			c->isfloating = rules[i].isfloating;
283 273
			for(j = 0; regs[i].tagregex && j < LENGTH(tags); j++) {
284 274
				if(!regexec(regs[i].tagregex, tags[j], 1, &tmp, 0)) {
285 275
					matched_tag = True;
286 -
					c->tags[j] = True;
276 +
					c->tags[j] = selview->id;
287 277
				}
288 278
			}
289 279
		}
292 282
	if(ch.res_name)
293 283
		XFree(ch.res_name);
294 284
	if(!matched_tag)
295 -
		memcpy(c->tags, monitorat()->seltags, sizeof initags);
296 -
	if (!matched_monitor)
297 -
		c->monitor = monitorat();
285 +
		memcpy(c->tags, seltags, sizeof initags);
298 286
}
299 287
288 +
289 +
300 290
void
301 -
arrange(Monitor *m) {
291 +
arrange(void) {
302 292
	unsigned int i;
303 293
	Client *c;
304 294
305 295
	for(c = clients; c; c = c->next)
306 -
		if(isvisible(c, c->monitor))
296 +
		if(isvisible(c))
307 297
			unban(c);
308 298
		else
309 299
			ban(c);
310 300
311 -
	if(m)
312 -
		m->layout->arrange(m);
313 -
	else
314 -
		for(i = 0; i < mcount; i++)
315 -
			monitors[i].layout->arrange(&monitors[i]);
301 +
	for(i = 0; i < nviews; i++) {
302 +
		views[i].layout->arrange(&views[i]);
303 +
		restack(&views[i]);
304 +
	}
316 305
	focus(NULL);
317 -
	restack(m);
318 306
}
319 307
320 308
void
335 323
ban(Client *c) {
336 324
	if(c->isbanned)
337 325
		return;
338 -
	XMoveWindow(dpy, c->win, c->x + 3 * c->monitor->sw, c->y);
326 +
	XMoveWindow(dpy, c->win, c->x + 3 * getview(c)->w, c->y);
339 327
	c->isbanned = True;
340 328
}
341 329
345 333
	Client *c;
346 334
	XButtonPressedEvent *ev = &e->xbutton;
347 335
348 -
	Monitor *m = monitorat();
336 +
	View *v = selview;
349 337
350 -
	if(ev->window == m->barwin) {
338 +
	if(ev->window == v->barwin) {
351 339
		x = 0;
352 340
		for(i = 0; i < LENGTH(tags); i++) {
353 341
			x += textw(tags[i]);
375 363
		if(CLEANMASK(ev->state) != MODKEY)
376 364
			return;
377 365
		if(ev->button == Button1) {
378 -
			restack(c->monitor);
366 +
			restack(getview(c));
379 367
			movemouse(c);
380 368
		}
381 369
		else if(ev->button == Button2) {
382 -
			if((floating != m->layout->arrange) && c->isfloating)
370 +
			if((floating != v->layout->arrange) && c->isfloating)
383 371
				togglefloating(NULL);
384 372
			else
385 373
				zoom(NULL);
386 374
		}
387 375
		else if(ev->button == Button3 && !c->isfixed) {
388 -
			restack(c->monitor);
376 +
			restack(getview(c));
389 377
			resizemouse(c);
390 378
		}
391 379
	}
426 414
	XFreeCursor(dpy, cursor[CurNormal]);
427 415
	XFreeCursor(dpy, cursor[CurResize]);
428 416
	XFreeCursor(dpy, cursor[CurMove]);
429 -
	for(i = 0; i < mcount; i++)
430 -
		XDestroyWindow(dpy, monitors[i].barwin);
417 +
	for(i = 0; i < nviews; i++)
418 +
		XDestroyWindow(dpy, views[i].barwin);
431 419
	XSync(dpy, False);
432 420
	XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
433 421
}
479 467
void
480 468
configurenotify(XEvent *e) {
481 469
	XConfigureEvent *ev = &e->xconfigure;
482 -
	Monitor *m = selmonitor;
470 +
	View *v = selview;
483 471
484 -
	if(ev->window == root && (ev->width != m->sw || ev->height != m->sh)) {
472 +
	if(ev->window == root && (ev->width != v->w || ev->height != v->h)) {
485 473
		/* TODO -- update Xinerama dimensions here */
486 -
		m->sw = ev->width;
487 -
		m->sh = ev->height;
474 +
		v->w = ev->width;
475 +
		v->h = ev->height;
488 476
		XFreePixmap(dpy, dc.drawable);
489 477
		dc.drawable = XCreatePixmap(dpy, root, DisplayWidth(root, screen), bh, DefaultDepth(dpy, screen));
490 -
		XResizeWindow(dpy, m->barwin, m->sw, bh);
491 -
		updatebarpos(m);
492 -
		arrange(m);
478 +
		XResizeWindow(dpy, v->barwin, v->w, bh);
479 +
		updatebarpos(v);
480 +
		arrange();
493 481
	}
494 482
}
495 483
500 488
	XWindowChanges wc;
501 489
502 490
	if((c = getclient(ev->window))) {
503 -
		Monitor *m = c->monitor;
491 +
		View *v = getview(c);
504 492
		if(ev->value_mask & CWBorderWidth)
505 493
			c->border = ev->border_width;
506 -
		if(c->isfixed || c->isfloating || (floating == m->layout->arrange)) {
494 +
		if(c->isfixed || c->isfloating || (floating == v->layout->arrange)) {
507 495
			if(ev->value_mask & CWX)
508 -
				c->x = m->sx+ev->x;
496 +
				c->x = v->x + ev->x;
509 497
			if(ev->value_mask & CWY)
510 -
				c->y = m->sy+ev->y;
498 +
				c->y = v->y + ev->y;
511 499
			if(ev->value_mask & CWWidth)
512 500
				c->w = ev->width;
513 501
			if(ev->value_mask & CWHeight)
514 502
				c->h = ev->height;
515 -
			if((c->x - m->sx + c->w) > m->sw && c->isfloating)
516 -
				c->x = m->sx + (m->sw / 2 - c->w / 2); /* center in x direction */
517 -
			if((c->y - m->sy + c->h) > m->sh && c->isfloating)
518 -
				c->y = m->sy + (m->sh / 2 - c->h / 2); /* center in y direction */
519 -
			if((ev->value_mask & (CWX | CWY))
520 -
			&& !(ev->value_mask & (CWWidth | CWHeight)))
503 +
			if((c->x - v->x + c->w) > v->w && c->isfloating)
504 +
				c->x = v->x + (v->w / 2 - c->w / 2); /* center in x direction */
505 +
			if((c->y - v->y + c->h) > v->h && c->isfloating)
506 +
				c->y = v->y + (v->h / 2 - c->h / 2); /* center in y direction */
507 +
			if((ev->value_mask & (CWX|CWY))
508 +
			&& !(ev->value_mask & (CWWidth|CWHeight)))
521 509
				configure(c);
522 -
			if(isvisible(c, monitorat()))
510 +
			if(isvisible(c))
523 511
				XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h);
524 512
		}
525 513
		else
567 555
}
568 556
569 557
void
570 -
drawbar(Monitor *m) {
571 -
	int j, x;
558 +
drawbar(View *v) {
559 +
	int i, x;
572 560
	Client *c;
573 561
574 562
	dc.x = 0;
575 -
	for(c = stack; c && !isvisible(c, m); c = c->snext);
576 -
	for(j = 0; j < LENGTH(tags); j++) {
577 -
		dc.w = textw(tags[j]);
578 -
		if(m->seltags[j]) {
579 -
			drawtext(m, tags[j], dc.sel, isurgent(m, j));
580 -
			drawsquare(m, c && c->tags[j] && c->monitor == m,
581 -
					isoccupied(m, j), isurgent(m, j), dc.sel);
563 +
	for(c = stack; c && !isvisible(c); c = c->snext);
564 +
	for(i = 0; i < LENGTH(tags); i++) {
565 +
		dc.w = textw(tags[i]);
566 +
		if(seltags[i]) {
567 +
			drawtext(v, tags[i], dc.sel, isurgent(i));
568 +
			drawsquare(v, c && c->tags[i], isoccupied(i), isurgent(i), dc.sel);
582 569
		}
583 570
		else {
584 -
			drawtext(m, tags[j], dc.norm, isurgent(m, j));
585 -
			drawsquare(m, c && c->tags[j] && c->monitor == m,
586 -
					isoccupied(m, j), isurgent(m, j), dc.norm);
571 +
			drawtext(v, tags[i], dc.norm, isurgent(i));
572 +
			drawsquare(v, c && c->tags[i], isoccupied(i), isurgent(i), dc.norm);
587 573
		}
588 574
		dc.x += dc.w;
589 575
	}
590 576
	dc.w = blw;
591 -
	drawtext(m, m->layout->symbol, dc.norm, False);
577 +
	drawtext(v, v->layout->symbol, dc.norm, False);
592 578
	x = dc.x + dc.w;
593 -
	if(m == selmonitor) {
579 +
	if(v == selview) {
594 580
		dc.w = textw(stext);
595 -
		dc.x = m->sw - dc.w;
581 +
		dc.x = v->w - dc.w;
596 582
		if(dc.x < x) {
597 583
			dc.x = x;
598 -
			dc.w = m->sw - x;
584 +
			dc.w = v->w - x;
599 585
		}
600 -
		drawtext(m, stext, dc.norm, False);
586 +
		drawtext(v, stext, dc.norm, False);
601 587
	}
602 588
	else
603 -
		dc.x = m->sw;
589 +
		dc.x = v->w;
604 590
	if((dc.w = dc.x - x) > bh) {
605 591
		dc.x = x;
606 592
		if(c) {
607 -
			drawtext(m, c->name, dc.sel, False);
608 -
			drawsquare(m, False, c->isfloating, False, dc.sel);
593 +
			drawtext(v, c->name, dc.sel, False);
594 +
			drawsquare(v, False, c->isfloating, False, dc.sel);
609 595
		}
610 596
		else
611 -
			drawtext(m, NULL, dc.norm, False);
597 +
			drawtext(v, NULL, dc.norm, False);
612 598
	}
613 -
	XCopyArea(dpy, dc.drawable, m->barwin, dc.gc, 0, 0, m->sw, bh, 0, 0);
599 +
	XCopyArea(dpy, dc.drawable, v->barwin, dc.gc, 0, 0, v->w, bh, 0, 0);
614 600
	XSync(dpy, False);
615 601
}
616 602
617 603
void
618 -
drawsquare(Monitor *m, Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]) {
604 +
drawsquare(View *v, Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]) {
619 605
	int x;
620 606
	XGCValues gcv;
621 607
	XRectangle r = { dc.x, dc.y, dc.w, dc.h };
636 622
}
637 623
638 624
void
639 -
drawtext(Monitor *m, const char *text, unsigned long col[ColLast], Bool invert) {
625 +
drawtext(View *v, const char *text, unsigned long col[ColLast], Bool invert) {
640 626
	int x, y, w, h;
641 627
	static char buf[256];
642 628
	unsigned int len, olen;
695 681
	}
696 682
	if((c = getclient(ev->window)))
697 683
		focus(c);
698 -
	else {
699 -
		selmonitor = monitorat();
700 -
		fprintf(stderr, "updating selmonitor %d\n", selmonitor - monitors);
684 +
	else
701 685
		focus(NULL);
702 -
	}
703 686
}
704 687
705 688
void
714 697
715 698
void
716 699
expose(XEvent *e) {
717 -
	Monitor *m;
700 +
	View *v;
718 701
	XExposeEvent *ev = &e->xexpose;
719 702
720 -
	if(ev->count == 0 && (m = getmonitor(ev->window)))
721 -
		drawbar(m);
703 +
	if(ev->count == 0 && (v = getviewbar(ev->window)))
704 +
		drawbar(v);
722 705
}
723 706
724 707
void
725 -
floating(Monitor *m) { /* default floating layout */
708 +
floating(View *v) { /* default floating layout */
726 709
	Client *c;
727 710
728 711
	domwfact = dozoom = False;
729 712
	for(c = clients; c; c = c->next)
730 -
		if(isvisible(c, m))
713 +
		if(isvisible(c))
731 714
			resize(c, c->x, c->y, c->w, c->h, True);
732 715
}
733 716
734 717
void
735 718
focus(Client *c) {
719 +
	View *v = selview;
736 720
	if(c)
737 -
		selmonitor = c->monitor;
738 -
	if(!c || (c && !isvisible(c, selmonitor)))
739 -
		for(c = stack; c && !isvisible(c, c->monitor); c = c->snext);
721 +
		selview = getview(c);
722 +
	else
723 +
		selview = viewat();
724 +
	if(selview != v)
725 +
		drawbar(v);
726 +
	if(!c || (c && !isvisible(c)))
727 +
		for(c = stack; c && !isvisible(c); c = c->snext);
740 728
	if(sel && sel != c) {
741 729
		grabbuttons(sel, False);
742 730
		XSetWindowBorder(dpy, sel->win, dc.norm[ColBorder]);
750 738
	if(c) {
751 739
		XSetWindowBorder(dpy, c->win, dc.sel[ColBorder]);
752 740
		XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime);
753 -
		selmonitor = c->monitor;
741 +
		selview = getview(c);
754 742
	}
755 743
	else
756 744
		XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
757 -
	drawbar(selmonitor);
745 +
	drawbar(selview);
758 746
}
759 747
760 748
void
771 759
772 760
	if(!sel)
773 761
		return;
774 -
	for(c = sel->next; c && !isvisible(c, selmonitor); c = c->next);
762 +
	for(c = sel->next; c && !isvisible(c); c = c->next);
775 763
	if(!c)
776 -
		for(c = clients; c && !isvisible(c, selmonitor); c = c->next);
764 +
		for(c = clients; c && !isvisible(c); c = c->next);
777 765
	if(c) {
778 766
		focus(c);
779 -
		restack(c->monitor);
767 +
		restack(getview(c));
780 768
	}
781 769
}
782 770
786 774
787 775
	if(!sel)
788 776
		return;
789 -
	for(c = sel->prev; c && !isvisible(c, selmonitor); c = c->prev);
777 +
	for(c = sel->prev; c && !isvisible(c); c = c->prev);
790 778
	if(!c) {
791 779
		for(c = clients; c && c->next; c = c->next);
792 -
		for(; c && !isvisible(c, selmonitor); c = c->prev);
780 +
		for(; c && !isvisible(c); c = c->prev);
793 781
	}
794 782
	if(c) {
795 783
		focus(c);
796 -
		restack(c->monitor);
784 +
		restack(getview(c));
797 785
	}
798 786
}
799 787
815 803
	return color.pixel;
816 804
}
817 805
818 -
Monitor *
819 -
getmonitor(Window barwin) {
806 +
View *
807 +
getviewbar(Window barwin) {
820 808
	unsigned int i;
821 809
822 -
	for(i = 0; i < mcount; i++)
823 -
		if(monitors[i].barwin == barwin)
824 -
			return &monitors[i];
810 +
	for(i = 0; i < nviews; i++)
811 +
		if(views[i].barwin == barwin)
812 +
			return &views[i];
825 813
	return NULL;
814 +
}
815 +
816 +
View *
817 +
getview(Client *c) {
818 +
	unsigned int i;
819 +
820 +
	for(i = 0; i < LENGTH(tags); i++)
821 +
		if(c->tags[i])
822 +
			return &views[c->tags[i] - 1];
823 +
	return &views[0]; /* fallback */
826 824
}
827 825
828 826
long
876 874
	if(focused) {
877 875
		XGrabButton(dpy, Button1, MODKEY, c->win, False, BUTTONMASK,
878 876
				GrabModeAsync, GrabModeSync, None, None);
879 -
		XGrabButton(dpy, Button1, MODKEY | LockMask, c->win, False, BUTTONMASK,
877 +
		XGrabButton(dpy, Button1, MODKEY|LockMask, c->win, False, BUTTONMASK,
880 878
				GrabModeAsync, GrabModeSync, None, None);
881 -
		XGrabButton(dpy, Button1, MODKEY | numlockmask, c->win, False, BUTTONMASK,
879 +
		XGrabButton(dpy, Button1, MODKEY|numlockmask, c->win, False, BUTTONMASK,
882 880
				GrabModeAsync, GrabModeSync, None, None);
883 -
		XGrabButton(dpy, Button1, MODKEY | numlockmask | LockMask, c->win, False, BUTTONMASK,
881 +
		XGrabButton(dpy, Button1, MODKEY|numlockmask|LockMask, c->win, False, BUTTONMASK,
884 882
				GrabModeAsync, GrabModeSync, None, None);
885 883
886 884
		XGrabButton(dpy, Button2, MODKEY, c->win, False, BUTTONMASK,
887 885
				GrabModeAsync, GrabModeSync, None, None);
888 -
		XGrabButton(dpy, Button2, MODKEY | LockMask, c->win, False, BUTTONMASK,
886 +
		XGrabButton(dpy, Button2, MODKEY|LockMask, c->win, False, BUTTONMASK,
889 887
				GrabModeAsync, GrabModeSync, None, None);
890 -
		XGrabButton(dpy, Button2, MODKEY | numlockmask, c->win, False, BUTTONMASK,
888 +
		XGrabButton(dpy, Button2, MODKEY|numlockmask, c->win, False, BUTTONMASK,
891 889
				GrabModeAsync, GrabModeSync, None, None);
892 -
		XGrabButton(dpy, Button2, MODKEY | numlockmask | LockMask, c->win, False, BUTTONMASK,
890 +
		XGrabButton(dpy, Button2, MODKEY|numlockmask|LockMask, c->win, False, BUTTONMASK,
893 891
				GrabModeAsync, GrabModeSync, None, None);
894 892
895 893
		XGrabButton(dpy, Button3, MODKEY, c->win, False, BUTTONMASK,
896 894
				GrabModeAsync, GrabModeSync, None, None);
897 -
		XGrabButton(dpy, Button3, MODKEY | LockMask, c->win, False, BUTTONMASK,
895 +
		XGrabButton(dpy, Button3, MODKEY|LockMask, c->win, False, BUTTONMASK,
898 896
				GrabModeAsync, GrabModeSync, None, None);
899 -
		XGrabButton(dpy, Button3, MODKEY | numlockmask, c->win, False, BUTTONMASK,
897 +
		XGrabButton(dpy, Button3, MODKEY|numlockmask, c->win, False, BUTTONMASK,
900 898
				GrabModeAsync, GrabModeSync, None, None);
901 -
		XGrabButton(dpy, Button3, MODKEY | numlockmask | LockMask, c->win, False, BUTTONMASK,
899 +
		XGrabButton(dpy, Button3, MODKEY|numlockmask|LockMask, c->win, False, BUTTONMASK,
902 900
				GrabModeAsync, GrabModeSync, None, None);
903 901
	}
904 902
	else
926 924
		code = XKeysymToKeycode(dpy, keys[i].keysym);
927 925
		XGrabKey(dpy, code, keys[i].mod, root, True,
928 926
				GrabModeAsync, GrabModeAsync);
929 -
		XGrabKey(dpy, code, keys[i].mod | LockMask, root, True,
927 +
		XGrabKey(dpy, code, keys[i].mod|LockMask, root, True,
930 928
				GrabModeAsync, GrabModeAsync);
931 -
		XGrabKey(dpy, code, keys[i].mod | numlockmask, root, True,
929 +
		XGrabKey(dpy, code, keys[i].mod|numlockmask, root, True,
932 930
				GrabModeAsync, GrabModeAsync);
933 -
		XGrabKey(dpy, code, keys[i].mod | numlockmask | LockMask, root, True,
931 +
		XGrabKey(dpy, code, keys[i].mod|numlockmask|LockMask, root, True,
934 932
				GrabModeAsync, GrabModeAsync);
935 933
	}
936 934
}
986 984
}
987 985
988 986
Bool
989 -
isoccupied(Monitor *monitor, unsigned int t) {
987 +
isoccupied(unsigned int t) {
990 988
	Client *c;
991 989
992 990
	for(c = clients; c; c = c->next)
993 -
		if(c->tags[t] && c->monitor == monitor)
991 +
		if(c->tags[t])
994 992
			return True;
995 993
	return False;
996 994
}
1011 1009
}
1012 1010
1013 1011
Bool
1014 -
isurgent(Monitor *monitor, unsigned int t) {
1012 +
isurgent(unsigned int t) {
1015 1013
	Client *c;
1016 1014
1017 1015
	for(c = clients; c; c = c->next)
1018 -
		if(c->monitor == monitor && c->isurgent && c->tags[t])
1016 +
		if(c->isurgent && c->tags[t])
1019 1017
			return True;
1020 1018
	return False;
1021 1019
}
1022 1020
1023 1021
Bool
1024 -
isvisible(Client *c, Monitor *m) {
1022 +
isvisible(Client *c) {
1025 1023
	unsigned int i;
1026 1024
1027 -
	if(c->monitor != m)
1028 -
		return False;
1029 1025
	for(i = 0; i < LENGTH(tags); i++)
1030 -
		if(c->tags[i] && c->monitor->seltags[i])
1026 +
		if(c->tags[i] && seltags[i])
1031 1027
			return True;
1032 1028
	return False;
1033 1029
}
1071 1067
void
1072 1068
manage(Window w, XWindowAttributes *wa) {
1073 1069
	Client *c, *t = NULL;
1074 -
	Monitor *m;
1070 +
	View *v;
1075 1071
	Status rettrans;
1076 1072
	Window trans;
1077 1073
	XWindowChanges wc;
1082 1078
1083 1079
	applyrules(c);
1084 1080
1085 -
	m = c->monitor;
1081 +
	v = getview(c);
1086 1082
1087 -
	c->x = wa->x + m->sx;
1088 -
	c->y = wa->y + m->sy;
1083 +
	c->x = wa->x + v->x;
1084 +
	c->y = wa->y + v->y;
1089 1085
	c->w = wa->width;
1090 1086
	c->h = wa->height;
1091 1087
	c->oldborder = wa->border_width;
1092 1088
1093 -
	if(c->w == m->sw && c->h == m->sh) {
1094 -
		c->x = m->sx;
1095 -
		c->y = m->sy;
1089 +
	if(c->w == v->w && c->h == v->h) {
1090 +
		c->x = v->x;
1091 +
		c->y = v->y;
1096 1092
		c->border = wa->border_width;
1097 1093
	}
1098 1094
	else {
1099 -
		if(c->x + c->w + 2 * c->border > m->wax + m->waw)
1100 -
			c->x = m->wax + m->waw - c->w - 2 * c->border;
1101 -
		if(c->y + c->h + 2 * c->border > m->way + m->wah)
1102 -
			c->y = m->way + m->wah - c->h - 2 * c->border;
1103 -
		if(c->x < m->wax)
1104 -
			c->x = m->wax;
1105 -
		if(c->y < m->way)
1106 -
			c->y = m->way;
1095 +
		if(c->x + c->w + 2 * c->border > v->wax + v->waw)
1096 +
			c->x = v->wax + v->waw - c->w - 2 * c->border;
1097 +
		if(c->y + c->h + 2 * c->border > v->way + v->wah)
1098 +
			c->y = v->way + v->wah - c->h - 2 * c->border;
1099 +
		if(c->x < v->wax)
1100 +
			c->x = v->wax;
1101 +
		if(c->y < v->way)
1102 +
			c->y = v->way;
1107 1103
		c->border = BORDERPX;
1108 1104
	}
1109 1105
	wc.border_width = c->border;
1111 1107
	XSetWindowBorder(dpy, w, dc.norm[ColBorder]);
1112 1108
	configure(c); /* propagates border_width, if size doesn't change */
1113 1109
	updatesizehints(c);
1114 -
	XSelectInput(dpy, w, EnterWindowMask | FocusChangeMask | PropertyChangeMask | StructureNotifyMask);
1110 +
	XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask);
1115 1111
	grabbuttons(c, False);
1116 1112
	updatetitle(c);
1117 1113
	if((rettrans = XGetTransientForHint(dpy, w, &trans) == Success))
1126 1122
	ban(c);
1127 1123
	XMapWindow(dpy, c->win);
1128 1124
	setclientstate(c, NormalState);
1129 -
	arrange(m);
1125 +
	arrange();
1130 1126
}
1131 1127
1132 1128
void
1151 1147
		manage(ev->window, &wa);
1152 1148
}
1153 1149
1154 -
Monitor *
1155 -
monitorat() {
1150 +
View *
1151 +
viewat() {
1156 1152
	int i, x, y;
1157 1153
	Window win;
1158 1154
	unsigned int mask;
1159 1155
1160 1156
	XQueryPointer(dpy, root, &win, &win, &x, &y, &i, &i, &mask);
1161 -
	for(i = 0; i < mcount; i++) {
1162 -
		if((x >= monitors[i].sx && x < monitors[i].sx + monitors[i].sw)
1163 -
		&& (y >= monitors[i].sy && y < monitors[i].sy + monitors[i].sh)) {
1164 -
			return &monitors[i];
1157 +
	for(i = 0; i < nviews; i++) {
1158 +
		if((x >= views[i].x && x < views[i].x + views[i].w)
1159 +
		&& (y >= views[i].y && y < views[i].y + views[i].h)) {
1160 +
			return &views[i];
1165 1161
		}
1166 1162
	}
1167 1163
	return NULL;
1171 1167
movemouse(Client *c) {
1172 1168
	int x1, y1, ocx, ocy, di, nx, ny;
1173 1169
	unsigned int dui;
1174 -
	Monitor *m;
1170 +
	View *v;
1175 1171
	Window dummy;
1176 1172
	XEvent ev;
1177 1173
1178 1174
	ocx = nx = c->x;
1179 1175
	ocy = ny = c->y;
1180 -
	m = c->monitor;
1176 +
	v = getview(c);
1181 1177
	if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
1182 1178
			None, cursor[CurMove], CurrentTime) != GrabSuccess)
1183 1179
		return;
1184 1180
	XQueryPointer(dpy, root, &dummy, &dummy, &x1, &y1, &di, &di, &dui);
1185 1181
	for(;;) {
1186 -
		XMaskEvent(dpy, MOUSEMASK | ExposureMask | SubstructureRedirectMask, &ev);
1182 +
		XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev);
1187 1183
		switch (ev.type) {
1188 1184
		case ButtonRelease:
1189 1185
			XUngrabPointer(dpy, CurrentTime);
1197 1193
			XSync(dpy, False);
1198 1194
			nx = ocx + (ev.xmotion.x - x1);
1199 1195
			ny = ocy + (ev.xmotion.y - y1);
1200 -
			if(abs(m->wax - nx) < SNAP)
1201 -
				nx = m->wax;
1202 -
			else if(abs((m->wax + m->waw) - (nx + c->w + 2 * c->border)) < SNAP)
1203 -
				nx = m->wax + m->waw - c->w - 2 * c->border;
1204 -
			if(abs(m->way - ny) < SNAP)
1205 -
				ny = m->way;
1206 -
			else if(abs((m->way + m->wah) - (ny + c->h + 2 * c->border)) < SNAP)
1207 -
				ny = m->way + m->wah - c->h - 2 * c->border;
1208 -
			if(!c->isfloating && (m->layout->arrange != floating) && (abs(nx - c->x) > SNAP || abs(ny - c->y) > SNAP))
1196 +
			if(abs(v->wax - nx) < SNAP)
1197 +
				nx = v->wax;
1198 +
			else if(abs((v->wax + v->waw) - (nx + c->w + 2 * c->border)) < SNAP)
1199 +
				nx = v->wax + v->waw - c->w - 2 * c->border;
1200 +
			if(abs(v->way - ny) < SNAP)
1201 +
				ny = v->way;
1202 +
			else if(abs((v->way + v->wah) - (ny + c->h + 2 * c->border)) < SNAP)
1203 +
				ny = v->way + v->wah - c->h - 2 * c->border;
1204 +
			if(!c->isfloating && (v->layout->arrange != floating) && (abs(nx - c->x) > SNAP || abs(ny - c->y) > SNAP))
1209 1205
				togglefloating(NULL);
1210 -
			if((m->layout->arrange == floating) || c->isfloating)
1206 +
			if((v->layout->arrange == floating) || c->isfloating)
1211 1207
				resize(c, nx, ny, c->w, c->h, False);
1212 1208
			break;
1213 1209
		}
1215 1211
}
1216 1212
1217 1213
Client *
1218 -
nexttiled(Client *c, Monitor *monitor) {
1219 -
	for(; c && (c->isfloating || !isvisible(c, monitor)); c = c->next);
1214 +
nexttiled(Client *c, View *v) {
1215 +
	for(; c && (c->isfloating || getview(c) != v || !isvisible(c)); c = c->next);
1220 1216
	return c;
1221 1217
}
1222 1218
1234 1230
		case XA_WM_TRANSIENT_FOR:
1235 1231
			XGetTransientForHint(dpy, c->win, &trans);
1236 1232
			if(!c->isfloating && (c->isfloating = (getclient(trans) != NULL)))
1237 -
				arrange(c->monitor);
1233 +
				arrange();
1238 1234
			break;
1239 1235
		case XA_WM_NORMAL_HINTS:
1240 1236
			updatesizehints(c);
1241 1237
			break;
1242 1238
		case XA_WM_HINTS:
1243 1239
			updatewmhints(c);
1244 -
			drawbar(c->monitor);
1240 +
			drawbar(getview(c));
1245 1241
			break;
1246 1242
		}
1247 1243
		if(ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) {
1248 1244
			updatetitle(c);
1249 1245
			if(c == sel)
1250 -
				drawbar(c->monitor);
1246 +
				drawbar(selview);
1251 1247
		}
1252 1248
	}
1253 1249
}
1266 1262
		memcpy(c->tags, zerotags, sizeof zerotags);
1267 1263
		applyrules(c);
1268 1264
	}
1269 -
	arrange(NULL);
1265 +
	arrange();
1270 1266
}
1271 1267
1272 1268
void
1273 1269
resize(Client *c, int x, int y, int w, int h, Bool sizehints) {
1274 -
	Monitor *m;
1270 +
	View *v;
1275 1271
	XWindowChanges wc;
1276 1272
1277 -
	m = c->monitor;
1273 +
	v = getview(c);
1278 1274
	if(sizehints) {
1279 1275
		/* set minimum possible */
1280 1276
		if (w < 1)
1315 1311
	}
1316 1312
	if(w <= 0 || h <= 0)
1317 1313
		return;
1318 -
	if(x > m->sw)
1319 -
		x = m->sw - w - 2 * c->border;
1320 -
	if(y > m->sh)
1321 -
		y = m->sh - h - 2 * c->border;
1322 -
	if(x + w + 2 * c->border < m->sx)
1323 -
		x = m->sx;
1324 -
	if(y + h + 2 * c->border < m->sy)
1325 -
		y = m->sy;
1326 -
	fprintf(stderr, "resize %d %d %d %d (%d %d %d %d)\n", x, y , w, h, m->sx, m->sy, m->sw, m->sh);
1314 +
	if(x > v->x + v->w)
1315 +
		x = v->w - w - 2 * c->border;
1316 +
	if(y > v->y + v->h)
1317 +
		y = v->h - h - 2 * c->border;
1318 +
	if(x + w + 2 * c->border < v->x)
1319 +
		x = v->x;
1320 +
	if(y + h + 2 * c->border < v->y)
1321 +
		y = v->y;
1327 1322
	if(c->x != x || c->y != y || c->w != w || c->h != h) {
1328 1323
		c->x = wc.x = x;
1329 1324
		c->y = wc.y = y;
1330 1325
		c->w = wc.width = w;
1331 1326
		c->h = wc.height = h;
1332 1327
		wc.border_width = c->border;
1333 -
		XConfigureWindow(dpy, c->win, CWX | CWY | CWWidth | CWHeight | CWBorderWidth, &wc);
1328 +
		XConfigureWindow(dpy, c->win,
1329 +
				CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc);
1334 1330
		configure(c);
1335 1331
		XSync(dpy, False);
1336 1332
	}
1340 1336
resizemouse(Client *c) {
1341 1337
	int ocx, ocy;
1342 1338
	int nw, nh;
1343 -
	Monitor *m;
1339 +
	View *v;
1344 1340
	XEvent ev;
1345 1341
1346 1342
	ocx = c->x;
1347 1343
	ocy = c->y;
1348 -
	m = c->monitor;
1344 +
	v = getview(c);
1349 1345
	if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
1350 1346
			None, cursor[CurResize], CurrentTime) != GrabSuccess)
1351 1347
		return;
1352 1348
	XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->border - 1, c->h + c->border - 1);
1353 1349
	for(;;) {
1354 -
		XMaskEvent(dpy, MOUSEMASK | ExposureMask | SubstructureRedirectMask , &ev);
1350 +
		XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask , &ev);
1355 1351
		switch(ev.type) {
1356 1352
		case ButtonRelease:
1357 1353
			XWarpPointer(dpy, None, c->win, 0, 0, 0, 0,
1370 1366
				nw = 1;
1371 1367
			if((nh = ev.xmotion.y - ocy - 2 * c->border + 1) <= 0)
1372 1368
				nh = 1;
1373 -
			if(!c->isfloating && (m->layout->arrange != floating) && (abs(nw - c->w) > SNAP || abs(nh - c->h) > SNAP))
1369 +
			if(!c->isfloating && (v->layout->arrange != floating) && (abs(nw - c->w) > SNAP || abs(nh - c->h) > SNAP))
1374 1370
				togglefloating(NULL);
1375 -
			if((m->layout->arrange == floating) || c->isfloating)
1371 +
			if((v->layout->arrange == floating) || c->isfloating)
1376 1372
				resize(c, c->x, c->y, nw, nh, True);
1377 1373
			break;
1378 1374
		}
1380 1376
}
1381 1377
1382 1378
void
1383 -
restack(Monitor *m) {
1379 +
restack(View *v) {
1384 1380
	Client *c;
1385 1381
	XEvent ev;
1386 1382
	XWindowChanges wc;
1387 1383
1388 -
	drawbar(m);
1384 +
	drawbar(v);
1389 1385
	if(!sel)
1390 1386
		return;
1391 -
	if(sel->isfloating || (m->layout->arrange == floating))
1387 +
	if(sel->isfloating || (v->layout->arrange == floating))
1392 1388
		XRaiseWindow(dpy, sel->win);
1393 -
	if(m->layout->arrange != floating) {
1389 +
	if(v->layout->arrange != floating) {
1394 1390
		wc.stack_mode = Below;
1395 -
		wc.sibling = m->barwin;
1391 +
		wc.sibling = v->barwin;
1396 1392
		if(!sel->isfloating) {
1397 -
			XConfigureWindow(dpy, sel->win, CWSibling | CWStackMode, &wc);
1393 +
			XConfigureWindow(dpy, sel->win, CWSibling|CWStackMode, &wc);
1398 1394
			wc.sibling = sel->win;
1399 1395
		}
1400 -
		for(c = nexttiled(clients, m); c; c = nexttiled(c->next, m)) {
1396 +
		for(c = nexttiled(clients, v); c; c = nexttiled(c->next, v)) {
1401 1397
			if(c == sel)
1402 1398
				continue;
1403 -
			XConfigureWindow(dpy, c->win, CWSibling | CWStackMode, &wc);
1399 +
			XConfigureWindow(dpy, c->win, CWSibling|CWStackMode, &wc);
1404 1400
			wc.sibling = c->win;
1405 1401
		}
1406 1402
	}
1458 1454
					}
1459 1455
				break;
1460 1456
			}
1461 -
			drawbar(selmonitor);
1457 +
			drawbar(selview);
1462 1458
		}
1463 1459
		while(XPending(dpy)) {
1464 1460
			XNextEvent(dpy, &ev);
1506 1502
void
1507 1503
setlayout(const char *arg) {
1508 1504
	unsigned int i;
1509 -
	Monitor *m = monitorat();
1505 +
	View *v = selview;
1510 1506
1511 1507
	if(!arg) {
1512 -
		m->layout++;
1513 -
		if(m->layout == &layouts[LENGTH(layouts)])
1514 -
			m->layout = &layouts[0];
1508 +
		v->layout++;
1509 +
		if(v->layout == &layouts[LENGTH(layouts)])
1510 +
			v->layout = &layouts[0];
1515 1511
	}
1516 1512
	else {
1517 1513
		for(i = 0; i < LENGTH(layouts); i++)
1519 1515
				break;
1520 1516
		if(i == LENGTH(layouts))
1521 1517
			return;
1522 -
		m->layout = &layouts[i];
1518 +
		v->layout = &layouts[i];
1523 1519
	}
1524 1520
	if(sel)
1525 -
		arrange(m);
1521 +
		arrange();
1526 1522
	else
1527 -
		drawbar(m);
1523 +
		drawbar(v);
1528 1524
}
1529 1525
1530 1526
void
1531 1527
setmwfact(const char *arg) {
1532 1528
	double delta;
1533 1529
1534 -
	Monitor *m = monitorat();
1530 +
	View *v = selview;
1535 1531
1536 1532
	if(!domwfact)
1537 1533
		return;
1538 1534
	/* arg handling, manipulate mwfact */
1539 1535
	if(arg == NULL)
1540 -
		m->mwfact = MWFACT;
1536 +
		v->mwfact = MWFACT;
1541 1537
	else if(sscanf(arg, "%lf", &delta) == 1) {
1542 1538
		if(arg[0] == '+' || arg[0] == '-')
1543 -
			m->mwfact += delta;
1539 +
			v->mwfact += delta;
1544 1540
		else
1545 -
			m->mwfact = delta;
1546 -
		if(m->mwfact < 0.1)
1547 -
			m->mwfact = 0.1;
1548 -
		else if(m->mwfact > 0.9)
1549 -
			m->mwfact = 0.9;
1541 +
			v->mwfact = delta;
1542 +
		if(v->mwfact < 0.1)
1543 +
			v->mwfact = 0.1;
1544 +
		else if(v->mwfact > 0.9)
1545 +
			v->mwfact = 0.9;
1550 1546
	}
1551 -
	arrange(m);
1547 +
	arrange();
1552 1548
}
1553 1549
1554 1550
void
1555 1551
setup(void) {
1556 1552
	unsigned int i;
1557 -
	Monitor *m;
1553 +
	View *v;
1558 1554
	XSetWindowAttributes wa;
1559 1555
	XineramaScreenInfo *info = NULL;
1560 1556
1571 1567
	cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing);
1572 1568
	cursor[CurMove] = XCreateFontCursor(dpy, XC_fleur);
1573 1569
1574 -
	// init screens/monitors first
1575 1570
	if((isxinerama = XineramaIsActive(dpy)))
1576 -
		info = XineramaQueryScreens(dpy, &mcount);
1577 -
	selmonitor = monitors = emallocz(mcount * sizeof(Monitor));
1571 +
		info = XineramaQueryScreens(dpy, &nviews);
1572 +
#if defined(AIM_XINERAMA)
1573 +
isxinerama = True;
1574 +
nviews = 2; /* aim Xinerama */
1575 +
#endif
1576 +
	selview = views = emallocz(nviews * sizeof(View));
1578 1577
1579 1578
	screen = DefaultScreen(dpy);
1580 1579
	root = RootWindow(dpy, screen);
1599 1598
		if(i > blw)
1600 1599
			blw = i;
1601 1600
	}
1602 -
	for(i = 0; i < mcount; i++) {
1601 +
1602 +
	seltags = emallocz(sizeof initags);
1603 +
	prevtags = emallocz(sizeof initags);
1604 +
	memcpy(seltags, initags, sizeof initags);
1605 +
	memcpy(prevtags, initags, sizeof initags);
1606 +
1607 +
	for(i = 0; i < nviews; i++) {
1603 1608
		/* init geometry */
1604 -
		m = &monitors[i];
1609 +
		v = &views[i];
1610 +
		v->id = i + 1;
1611 +
1612 +
		if(nviews != 1 && isxinerama) {
1605 1613
1606 -
		if(mcount != 1 && isxinerama) {
1607 -
			m->sx = info[i].x_org;
1608 -
			m->sy = info[i].y_org;
1609 -
			m->sw = info[i].width;
1610 -
			m->sh = info[i].height;
1611 -
			fprintf(stderr, "monitor[%d]: %d,%d,%d,%d\n", i, m->sx, m->sy, m->sw, m->sh);
1614 +
#if defined(AIM_XINERAMA)
1615 +
v->w = DisplayWidth(dpy, screen) / 2;
1616 +
v->x = (i == 0) ? 0 : v->w;
1617 +
v->y = 0;
1618 +
v->h = DisplayHeight(dpy, screen);
1619 +
#else
1620 +
			v->x = info[i].x_org;
1621 +
			v->y = info[i].y_org;
1622 +
			v->w = info[i].width;
1623 +
			v->h = info[i].height;
1624 +
#endif
1612 1625
		}
1613 1626
		else {
1614 -
			m->sx = 0;
1615 -
			m->sy = 0;
1616 -
			m->sw = DisplayWidth(dpy, screen);
1617 -
			m->sh = DisplayHeight(dpy, screen);
1627 +
			v->x = 0;
1628 +
			v->y = 0;
1629 +
			v->w = DisplayWidth(dpy, screen);
1630 +
			v->h = DisplayHeight(dpy, screen);
1618 1631
		}
1619 1632
1620 -
		m->seltags = emallocz(sizeof initags);
1621 -
		m->prevtags = emallocz(sizeof initags);
1622 -
1623 -
		memcpy(m->seltags, initags, sizeof initags);
1624 -
		memcpy(m->prevtags, initags, sizeof initags);
1625 -
1626 1633
		/* init layouts */
1627 -
		m->mwfact = MWFACT;
1628 -
		m->layout = &layouts[0];
1634 +
		v->mwfact = MWFACT;
1635 +
		v->layout = &layouts[0];
1629 1636
1630 1637
		// TODO: bpos per screen?
1631 1638
		bpos = BARPOS;
1632 1639
		wa.override_redirect = 1;
1633 1640
		wa.background_pixmap = ParentRelative;
1634 -
		wa.event_mask = ButtonPressMask | ExposureMask;
1641 +
		wa.event_mask = ButtonPressMask|ExposureMask;
1635 1642
1636 1643
		/* init bars */
1637 -
		m->barwin = XCreateWindow(dpy, root, m->sx, m->sy, m->sw, bh, 0,
1644 +
		v->barwin = XCreateWindow(dpy, root, v->x, v->y, v->w, bh, 0,
1638 1645
				DefaultDepth(dpy, screen), CopyFromParent, DefaultVisual(dpy, screen),
1639 -
				CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa);
1640 -
		XDefineCursor(dpy, m->barwin, cursor[CurNormal]);
1641 -
		updatebarpos(m);
1642 -
		XMapRaised(dpy, m->barwin);
1646 +
				CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa);
1647 +
		XDefineCursor(dpy, v->barwin, cursor[CurNormal]);
1648 +
		updatebarpos(v);
1649 +
		XMapRaised(dpy, v->barwin);
1643 1650
		strcpy(stext, "dwm-"VERSION);
1644 1651
1645 -
		/* EWMH support per monitor */
1652 +
		/* EWMH support per view */
1646 1653
		XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32,
1647 1654
				PropModeReplace, (unsigned char *) netatom, NetLast);
1648 1655
1649 1656
		/* select for events */
1650 -
		wa.event_mask = SubstructureRedirectMask | SubstructureNotifyMask
1651 -
				| EnterWindowMask | LeaveWindowMask | StructureNotifyMask;
1652 -
		XChangeWindowAttributes(dpy, root, CWEventMask | CWCursor, &wa);
1657 +
		wa.event_mask = SubstructureRedirectMask|SubstructureNotifyMask
1658 +
				|EnterWindowMask|LeaveWindowMask|StructureNotifyMask;
1659 +
		XChangeWindowAttributes(dpy, root, CWEventMask|CWCursor, &wa);
1653 1660
		XSelectInput(dpy, root, wa.event_mask);
1654 1661
1655 -
		drawbar(m);
1662 +
		drawbar(v);
1656 1663
	}
1657 1664
	if(info)
1658 1665
		XFree(info);
1663 1670
	/* init tags */
1664 1671
	compileregs();
1665 1672
1666 -
	selmonitor = monitorat();
1667 -
	fprintf(stderr, "selmonitor == %d\n", selmonitor - monitors);
1673 +
	selview = &views[0];
1668 1674
}
1669 1675
1670 1676
void
1698 1704
	if(!sel)
1699 1705
		return;
1700 1706
	for(i = 0; i < LENGTH(tags); i++)
1701 -
		sel->tags[i] = (NULL == arg);
1702 -
	sel->tags[idxoftag(arg)] = True;
1703 -
	arrange(sel->monitor);
1707 +
		sel->tags[i] = (NULL == arg) ? selview->id : 0;
1708 +
	sel->tags[idxoftag(arg)] = selview->id;
1709 +
	arrange();
1704 1710
}
1705 1711
1706 1712
unsigned int
1720 1726
}
1721 1727
1722 1728
void
1723 -
tile(Monitor *m) {
1729 +
tile(View *v) {
1724 1730
	unsigned int i, n, nx, ny, nw, nh, mw, th;
1725 1731
	Client *c, *mc;
1726 1732
1727 1733
	domwfact = dozoom = True;
1728 -
	nx = m->wax;
1729 -
	ny = m->way;
1734 +
	nx = v->wax;
1735 +
	ny = v->way;
1730 1736
	nw = 0;
1731 -
	for(n = 0, c = nexttiled(clients, m); c; c = nexttiled(c->next, m))
1737 +
	for(n = 0, c = nexttiled(clients, v); c; c = nexttiled(c->next, v))
1732 1738
		n++;
1733 1739
1734 1740
	/* window geoms */
1735 -
	mw = (n == 1) ? m->waw : m->mwfact * m->waw;
1736 -
	th = (n > 1) ? m->wah / (n - 1) : 0;
1741 +
	mw = (n == 1) ? v->waw : v->mwfact * v->waw;
1742 +
	th = (n > 1) ? v->wah / (n - 1) : 0;
1737 1743
	if(n > 1 && th < bh)
1738 -
		th = m->wah;
1744 +
		th = v->wah;
1739 1745
1740 -
	for(i = 0, c = mc = nexttiled(clients, m); c; c = nexttiled(c->next, m)) {
1746 +
	for(i = 0, c = mc = nexttiled(clients, v); c; c = nexttiled(c->next, v)) {
1741 1747
		if(i == 0) { /* master */
1742 -
			nx = m->wax;
1743 -
			ny = m->way;
1748 +
			nx = v->wax;
1749 +
			ny = v->way;
1744 1750
			nw = mw - 2 * c->border;
1745 -
			nh = m->wah - 2 * c->border;
1751 +
			nh = v->wah - 2 * c->border;
1746 1752
		}
1747 1753
		else {  /* tile window */
1748 1754
			if(i == 1) {
1749 -
				ny = m->way;
1755 +
				ny = v->way;
1750 1756
				nx += mc->w + 2 * mc->border;
1751 -
				nw = m->waw - mw - 2 * c->border;
1757 +
				nw = v->waw - mw - 2 * c->border;
1752 1758
			}
1753 1759
			if(i + 1 == n) /* remainder */
1754 -
				nh = (m->way + m->wah) - ny - 2 * c->border;
1760 +
				nh = (v->way + v->wah) - ny - 2 * c->border;
1755 1761
			else
1756 1762
				nh = th - 2 * c->border;
1757 1763
		}
1760 1766
		if((RESIZEHINTS) && ((c->h < bh) || (c->h > nh) || (c->w < bh) || (c->w > nw)))
1761 1767
			/* client doesn't accept size constraints */
1762 1768
			resize(c, nx, ny, nw, nh, False);
1763 -
		if(n > 1 && th != m->wah)
1769 +
		if(n > 1 && th != v->wah)
1764 1770
			ny = c->y + c->h + 2 * c->border;
1765 1771
		i++;
1766 1772
	}
1772 1778
		bpos = (BARPOS == BarOff) ? BarTop : BARPOS;
1773 1779
	else
1774 1780
		bpos = BarOff;
1775 -
	updatebarpos(monitorat());
1776 -
	arrange(monitorat());
1781 +
	updatebarpos(selview);
1782 +
	arrange();
1777 1783
}
1778 1784
1779 1785
void
1783 1789
	sel->isfloating = !sel->isfloating;
1784 1790
	if(sel->isfloating)
1785 1791
		resize(sel, sel->x, sel->y, sel->w, sel->h, True);
1786 -
	arrange(sel->monitor);
1792 +
	arrange();
1787 1793
}
1788 1794
1789 1795
void
1796 1802
	sel->tags[i] = !sel->tags[i];
1797 1803
	for(j = 0; j < LENGTH(tags) && !sel->tags[j]; j++);
1798 1804
	if(j == LENGTH(tags))
1799 -
		sel->tags[i] = True; /* at least one tag must be enabled */
1800 -
	arrange(sel->monitor);
1805 +
		sel->tags[i] = selview->id; /* at least one tag must be enabled */
1806 +
	arrange();
1801 1807
}
1802 1808
1803 1809
void
1804 1810
toggleview(const char *arg) {
1805 1811
	unsigned int i, j;
1806 -
	Monitor *m = monitorat();
1807 1812
1808 1813
	i = idxoftag(arg);
1809 -
	m->seltags[i] = !m->seltags[i];
1810 -
	for(j = 0; j < LENGTH(tags) && !m->seltags[j]; j++);
1814 +
	seltags[i] = !seltags[i];
1815 +
	for(j = 0; j < LENGTH(tags) && !seltags[j]; j++);
1811 1816
	if(j == LENGTH(tags))
1812 -
		m->seltags[i] = True; /* at least one tag must be viewed */
1813 -
	arrange(m);
1817 +
		seltags[i] = selview->id; /* at least one tag must be viewed */
1818 +
	arrange();
1814 1819
}
1815 1820
1816 1821
void
1823 1828
1824 1829
void
1825 1830
unmanage(Client *c) {
1826 -
	Monitor *m = c->monitor;
1827 1831
	XWindowChanges wc;
1828 1832
1829 1833
	wc.border_width = c->oldborder;
1842 1846
	XSync(dpy, False);
1843 1847
	XSetErrorHandler(xerror);
1844 1848
	XUngrabServer(dpy);
1845 -
	arrange(m);
1849 +
	arrange();
1846 1850
}
1847 1851
1848 1852
void
1855 1859
}
1856 1860
1857 1861
void
1858 -
updatebarpos(Monitor *m) {
1862 +
updatebarpos(View *v) {
1859 1863
	XEvent ev;
1860 1864
1861 -
	m->wax = m->sx;
1862 -
	m->way = m->sy;
1863 -
	m->wah = m->sh;
1864 -
	m->waw = m->sw;
1865 +
	v->wax = v->x;
1866 +
	v->way = v->y;
1867 +
	v->wah = v->h;
1868 +
	v->waw = v->w;
1865 1869
	switch(bpos) {
1866 1870
	default:
1867 -
		m->wah -= bh;
1868 -
		m->way += bh;
1869 -
		XMoveWindow(dpy, m->barwin, m->sx, m->sy);
1871 +
		v->wah -= bh;
1872 +
		v->way += bh;
1873 +
		XMoveWindow(dpy, v->barwin, v->x, v->y);
1870 1874
		break;
1871 1875
	case BarBot:
1872 -
		m->wah -= bh;
1873 -
		XMoveWindow(dpy, m->barwin, m->sx, m->sy + m->wah);
1876 +
		v->wah -= bh;
1877 +
		XMoveWindow(dpy, v->barwin, v->x, v->y + v->wah);
1874 1878
		break;
1875 1879
	case BarOff:
1876 -
		XMoveWindow(dpy, m->barwin, m->sx, m->sy - bh);
1880 +
		XMoveWindow(dpy, v->barwin, v->x, v->y - bh);
1877 1881
		break;
1878 1882
	}
1879 1883
	XSync(dpy, False);
1968 1972
}
1969 1973
1970 1974
int
1971 -
xerrordummy(Display *dsply, XErrorEvent *ee) {
1975 +
xerrordummy(Display *dpy, XErrorEvent *ee) {
1972 1976
	return 0;
1973 1977
}
1974 1978
1975 1979
/* Startup Error handler to check if another window manager
1976 1980
 * is already running. */
1977 1981
int
1978 -
xerrorstart(Display *dsply, XErrorEvent *ee) {
1982 +
xerrorstart(Display *dpy, XErrorEvent *ee) {
1979 1983
	otherwm = True;
1980 1984
	return -1;
1981 1985
}
1983 1987
void
1984 1988
view(const char *arg) {
1985 1989
	unsigned int i;
1986 -
	Bool tmp[LENGTH(tags)];
1987 -
	Monitor *m = monitorat();
1990 +
	int tmp[LENGTH(tags)];
1988 1991
1989 1992
	for(i = 0; i < LENGTH(tags); i++)
1990 -
		tmp[i] = (NULL == arg);
1991 -
	tmp[idxoftag(arg)] = True;
1992 -
	if(memcmp(m->seltags, tmp, sizeof initags) != 0) {
1993 -
		memcpy(m->prevtags, m->seltags, sizeof initags);
1994 -
		memcpy(m->seltags, tmp, sizeof initags);
1995 -
		arrange(m);
1993 +
		tmp[i] = (NULL == arg) ? selview->id : 0;
1994 +
	tmp[idxoftag(arg)] = selview->id;
1995 +
	if(memcmp(seltags, tmp, sizeof initags) != 0) {
1996 +
		memcpy(prevtags, seltags, sizeof initags);
1997 +
		memcpy(seltags, tmp, sizeof initags);
1998 +
		arrange();
1996 1999
	}
1997 2000
}
1998 2001
2000 2003
viewprevtag(const char *arg) {
2001 2004
	static Bool tmp[LENGTH(tags)];
2002 2005
2003 -
	Monitor *m = monitorat();
2004 -
2005 -
	memcpy(tmp, m->seltags, sizeof initags);
2006 -
	memcpy(m->seltags, m->prevtags, sizeof initags);
2007 -
	memcpy(m->prevtags, tmp, sizeof initags);
2008 -
	arrange(m);
2006 +
	memcpy(tmp, seltags, sizeof initags);
2007 +
	memcpy(seltags, prevtags, sizeof initags);
2008 +
	memcpy(prevtags, tmp, sizeof initags);
2009 +
	arrange();
2009 2010
}
2010 2011
2011 2012
void
2014 2015
2015 2016
	if(!sel || !dozoom || sel->isfloating)
2016 2017
		return;
2017 -
	if(c == nexttiled(clients, c->monitor))
2018 -
		if(!(c = nexttiled(c->next, c->monitor)))
2018 +
	if(c == nexttiled(clients, getview(c)))
2019 +
		if(!(c = nexttiled(c->next, getview(c))))
2019 2020
			return;
2020 2021
	detach(c);
2021 2022
	attach(c);
2022 2023
	focus(c);
2023 -
	arrange(c->monitor);
2024 +
	arrange();
2024 2025
}
2025 2026
2026 2027
void
2027 -
movetomonitor(const char *arg) {
2028 +
selectview(const char *arg) {
2028 2029
	int i;
2030 +
	View *v;
2029 2031
2030 -
	if (sel)
2032 +
	if(!arg)
2031 2033
		return;
2032 2034
	if(arg)
2033 2035
		i = atoi(arg);
2034 -
	else {
2035 -
		for(i = 0; &monitors[i] != sel->monitor && i < mcount; i++);
2036 -
		i++;
2037 -
	}
2038 -
	sel->monitor = &monitors[i % mcount];
2039 -
2040 -
	memcpy(sel->tags, sel->monitor->seltags, sizeof initags);
2041 -
	resize(sel, sel->monitor->wax, sel->monitor->way, sel->w, sel->h, True);
2042 -
	arrange(sel->monitor);
2043 -
}
2044 -
2045 -
void
2046 -
selectmonitor(const char *arg) {
2047 -
	int i;
2048 -
	Monitor *m;
2049 -
2050 -
	if(arg)
2051 -
		i = atoi(arg);
2052 -
	else {
2053 -
		for(i = 0; &monitors[i] != sel->monitor && i < mcount; i++);
2054 -
		i++;
2055 -
	}
2056 -
	m = &monitors[i % mcount];
2057 -
	XWarpPointer(dpy, None, root, 0, 0, 0, 0, m->wax+m->waw/2, m->way+m->wah/2);
2036 +
	v = &views[i % nviews];
2037 +
	XWarpPointer(dpy, None, root, 0, 0, 0, 0, v->wax+v->waw/2, v->way+v->wah/2);
2058 2038
	focus(NULL);
2059 2039
}
2060 2040
2061 2041
2062 2042
int
2063 2043
main(int argc, char *argv[]) {
2064 -
	fprintf(stderr, "%u\n", sizeof("jsjsjsjsjssjsj"));
2065 2044
	if(argc == 2 && !strcmp("-v", argv[1]))
2066 2045
		eprint("dwm-"VERSION", © 2006-2008 dwm engineers, see LICENSE for details\n");
2067 2046
	else if(argc != 1)