dwm.c
changeset 1397 4498d81938b0
parent 1396 440dda47ae5b
child 1398 597063a22a73
equal deleted inserted replaced
1396:440dda47ae5b 1397:4498d81938b0
    42 
    42 
    43 /* macros */
    43 /* macros */
    44 #define BUTTONMASK              (ButtonPressMask|ButtonReleaseMask)
    44 #define BUTTONMASK              (ButtonPressMask|ButtonReleaseMask)
    45 #define CLEANMASK(mask)         (mask & ~(numlockmask|LockMask))
    45 #define CLEANMASK(mask)         (mask & ~(numlockmask|LockMask))
    46 #define INRECT(X,Y,RX,RY,RW,RH) ((X) >= (RX) && (X) < (RX) + (RW) && (Y) >= (RY) && (Y) < (RY) + (RH))
    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 #define LENGTH(x)               (sizeof x / sizeof x[0])
    48 #define LENGTH(x)               (sizeof x / sizeof x[0])
    49 #define MAX(a, b)               ((a) > (b) ? (a) : (b))
    49 #define MAX(a, b)               ((a) > (b) ? (a) : (b))
    50 #define MIN(a, b)               ((a) < (b) ? (a) : (b))
    50 #define MIN(a, b)               ((a) < (b) ? (a) : (b))
    51 #define MOUSEMASK               (BUTTONMASK|PointerMotionMask)
    51 #define MOUSEMASK               (BUTTONMASK|PointerMotionMask)
    52 #define WIDTH(x)                ((x)->w + 2 * (x)->bw)
    52 #define WIDTH(x)                ((x)->w + 2 * (x)->bw)
    83 	float mina, maxa;
    83 	float mina, maxa;
    84 	int x, y, w, h;
    84 	int x, y, w, h;
    85 	int basew, baseh, incw, inch, maxw, maxh, minw, minh;
    85 	int basew, baseh, incw, inch, maxw, maxh, minw, minh;
    86 	int bw, oldbw;
    86 	int bw, oldbw;
    87 	unsigned int tags;
    87 	unsigned int tags;
       
    88 	unsigned int mon;
    88 	Bool isfixed, isfloating, isurgent;
    89 	Bool isfixed, isfloating, isurgent;
    89 	Client *next;
    90 	Client *next;
    90 	Client *snext;
    91 	Client *snext;
    91 	Window win;
    92 	Window win;
    92 };
    93 };
   115 
   116 
   116 typedef struct {
   117 typedef struct {
   117 	const char *symbol;
   118 	const char *symbol;
   118 	void (*arrange)(void);
   119 	void (*arrange)(void);
   119 } Layout;
   120 } Layout;
       
   121 
       
   122 typedef struct {
       
   123 	int wx, wy, ww, wh;
       
   124 	unsigned int seltags;
       
   125 	unsigned int sellt;
       
   126 } Monitor;
   120 
   127 
   121 typedef struct {
   128 typedef struct {
   122 	const char *class;
   129 	const char *class;
   123 	const char *instance;
   130 	const char *instance;
   124 	const char *title;
   131 	const char *title;
   206 /* variables */
   213 /* variables */
   207 static char stext[256];
   214 static char stext[256];
   208 static int screen;
   215 static int screen;
   209 static int sx, sy, sw, sh; /* X display screen geometry x, y, width, height */ 
   216 static int sx, sy, sw, sh; /* X display screen geometry x, y, width, height */ 
   210 static int by, bh, blw;    /* bar geometry y, height and layout symbol width */
   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 static int (*xerrorxlib)(Display *, XErrorEvent *);
   218 static int (*xerrorxlib)(Display *, XErrorEvent *);
   214 static unsigned int numlockmask = 0;
   219 static unsigned int numlockmask = 0;
   215 static void (*handler[LASTEvent]) (XEvent *) = {
   220 static void (*handler[LASTEvent]) (XEvent *) = {
   216 	[ButtonPress] = buttonpress,
   221 	[ButtonPress] = buttonpress,
   217 	[ConfigureRequest] = configurerequest,
   222 	[ConfigureRequest] = configurerequest,
   234 static Client *stack = NULL;
   239 static Client *stack = NULL;
   235 static Cursor cursor[CurLast];
   240 static Cursor cursor[CurLast];
   236 static Display *dpy;
   241 static Display *dpy;
   237 static DC dc;
   242 static DC dc;
   238 static Layout *lt[] = { NULL, NULL };
   243 static Layout *lt[] = { NULL, NULL };
       
   244 static Monitor *mon = NULL, *selmon = NULL;
       
   245 static unsigned int nmons;
   239 static Window root, barwin;
   246 static Window root, barwin;
   240 /* configuration, allows nested code to access above variables */
   247 /* configuration, allows nested code to access above variables */
   241 #include "config.h"
   248 #include "config.h"
   242 
   249 
   243 /* compile-time check if all tags fit into an unsigned int bit array. */
   250 /* compile-time check if all tags fit into an unsigned int bit array. */
   265 		if(ch.res_class)
   272 		if(ch.res_class)
   266 			XFree(ch.res_class);
   273 			XFree(ch.res_class);
   267 		if(ch.res_name)
   274 		if(ch.res_name)
   268 			XFree(ch.res_name);
   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 Bool
   280 Bool
   274 applysizehints(Client *c, int *x, int *y, int *w, int *h) {
   281 applysizehints(Client *c, int *x, int *y, int *w, int *h) {
   275 	Bool baseismin;
   282 	Bool baseismin;
   337 
   344 
   338 void
   345 void
   339 arrange(void) {
   346 arrange(void) {
   340 	showhide(stack);
   347 	showhide(stack);
   341 	focus(NULL);
   348 	focus(NULL);
   342 	if(lt[sellt]->arrange)
   349 	if(lt[selmon->sellt]->arrange)
   343 		lt[sellt]->arrange();
   350 		lt[selmon->sellt]->arrange();
   344 	restack();
   351 	restack();
   345 }
   352 }
   346 
   353 
   347 void
   354 void
   348 attach(Client *c) {
   355 attach(Client *c) {
   371 			click = ClkTagBar;
   378 			click = ClkTagBar;
   372 			arg.ui = 1 << i;
   379 			arg.ui = 1 << i;
   373 		}
   380 		}
   374 		else if(ev->x < x + blw)
   381 		else if(ev->x < x + blw)
   375 			click = ClkLtSymbol;
   382 			click = ClkLtSymbol;
   376 		else if(ev->x > wx + ww - TEXTW(stext))
   383 		else if(ev->x > selmon->wx + selmon->ww - TEXTW(stext))
   377 			click = ClkStatusText;
   384 			click = ClkStatusText;
   378 		else
   385 		else
   379 			click = ClkWinTitle;
   386 			click = ClkWinTitle;
   380 	}
   387 	}
   381 	else if((c = getclient(ev->window))) {
   388 	else if((c = getclient(ev->window))) {
   407 cleanup(void) {
   414 cleanup(void) {
   408 	Arg a = {.ui = ~0};
   415 	Arg a = {.ui = ~0};
   409 	Layout foo = { "", NULL };
   416 	Layout foo = { "", NULL };
   410 
   417 
   411 	view(&a);
   418 	view(&a);
   412 	lt[sellt] = &foo;
   419 	lt[selmon->sellt] = &foo;
   413 	while(stack)
   420 	while(stack)
   414 		unmanage(stack);
   421 		unmanage(stack);
   415 	if(dc.font.set)
   422 	if(dc.font.set)
   416 		XFreeFontSet(dpy, dc.font.set);
   423 		XFreeFontSet(dpy, dc.font.set);
   417 	else
   424 	else
   477 	XWindowChanges wc;
   484 	XWindowChanges wc;
   478 
   485 
   479 	if((c = getclient(ev->window))) {
   486 	if((c = getclient(ev->window))) {
   480 		if(ev->value_mask & CWBorderWidth)
   487 		if(ev->value_mask & CWBorderWidth)
   481 			c->bw = ev->border_width;
   488 			c->bw = ev->border_width;
   482 		else if(c->isfloating || !lt[sellt]->arrange) {
   489 		else if(c->isfloating || !lt[selmon->sellt]->arrange) {
   483 			if(ev->value_mask & CWX)
   490 			if(ev->value_mask & CWX)
   484 				c->x = sx + ev->x;
   491 				c->x = sx + ev->x;
   485 			if(ev->value_mask & CWY)
   492 			if(ev->value_mask & CWY)
   486 				c->y = sy + ev->y;
   493 				c->y = sy + ev->y;
   487 			if(ev->value_mask & CWWidth)
   494 			if(ev->value_mask & CWWidth)
   562 	}
   569 	}
   563 
   570 
   564 	dc.x = 0;
   571 	dc.x = 0;
   565 	for(i = 0; i < LENGTH(tags); i++) {
   572 	for(i = 0; i < LENGTH(tags); i++) {
   566 		dc.w = TEXTW(tags[i]);
   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 		drawtext(tags[i], col, urg & 1 << i);
   575 		drawtext(tags[i], col, urg & 1 << i);
   569 		drawsquare(sel && sel->tags & 1 << i, occ & 1 << i, urg & 1 << i, col);
   576 		drawsquare(sel && sel->tags & 1 << i, occ & 1 << i, urg & 1 << i, col);
   570 		dc.x += dc.w;
   577 		dc.x += dc.w;
   571 	}
   578 	}
   572 	if(blw > 0) {
   579 	if(blw > 0) {
   573 		dc.w = blw;
   580 		dc.w = blw;
   574 		drawtext(lt[sellt]->symbol, dc.norm, False);
   581 		drawtext(lt[selmon->sellt]->symbol, dc.norm, False);
   575 		x = dc.x + dc.w;
   582 		x = dc.x + dc.w;
   576 	}
   583 	}
   577 	else
   584 	else
   578 		x = dc.x;
   585 		x = dc.x;
   579 	dc.w = TEXTW(stext);
   586 	dc.w = TEXTW(stext);
   580 	dc.x = ww - dc.w;
   587 	dc.x = selmon->ww - dc.w;
   581 	if(dc.x < x) {
   588 	if(dc.x < x) {
   582 		dc.x = x;
   589 		dc.x = x;
   583 		dc.w = ww - x;
   590 		dc.w = selmon->ww - x;
   584 	}
   591 	}
   585 	drawtext(stext, dc.norm, False);
   592 	drawtext(stext, dc.norm, False);
   586 	if((dc.w = dc.x - x) > bh) {
   593 	if((dc.w = dc.x - x) > bh) {
   587 		dc.x = x;
   594 		dc.x = x;
   588 		if(sel) {
   595 		if(sel) {
   590 			drawsquare(sel->isfixed, sel->isfloating, False, dc.sel);
   597 			drawsquare(sel->isfixed, sel->isfloating, False, dc.sel);
   591 		}
   598 		}
   592 		else
   599 		else
   593 			drawtext(NULL, dc.norm, False);
   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 	XSync(dpy, False);
   603 	XSync(dpy, False);
   597 }
   604 }
   598 
   605 
   599 void
   606 void
   600 drawsquare(Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]) {
   607 drawsquare(Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]) {
   917 
   924 
   918 	if(!(c = malloc(sizeof(Client))))
   925 	if(!(c = malloc(sizeof(Client))))
   919 		die("fatal: could not malloc() %u bytes\n", sizeof(Client));
   926 		die("fatal: could not malloc() %u bytes\n", sizeof(Client));
   920 	*c = cz;
   927 	*c = cz;
   921 	c->win = w;
   928 	c->win = w;
       
   929 	for(c->mon = 0; selmon != &mon[c->mon]; c->mon++);
   922 
   930 
   923 	/* geometry */
   931 	/* geometry */
   924 	c->x = wa->x;
   932 	c->x = wa->x;
   925 	c->y = wa->y;
   933 	c->y = wa->y;
   926 	c->w = wa->width;
   934 	c->w = wa->width;
   936 			c->x = sx + sw - WIDTH(c);
   944 			c->x = sx + sw - WIDTH(c);
   937 		if(c->y + HEIGHT(c) > sy + sh)
   945 		if(c->y + HEIGHT(c) > sy + sh)
   938 			c->y = sy + sh - HEIGHT(c);
   946 			c->y = sy + sh - HEIGHT(c);
   939 		c->x = MAX(c->x, sx);
   947 		c->x = MAX(c->x, sx);
   940 		/* only fix client y-offset, if the client center might cover the bar */
   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)
   949 		/* TODO: is c always attached to selmon? */
   942 		                            && (c->x + (c->w / 2) < wx + ww)) ? bh : sy);
   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 		c->bw = borderpx;
   952 		c->bw = borderpx;
   944 	}
   953 	}
   945 
   954 
   946 	wc.border_width = c->bw;
   955 	wc.border_width = c->bw;
   947 	XConfigureWindow(dpy, w, CWBorderWidth, &wc);
   956 	XConfigureWindow(dpy, w, CWBorderWidth, &wc);
   992 }
  1001 }
   993 
  1002 
   994 void
  1003 void
   995 monocle(void) {
  1004 monocle(void) {
   996 	Client *c;
  1005 	Client *c;
       
  1006 	Monitor *m;
   997 
  1007 
   998 	for(c = nexttiled(clients); c; c = nexttiled(c->next)) {
  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 
  1003 void
  1014 void
  1004 movemouse(const Arg *arg) {
  1015 movemouse(const Arg *arg) {
  1026 			handler[ev.type](&ev);
  1037 			handler[ev.type](&ev);
  1027 			break;
  1038 			break;
  1028 		case MotionNotify:
  1039 		case MotionNotify:
  1029 			nx = ocx + (ev.xmotion.x - x);
  1040 			nx = ocx + (ev.xmotion.x - x);
  1030 			ny = ocy + (ev.xmotion.y - y);
  1041 			ny = ocy + (ev.xmotion.y - y);
  1031 			if(snap && nx >= wx && nx <= wx + ww
  1042 			if(snap && nx >= selmon->wx && nx <= selmon->wx + selmon->ww
  1032 			        && ny >= wy && ny <= wy + wh) {
  1043 			        && ny >= selmon->wy && ny <= selmon->wy + selmon->wh) {
  1033 				if(abs(wx - nx) < snap)
  1044 				if(abs(selmon->wx - nx) < snap)
  1034 					nx = wx;
  1045 					nx = selmon->wx;
  1035 				else if(abs((wx + ww) - (nx + WIDTH(c))) < snap)
  1046 				else if(abs((selmon->wx + selmon->ww) - (nx + WIDTH(c))) < snap)
  1036 					nx = wx + ww - WIDTH(c);
  1047 					nx = selmon->wx + selmon->ww - WIDTH(c);
  1037 				if(abs(wy - ny) < snap)
  1048 				if(abs(selmon->wy - ny) < snap)
  1038 					ny = wy;
  1049 					ny = selmon->wy;
  1039 				else if(abs((wy + wh) - (ny + HEIGHT(c))) < snap)
  1050 				else if(abs((selmon->wy + selmon->wh) - (ny + HEIGHT(c))) < snap)
  1040 					ny = wy + wh - HEIGHT(c);
  1051 					ny = selmon->wy + selmon->wh - HEIGHT(c);
  1041 				if(!c->isfloating && lt[sellt]->arrange
  1052 				if(!c->isfloating && lt[selmon->sellt]->arrange
  1042 				                  && (abs(nx - c->x) > snap || abs(ny - c->y) > snap))
  1053 				                  && (abs(nx - c->x) > snap || abs(ny - c->y) > snap))
  1043 					togglefloating(NULL);
  1054 					togglefloating(NULL);
  1044 			}
  1055 			}
  1045 			if(!lt[sellt]->arrange || c->isfloating)
  1056 			if(!lt[selmon->sellt]->arrange || c->isfloating)
  1046 				resize(c, nx, ny, c->w, c->h);
  1057 				resize(c, nx, ny, c->w, c->h);
  1047 			break;
  1058 			break;
  1048 		}
  1059 		}
  1049 	}
  1060 	}
  1050 	while(ev.type != ButtonRelease);
  1061 	while(ev.type != ButtonRelease);
  1139 			break;
  1150 			break;
  1140 		case MotionNotify:
  1151 		case MotionNotify:
  1141 			nw = MAX(ev.xmotion.x - ocx - 2 * c->bw + 1, 1);
  1152 			nw = MAX(ev.xmotion.x - ocx - 2 * c->bw + 1, 1);
  1142 			nh = MAX(ev.xmotion.y - ocy - 2 * c->bw + 1, 1);
  1153 			nh = MAX(ev.xmotion.y - ocy - 2 * c->bw + 1, 1);
  1143 
  1154 
  1144 			if(snap && nw >= wx && nw <= wx + ww
  1155 			if(snap && nw >= selmon->wx && nw <= selmon->wx + selmon->ww
  1145 			        && nh >= wy && nh <= wy + wh) {
  1156 			        && nh >= selmon->wy && nh <= selmon->wy + selmon->wh) {
  1146 				if(!c->isfloating && lt[sellt]->arrange
  1157 				if(!c->isfloating && lt[selmon->sellt]->arrange
  1147 				   && (abs(nw - c->w) > snap || abs(nh - c->h) > snap))
  1158 				   && (abs(nw - c->w) > snap || abs(nh - c->h) > snap))
  1148 					togglefloating(NULL);
  1159 					togglefloating(NULL);
  1149 			}
  1160 			}
  1150 			if(!lt[sellt]->arrange || c->isfloating)
  1161 			if(!lt[selmon->sellt]->arrange || c->isfloating)
  1151 				resize(c, c->x, c->y, nw, nh);
  1162 				resize(c, c->x, c->y, nw, nh);
  1152 			break;
  1163 			break;
  1153 		}
  1164 		}
  1154 	}
  1165 	}
  1155 	while(ev.type != ButtonRelease);
  1166 	while(ev.type != ButtonRelease);
  1165 	XWindowChanges wc;
  1176 	XWindowChanges wc;
  1166 
  1177 
  1167 	drawbar();
  1178 	drawbar();
  1168 	if(!sel)
  1179 	if(!sel)
  1169 		return;
  1180 		return;
  1170 	if(sel->isfloating || !lt[sellt]->arrange)
  1181 	if(sel->isfloating || !lt[selmon->sellt]->arrange)
  1171 		XRaiseWindow(dpy, sel->win);
  1182 		XRaiseWindow(dpy, sel->win);
  1172 	if(lt[sellt]->arrange) {
  1183 	if(lt[selmon->sellt]->arrange) {
  1173 		wc.stack_mode = Below;
  1184 		wc.stack_mode = Below;
  1174 		wc.sibling = barwin;
  1185 		wc.sibling = barwin;
  1175 		for(c = stack; c; c = c->snext)
  1186 		for(c = stack; c; c = c->snext)
  1176 			if(!c->isfloating && ISVISIBLE(c)) {
  1187 			if(!c->isfloating && ISVISIBLE(c)) {
  1177 				XConfigureWindow(dpy, c->win, CWSibling|CWStackMode, &wc);
  1188 				XConfigureWindow(dpy, c->win, CWSibling|CWStackMode, &wc);
  1228 			PropModeReplace, (unsigned char *)data, 2);
  1239 			PropModeReplace, (unsigned char *)data, 2);
  1229 }
  1240 }
  1230 
  1241 
  1231 void
  1242 void
  1232 setlayout(const Arg *arg) {
  1243 setlayout(const Arg *arg) {
  1233 	if(!arg || !arg->v || arg->v != lt[sellt])
  1244 	if(!arg || !arg->v || arg->v != lt[selmon->sellt])
  1234 		sellt ^= 1;
  1245 		selmon->sellt ^= 1;
  1235 	if(arg && arg->v)
  1246 	if(arg && arg->v)
  1236 		lt[sellt] = (Layout *)arg->v;
  1247 		lt[selmon->sellt] = (Layout *)arg->v;
  1237 	if(sel)
  1248 	if(sel)
  1238 		arrange();
  1249 		arrange();
  1239 	else
  1250 	else
  1240 		drawbar();
  1251 		drawbar();
  1241 }
  1252 }
  1243 /* arg > 1.0 will set mfact absolutly */
  1254 /* arg > 1.0 will set mfact absolutly */
  1244 void
  1255 void
  1245 setmfact(const Arg *arg) {
  1256 setmfact(const Arg *arg) {
  1246 	float f;
  1257 	float f;
  1247 
  1258 
  1248 	if(!arg || !lt[sellt]->arrange)
  1259 	if(!arg || !lt[selmon->sellt]->arrange)
  1249 		return;
  1260 		return;
  1250 	f = arg->f < 1.0 ? arg->f + mfact : arg->f - 1.0;
  1261 	f = arg->f < 1.0 ? arg->f + mfact : arg->f - 1.0;
  1251 	if(f < 0.1 || f > 0.9)
  1262 	if(f < 0.1 || f > 0.9)
  1252 		return;
  1263 		return;
  1253 	mfact = f;
  1264 	mfact = f;
  1306 
  1317 
  1307 	wa.override_redirect = True;
  1318 	wa.override_redirect = True;
  1308 	wa.background_pixmap = ParentRelative;
  1319 	wa.background_pixmap = ParentRelative;
  1309 	wa.event_mask = ButtonPressMask|ExposureMask;
  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 			CopyFromParent, DefaultVisual(dpy, screen),
  1323 			CopyFromParent, DefaultVisual(dpy, screen),
  1313 			CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa);
  1324 			CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa);
  1314 	XDefineCursor(dpy, barwin, cursor[CurNormal]);
  1325 	XDefineCursor(dpy, barwin, cursor[CurNormal]);
  1315 	XMapRaised(dpy, barwin);
  1326 	XMapRaised(dpy, barwin);
  1316 	updatestatus();
  1327 	updatestatus();
  1333 showhide(Client *c) {
  1344 showhide(Client *c) {
  1334 	if(!c)
  1345 	if(!c)
  1335 		return;
  1346 		return;
  1336 	if(ISVISIBLE(c)) { /* show clients top down */
  1347 	if(ISVISIBLE(c)) { /* show clients top down */
  1337 		XMoveWindow(dpy, c->win, c->x, c->y);
  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 			resize(c, c->x, c->y, c->w, c->h);
  1350 			resize(c, c->x, c->y, c->w, c->h);
  1340 		showhide(c->snext);
  1351 		showhide(c->snext);
  1341 	}
  1352 	}
  1342 	else { /* hide clients bottom up */
  1353 	else { /* hide clients bottom up */
  1343 		showhide(c->snext);
  1354 		showhide(c->snext);
  1387 void
  1398 void
  1388 tile(void) {
  1399 tile(void) {
  1389 	int x, y, h, w, mw;
  1400 	int x, y, h, w, mw;
  1390 	unsigned int i, n;
  1401 	unsigned int i, n;
  1391 	Client *c;
  1402 	Client *c;
       
  1403 	Monitor *m;
  1392 
  1404 
  1393 	for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next), n++);
  1405 	for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next), n++);
  1394 	if(n == 0)
  1406 	if(n == 0)
  1395 		return;
  1407 		return;
  1396 
  1408 
  1397 	/* master */
  1409 	/* master */
  1398 	c = nexttiled(clients);
  1410 	c = nexttiled(clients);
  1399 	mw = mfact * ww;
  1411 	m = &mon[c->mon];
  1400 	resize(c, wx, wy, (n == 1 ? ww : mw) - 2 * c->bw, wh - 2 * c->bw);
  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 	if(--n == 0)
  1415 	if(--n == 0)
  1403 		return;
  1416 		return;
  1404 
  1417 
  1405 	/* tile stack */
  1418 	/* tile stack */
  1406 	x = (wx + mw > c->x + c->w) ? c->x + c->w + 2 * c->bw : wx + mw;
  1419 	x = (m->wx + mw > c->x + c->w) ? c->x + c->w + 2 * c->bw : m->wx + mw;
  1407 	y = wy;
  1420 	y = m->wy;
  1408 	w = (wx + mw > c->x + c->w) ? wx + ww - x : ww - mw;
  1421 	w = (m->wx + mw > c->x + c->w) ? m->wx + m->ww - x : m->ww - mw;
  1409 	h = wh / n;
  1422 	h = m->wh / n;
  1410 	if(h < bh)
  1423 	if(h < bh)
  1411 		h = wh;
  1424 		h = m->wh;
  1412 
  1425 
  1413 	for(i = 0, c = nexttiled(c->next); c; c = nexttiled(c->next), i++) {
  1426 	for(i = 0, c = nexttiled(c->next); c; c = nexttiled(c->next), i++) {
  1414 		resize(c, x, y, w - 2 * c->bw, /* remainder */ ((i + 1 == n)
  1427 		resize(c, x, y, w - 2 * c->bw, /* remainder */ ((i + 1 == n)
  1415 		       ? wy + wh - y - 2 * c->bw : h - 2 * c->bw));
  1428 		       ? m->wy + m->wh - y - 2 * c->bw : h - 2 * c->bw));
  1416 		if(h != wh)
  1429 		if(h != m->wh)
  1417 			y = c->y + HEIGHT(c);
  1430 			y = c->y + HEIGHT(c);
  1418 	}
  1431 	}
  1419 }
  1432 }
  1420 
  1433 
  1421 void
  1434 void
  1450 	}
  1463 	}
  1451 }
  1464 }
  1452 
  1465 
  1453 void
  1466 void
  1454 toggleview(const Arg *arg) {
  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 	if(mask) {
  1470 	if(mask) {
  1458 		tagset[seltags] = mask;
  1471 		tagset[selmon->seltags] = mask;
  1459 		arrange();
  1472 		arrange();
  1460 	}
  1473 	}
  1461 }
  1474 }
  1462 
  1475 
  1463 void
  1476 void
  1493 
  1506 
  1494 void
  1507 void
  1495 updatebar(void) {
  1508 updatebar(void) {
  1496 	if(dc.drawable != 0)
  1509 	if(dc.drawable != 0)
  1497 		XFreePixmap(dpy, dc.drawable);
  1510 		XFreePixmap(dpy, dc.drawable);
  1498 	dc.drawable = XCreatePixmap(dpy, root, ww, bh, DefaultDepth(dpy, screen));
  1511 	dc.drawable = XCreatePixmap(dpy, root, selmon->ww, bh, DefaultDepth(dpy, screen));
  1499 	XMoveResizeWindow(dpy, barwin, wx, by, ww, bh);
  1512 	XMoveResizeWindow(dpy, barwin, selmon->wx, by, selmon->ww, bh);
  1500 }
  1513 }
  1501 
  1514 
  1502 void
  1515 void
  1503 updategeom(void) {
  1516 updategeom(void) {
  1504 #ifdef XINERAMA
  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 	XineramaScreenInfo *info = NULL;
  1523 	XineramaScreenInfo *info = NULL;
  1507 
  1524 
  1508 	/* window area geometry */
  1525 	/* window area geometry */
  1509 	if(XineramaIsActive(dpy) && (info = XineramaQueryScreens(dpy, &n))) { 
  1526 	if(XineramaIsActive(dpy) && (info = XineramaQueryScreens(dpy, &n))) { 
  1510 		if(n > 1) {
  1527 		nmons = (unsigned int)n;
  1511 			int di, x, y;
  1528 		for(c = clients; c; c = c->next)
  1512 			unsigned int dui;
  1529 			if(c->mon >= nmons)
  1513 			Window dummy;
  1530 				c->mon = nmons - 1;
  1514 			if(XQueryPointer(dpy, root, &dummy, &dummy, &x, &y, &di, &di, &dui))
  1531 		if(!(mon = (Monitor *)realloc(mon, sizeof(Monitor) * nmons)))
  1515 				for(i = 0; i < n; i++)
  1532 			die("fatal: could not realloc() %u bytes\n", sizeof(Monitor) * nmons);
  1516 					if(INRECT(x, y, info[i].x_org, info[i].y_org, info[i].width, info[i].height))
  1533 		pquery = XQueryPointer(dpy, root, &dummy, &dummy, &x, &y, &di, &di, &dui);
  1517 						break;
  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;
  1545 		/* bar adjustments of selmon */
  1520 		wy = showbar && topbar ?  info[i].y_org + bh : info[i].y_org;
  1546 		selmon->wy = showbar && topbar ?  selmon->wy + bh : selmon->wy;
  1521 		ww = info[i].width;
  1547 		selmon->wh = showbar ? selmon->wh - bh : selmon->wh;
  1522 		wh = showbar ? info[i].height - bh : info[i].height;
       
  1523 		XFree(info);
  1548 		XFree(info);
  1524 	}
  1549 	}
  1525 	else
  1550 	else
  1526 #endif
  1551 #endif
  1527 	{
  1552 	{
  1528 		wx = sx;
  1553 		nmons = 1;
  1529 		wy = showbar && topbar ? sy + bh : sy;
  1554 		if(!(mon = (Monitor *)realloc(mon, sizeof(Monitor))))
  1530 		ww = sw;
  1555 			die("fatal: could not realloc() %u bytes\n", sizeof(Monitor));
  1531 		wh = showbar ? sh - bh : sh;
  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 	/* bar position */
  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 void
  1569 void
  1539 updatenumlockmask(void) {
  1570 updatenumlockmask(void) {
  1540 	unsigned int i, j;
  1571 	unsigned int i, j;
  1629 	}
  1660 	}
  1630 }
  1661 }
  1631 
  1662 
  1632 void
  1663 void
  1633 view(const Arg *arg) {
  1664 view(const Arg *arg) {
  1634 	if((arg->ui & TAGMASK) == tagset[seltags])
  1665 	if((arg->ui & TAGMASK) == tagset[selmon->seltags])
  1635 		return;
  1666 		return;
  1636 	seltags ^= 1; /* toggle sel tagset */
  1667 	selmon->seltags ^= 1; /* toggle sel tagset */
  1637 	if(arg->ui & TAGMASK)
  1668 	if(arg->ui & TAGMASK)
  1638 		tagset[seltags] = arg->ui & TAGMASK;
  1669 		tagset[selmon->seltags] = arg->ui & TAGMASK;
  1639 	arrange();
  1670 	arrange();
  1640 }
  1671 }
  1641 
  1672 
  1642 /* There's no way to check accesses to destroyed windows, thus those cases are
  1673 /* There's no way to check accesses to destroyed windows, thus those cases are
  1643  * ignored (especially on UnmapNotify's).  Other types of errors call Xlibs
  1674  * ignored (especially on UnmapNotify's).  Other types of errors call Xlibs
  1674 
  1705 
  1675 void
  1706 void
  1676 zoom(const Arg *arg) {
  1707 zoom(const Arg *arg) {
  1677 	Client *c = sel;
  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 		return;
  1711 		return;
  1681 	if(c == nexttiled(clients))
  1712 	if(c == nexttiled(clients))
  1682 		if(!c || !(c = nexttiled(c->next)))
  1713 		if(!c || !(c = nexttiled(c->next)))
  1683 			return;
  1714 			return;
  1684 	detach(c);
  1715 	detach(c);