dwm.c
changeset 1430 c4b9f97e4bd7
parent 1429 a6f93a5772b2
child 1431 5b2240f2d21f
equal deleted inserted replaced
1429:a6f93a5772b2 1430:c4b9f97e4bd7
     1 //#define XINULATOR /* debug, simulates dual head */
       
     2 /* See LICENSE file for copyright and license details.
     1 /* See LICENSE file for copyright and license details.
     3  *
     2  *
     4  * dynamic window manager is designed like any other X client as well. It is
     3  * dynamic window manager is designed like any other X client as well. It is
     5  * driven through handling X events. In contrast to other X clients, a window
     4  * driven through handling X events. In contrast to other X clients, a window
     6  * manager selects for SubstructureRedirectMask on the root window, to receive
     5  * manager selects for SubstructureRedirectMask on the root window, to receive
   172 static void enternotify(XEvent *e);
   171 static void enternotify(XEvent *e);
   173 static void expose(XEvent *e);
   172 static void expose(XEvent *e);
   174 static void focus(Client *c);
   173 static void focus(Client *c);
   175 static void focusin(XEvent *e);
   174 static void focusin(XEvent *e);
   176 static void focusstack(const Arg *arg);
   175 static void focusstack(const Arg *arg);
   177 static Client *getclient(Window w);
       
   178 static unsigned long getcolor(const char *colstr);
   176 static unsigned long getcolor(const char *colstr);
   179 static Monitor *getmon(Window w);
       
   180 static Monitor *getmonn(unsigned int n);
       
   181 static Monitor *getmonxy(int x, int y);
       
   182 static Bool getrootpointer(int *x, int *y);
   177 static Bool getrootpointer(int *x, int *y);
   183 static long getstate(Window w);
   178 static long getstate(Window w);
   184 static Bool gettextprop(Window w, Atom atom, char *text, unsigned int size);
   179 static Bool gettextprop(Window w, Atom atom, char *text, unsigned int size);
   185 static void grabbuttons(Client *c, Bool focused);
   180 static void grabbuttons(Client *c, Bool focused);
   186 static void grabkeys(void);
   181 static void grabkeys(void);
       
   182 static Monitor *idxtomon(unsigned int n);
   187 static void initfont(const char *fontstr);
   183 static void initfont(const char *fontstr);
   188 static Bool isprotodel(Client *c);
   184 static Bool isprotodel(Client *c);
   189 static void keypress(XEvent *e);
   185 static void keypress(XEvent *e);
   190 static void killclient(const Arg *arg);
   186 static void killclient(const Arg *arg);
   191 static void manage(Window w, XWindowAttributes *wa);
   187 static void manage(Window w, XWindowAttributes *wa);
   192 static void mappingnotify(XEvent *e);
   188 static void mappingnotify(XEvent *e);
   193 static void maprequest(XEvent *e);
   189 static void maprequest(XEvent *e);
   194 static void monocle(Monitor *m);
   190 static void monocle(Monitor *m);
   195 static void movemouse(const Arg *arg);
   191 static void movemouse(const Arg *arg);
   196 static Client *nexttiled(Client *c);
   192 static Client *nexttiled(Client *c);
       
   193 static Monitor *pointertomon(int x, int y);
   197 static void propertynotify(XEvent *e);
   194 static void propertynotify(XEvent *e);
   198 static void quit(const Arg *arg);
   195 static void quit(const Arg *arg);
   199 static void resize(Client *c, int x, int y, int w, int h);
   196 static void resize(Client *c, int x, int y, int w, int h);
   200 static void resizemouse(const Arg *arg);
   197 static void resizemouse(const Arg *arg);
   201 static void restack(Monitor *m);
   198 static void restack(Monitor *m);
   226 static void updatesizehints(Client *c);
   223 static void updatesizehints(Client *c);
   227 static void updatestatus(void);
   224 static void updatestatus(void);
   228 static void updatetitle(Client *c);
   225 static void updatetitle(Client *c);
   229 static void updatewmhints(Client *c);
   226 static void updatewmhints(Client *c);
   230 static void view(const Arg *arg);
   227 static void view(const Arg *arg);
       
   228 static Client *wintoclient(Window w);
       
   229 static Monitor *wintomon(Window w);
   231 static int xerror(Display *dpy, XErrorEvent *ee);
   230 static int xerror(Display *dpy, XErrorEvent *ee);
   232 static int xerrordummy(Display *dpy, XErrorEvent *ee);
   231 static int xerrordummy(Display *dpy, XErrorEvent *ee);
   233 static int xerrorstart(Display *dpy, XErrorEvent *ee);
   232 static int xerrorstart(Display *dpy, XErrorEvent *ee);
   234 static void zoom(const Arg *arg);
   233 static void zoom(const Arg *arg);
   235 #ifdef XINERAMA
   234 #ifdef XINERAMA
   400 	Monitor *m;
   399 	Monitor *m;
   401 	XButtonPressedEvent *ev = &e->xbutton;
   400 	XButtonPressedEvent *ev = &e->xbutton;
   402 
   401 
   403 	click = ClkRootWin;
   402 	click = ClkRootWin;
   404 	/* focus monitor if necessary */
   403 	/* focus monitor if necessary */
   405 	if((m = getmon(ev->window)) && m != selmon) {
   404 	if((m = wintomon(ev->window)) && m != selmon) {
   406 		unfocus(selmon->sel);
   405 		unfocus(selmon->sel);
   407 		selmon = m;
   406 		selmon = m;
   408 		focus(NULL);
   407 		focus(NULL);
   409 	}
   408 	}
   410 	if(ev->window == selmon->barwin && ev->x >= selmon->btx) {
   409 	if(ev->window == selmon->barwin && ev->x >= selmon->btx) {
   422 		else if(ev->x > selmon->wx + selmon->ww - TEXTW(stext))
   421 		else if(ev->x > selmon->wx + selmon->ww - TEXTW(stext))
   423 			click = ClkStatusText;
   422 			click = ClkStatusText;
   424 		else
   423 		else
   425 			click = ClkWinTitle;
   424 			click = ClkWinTitle;
   426 	}
   425 	}
   427 	else if((c = getclient(ev->window))) {
   426 	else if((c = wintoclient(ev->window))) {
   428 		focus(c);
   427 		focus(c);
   429 		click = ClkClientWin;
   428 		click = ClkClientWin;
   430 	}
   429 	}
   431 
   430 
   432 	for(i = 0; i < LENGTH(buttons); i++)
   431 	for(i = 0; i < LENGTH(buttons); i++)
   455 	Layout foo = { "", NULL };
   454 	Layout foo = { "", NULL };
   456 	Monitor *m;
   455 	Monitor *m;
   457 
   456 
   458 	view(&a);
   457 	view(&a);
   459 	lt[selmon->sellt] = &foo;
   458 	lt[selmon->sellt] = &foo;
   460 
       
   461 	/* TODO: consider simplifying cleanup code of the stack, perhaps do that in cleanmons() ? */
       
   462 	for(m = mons; m; m = m->next)
   459 	for(m = mons; m; m = m->next)
   463 		while(m->stack)
   460 		while(m->stack)
   464 			unmanage(m->stack);
   461 			unmanage(m->stack);
   465 	if(dc.font.set)
   462 	if(dc.font.set)
   466 		XFreeFontSet(dpy, dc.font.set);
   463 		XFreeFontSet(dpy, dc.font.set);
   544 	Client *c;
   541 	Client *c;
   545 	Monitor *m;
   542 	Monitor *m;
   546 	XConfigureRequestEvent *ev = &e->xconfigurerequest;
   543 	XConfigureRequestEvent *ev = &e->xconfigurerequest;
   547 	XWindowChanges wc;
   544 	XWindowChanges wc;
   548 
   545 
   549 	if((c = getclient(ev->window))) {
   546 	if((c = wintoclient(ev->window))) {
   550 		if(ev->value_mask & CWBorderWidth)
   547 		if(ev->value_mask & CWBorderWidth)
   551 			c->bw = ev->border_width;
   548 			c->bw = ev->border_width;
   552 		else if(c->isfloating || !lt[selmon->sellt]->arrange) {
   549 		else if(c->isfloating || !lt[selmon->sellt]->arrange) {
   553 			m = c->mon;
   550 			m = c->mon;
   554 			if(ev->value_mask & CWX)
   551 			if(ev->value_mask & CWX)
   587 void
   584 void
   588 destroynotify(XEvent *e) {
   585 destroynotify(XEvent *e) {
   589 	Client *c;
   586 	Client *c;
   590 	XDestroyWindowEvent *ev = &e->xdestroywindow;
   587 	XDestroyWindowEvent *ev = &e->xdestroywindow;
   591 
   588 
   592 	if((c = getclient(ev->window)))
   589 	if((c = wintoclient(ev->window)))
   593 		unmanage(c);
   590 		unmanage(c);
   594 }
   591 }
   595 
   592 
   596 void
   593 void
   597 detach(Client *c) {
   594 detach(Client *c) {
   605 detachstack(Client *c) {
   602 detachstack(Client *c) {
   606 	Client **tc;
   603 	Client **tc;
   607 
   604 
   608 	for(tc = &c->mon->stack; *tc && *tc != c; tc = &(*tc)->snext);
   605 	for(tc = &c->mon->stack; *tc && *tc != c; tc = &(*tc)->snext);
   609 	*tc = c->snext;
   606 	*tc = c->snext;
       
   607 
       
   608 	if(c == c->mon->sel) {
       
   609 		for(*tc = c->mon->stack; *tc && !ISVISIBLE((*tc)); *tc = (*tc)->snext);
       
   610 		c->mon->sel = *tc;
       
   611 	}
   610 }
   612 }
   611 
   613 
   612 void
   614 void
   613 die(const char *errstr, ...) {
   615 die(const char *errstr, ...) {
   614 	va_list ap;
   616 	va_list ap;
   748 	Monitor *m;
   750 	Monitor *m;
   749 	XCrossingEvent *ev = &e->xcrossing;
   751 	XCrossingEvent *ev = &e->xcrossing;
   750 
   752 
   751 	if((ev->mode != NotifyNormal || ev->detail == NotifyInferior) && ev->window != root)
   753 	if((ev->mode != NotifyNormal || ev->detail == NotifyInferior) && ev->window != root)
   752 		return;
   754 		return;
   753 	if((m = getmon(ev->window)) && m != selmon) {
   755 	if((m = wintomon(ev->window)) && m != selmon) {
   754 		unfocus(selmon->sel);
   756 		unfocus(selmon->sel);
   755 		selmon = m;
   757 		selmon = m;
   756 	}
   758 	}
   757 	if((c = getclient(ev->window)))
   759 	if((c = wintoclient(ev->window)))
   758 		focus(c);
   760 		focus(c);
   759 	else
   761 	else
   760 		focus(NULL);
   762 		focus(NULL);
   761 }
   763 }
   762 
   764 
   763 void
   765 void
   764 expose(XEvent *e) {
   766 expose(XEvent *e) {
   765 	Monitor *m;
   767 	Monitor *m;
   766 	XExposeEvent *ev = &e->xexpose;
   768 	XExposeEvent *ev = &e->xexpose;
   767 
   769 
   768 	if(ev->count == 0 && (m = getmon(ev->window)))
   770 	if(ev->count == 0 && (m = wintomon(ev->window)))
   769 		drawbar(m);
   771 		drawbar(m);
   770 }
   772 }
   771 
   773 
   772 void
   774 void
   773 focus(Client *c) {
   775 focus(Client *c) {
   803 #ifdef XINERAMA
   805 #ifdef XINERAMA
   804 void
   806 void
   805 focusmon(const Arg *arg) {
   807 focusmon(const Arg *arg) {
   806 	Monitor *m;
   808 	Monitor *m;
   807 
   809 
   808 	if(!(m = getmonn(arg->ui)) || m == selmon)
   810 	if(!(m = idxtomon(arg->ui)) || m == selmon)
   809 		return;
   811 		return;
   810 	unfocus(selmon->sel);
   812 	unfocus(selmon->sel);
   811 	selmon = m;
   813 	selmon = m;
   812 	focus(NULL);
   814 	focus(NULL);
   813 }
   815 }
   837 		focus(c);
   839 		focus(c);
   838 		restack(selmon);
   840 		restack(selmon);
   839 	}
   841 	}
   840 }
   842 }
   841 
   843 
   842 Client *
       
   843 getclient(Window w) {
       
   844 	Client *c;
       
   845 	Monitor *m;
       
   846 
       
   847 	for(m = mons; m; m = m->next)
       
   848 		for(c = m->clients; c; c = c->next)
       
   849 			if(c->win == w)
       
   850 				return c;
       
   851 	return NULL;
       
   852 }
       
   853 
       
   854 unsigned long
   844 unsigned long
   855 getcolor(const char *colstr) {
   845 getcolor(const char *colstr) {
   856 	Colormap cmap = DefaultColormap(dpy, screen);
   846 	Colormap cmap = DefaultColormap(dpy, screen);
   857 	XColor color;
   847 	XColor color;
   858 
   848 
   859 	if(!XAllocNamedColor(dpy, cmap, colstr, &color, &color))
   849 	if(!XAllocNamedColor(dpy, cmap, colstr, &color, &color))
   860 		die("error, cannot allocate color '%s'\n", colstr);
   850 		die("error, cannot allocate color '%s'\n", colstr);
   861 	return color.pixel;
   851 	return color.pixel;
   862 }
       
   863 
       
   864 Monitor *
       
   865 getmon(Window w) {
       
   866 	int x, y;
       
   867 	Client *c;
       
   868 	Monitor *m;
       
   869 
       
   870 	if(w == root && getrootpointer(&x, &y))
       
   871 		return getmonxy(x, y);
       
   872 	for(m = mons; m; m = m->next)
       
   873 		if(w == m->barwin)
       
   874 			return m;
       
   875 	if((c = getclient(w)))
       
   876 		return c->mon;
       
   877 	return mons;
       
   878 }
       
   879 
       
   880 Monitor *
       
   881 getmonn(unsigned int n) {
       
   882 	unsigned int i;
       
   883 	Monitor *m;
       
   884 
       
   885 	for(m = mons, i = 0; m && i != n; m = m->next, i++);
       
   886 	return m;
       
   887 }
       
   888 
       
   889 Monitor *
       
   890 getmonxy(int x, int y) {
       
   891 	Monitor *m;
       
   892 
       
   893 	for(m = mons; m; m = m->next)
       
   894 		if(INRECT(x, y, m->wx, m->wy, m->ww, m->wh))
       
   895 			return m;
       
   896 	return mons;
       
   897 }
   852 }
   898 
   853 
   899 Bool
   854 Bool
   900 getrootpointer(int *x, int *y) {
   855 getrootpointer(int *x, int *y) {
   901 	int di;
   856 	int di;
   985 						 True, GrabModeAsync, GrabModeAsync);
   940 						 True, GrabModeAsync, GrabModeAsync);
   986 		}
   941 		}
   987 	}
   942 	}
   988 }
   943 }
   989 
   944 
       
   945 Monitor *
       
   946 idxtomon(unsigned int n) {
       
   947 	unsigned int i;
       
   948 	Monitor *m;
       
   949 
       
   950 	for(m = mons, i = 0; m && i != n; m = m->next, i++);
       
   951 	return m;
       
   952 }
       
   953 
   990 void
   954 void
   991 initfont(const char *fontstr) {
   955 initfont(const char *fontstr) {
   992 	char *def, **missing;
   956 	char *def, **missing;
   993 	int i, n;
   957 	int i, n;
   994 
   958 
  1114 	updatesizehints(c);
  1078 	updatesizehints(c);
  1115 	XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask);
  1079 	XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask);
  1116 	grabbuttons(c, False);
  1080 	grabbuttons(c, False);
  1117 	updatetitle(c);
  1081 	updatetitle(c);
  1118 	if(XGetTransientForHint(dpy, w, &trans))
  1082 	if(XGetTransientForHint(dpy, w, &trans))
  1119 		t = getclient(trans);
  1083 		t = wintoclient(trans);
  1120 	if(t)
  1084 	if(t)
  1121 		c->tags = t->tags;
  1085 		c->tags = t->tags;
  1122 	else
  1086 	else
  1123 		applyrules(c);
  1087 		applyrules(c);
  1124 	if(!c->isfloating)
  1088 	if(!c->isfloating)
  1149 
  1113 
  1150 	if(!XGetWindowAttributes(dpy, ev->window, &wa))
  1114 	if(!XGetWindowAttributes(dpy, ev->window, &wa))
  1151 		return;
  1115 		return;
  1152 	if(wa.override_redirect)
  1116 	if(wa.override_redirect)
  1153 		return;
  1117 		return;
  1154 	if(!getclient(ev->window))
  1118 	if(!wintoclient(ev->window))
  1155 		manage(ev->window, &wa);
  1119 		manage(ev->window, &wa);
  1156 }
  1120 }
  1157 
  1121 
  1158 void
  1122 void
  1159 monocle(Monitor *m) {
  1123 monocle(Monitor *m) {
  1210 			break;
  1174 			break;
  1211 		}
  1175 		}
  1212 	}
  1176 	}
  1213 	while(ev.type != ButtonRelease);
  1177 	while(ev.type != ButtonRelease);
  1214 	XUngrabPointer(dpy, CurrentTime);
  1178 	XUngrabPointer(dpy, CurrentTime);
  1215 	if((m = getmonxy(c->x + c->w / 2, c->y + c->h / 2)) != selmon) {
  1179 	if((m = pointertomon(c->x + c->w / 2, c->y + c->h / 2)) != selmon) {
  1216 		sendmon(c, m);
  1180 		sendmon(c, m);
  1217 		selmon = m;
  1181 		selmon = m;
  1218 		focus(NULL);
  1182 		focus(NULL);
  1219 	}
  1183 	}
  1220 }
  1184 }
  1223 nexttiled(Client *c) {
  1187 nexttiled(Client *c) {
  1224 	for(; c && (c->isfloating || !ISVISIBLE(c)); c = c->next);
  1188 	for(; c && (c->isfloating || !ISVISIBLE(c)); c = c->next);
  1225 	return c;
  1189 	return c;
  1226 }
  1190 }
  1227 
  1191 
       
  1192 Monitor *
       
  1193 pointertomon(int x, int y) {
       
  1194 	Monitor *m;
       
  1195 
       
  1196 	for(m = mons; m; m = m->next)
       
  1197 		if(INRECT(x, y, m->wx, m->wy, m->ww, m->wh))
       
  1198 			return m;
       
  1199 	return mons;
       
  1200 }
       
  1201 
  1228 void
  1202 void
  1229 propertynotify(XEvent *e) {
  1203 propertynotify(XEvent *e) {
  1230 	Client *c;
  1204 	Client *c;
  1231 	Window trans;
  1205 	Window trans;
  1232 	XPropertyEvent *ev = &e->xproperty;
  1206 	XPropertyEvent *ev = &e->xproperty;
  1233 
  1207 
  1234 	if((ev->window == root) && (ev->atom == XA_WM_NAME))
  1208 	if((ev->window == root) && (ev->atom == XA_WM_NAME))
  1235 		updatestatus();
  1209 		updatestatus();
  1236 	else if(ev->state == PropertyDelete)
  1210 	else if(ev->state == PropertyDelete)
  1237 		return; /* ignore */
  1211 		return; /* ignore */
  1238 	else if((c = getclient(ev->window))) {
  1212 	else if((c = wintoclient(ev->window))) {
  1239 		switch (ev->atom) {
  1213 		switch (ev->atom) {
  1240 		default: break;
  1214 		default: break;
  1241 		case XA_WM_TRANSIENT_FOR:
  1215 		case XA_WM_TRANSIENT_FOR:
  1242 			XGetTransientForHint(dpy, c->win, &trans);
  1216 			XGetTransientForHint(dpy, c->win, &trans);
  1243 			if(!c->isfloating && (c->isfloating = (getclient(trans) != NULL)))
  1217 			if(!c->isfloating && (c->isfloating = (wintoclient(trans) != NULL)))
  1244 				arrange();
  1218 				arrange();
  1245 			break;
  1219 			break;
  1246 		case XA_WM_NORMAL_HINTS:
  1220 		case XA_WM_NORMAL_HINTS:
  1247 			updatesizehints(c);
  1221 			updatesizehints(c);
  1248 			break;
  1222 			break;
  1322 	}
  1296 	}
  1323 	while(ev.type != ButtonRelease);
  1297 	while(ev.type != ButtonRelease);
  1324 	XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1);
  1298 	XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1);
  1325 	XUngrabPointer(dpy, CurrentTime);
  1299 	XUngrabPointer(dpy, CurrentTime);
  1326 	while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
  1300 	while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
  1327 	if((m = getmonxy(c->x + c->w / 2, c->y + c->h / 2)) != selmon) {
  1301 	if((m = pointertomon(c->x + c->w / 2, c->y + c->h / 2)) != selmon) {
  1328 		sendmon(c, m);
  1302 		sendmon(c, m);
  1329 		selmon = m;
  1303 		selmon = m;
  1330 		focus(NULL);
  1304 		focus(NULL);
  1331 	}
  1305 	}
  1332 }
  1306 }
  1555 #ifdef XINERAMA
  1529 #ifdef XINERAMA
  1556 void
  1530 void
  1557 tagmon(const Arg *arg) {
  1531 tagmon(const Arg *arg) {
  1558 	Monitor *m;
  1532 	Monitor *m;
  1559 
  1533 
  1560 	if(!selmon->sel || !(m = getmonn(arg->ui)))
  1534 	if(!selmon->sel || !(m = idxtomon(arg->ui)))
  1561 		return;
  1535 		return;
  1562 	sendmon(selmon->sel, m);
  1536 	sendmon(selmon->sel, m);
  1563 }
  1537 }
  1564 #endif /* XINERAMA */
  1538 #endif /* XINERAMA */
  1565 
  1539 
  1668 	XGrabServer(dpy);
  1642 	XGrabServer(dpy);
  1669 	XSetErrorHandler(xerrordummy);
  1643 	XSetErrorHandler(xerrordummy);
  1670 	XConfigureWindow(dpy, c->win, CWBorderWidth, &wc); /* restore border */
  1644 	XConfigureWindow(dpy, c->win, CWBorderWidth, &wc); /* restore border */
  1671 	detach(c);
  1645 	detach(c);
  1672 	detachstack(c);
  1646 	detachstack(c);
  1673 	if(c->mon->sel == c) {
       
  1674 		/* TODO: consider separate the next code into a function or into detachstack? */
       
  1675 		Client *tc;
       
  1676 		for(tc = c->mon->stack; tc && !ISVISIBLE(tc); tc = tc->snext);
       
  1677 		c->mon->sel = tc;
       
  1678 		focus(NULL);
       
  1679 	}
       
  1680 	XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
  1647 	XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
  1681 	setclientstate(c, WithdrawnState);
  1648 	setclientstate(c, WithdrawnState);
  1682 	free(c);
  1649 	free(c);
  1683 	XSync(dpy, False);
  1650 	XSync(dpy, False);
  1684 	XSetErrorHandler(xerror);
  1651 	XSetErrorHandler(xerror);
  1685 	XUngrabServer(dpy);
  1652 	XUngrabServer(dpy);
       
  1653 	focus(NULL);
  1686 	arrange();
  1654 	arrange();
  1687 }
  1655 }
  1688 
  1656 
  1689 void
  1657 void
  1690 unmapnotify(XEvent *e) {
  1658 unmapnotify(XEvent *e) {
  1691 	Client *c;
  1659 	Client *c;
  1692 	XUnmapEvent *ev = &e->xunmap;
  1660 	XUnmapEvent *ev = &e->xunmap;
  1693 
  1661 
  1694 	if((c = getclient(ev->window)))
  1662 	if((c = wintoclient(ev->window)))
  1695 		unmanage(c);
  1663 		unmanage(c);
  1696 }
  1664 }
  1697 
  1665 
  1698 void
  1666 void
  1699 updatebars(void) {
  1667 updatebars(void) {
  1731 updategeom(void) {
  1699 updategeom(void) {
  1732 	int i, n = 1;
  1700 	int i, n = 1;
  1733 	Client *c;
  1701 	Client *c;
  1734 	Monitor *newmons = NULL, *m, *tm;
  1702 	Monitor *newmons = NULL, *m, *tm;
  1735 
  1703 
  1736 #ifdef XINULATOR
  1704 #ifdef XINERAMA
  1737 	n = 2;
       
  1738 #elif defined(XINERAMA)
       
  1739 	XineramaScreenInfo *info = NULL;
  1705 	XineramaScreenInfo *info = NULL;
  1740 
  1706 
  1741 	if(XineramaIsActive(dpy))
  1707 	if(XineramaIsActive(dpy))
  1742 		info = XineramaQueryScreens(dpy, &n);
  1708 		info = XineramaQueryScreens(dpy, &n);
  1743 #endif
  1709 #endif /* XINERAMA */
  1744 	/* allocate monitor(s) for the new geometry setup */
  1710 	/* allocate monitor(s) for the new geometry setup */
  1745 	for(i = 0; i < n; i++) {
  1711 	for(i = 0; i < n; i++) {
  1746 		m = (Monitor *)malloc(sizeof(Monitor));
  1712 		m = (Monitor *)malloc(sizeof(Monitor));
  1747 		m->next = newmons;
  1713 		m->next = newmons;
  1748 		newmons = m;
  1714 		newmons = m;
  1749 	}
  1715 	}
  1750 
  1716 
  1751 	/* initialise monitor(s) */
  1717 	/* initialise monitor(s) */
  1752 #ifdef XINULATOR
  1718 #ifdef XINERAMA
  1753 	if(1) {
       
  1754 		m = newmons;
       
  1755 		m->screen_number = 0;
       
  1756 		m->wx = sx;
       
  1757 		m->my = m->wy = sy;
       
  1758 		m->ww = sw;
       
  1759 		m->mh = m->wh = sh / 2;
       
  1760 		m = newmons->next;
       
  1761 		m->screen_number = 1;
       
  1762 		m->wx = sx;
       
  1763 		m->my = m->wy = sy + sh / 2;
       
  1764 		m->ww = sw;
       
  1765 		m->mh = m->wh = sh / 2;
       
  1766 	}
       
  1767 	else
       
  1768 #elif defined(XINERAMA)
       
  1769 	if(XineramaIsActive(dpy)) {
  1719 	if(XineramaIsActive(dpy)) {
  1770 		for(i = 0, m = newmons; m; m = m->next, i++) {
  1720 		for(i = 0, m = newmons; m; m = m->next, i++) {
  1771 			m->screen_number = info[i].screen_number;
  1721 			m->screen_number = info[i].screen_number;
  1772 			m->mx = m->wx = info[i].x_org;
  1722 			m->mx = m->wx = info[i].x_org;
  1773 			m->my = m->wy = info[i].y_org;
  1723 			m->my = m->wy = info[i].y_org;
  1775 			m->mh = m->wh = info[i].height;
  1725 			m->mh = m->wh = info[i].height;
  1776 		}
  1726 		}
  1777 		XFree(info);
  1727 		XFree(info);
  1778 	}
  1728 	}
  1779 	else
  1729 	else
  1780 #endif
  1730 #endif /* XINERAMA */
  1781 	/* default monitor setup */
  1731 	/* default monitor setup */
  1782 	{
  1732 	{
  1783 		m->screen_number = 0;
  1733 		m->screen_number = 0;
  1784 		m->wx = sx;
  1734 		m->wx = sx;
  1785 		m->my = m->wy = sy;
  1735 		m->my = m->wy = sy;
  1787 		m->mh = m->wh = sh;
  1737 		m->mh = m->wh = sh;
  1788 	}
  1738 	}
  1789 
  1739 
  1790 	/* bar geometry setup */
  1740 	/* bar geometry setup */
  1791 	for(m = newmons; m; m = m->next) {
  1741 	for(m = newmons; m; m = m->next) {
  1792 		/* TODO: consider removing the following values from config.h */
  1742 		m->sel = m->stack = m->clients = NULL;
  1793 		m->clients = NULL;
       
  1794 		m->sel = NULL;
       
  1795 		m->stack = NULL;
       
  1796 		m->seltags = 0;
  1743 		m->seltags = 0;
  1797 		m->sellt = 0;
  1744 		m->sellt = 0;
  1798 		m->tagset[0] = m->tagset[1] = 1;
  1745 		m->tagset[0] = m->tagset[1] = 1;
  1799 		m->mfact = mfact;
  1746 		m->mfact = mfact;
  1800 		m->showbar = showbar;
  1747 		m->showbar = SHOWBAR;
  1801 		m->topbar = topbar;
  1748 		m->topbar = TOPBAR;
  1802 		updatebarpos(m);
  1749 		updatebarpos(m);
  1803 	}
  1750 	}
  1804 
  1751 
  1805 	/* reassign left over clients of disappeared monitors */
  1752 	/* reassign left over clients of disappeared monitors */
  1806 	for(tm = mons; tm; tm = tm->next)
  1753 	for(tm = mons; tm; tm = tm->next)
  1814 		}
  1761 		}
  1815 
  1762 
  1816 	/* select focused monitor */
  1763 	/* select focused monitor */
  1817 	cleanupmons();
  1764 	cleanupmons();
  1818 	mons = newmons;
  1765 	mons = newmons;
  1819 	selmon = getmon(root);
  1766 	selmon = wintomon(root);
  1820 }
  1767 }
  1821 
  1768 
  1822 void
  1769 void
  1823 updatenumlockmask(void) {
  1770 updatenumlockmask(void) {
  1824 	unsigned int i, j;
  1771 	unsigned int i, j;
  1919 		return;
  1866 		return;
  1920 	selmon->seltags ^= 1; /* toggle sel tagset */
  1867 	selmon->seltags ^= 1; /* toggle sel tagset */
  1921 	if(arg->ui & TAGMASK)
  1868 	if(arg->ui & TAGMASK)
  1922 		selmon->tagset[selmon->seltags] = arg->ui & TAGMASK;
  1869 		selmon->tagset[selmon->seltags] = arg->ui & TAGMASK;
  1923 	arrange();
  1870 	arrange();
       
  1871 }
       
  1872 
       
  1873 Client *
       
  1874 wintoclient(Window w) {
       
  1875 	Client *c;
       
  1876 	Monitor *m;
       
  1877 
       
  1878 	for(m = mons; m; m = m->next)
       
  1879 		for(c = m->clients; c; c = c->next)
       
  1880 			if(c->win == w)
       
  1881 				return c;
       
  1882 	return NULL;
       
  1883 }
       
  1884 
       
  1885 Monitor *
       
  1886 wintomon(Window w) {
       
  1887 	int x, y;
       
  1888 	Client *c;
       
  1889 	Monitor *m;
       
  1890 
       
  1891 	if(w == root && getrootpointer(&x, &y))
       
  1892 		return pointertomon(x, y);
       
  1893 	for(m = mons; m; m = m->next)
       
  1894 		if(w == m->barwin)
       
  1895 			return m;
       
  1896 	if((c = wintoclient(w)))
       
  1897 		return c->mon;
       
  1898 	return mons;
  1924 }
  1899 }
  1925 
  1900 
  1926 /* There's no way to check accesses to destroyed windows, thus those cases are
  1901 /* There's no way to check accesses to destroyed windows, thus those cases are
  1927  * ignored (especially on UnmapNotify's).  Other types of errors call Xlibs
  1902  * ignored (especially on UnmapNotify's).  Other types of errors call Xlibs
  1928  * default error handler, which may call exit.  */
  1903  * default error handler, which may call exit.  */