dwm.c
changeset 1079 ba7486659f1d
parent 1078 5cfd3c602ede
child 1080 9bfb57c89407
equal deleted inserted replaced
1078:5cfd3c602ede 1079:ba7486659f1d
   164 void grabkeys(void);
   164 void grabkeys(void);
   165 unsigned int idxoftag(const char *tag);
   165 unsigned int idxoftag(const char *tag);
   166 void initfont(Monitor*, const char *fontstr);
   166 void initfont(Monitor*, const char *fontstr);
   167 Bool isoccupied(Monitor *m, unsigned int t);
   167 Bool isoccupied(Monitor *m, unsigned int t);
   168 Bool isprotodel(Client *c);
   168 Bool isprotodel(Client *c);
   169 Bool isvisible(Client *c, Monitor *m);
   169 Bool isvisible(Client *c, int monitor);
   170 void keypress(XEvent *e);
   170 void keypress(XEvent *e);
   171 void killclient(const char *arg);
   171 void killclient(const char *arg);
   172 void manage(Window w, XWindowAttributes *wa);
   172 void manage(Window w, XWindowAttributes *wa);
   173 void mappingnotify(XEvent *e);
   173 void mappingnotify(XEvent *e);
   174 void maprequest(XEvent *e);
   174 void maprequest(XEvent *e);
   175 void movemouse(Client *c);
   175 void movemouse(Client *c);
   176 Client *nexttiled(Client *c, Monitor *m);
   176 Client *nexttiled(Client *c, int monitor);
   177 void propertynotify(XEvent *e);
   177 void propertynotify(XEvent *e);
   178 void quit(const char *arg);
   178 void quit(const char *arg);
   179 void reapply(const char *arg);
   179 void reapply(const char *arg);
   180 void resize(Client *c, int x, int y, int w, int h, Bool sizehints);
   180 void resize(Client *c, int x, int y, int w, int h, Bool sizehints);
   181 void resizemouse(Client *c);
   181 void resizemouse(Client *c);
   205 void viewprevtag(const char *arg);	/* views previous selected tags */
   205 void viewprevtag(const char *arg);	/* views previous selected tags */
   206 int xerror(Display *dpy, XErrorEvent *ee);
   206 int xerror(Display *dpy, XErrorEvent *ee);
   207 int xerrordummy(Display *dsply, XErrorEvent *ee);
   207 int xerrordummy(Display *dsply, XErrorEvent *ee);
   208 int xerrorstart(Display *dsply, XErrorEvent *ee);
   208 int xerrorstart(Display *dsply, XErrorEvent *ee);
   209 void zoom(const char *arg);
   209 void zoom(const char *arg);
   210 int monitorat(int, int);
   210 int monitorat(void);
   211 void movetomonitor(const char *arg);
   211 void movetomonitor(const char *arg);
   212 void selectmonitor(const char *arg);
   212 void selectmonitor(const char *arg);
   213 
   213 
   214 /* variables */
   214 /* variables */
   215 char stext[256];
   215 char stext[256];
   216 int mcount = 1;
   216 int mcount = 1;
   217 //double mwfact;
       
   218 int (*xerrorxlib)(Display *, XErrorEvent *);
   217 int (*xerrorxlib)(Display *, XErrorEvent *);
   219 unsigned int bh, bpos;
   218 unsigned int bh, bpos;
   220 unsigned int blw = 0;
   219 unsigned int blw = 0;
   221 unsigned int numlockmask = 0;
   220 unsigned int numlockmask = 0;
   222 void (*handler[LASTEvent]) (XEvent *) = {
   221 void (*handler[LASTEvent]) (XEvent *) = {
   232 	[MapRequest] = maprequest,
   231 	[MapRequest] = maprequest,
   233 	[PropertyNotify] = propertynotify,
   232 	[PropertyNotify] = propertynotify,
   234 	[UnmapNotify] = unmapnotify
   233 	[UnmapNotify] = unmapnotify
   235 };
   234 };
   236 Atom wmatom[WMLast], netatom[NetLast];
   235 Atom wmatom[WMLast], netatom[NetLast];
       
   236 Bool isxinerama = False;
   237 Bool domwfact = True;
   237 Bool domwfact = True;
   238 Bool dozoom = True;
   238 Bool dozoom = True;
   239 Bool otherwm, readin;
   239 Bool otherwm, readin;
   240 Bool running = True;
   240 Bool running = True;
   241 Client *clients = NULL;
   241 Client *clients = NULL;
   286 	if(ch.res_class)
   286 	if(ch.res_class)
   287 		XFree(ch.res_class);
   287 		XFree(ch.res_class);
   288 	if(ch.res_name)
   288 	if(ch.res_name)
   289 		XFree(ch.res_name);
   289 		XFree(ch.res_name);
   290 	if(!matched_tag)
   290 	if(!matched_tag)
   291 		memcpy(c->tags, monitors[monitorat(-1, -1)].seltags, sizeof initags);
   291 		memcpy(c->tags, monitors[monitorat()].seltags, sizeof initags);
   292 	if (!matched_monitor)
   292 	if (!matched_monitor)
   293 		c->monitor = monitorat(-1, -1);
   293 		c->monitor = monitorat();
   294 }
   294 }
   295 
   295 
   296 void
   296 void
   297 arrange(void) {
   297 arrange(void) {
   298 	Client *c;
   298 	Client *c;
   299 
   299 
   300 	for(c = clients; c; c = c->next)
   300 	for(c = clients; c; c = c->next)
   301 		if(isvisible(c, &monitors[c->monitor]))
   301 		if(isvisible(c, c->monitor))
   302 			unban(c);
   302 			unban(c);
   303 		else
   303 		else
   304 			ban(c);
   304 			ban(c);
   305 
   305 
   306 	monitors[selmonitor].layout->arrange();
   306 	monitors[selmonitor].layout->arrange();
   334 buttonpress(XEvent *e) {
   334 buttonpress(XEvent *e) {
   335 	unsigned int i, x;
   335 	unsigned int i, x;
   336 	Client *c;
   336 	Client *c;
   337 	XButtonPressedEvent *ev = &e->xbutton;
   337 	XButtonPressedEvent *ev = &e->xbutton;
   338 
   338 
   339 	Monitor *m = &monitors[monitorat(-1, -1)];
   339 	Monitor *m = &monitors[monitorat()];
   340 
   340 
   341 	if(ev->window == m->barwin) {
   341 	if(ev->window == m->barwin) {
   342 		x = 0;
   342 		x = 0;
   343 		for(i = 0; i < LENGTH(tags); i++) {
   343 		for(i = 0; i < LENGTH(tags); i++) {
   344 			x += textw(m, tags[i]);
   344 			x += textw(m, tags[i]);
   514 			if((c->y - m->sy + c->h) > m->sh && c->isfloating)
   514 			if((c->y - m->sy + c->h) > m->sh && c->isfloating)
   515 				c->y = m->sy + (m->sh / 2 - c->h / 2); /* center in y direction */
   515 				c->y = m->sy + (m->sh / 2 - c->h / 2); /* center in y direction */
   516 			if((ev->value_mask & (CWX | CWY))
   516 			if((ev->value_mask & (CWX | CWY))
   517 			&& !(ev->value_mask & (CWWidth | CWHeight)))
   517 			&& !(ev->value_mask & (CWWidth | CWHeight)))
   518 				configure(c);
   518 				configure(c);
   519 			if(isvisible(c, &monitors[monitorat(-1,-1)]))
   519 			if(isvisible(c, monitorat()))
   520 				XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h);
   520 				XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h);
   521 		}
   521 		}
   522 		else
   522 		else
   523 			configure(c);
   523 			configure(c);
   524 	}
   524 	}
   676 	return res;
   676 	return res;
   677 }
   677 }
   678 
   678 
   679 void
   679 void
   680 enternotify(XEvent *e) {
   680 enternotify(XEvent *e) {
   681 	unsigned int i;
       
   682 	Client *c;
   681 	Client *c;
   683 	XCrossingEvent *ev = &e->xcrossing;
   682 	XCrossingEvent *ev = &e->xcrossing;
   684 
   683 
   685 	if(ev->mode != NotifyNormal || ev->detail == NotifyInferior)
   684 	if(ev->mode != NotifyNormal || ev->detail == NotifyInferior);
   686 		return;
   685 		//return;
   687 	if((c = getclient(ev->window)))
   686 	if((c = getclient(ev->window)))
   688 		focus(c);
   687 		focus(c);
   689 	else {
   688 	else {
   690 		for(i = 0; i < mcount; i++)
   689 		selmonitor = monitorat();
   691 			if(ev->window == monitors[i].root) {
   690 		fprintf(stderr, "updating selmonitor %d\n", selmonitor);
   692 				selmonitor = i;
   691 		focus(NULL);
   693 				focus(NULL);
       
   694 				break;
       
   695 			}
       
   696 	}
   692 	}
   697 }
   693 }
   698 
   694 
   699 void
   695 void
   700 eprint(const char *errstr, ...) {
   696 eprint(const char *errstr, ...) {
   720 floating(void) { /* default floating layout */
   716 floating(void) { /* default floating layout */
   721 	Client *c;
   717 	Client *c;
   722 
   718 
   723 	domwfact = dozoom = False;
   719 	domwfact = dozoom = False;
   724 	for(c = clients; c; c = c->next)
   720 	for(c = clients; c; c = c->next)
   725 		if(isvisible(c, &monitors[selmonitor]))
   721 		if(isvisible(c, selmonitor))
   726 			resize(c, c->x, c->y, c->w, c->h, True);
   722 			resize(c, c->x, c->y, c->w, c->h, True);
   727 }
   723 }
   728 
   724 
   729 void
   725 void
   730 focus(Client *c) {
   726 focus(Client *c) {
   731 	Monitor *m = &monitors[c ? c->monitor : selmonitor];
   727 	Monitor *m;
   732 	if(!c || (c && !isvisible(c, m)))
   728 
   733 		for(c = stack; c && !isvisible(c, m); c = c->snext);
   729 	if(c)
       
   730 		selmonitor = c->monitor;
       
   731 	m = &monitors[selmonitor];
       
   732 	if(!c || (c && !isvisible(c, selmonitor)))
       
   733 		for(c = stack; c && !isvisible(c, c->monitor); c = c->snext);
   734 	if(sel && sel != c) {
   734 	if(sel && sel != c) {
   735 		grabbuttons(sel, False);
   735 		grabbuttons(sel, False);
   736 		XSetWindowBorder(dpy, sel->win, monitors[sel->monitor].dc.norm[ColBorder]);
   736 		XSetWindowBorder(dpy, sel->win, monitors[sel->monitor].dc.norm[ColBorder]);
   737 	}
   737 	}
   738 	if(c) {
   738 	if(c) {
   761 }
   761 }
   762 
   762 
   763 void
   763 void
   764 focusnext(const char *arg) {
   764 focusnext(const char *arg) {
   765 	Client *c;
   765 	Client *c;
   766 	Monitor *m = &monitors[selmonitor];
       
   767 
   766 
   768 	if(!sel)
   767 	if(!sel)
   769 		return;
   768 		return;
   770 	for(c = sel->next; c && !isvisible(c, m); c = c->next);
   769 	for(c = sel->next; c && !isvisible(c, selmonitor); c = c->next);
   771 	if(!c)
   770 	if(!c)
   772 		for(c = clients; c && !isvisible(c, m); c = c->next);
   771 		for(c = clients; c && !isvisible(c, selmonitor); c = c->next);
   773 	if(c) {
   772 	if(c) {
   774 		focus(c);
   773 		focus(c);
   775 		restack();
   774 		restack();
   776 	}
   775 	}
   777 }
   776 }
   778 
   777 
   779 void
   778 void
   780 focusprev(const char *arg) {
   779 focusprev(const char *arg) {
   781 	Client *c;
   780 	Client *c;
   782 	Monitor *m = &monitors[selmonitor];
       
   783 
   781 
   784 	if(!sel)
   782 	if(!sel)
   785 		return;
   783 		return;
   786 	for(c = sel->prev; c && !isvisible(c, m); c = c->prev);
   784 	for(c = sel->prev; c && !isvisible(c, selmonitor); c = c->prev);
   787 	if(!c) {
   785 	if(!c) {
   788 		for(c = clients; c && c->next; c = c->next);
   786 		for(c = clients; c && c->next; c = c->next);
   789 		for(; c && !isvisible(c, m); c = c->prev);
   787 		for(; c && !isvisible(c, selmonitor); c = c->prev);
   790 	}
   788 	}
   791 	if(c) {
   789 	if(c) {
   792 		focus(c);
   790 		focus(c);
   793 		restack();
   791 		restack();
   794 	}
   792 	}
   999 	}
   997 	}
  1000 	return ret;
   998 	return ret;
  1001 }
   999 }
  1002 
  1000 
  1003 Bool
  1001 Bool
  1004 isvisible(Client *c, Monitor *m) {
  1002 isvisible(Client *c, int monitor) {
  1005 	unsigned int i;
  1003 	unsigned int i;
  1006 
  1004 
  1007 	for(i = 0; i < LENGTH(tags); i++)
  1005 	for(i = 0; i < LENGTH(tags); i++)
  1008 		if(c->tags[i] && monitors[c->monitor].seltags[i] && c->monitor == selmonitor)
  1006 		if(c->tags[i] && monitors[c->monitor].seltags[i] && c->monitor == monitor)
  1009 			return True;
  1007 			return True;
  1010 	return False;
  1008 	return False;
  1011 }
  1009 }
  1012 
  1010 
  1013 void
  1011 void
  1047 }
  1045 }
  1048 
  1046 
  1049 void
  1047 void
  1050 manage(Window w, XWindowAttributes *wa) {
  1048 manage(Window w, XWindowAttributes *wa) {
  1051 	Client *c, *t = NULL;
  1049 	Client *c, *t = NULL;
  1052 	Monitor *m = &monitors[selmonitor];
  1050 	Monitor *m;
  1053 	Status rettrans;
  1051 	Status rettrans;
  1054 	Window trans;
  1052 	Window trans;
  1055 	XWindowChanges wc;
  1053 	XWindowChanges wc;
  1056 
  1054 
  1057 	c = emallocz(sizeof(Client));
  1055 	c = emallocz(sizeof(Client));
  1058 	c->tags = emallocz(sizeof initags);
  1056 	c->tags = emallocz(sizeof initags);
  1059 	c->win = w;
  1057 	c->win = w;
  1060 
  1058 
  1061 	applyrules(c);
  1059 	applyrules(c);
       
  1060 
       
  1061 	m = &monitors[c->monitor];
  1062 
  1062 
  1063 	c->x = wa->x + m->sx;
  1063 	c->x = wa->x + m->sx;
  1064 	c->y = wa->y + m->sy;
  1064 	c->y = wa->y + m->sy;
  1065 	c->w = wa->width;
  1065 	c->w = wa->width;
  1066 	c->h = wa->height;
  1066 	c->h = wa->height;
  1067 	c->oldborder = wa->border_width;
  1067 	c->oldborder = wa->border_width;
  1068 
       
  1069 	if (monitorat(c->x, c->y) != c->monitor) {
       
  1070 		c->x = m->sx;
       
  1071 		c->y = m->sy;
       
  1072 	}
       
  1073 
  1068 
  1074 	if(c->w == m->sw && c->h == m->sh) {
  1069 	if(c->w == m->sw && c->h == m->sh) {
  1075 		c->x = m->sx;
  1070 		c->x = m->sx;
  1076 		c->y = m->sy;
  1071 		c->y = m->sy;
  1077 		c->border = wa->border_width;
  1072 		c->border = wa->border_width;
  1130 		return;
  1125 		return;
  1131 	if(!getclient(ev->window))
  1126 	if(!getclient(ev->window))
  1132 		manage(ev->window, &wa);
  1127 		manage(ev->window, &wa);
  1133 }
  1128 }
  1134 
  1129 
       
  1130 int
       
  1131 monitorat() {
       
  1132 	int i, x, y;
       
  1133 	Window win;
       
  1134 	unsigned int mask;
       
  1135 
       
  1136 	XQueryPointer(dpy, monitors[selmonitor].root, &win, &win, &x, &y, &i, &i, &mask);
       
  1137 	for(i = 0; i < mcount; i++) {
       
  1138 		fprintf(stderr, "checking monitor[%d]: %d %d %d %d\n", i, monitors[i].sx, monitors[i].sy, monitors[i].sw, monitors[i].sh);
       
  1139 		if((x >= monitors[i].sx && x < monitors[i].sx + monitors[i].sw)
       
  1140 		&& (y >= monitors[i].sy && y < monitors[i].sy + monitors[i].sh)) {
       
  1141 			fprintf(stderr, "%d,%d -> %d\n", x, y, i);
       
  1142 			return i;
       
  1143 		}
       
  1144 	}
       
  1145 	fprintf(stderr, "?,? -> 0\n");
       
  1146 	return 0;
       
  1147 }
       
  1148 
  1135 void
  1149 void
  1136 movemouse(Client *c) {
  1150 movemouse(Client *c) {
  1137 	int x1, y1, ocx, ocy, di, nx, ny;
  1151 	int x1, y1, ocx, ocy, di, nx, ny;
  1138 	unsigned int dui;
  1152 	unsigned int dui;
  1139 	Window dummy;
  1153 	Window dummy;
  1158 			break;
  1172 			break;
  1159 		case MotionNotify:
  1173 		case MotionNotify:
  1160 			XSync(dpy, False);
  1174 			XSync(dpy, False);
  1161 			nx = ocx + (ev.xmotion.x - x1);
  1175 			nx = ocx + (ev.xmotion.x - x1);
  1162 			ny = ocy + (ev.xmotion.y - y1);
  1176 			ny = ocy + (ev.xmotion.y - y1);
  1163 			Monitor *m = &monitors[monitorat(nx, ny)];
  1177 			Monitor *m = &monitors[monitorat()];
  1164 			if(abs(m->wax - nx) < SNAP)
  1178 			if(abs(m->wax - nx) < SNAP)
  1165 				nx = m->wax;
  1179 				nx = m->wax;
  1166 			else if(abs((m->wax + m->waw) - (nx + c->w + 2 * c->border)) < SNAP)
  1180 			else if(abs((m->wax + m->waw) - (nx + c->w + 2 * c->border)) < SNAP)
  1167 				nx = m->wax + m->waw - c->w - 2 * c->border;
  1181 				nx = m->wax + m->waw - c->w - 2 * c->border;
  1168 			if(abs(m->way - ny) < SNAP)
  1182 			if(abs(m->way - ny) < SNAP)
  1169 				ny = m->way;
  1183 				ny = m->way;
  1170 			else if(abs((m->way + m->wah) - (ny + c->h + 2 * c->border)) < SNAP)
  1184 			else if(abs((m->way + m->wah) - (ny + c->h + 2 * c->border)) < SNAP)
  1171 				ny = m->way + m->wah - c->h - 2 * c->border;
  1185 				ny = m->way + m->wah - c->h - 2 * c->border;
  1172 			resize(c, nx, ny, c->w, c->h, False);
  1186 			resize(c, nx, ny, c->w, c->h, False);
  1173 			memcpy(c->tags, monitors[monitorat(nx, ny)].seltags, sizeof initags);
  1187 			memcpy(c->tags, monitors[monitorat()].seltags, sizeof initags);
  1174 			break;
  1188 			break;
  1175 		}
  1189 		}
  1176 	}
  1190 	}
  1177 }
  1191 }
  1178 
  1192 
  1179 Client *
  1193 Client *
  1180 nexttiled(Client *c, Monitor *m) {
  1194 nexttiled(Client *c, int monitor) {
  1181 	for(; c && (c->isfloating || !isvisible(c, m)); c = c->next);
  1195 	for(; c && (c->isfloating || !isvisible(c, monitor)); c = c->next);
  1182 	return c;
  1196 	return c;
  1183 }
  1197 }
  1184 
  1198 
  1185 void
  1199 void
  1186 propertynotify(XEvent *e) {
  1200 propertynotify(XEvent *e) {
  1228 }
  1242 }
  1229 
  1243 
  1230 void
  1244 void
  1231 resize(Client *c, int x, int y, int w, int h, Bool sizehints) {
  1245 resize(Client *c, int x, int y, int w, int h, Bool sizehints) {
  1232 	XWindowChanges wc;
  1246 	XWindowChanges wc;
  1233 	Monitor scr = monitors[monitorat(x, y)];
  1247 	//Monitor scr = monitors[monitorat()];
  1234 	c->monitor = monitorat(x, y);
  1248 //	c->monitor = monitorat();
  1235 
  1249 
  1236 	if(sizehints) {
  1250 	if(sizehints) {
  1237 		/* set minimum possible */
  1251 		/* set minimum possible */
  1238 		if (w < 1)
  1252 		if (w < 1)
  1239 			w = 1;
  1253 			w = 1;
  1352 		if(!sel->isfloating) {
  1366 		if(!sel->isfloating) {
  1353 			XConfigureWindow(dpy, sel->win, CWSibling | CWStackMode, &wc);
  1367 			XConfigureWindow(dpy, sel->win, CWSibling | CWStackMode, &wc);
  1354 			wc.sibling = sel->win;
  1368 			wc.sibling = sel->win;
  1355 		}
  1369 		}
  1356 		for(i = 0; i < mcount; i++) {
  1370 		for(i = 0; i < mcount; i++) {
  1357 			for(c = nexttiled(clients, &monitors[i]); c; c = nexttiled(c->next, &monitors[i])) {
  1371 			for(c = nexttiled(clients, i); c; c = nexttiled(c->next, i)) {
  1358 				if(c == sel)
  1372 				if(c == sel)
  1359 					continue;
  1373 					continue;
  1360 				XConfigureWindow(dpy, c->win, CWSibling | CWStackMode, &wc);
  1374 				XConfigureWindow(dpy, c->win, CWSibling | CWStackMode, &wc);
  1361 				wc.sibling = c->win;
  1375 				wc.sibling = c->win;
  1362 			}
  1376 			}
  1465 }
  1479 }
  1466 
  1480 
  1467 void
  1481 void
  1468 setlayout(const char *arg) {
  1482 setlayout(const char *arg) {
  1469 	unsigned int i;
  1483 	unsigned int i;
  1470 	Monitor *m = &monitors[monitorat(-1, -1)];
  1484 	Monitor *m = &monitors[monitorat()];
  1471 
  1485 
  1472 	if(!arg) {
  1486 	if(!arg) {
  1473 		m->layout++;
  1487 		m->layout++;
  1474 		if(m->layout == &layouts[LENGTH(layouts)])
  1488 		if(m->layout == &layouts[LENGTH(layouts)])
  1475 			m->layout = &layouts[0];
  1489 			m->layout = &layouts[0];
  1490 
  1504 
  1491 void
  1505 void
  1492 setmwfact(const char *arg) {
  1506 setmwfact(const char *arg) {
  1493 	double delta;
  1507 	double delta;
  1494 
  1508 
  1495 	Monitor *m = &monitors[monitorat(-1, -1)];
  1509 	Monitor *m = &monitors[monitorat()];
  1496 
  1510 
  1497 	if(!domwfact)
  1511 	if(!domwfact)
  1498 		return;
  1512 		return;
  1499 	/* arg handling, manipulate mwfact */
  1513 	/* arg handling, manipulate mwfact */
  1500 	if(arg == NULL)
  1514 	if(arg == NULL)
  1531 	wa.cursor = cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr);
  1545 	wa.cursor = cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr);
  1532 	cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing);
  1546 	cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing);
  1533 	cursor[CurMove] = XCreateFontCursor(dpy, XC_fleur);
  1547 	cursor[CurMove] = XCreateFontCursor(dpy, XC_fleur);
  1534 
  1548 
  1535 	// init screens/monitors first
  1549 	// init screens/monitors first
  1536 	if (XineramaIsActive(dpy)) {
  1550 	mcount = 1;
       
  1551 	if((isxinerama = XineramaIsActive(dpy)))
  1537 		info = XineramaQueryScreens(dpy, &mcount);
  1552 		info = XineramaQueryScreens(dpy, &mcount);
  1538 	}
       
  1539 	mcount = 1;
       
  1540 	monitors = emallocz(mcount * sizeof(Monitor));
  1553 	monitors = emallocz(mcount * sizeof(Monitor));
  1541 
  1554 
  1542 	for(i = 0; i < mcount; i++) {
  1555 	for(i = 0; i < mcount; i++) {
  1543 		/* init geometry */
  1556 		/* init geometry */
  1544 		m = &monitors[i];
  1557 		m = &monitors[i];
  1545 
  1558 
  1546 		m->screen = i;
  1559 		m->screen = isxinerama ? 0 : i;
  1547 		m->root = RootWindow(dpy, i);
  1560 		m->root = RootWindow(dpy, m->screen);
  1548 
  1561 
  1549 		if (mcount != 1) { // TODO: Xinerama
  1562 		if (mcount != 1 && isxinerama) {
  1550 			m->sx = info[i].x_org;
  1563 			m->sx = info[i].x_org;
  1551 			m->sy = info[i].y_org;
  1564 			m->sy = info[i].y_org;
  1552 			m->sw = info[i].width;
  1565 			m->sw = info[i].width;
  1553 			m->sh = info[i].height;
  1566 			m->sh = info[i].height;
       
  1567 			fprintf(stderr, "monitor[%d]: %d,%d,%d,%d\n", i, m->sx, m->sy, m->sw, m->sh);
  1554 		}
  1568 		}
  1555 		else {
  1569 		else {
  1556 			m->sx = 0;
  1570 			m->sx = 0;
  1557 			m->sy = 0;
  1571 			m->sy = 0;
  1558 			m->sw = DisplayWidth(dpy, m->screen);
  1572 			m->sw = DisplayWidth(dpy, m->screen);
  1564 
  1578 
  1565 		memcpy(m->seltags, initags, sizeof initags);
  1579 		memcpy(m->seltags, initags, sizeof initags);
  1566 		memcpy(m->prevtags, initags, sizeof initags);
  1580 		memcpy(m->prevtags, initags, sizeof initags);
  1567 
  1581 
  1568 		/* init appearance */
  1582 		/* init appearance */
  1569 		m->dc.norm[ColBorder] = getcolor(NORMBORDERCOLOR, i);
  1583 		m->dc.norm[ColBorder] = getcolor(NORMBORDERCOLOR, m->screen);
  1570 		m->dc.norm[ColBG] = getcolor(NORMBGCOLOR, i);
  1584 		m->dc.norm[ColBG] = getcolor(NORMBGCOLOR, m->screen);
  1571 		m->dc.norm[ColFG] = getcolor(NORMFGCOLOR, i);
  1585 		m->dc.norm[ColFG] = getcolor(NORMFGCOLOR, m->screen);
  1572 		m->dc.sel[ColBorder] = getcolor(SELBORDERCOLOR, i);
  1586 		m->dc.sel[ColBorder] = getcolor(SELBORDERCOLOR, m->screen);
  1573 		m->dc.sel[ColBG] = getcolor(SELBGCOLOR, i);
  1587 		m->dc.sel[ColBG] = getcolor(SELBGCOLOR, m->screen);
  1574 		m->dc.sel[ColFG] = getcolor(SELFGCOLOR, i);
  1588 		m->dc.sel[ColFG] = getcolor(SELFGCOLOR, m->screen);
  1575 		initfont(m, FONT);
  1589 		initfont(m, FONT);
  1576 		m->dc.h = bh = m->dc.font.height + 2;
  1590 		m->dc.h = bh = m->dc.font.height + 2;
  1577 
  1591 
  1578 		/* init layouts */
  1592 		/* init layouts */
  1579 		m->mwfact = MWFACT;
  1593 		m->mwfact = MWFACT;
  1612 		wa.event_mask = SubstructureRedirectMask | SubstructureNotifyMask
  1626 		wa.event_mask = SubstructureRedirectMask | SubstructureNotifyMask
  1613 				| EnterWindowMask | LeaveWindowMask | StructureNotifyMask;
  1627 				| EnterWindowMask | LeaveWindowMask | StructureNotifyMask;
  1614 		XChangeWindowAttributes(dpy, m->root, CWEventMask | CWCursor, &wa);
  1628 		XChangeWindowAttributes(dpy, m->root, CWEventMask | CWCursor, &wa);
  1615 		XSelectInput(dpy, m->root, wa.event_mask);
  1629 		XSelectInput(dpy, m->root, wa.event_mask);
  1616 	}
  1630 	}
       
  1631 	if(info)
       
  1632 		XFree(info);
  1617 
  1633 
  1618 	/* grab keys */
  1634 	/* grab keys */
  1619 	grabkeys();
  1635 	grabkeys();
  1620 
  1636 
  1621 	/* init tags */
  1637 	/* init tags */
  1622 	compileregs();
  1638 	compileregs();
       
  1639 
       
  1640 	selmonitor = monitorat();
       
  1641 	fprintf(stderr, "selmonitor == %d\n", selmonitor);
  1623 }
  1642 }
  1624 
  1643 
  1625 void
  1644 void
  1626 spawn(const char *arg) {
  1645 spawn(const char *arg) {
  1627 	static char *shell = NULL;
  1646 	static char *shell = NULL;
  1679 	unsigned int i, j, n, nx, ny, nw, nh, mw, th;
  1698 	unsigned int i, j, n, nx, ny, nw, nh, mw, th;
  1680 	Client *c, *mc;
  1699 	Client *c, *mc;
  1681 
  1700 
  1682 	domwfact = dozoom = True;
  1701 	domwfact = dozoom = True;
  1683 
  1702 
  1684 	nw = 0; /* gcc stupidity requires this */
  1703 	nx = ny = nw = 0; /* gcc stupidity requires this */
  1685 
  1704 
  1686 	for (i = 0; i < mcount; i++) {
  1705 	for (i = 0; i < mcount; i++) {
  1687 		Monitor *m = &monitors[i];
  1706 		Monitor *m = &monitors[i];
  1688 
  1707 
  1689 		for(n = 0, c = nexttiled(clients, m); c; c = nexttiled(c->next, m))
  1708 		for(n = 0, c = nexttiled(clients, i); c; c = nexttiled(c->next, i))
  1690 			n++;
  1709 			n++;
  1691 
  1710 
  1692 		for(j = 0, c = mc = nexttiled(clients, m); c; c = nexttiled(c->next, m)) {
  1711 		for(j = 0, c = mc = nexttiled(clients, i); c; c = nexttiled(c->next, i)) {
  1693 			/* window geoms */
  1712 			/* window geoms */
  1694 			mw = (n == 1) ? m->waw : m->mwfact * m->waw;
  1713 			mw = (n == 1) ? m->waw : m->mwfact * m->waw;
  1695 			th = (n > 1) ? m->wah / (n - 1) : 0;
  1714 			th = (n > 1) ? m->wah / (n - 1) : 0;
  1696 			if(n > 1 && th < bh)
  1715 			if(n > 1 && th < bh)
  1697 				th = m->wah;
  1716 				th = m->wah;
  1710 				if(j + 1 == n) /* remainder */
  1729 				if(j + 1 == n) /* remainder */
  1711 					nh = (m->way + m->wah) - ny - 2 * c->border;
  1730 					nh = (m->way + m->wah) - ny - 2 * c->border;
  1712 				else
  1731 				else
  1713 					nh = th - 2 * c->border;
  1732 					nh = th - 2 * c->border;
  1714 			}
  1733 			}
       
  1734 			fprintf(stderr, "tile(%d, %d, %d, %d)\n", nx, ny, nw, nh);
  1715 			resize(c, nx, ny, nw, nh, RESIZEHINTS);
  1735 			resize(c, nx, ny, nw, nh, RESIZEHINTS);
  1716 			if((RESIZEHINTS) && ((c->h < bh) || (c->h > nh) || (c->w < bh) || (c->w > nw)))
  1736 			if((RESIZEHINTS) && ((c->h < bh) || (c->h > nh) || (c->w < bh) || (c->w > nw)))
  1717 				/* client doesn't accept size constraints */
  1737 				/* client doesn't accept size constraints */
  1718 				resize(c, nx, ny, nw, nh, False);
  1738 				resize(c, nx, ny, nw, nh, False);
  1719 			if(n > 1 && th != m->wah)
  1739 			if(n > 1 && th != m->wah)
  1720 				ny = c->y + c->h + 2 * c->border;
  1740 				ny = c->y + c->h + 2 * c->border;
  1721 
  1741 
  1722 			j++;
  1742 			j++;
  1723 		}
  1743 		}
  1724 	}
  1744 	}
       
  1745 	fprintf(stderr, "done\n");
  1725 }
  1746 }
  1726 void
  1747 void
  1727 togglebar(const char *arg) {
  1748 togglebar(const char *arg) {
  1728 	if(bpos == BarOff)
  1749 	if(bpos == BarOff)
  1729 		bpos = (BARPOS == BarOff) ? BarTop : BARPOS;
  1750 		bpos = (BARPOS == BarOff) ? BarTop : BARPOS;
  1730 	else
  1751 	else
  1731 		bpos = BarOff;
  1752 		bpos = BarOff;
  1732 	updatebarpos(&monitors[monitorat(-1,-1)]);
  1753 	updatebarpos(&monitors[monitorat()]);
  1733 	arrange();
  1754 	arrange();
  1734 }
  1755 }
  1735 
  1756 
  1736 void
  1757 void
  1737 togglefloating(const char *arg) {
  1758 togglefloating(const char *arg) {
  1759 
  1780 
  1760 void
  1781 void
  1761 toggleview(const char *arg) {
  1782 toggleview(const char *arg) {
  1762 	unsigned int i, j;
  1783 	unsigned int i, j;
  1763 
  1784 
  1764 	Monitor *m = &monitors[monitorat(-1, -1)];
  1785 	Monitor *m = &monitors[monitorat()];
  1765 
  1786 
  1766 	i = idxoftag(arg);
  1787 	i = idxoftag(arg);
  1767 	m->seltags[i] = !m->seltags[i];
  1788 	m->seltags[i] = !m->seltags[i];
  1768 	for(j = 0; j < LENGTH(tags) && !m->seltags[j]; j++);
  1789 	for(j = 0; j < LENGTH(tags) && !m->seltags[j]; j++);
  1769 	if(j == LENGTH(tags))
  1790 	if(j == LENGTH(tags))
  1929 
  1950 
  1930 void
  1951 void
  1931 view(const char *arg) {
  1952 view(const char *arg) {
  1932 	unsigned int i;
  1953 	unsigned int i;
  1933 
  1954 
  1934 	Monitor *m = &monitors[monitorat(-1, -1)];
  1955 	Monitor *m = &monitors[monitorat()];
  1935 
  1956 
  1936 	memcpy(m->prevtags, m->seltags, sizeof initags);
  1957 	memcpy(m->prevtags, m->seltags, sizeof initags);
  1937 	for(i = 0; i < LENGTH(tags); i++)
  1958 	for(i = 0; i < LENGTH(tags); i++)
  1938 		m->seltags[i] = (NULL == arg);
  1959 		m->seltags[i] = (NULL == arg);
  1939 	m->seltags[idxoftag(arg)] = True;
  1960 	m->seltags[idxoftag(arg)] = True;
  1942 
  1963 
  1943 void
  1964 void
  1944 viewprevtag(const char *arg) {
  1965 viewprevtag(const char *arg) {
  1945 	static Bool tmp[LENGTH(tags)];
  1966 	static Bool tmp[LENGTH(tags)];
  1946 
  1967 
  1947 	Monitor *m = &monitors[monitorat(-1, -1)];
  1968 	Monitor *m = &monitors[monitorat()];
  1948 
  1969 
  1949 	memcpy(tmp, m->seltags, sizeof initags);
  1970 	memcpy(tmp, m->seltags, sizeof initags);
  1950 	memcpy(m->seltags, m->prevtags, sizeof initags);
  1971 	memcpy(m->seltags, m->prevtags, sizeof initags);
  1951 	memcpy(m->prevtags, tmp, sizeof initags);
  1972 	memcpy(m->prevtags, tmp, sizeof initags);
  1952 	arrange();
  1973 	arrange();
  1956 zoom(const char *arg) {
  1977 zoom(const char *arg) {
  1957 	Client *c;
  1978 	Client *c;
  1958 
  1979 
  1959 	if(!sel || !dozoom || sel->isfloating)
  1980 	if(!sel || !dozoom || sel->isfloating)
  1960 		return;
  1981 		return;
  1961 	if((c = sel) == nexttiled(clients, &monitors[c->monitor]))
  1982 	if((c = sel) == nexttiled(clients, c->monitor))
  1962 		if(!(c = nexttiled(c->next, &monitors[c->monitor])))
  1983 		if(!(c = nexttiled(c->next, c->monitor)))
  1963 			return;
  1984 			return;
  1964 	detach(c);
  1985 	detach(c);
  1965 	attach(c);
  1986 	attach(c);
  1966 	focus(c);
  1987 	focus(c);
  1967 	arrange();
  1988 	arrange();
  1968 }
  1989 }
  1969 
  1990 
  1970 int
       
  1971 monitorat(int x, int y) {
       
  1972 	int i;
       
  1973 
       
  1974 	return 0;
       
  1975 	if(!XineramaIsActive(dpy))
       
  1976 		return 0;
       
  1977 
       
  1978 	if (x < 0 || y < 0) {
       
  1979 		Window win;
       
  1980 		unsigned int mask;
       
  1981 		XQueryPointer(dpy, DefaultRootWindow(dpy), &win, &win, &x, &y, &i, &i, &mask);
       
  1982 	}
       
  1983 
       
  1984 	for(i = 0; i < mcount; i++) {
       
  1985 		Monitor *m = &monitors[i];
       
  1986 		if((x < 0 || (x >= m->sx && x < m->sx + m->sw))
       
  1987 				&& (y < 0 || (y >= m->sy && y < m->sy + m->sh)))
       
  1988 		{
       
  1989 			return i;
       
  1990 		}
       
  1991 	}
       
  1992 	return 0;
       
  1993 }
       
  1994 
       
  1995 void
  1991 void
  1996 movetomonitor(const char *arg) {
  1992 movetomonitor(const char *arg) {
  1997 	if (sel) {
  1993 	if (sel) {
  1998 		sel->monitor = arg ? atoi(arg) : (sel->monitor+1) % mcount;
  1994 		sel->monitor = arg ? atoi(arg) : (sel->monitor+1) % mcount;
  1999 
  1995 
  2003 	}
  1999 	}
  2004 }
  2000 }
  2005 
  2001 
  2006 void
  2002 void
  2007 selectmonitor(const char *arg) {
  2003 selectmonitor(const char *arg) {
  2008 	Monitor *m = &monitors[arg ? atoi(arg) : (monitorat(-1, -1)+1) % mcount];
  2004 	Monitor *m = &monitors[arg ? atoi(arg) : (monitorat()+1) % mcount];
  2009 
  2005 
  2010 	XWarpPointer(dpy, None, m->root, 0, 0, 0, 0, m->wax+m->waw/2, m->way+m->wah/2);
  2006 	XWarpPointer(dpy, None, m->root, 0, 0, 0, 0, m->wax+m->waw/2, m->way+m->wah/2);
  2011 	focus(NULL);
  2007 	focus(NULL);
  2012 }
  2008 }
  2013 
  2009