introduction of Monitor for better Xinerama support, work in progress f27ccc5c
Anselm R Garbe · 2009-06-19 20:15 2 file(s) · +109 −78
config.mk +2 −2
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}
dwm.c +107 −76
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[seltags])
47 +
#define ISVISIBLE(x)            (x->tags & tagset[selmon->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))
85 85
	int basew, baseh, incw, inch, maxw, maxh, minw, minh;
86 86
	int bw, oldbw;
87 87
	unsigned int tags;
88 +
	unsigned int mon;
88 89
	Bool isfixed, isfloating, isurgent;
89 90
	Client *next;
90 91
	Client *snext;
119 120
} Layout;
120 121
121 122
typedef struct {
123 +
	int wx, wy, ww, wh;
124 +
	unsigned int seltags;
125 +
	unsigned int sellt;
126 +
} Monitor;
127 +
128 +
typedef struct {
122 129
	const char *class;
123 130
	const char *instance;
124 131
	const char *title;
208 215
static int screen;
209 216
static int sx, sy, sw, sh; /* X display screen geometry x, y, width, height */ 
210 217
static int by, bh, blw;    /* bar geometry y, height and layout symbol width */
211 -
static int wx, wy, ww, wh; /* window area geometry x, y, width, height, bar excluded */
212 -
static unsigned int seltags = 0, sellt = 0;
213 218
static int (*xerrorxlib)(Display *, XErrorEvent *);
214 219
static unsigned int numlockmask = 0;
215 220
static void (*handler[LASTEvent]) (XEvent *) = {
236 241
static Display *dpy;
237 242
static DC dc;
238 243
static Layout *lt[] = { NULL, NULL };
244 +
static Monitor *mon = NULL, *selmon = NULL;
245 +
static unsigned int nmons;
239 246
static Window root, barwin;
240 247
/* configuration, allows nested code to access above variables */
241 248
#include "config.h"
267 274
		if(ch.res_name)
268 275
			XFree(ch.res_name);
269 276
	}
270 -
	c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : tagset[seltags];
277 +
	c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : tagset[mon[c->mon].seltags];
271 278
}
272 279
273 280
Bool
339 346
arrange(void) {
340 347
	showhide(stack);
341 348
	focus(NULL);
342 -
	if(lt[sellt]->arrange)
343 -
		lt[sellt]->arrange();
349 +
	if(lt[selmon->sellt]->arrange)
350 +
		lt[selmon->sellt]->arrange();
344 351
	restack();
345 352
}
346 353
373 380
		}
374 381
		else if(ev->x < x + blw)
375 382
			click = ClkLtSymbol;
376 -
		else if(ev->x > wx + ww - TEXTW(stext))
383 +
		else if(ev->x > selmon->wx + selmon->ww - TEXTW(stext))
377 384
			click = ClkStatusText;
378 385
		else
379 386
			click = ClkWinTitle;
409 416
	Layout foo = { "", NULL };
410 417
411 418
	view(&a);
412 -
	lt[sellt] = &foo;
419 +
	lt[selmon->sellt] = &foo;
413 420
	while(stack)
414 421
		unmanage(stack);
415 422
	if(dc.font.set)
479 486
	if((c = getclient(ev->window))) {
480 487
		if(ev->value_mask & CWBorderWidth)
481 488
			c->bw = ev->border_width;
482 -
		else if(c->isfloating || !lt[sellt]->arrange) {
489 +
		else if(c->isfloating || !lt[selmon->sellt]->arrange) {
483 490
			if(ev->value_mask & CWX)
484 491
				c->x = sx + ev->x;
485 492
			if(ev->value_mask & CWY)
564 571
	dc.x = 0;
565 572
	for(i = 0; i < LENGTH(tags); i++) {
566 573
		dc.w = TEXTW(tags[i]);
567 -
		col = tagset[seltags] & 1 << i ? dc.sel : dc.norm;
574 +
		col = tagset[selmon->seltags] & 1 << i ? dc.sel : dc.norm;
568 575
		drawtext(tags[i], col, urg & 1 << i);
569 576
		drawsquare(sel && sel->tags & 1 << i, occ & 1 << i, urg & 1 << i, col);
570 577
		dc.x += dc.w;
571 578
	}
572 579
	if(blw > 0) {
573 580
		dc.w = blw;
574 -
		drawtext(lt[sellt]->symbol, dc.norm, False);
581 +
		drawtext(lt[selmon->sellt]->symbol, dc.norm, False);
575 582
		x = dc.x + dc.w;
576 583
	}
577 584
	else
578 585
		x = dc.x;
579 586
	dc.w = TEXTW(stext);
580 -
	dc.x = ww - dc.w;
587 +
	dc.x = selmon->ww - dc.w;
581 588
	if(dc.x < x) {
582 589
		dc.x = x;
583 -
		dc.w = ww - x;
590 +
		dc.w = selmon->ww - x;
584 591
	}
585 592
	drawtext(stext, dc.norm, False);
586 593
	if((dc.w = dc.x - x) > bh) {
592 599
		else
593 600
			drawtext(NULL, dc.norm, False);
594 601
	}
595 -
	XCopyArea(dpy, dc.drawable, barwin, dc.gc, 0, 0, ww, bh, 0, 0);
602 +
	XCopyArea(dpy, dc.drawable, barwin, dc.gc, 0, 0, selmon->ww, bh, 0, 0);
596 603
	XSync(dpy, False);
597 604
}
598 605
919 926
		die("fatal: could not malloc() %u bytes\n", sizeof(Client));
920 927
	*c = cz;
921 928
	c->win = w;
929 +
	for(c->mon = 0; selmon != &mon[c->mon]; c->mon++);
922 930
923 931
	/* geometry */
924 932
	c->x = wa->x;
938 946
			c->y = sy + sh - HEIGHT(c);
939 947
		c->x = MAX(c->x, sx);
940 948
		/* only fix client y-offset, if the client center might cover the bar */
941 -
		c->y = MAX(c->y, ((by == 0) && (c->x + (c->w / 2) >= wx)
942 -
		                            && (c->x + (c->w / 2) < wx + ww)) ? bh : sy);
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);
943 952
		c->bw = borderpx;
944 953
	}
945 954
994 1003
void
995 1004
monocle(void) {
996 1005
	Client *c;
1006 +
	Monitor *m;
997 1007
998 1008
	for(c = nexttiled(clients); c; c = nexttiled(c->next)) {
999 -
		resize(c, wx, wy, ww - 2 * c->bw, wh - 2 * c->bw);
1009 +
		m = &mon[c->mon];
1010 +
		resize(c, m->wx, m->wy, m->ww - 2 * c->bw, m->wh - 2 * c->bw);
1000 1011
	}
1001 1012
}
1002 1013
1028 1039
		case MotionNotify:
1029 1040
			nx = ocx + (ev.xmotion.x - x);
1030 1041
			ny = ocy + (ev.xmotion.y - y);
1031 -
			if(snap && nx >= wx && nx <= wx + ww
1032 -
			        && ny >= wy && ny <= wy + wh) {
1033 -
				if(abs(wx - nx) < snap)
1034 -
					nx = wx;
1035 -
				else if(abs((wx + ww) - (nx + WIDTH(c))) < snap)
1036 -
					nx = wx + ww - WIDTH(c);
1037 -
				if(abs(wy - ny) < snap)
1038 -
					ny = wy;
1039 -
				else if(abs((wy + wh) - (ny + HEIGHT(c))) < snap)
1040 -
					ny = wy + wh - HEIGHT(c);
1041 -
				if(!c->isfloating && lt[sellt]->arrange
1042 +
			if(snap && nx >= selmon->wx && nx <= selmon->wx + selmon->ww
1043 +
			        && ny >= selmon->wy && ny <= selmon->wy + selmon->wh) {
1044 +
				if(abs(selmon->wx - nx) < snap)
1045 +
					nx = selmon->wx;
1046 +
				else if(abs((selmon->wx + selmon->ww) - (nx + WIDTH(c))) < snap)
1047 +
					nx = selmon->wx + selmon->ww - WIDTH(c);
1048 +
				if(abs(selmon->wy - ny) < snap)
1049 +
					ny = selmon->wy;
1050 +
				else if(abs((selmon->wy + selmon->wh) - (ny + HEIGHT(c))) < snap)
1051 +
					ny = selmon->wy + selmon->wh - HEIGHT(c);
1052 +
				if(!c->isfloating && lt[selmon->sellt]->arrange
1042 1053
				                  && (abs(nx - c->x) > snap || abs(ny - c->y) > snap))
1043 1054
					togglefloating(NULL);
1044 1055
			}
1045 -
			if(!lt[sellt]->arrange || c->isfloating)
1056 +
			if(!lt[selmon->sellt]->arrange || c->isfloating)
1046 1057
				resize(c, nx, ny, c->w, c->h);
1047 1058
			break;
1048 1059
		}
1141 1152
			nw = MAX(ev.xmotion.x - ocx - 2 * c->bw + 1, 1);
1142 1153
			nh = MAX(ev.xmotion.y - ocy - 2 * c->bw + 1, 1);
1143 1154
1144 -
			if(snap && nw >= wx && nw <= wx + ww
1145 -
			        && nh >= wy && nh <= wy + wh) {
1146 -
				if(!c->isfloating && lt[sellt]->arrange
1155 +
			if(snap && nw >= selmon->wx && nw <= selmon->wx + selmon->ww
1156 +
			        && nh >= selmon->wy && nh <= selmon->wy + selmon->wh) {
1157 +
				if(!c->isfloating && lt[selmon->sellt]->arrange
1147 1158
				   && (abs(nw - c->w) > snap || abs(nh - c->h) > snap))
1148 1159
					togglefloating(NULL);
1149 1160
			}
1150 -
			if(!lt[sellt]->arrange || c->isfloating)
1161 +
			if(!lt[selmon->sellt]->arrange || c->isfloating)
1151 1162
				resize(c, c->x, c->y, nw, nh);
1152 1163
			break;
1153 1164
		}
1167 1178
	drawbar();
1168 1179
	if(!sel)
1169 1180
		return;
1170 -
	if(sel->isfloating || !lt[sellt]->arrange)
1181 +
	if(sel->isfloating || !lt[selmon->sellt]->arrange)
1171 1182
		XRaiseWindow(dpy, sel->win);
1172 -
	if(lt[sellt]->arrange) {
1183 +
	if(lt[selmon->sellt]->arrange) {
1173 1184
		wc.stack_mode = Below;
1174 1185
		wc.sibling = barwin;
1175 1186
		for(c = stack; c; c = c->snext)
1230 1241
1231 1242
void
1232 1243
setlayout(const Arg *arg) {
1233 -
	if(!arg || !arg->v || arg->v != lt[sellt])
1234 -
		sellt ^= 1;
1244 +
	if(!arg || !arg->v || arg->v != lt[selmon->sellt])
1245 +
		selmon->sellt ^= 1;
1235 1246
	if(arg && arg->v)
1236 -
		lt[sellt] = (Layout *)arg->v;
1247 +
		lt[selmon->sellt] = (Layout *)arg->v;
1237 1248
	if(sel)
1238 1249
		arrange();
1239 1250
	else
1245 1256
setmfact(const Arg *arg) {
1246 1257
	float f;
1247 1258
1248 -
	if(!arg || !lt[sellt]->arrange)
1259 +
	if(!arg || !lt[selmon->sellt]->arrange)
1249 1260
		return;
1250 1261
	f = arg->f < 1.0 ? arg->f + mfact : arg->f - 1.0;
1251 1262
	if(f < 0.1 || f > 0.9)
1308 1319
	wa.background_pixmap = ParentRelative;
1309 1320
	wa.event_mask = ButtonPressMask|ExposureMask;
1310 1321
1311 -
	barwin = XCreateWindow(dpy, root, wx, by, ww, bh, 0, DefaultDepth(dpy, screen),
1322 +
	barwin = XCreateWindow(dpy, root, selmon->wx, by, selmon->ww, bh, 0, DefaultDepth(dpy, screen),
1312 1323
			CopyFromParent, DefaultVisual(dpy, screen),
1313 1324
			CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa);
1314 1325
	XDefineCursor(dpy, barwin, cursor[CurNormal]);
1335 1346
		return;
1336 1347
	if(ISVISIBLE(c)) { /* show clients top down */
1337 1348
		XMoveWindow(dpy, c->win, c->x, c->y);
1338 -
		if(!lt[sellt]->arrange || c->isfloating)
1349 +
		if(!lt[selmon->sellt]->arrange || c->isfloating)
1339 1350
			resize(c, c->x, c->y, c->w, c->h);
1340 1351
		showhide(c->snext);
1341 1352
	}
1389 1400
	int x, y, h, w, mw;
1390 1401
	unsigned int i, n;
1391 1402
	Client *c;
1403 +
	Monitor *m;
1392 1404
1393 1405
	for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next), n++);
1394 1406
	if(n == 0)
1396 1408
1397 1409
	/* master */
1398 1410
	c = nexttiled(clients);
1399 -
	mw = mfact * ww;
1400 -
	resize(c, wx, wy, (n == 1 ? ww : mw) - 2 * c->bw, wh - 2 * c->bw);
1411 +
	m = &mon[c->mon];
1412 +
	mw = mfact * m->ww;
1413 +
	resize(c, m->wx, m->wy, (n == 1 ? m->ww : mw) - 2 * c->bw, m->wh - 2 * c->bw);
1401 1414
1402 1415
	if(--n == 0)
1403 1416
		return;
1404 1417
1405 1418
	/* tile stack */
1406 -
	x = (wx + mw > c->x + c->w) ? c->x + c->w + 2 * c->bw : wx + mw;
1407 -
	y = wy;
1408 -
	w = (wx + mw > c->x + c->w) ? wx + ww - x : ww - mw;
1409 -
	h = wh / n;
1419 +
	x = (m->wx + mw > c->x + c->w) ? c->x + c->w + 2 * c->bw : m->wx + mw;
1420 +
	y = m->wy;
1421 +
	w = (m->wx + mw > c->x + c->w) ? m->wx + m->ww - x : m->ww - mw;
1422 +
	h = m->wh / n;
1410 1423
	if(h < bh)
1411 -
		h = wh;
1424 +
		h = m->wh;
1412 1425
1413 1426
	for(i = 0, c = nexttiled(c->next); c; c = nexttiled(c->next), i++) {
1414 1427
		resize(c, x, y, w - 2 * c->bw, /* remainder */ ((i + 1 == n)
1415 -
		       ? wy + wh - y - 2 * c->bw : h - 2 * c->bw));
1416 -
		if(h != wh)
1428 +
		       ? m->wy + m->wh - y - 2 * c->bw : h - 2 * c->bw));
1429 +
		if(h != m->wh)
1417 1430
			y = c->y + HEIGHT(c);
1418 1431
	}
1419 1432
}
1452 1465
1453 1466
void
1454 1467
toggleview(const Arg *arg) {
1455 -
	unsigned int mask = tagset[seltags] ^ (arg->ui & TAGMASK);
1468 +
	unsigned int mask = tagset[selmon->seltags] ^ (arg->ui & TAGMASK);
1456 1469
1457 1470
	if(mask) {
1458 -
		tagset[seltags] = mask;
1471 +
		tagset[selmon->seltags] = mask;
1459 1472
		arrange();
1460 1473
	}
1461 1474
}
1495 1508
updatebar(void) {
1496 1509
	if(dc.drawable != 0)
1497 1510
		XFreePixmap(dpy, dc.drawable);
1498 -
	dc.drawable = XCreatePixmap(dpy, root, ww, bh, DefaultDepth(dpy, screen));
1499 -
	XMoveResizeWindow(dpy, barwin, wx, by, ww, bh);
1511 +
	dc.drawable = XCreatePixmap(dpy, root, selmon->ww, bh, DefaultDepth(dpy, screen));
1512 +
	XMoveResizeWindow(dpy, barwin, selmon->wx, by, selmon->ww, bh);
1500 1513
}
1501 1514
1502 1515
void
1503 1516
updategeom(void) {
1504 1517
#ifdef XINERAMA
1505 -
	int n, i = 0;
1518 +
	int di, x, y, n;
1519 +
	unsigned int dui, i = 0;
1520 +
	Bool pquery;
1521 +
	Client *c;
1522 +
	Window dummy;
1506 1523
	XineramaScreenInfo *info = NULL;
1507 1524
1508 1525
	/* window area geometry */
1509 1526
	if(XineramaIsActive(dpy) && (info = XineramaQueryScreens(dpy, &n))) { 
1510 -
		if(n > 1) {
1511 -
			int di, x, y;
1512 -
			unsigned int dui;
1513 -
			Window dummy;
1514 -
			if(XQueryPointer(dpy, root, &dummy, &dummy, &x, &y, &di, &di, &dui))
1515 -
				for(i = 0; i < n; i++)
1516 -
					if(INRECT(x, y, info[i].x_org, info[i].y_org, info[i].width, info[i].height))
1517 -
						break;
1527 +
		nmons = (unsigned int)n;
1528 +
		for(c = clients; c; c = c->next)
1529 +
			if(c->mon >= nmons)
1530 +
				c->mon = nmons - 1;
1531 +
		if(!(mon = (Monitor *)realloc(mon, sizeof(Monitor) * nmons)))
1532 +
			die("fatal: could not realloc() %u bytes\n", sizeof(Monitor) * nmons);
1533 +
		pquery = XQueryPointer(dpy, root, &dummy, &dummy, &x, &y, &di, &di, &dui);
1534 +
		for(i = 0; i < nmons; i++) {
1535 +
			/* TODO: consider re-using XineramaScreenInfo */
1536 +
			mon[i].wx = info[i].x_org;
1537 +
			mon[i].wy = info[i].y_org;
1538 +
			mon[i].ww = info[i].width;
1539 +
			mon[i].wh = info[i].height;
1540 +
			mon[i].seltags = 0;
1541 +
			mon[i].sellt = 0;
1542 +
			if(pquery && INRECT(x, y, info[i].x_org, info[i].y_org, info[i].width, info[i].height))
1543 +
				selmon = &mon[i];
1518 1544
		}
1519 -
		wx = info[i].x_org;
1520 -
		wy = showbar && topbar ?  info[i].y_org + bh : info[i].y_org;
1521 -
		ww = info[i].width;
1522 -
		wh = showbar ? info[i].height - bh : info[i].height;
1545 +
		/* bar adjustments of selmon */
1546 +
		selmon->wy = showbar && topbar ?  selmon->wy + bh : selmon->wy;
1547 +
		selmon->wh = showbar ? selmon->wh - bh : selmon->wh;
1523 1548
		XFree(info);
1524 1549
	}
1525 1550
	else
1526 1551
#endif
1527 1552
	{
1528 -
		wx = sx;
1529 -
		wy = showbar && topbar ? sy + bh : sy;
1530 -
		ww = sw;
1531 -
		wh = showbar ? sh - bh : sh;
1553 +
		nmons = 1;
1554 +
		if(!(mon = (Monitor *)realloc(mon, sizeof(Monitor))))
1555 +
			die("fatal: could not realloc() %u bytes\n", sizeof(Monitor));
1556 +
		selmon = &mon[0];
1557 +
		mon[0].wx = sx;
1558 +
		mon[0].wy = showbar && topbar ? sy + bh : sy;
1559 +
		mon[0].ww = sw;
1560 +
		mon[0].wh = showbar ? sh - bh : sh;
1561 +
		mon[0].seltags = 0;
1562 +
		mon[0].sellt = 0;
1532 1563
	}
1533 1564
1534 1565
	/* bar position */
1535 -
	by = showbar ? (topbar ? wy - bh : wy + wh) : -bh;
1566 +
	by = showbar ? (topbar ? selmon->wy - bh : selmon->wy + selmon->wh) : -bh;
1536 1567
}
1537 1568
1538 1569
void
1631 1662
1632 1663
void
1633 1664
view(const Arg *arg) {
1634 -
	if((arg->ui & TAGMASK) == tagset[seltags])
1665 +
	if((arg->ui & TAGMASK) == tagset[selmon->seltags])
1635 1666
		return;
1636 -
	seltags ^= 1; /* toggle sel tagset */
1667 +
	selmon->seltags ^= 1; /* toggle sel tagset */
1637 1668
	if(arg->ui & TAGMASK)
1638 -
		tagset[seltags] = arg->ui & TAGMASK;
1669 +
		tagset[selmon->seltags] = arg->ui & TAGMASK;
1639 1670
	arrange();
1640 1671
}
1641 1672
1676 1707
zoom(const Arg *arg) {
1677 1708
	Client *c = sel;
1678 1709
1679 -
	if(!lt[sellt]->arrange || lt[sellt]->arrange == monocle || (sel && sel->isfloating))
1710 +
	if(!lt[selmon->sellt]->arrange || lt[selmon->sellt]->arrange == monocle || (sel && sel->isfloating))
1680 1711
		return;
1681 1712
	if(c == nexttiled(clients))
1682 1713
		if(!c || !(c = nexttiled(c->next)))