dwm.c
changeset 1425 120ed5f8018b
parent 1424 499cb1ee2b93
child 1426 f8ee1d055e66
equal deleted inserted replaced
1424:499cb1ee2b93 1425:120ed5f8018b
   164 static void destroynotify(XEvent *e);
   164 static void destroynotify(XEvent *e);
   165 static void detach(Client *c);
   165 static void detach(Client *c);
   166 static void detachstack(Client *c);
   166 static void detachstack(Client *c);
   167 static void die(const char *errstr, ...);
   167 static void die(const char *errstr, ...);
   168 static void drawbar(Monitor *m);
   168 static void drawbar(Monitor *m);
   169 static void drawbars();
   169 static void drawbars(void);
   170 static void drawsquare(Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]);
   170 static void drawsquare(Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]);
   171 static void drawtext(const char *text, unsigned long col[ColLast], Bool invert);
   171 static void drawtext(const char *text, unsigned long col[ColLast], Bool invert);
   172 static void enternotify(XEvent *e);
   172 static void enternotify(XEvent *e);
   173 static void expose(XEvent *e);
   173 static void expose(XEvent *e);
   174 static void focus(Client *c);
   174 static void focus(Client *c);
   175 static void focusin(XEvent *e);
   175 static void focusin(XEvent *e);
   176 static void focusstack(const Arg *arg);
   176 static void focusstack(const Arg *arg);
   177 static Client *getclient(Window w);
   177 static Client *getclient(Window w);
   178 static unsigned long getcolor(const char *colstr);
   178 static unsigned long getcolor(const char *colstr);
       
   179 static Monitor *getmonitor(Window w);
       
   180 static Monitor *getmonitorxy(int x, int y);
       
   181 static Bool getrootpointer(int *x, int *y);
   179 static long getstate(Window w);
   182 static long getstate(Window w);
   180 static Bool gettextprop(Window w, Atom atom, char *text, unsigned int size);
   183 static Bool gettextprop(Window w, Atom atom, char *text, unsigned int size);
   181 static void grabbuttons(Client *c, Bool focused);
   184 static void grabbuttons(Client *c, Bool focused);
   182 static void grabkeys(void);
   185 static void grabkeys(void);
   183 static void initfont(const char *fontstr);
   186 static void initfont(const char *fontstr);
   195 static void resize(Client *c, int x, int y, int w, int h);
   198 static void resize(Client *c, int x, int y, int w, int h);
   196 static void resizemouse(const Arg *arg);
   199 static void resizemouse(const Arg *arg);
   197 static void restack(Monitor *m);
   200 static void restack(Monitor *m);
   198 static void run(void);
   201 static void run(void);
   199 static void scan(void);
   202 static void scan(void);
       
   203 static void sendmon(Client *c, Monitor *m);
   200 static void setclientstate(Client *c, long state);
   204 static void setclientstate(Client *c, long state);
   201 static void setlayout(const Arg *arg);
   205 static void setlayout(const Arg *arg);
   202 static void setmfact(const Arg *arg);
   206 static void setmfact(const Arg *arg);
   203 static void setup(void);
   207 static void setup(void);
   204 static void showhide(Client *c);
   208 static void showhide(Client *c);
   395 	Monitor *m;
   399 	Monitor *m;
   396 	XButtonPressedEvent *ev = &e->xbutton;
   400 	XButtonPressedEvent *ev = &e->xbutton;
   397 
   401 
   398 	click = ClkRootWin;
   402 	click = ClkRootWin;
   399 	/* focus monitor if necessary */
   403 	/* focus monitor if necessary */
   400 	for(m = mons; m; m = m->next)
   404 	if((m = getmonitor(ev->window)) && m != selmon) {
   401 		if(ev->window == m->barwin) {
   405 		unfocus(selmon->sel);
   402 			if(m != selmon) {
   406 		selmon = m;
   403 				unfocus(selmon->stack);
   407 		focus(NULL);
   404 				selmon = m;
   408 	}
   405 				focus(NULL);
       
   406 			}
       
   407 			break;
       
   408 		}
       
   409 	if(ev->window == selmon->barwin && ev->x >= selmon->btx) {
   409 	if(ev->window == selmon->barwin && ev->x >= selmon->btx) {
   410 		i = 0;
   410 		i = 0;
   411 		x = selmon->btx;
   411 		x = selmon->btx;
   412 		do
   412 		do
   413 			x += TEXTW(tags[i]);
   413 			x += TEXTW(tags[i]);
   681 	XCopyArea(dpy, dc.drawable, m->barwin, dc.gc, 0, 0, m->ww, bh, 0, 0);
   681 	XCopyArea(dpy, dc.drawable, m->barwin, dc.gc, 0, 0, m->ww, bh, 0, 0);
   682 	XSync(dpy, False);
   682 	XSync(dpy, False);
   683 }
   683 }
   684 
   684 
   685 void
   685 void
   686 drawbars() {
   686 drawbars(void) {
   687 	Monitor *m;
   687 	Monitor *m;
   688 
   688 
   689 	for(m = mons; m; m = m->next)
   689 	for(m = mons; m; m = m->next)
   690 		drawbar(m);
   690 		drawbar(m);
   691 }
   691 }
   740 }
   740 }
   741 
   741 
   742 void
   742 void
   743 enternotify(XEvent *e) {
   743 enternotify(XEvent *e) {
   744 	Client *c;
   744 	Client *c;
       
   745 	Monitor *m;
   745 	XCrossingEvent *ev = &e->xcrossing;
   746 	XCrossingEvent *ev = &e->xcrossing;
   746 
   747 
   747 	if((ev->mode != NotifyNormal || ev->detail == NotifyInferior) && ev->window != root)
   748 	if((ev->mode != NotifyNormal || ev->detail == NotifyInferior) && ev->window != root)
   748 		return;
   749 		return;
       
   750 	if((m = getmonitor(ev->window)) && m != selmon) {
       
   751 		unfocus(selmon->sel);
       
   752 		selmon = m;
       
   753 	}
   749 	if((c = getclient(ev->window)))
   754 	if((c = getclient(ev->window)))
   750 		focus(c);
   755 		focus(c);
   751 	else
   756 	else
   752 		focus(NULL);
   757 		focus(NULL);
   753 }
   758 }
   755 void
   760 void
   756 expose(XEvent *e) {
   761 expose(XEvent *e) {
   757 	Monitor *m;
   762 	Monitor *m;
   758 	XExposeEvent *ev = &e->xexpose;
   763 	XExposeEvent *ev = &e->xexpose;
   759 
   764 
   760 	if(ev->count == 0)
   765 	if(ev->count == 0 && (m = getmonitor(ev->window)))
   761 		for(m = mons; m; m = m->next)
   766 		drawbar(m);
   762 			if(ev->window == m->barwin) {
       
   763 				drawbar(m);
       
   764 				break;
       
   765 			}
       
   766 }
   767 }
   767 
   768 
   768 void
   769 void
   769 focus(Client *c) {
   770 focus(Client *c) {
   770 	if(!c || !ISVISIBLE(c))
   771 	if(!c || !ISVISIBLE(c))
   807 			if(m == selmon)
   808 			if(m == selmon)
   808 				return;
   809 				return;
   809 			unfocus(selmon->sel);
   810 			unfocus(selmon->sel);
   810 			selmon = m;
   811 			selmon = m;
   811 			focus(NULL);
   812 			focus(NULL);
   812 			drawbars();
       
   813 			break;
   813 			break;
   814 		}
   814 		}
   815 }
   815 }
   816 #endif /* XINERAMA */
   816 #endif /* XINERAMA */
   817 
   817 
   859 	XColor color;
   859 	XColor color;
   860 
   860 
   861 	if(!XAllocNamedColor(dpy, cmap, colstr, &color, &color))
   861 	if(!XAllocNamedColor(dpy, cmap, colstr, &color, &color))
   862 		die("error, cannot allocate color '%s'\n", colstr);
   862 		die("error, cannot allocate color '%s'\n", colstr);
   863 	return color.pixel;
   863 	return color.pixel;
       
   864 }
       
   865 
       
   866 Monitor *
       
   867 getmonitor(Window w) {
       
   868 	int x, y;
       
   869 	Client *c;
       
   870 	Monitor *m;
       
   871 
       
   872 	if(w == root && getrootpointer(&x, &y))
       
   873 		return getmonitorxy(x, y);
       
   874 	for(m = mons; m; m = m->next)
       
   875 		if(w == m->barwin)
       
   876 			return m;
       
   877 	if((c = getclient(w)))
       
   878 		return c->mon;
       
   879 	return NULL;
       
   880 }
       
   881 
       
   882 Monitor *
       
   883 getmonitorxy(int x, int y) {
       
   884 	Monitor *m;
       
   885 
       
   886 	for(m = mons; m; m = m->next)
       
   887 		if(INRECT(x, y, m->wx, m->wy, m->ww, m->wh))
       
   888 			return m;
       
   889 	return NULL;
       
   890 }
       
   891 
       
   892 Bool
       
   893 getrootpointer(int *x, int *y) {
       
   894 	int di;
       
   895 	unsigned int dui;
       
   896 	Window dummy;
       
   897 	return XQueryPointer(dpy, root, &dummy, &dummy, x, y, &di, &di, &dui);
   864 }
   898 }
   865 
   899 
   866 long
   900 long
   867 getstate(Window w) {
   901 getstate(Window w) {
   868 	int format, status;
   902 	int format, status;
  1122 		resize(c, m->wx, m->wy, m->ww - 2 * c->bw, m->wh - 2 * c->bw);
  1156 		resize(c, m->wx, m->wy, m->ww - 2 * c->bw, m->wh - 2 * c->bw);
  1123 }
  1157 }
  1124 
  1158 
  1125 void
  1159 void
  1126 movemouse(const Arg *arg) {
  1160 movemouse(const Arg *arg) {
  1127 	int x, y, ocx, ocy, di, nx, ny;
  1161 	int x, y, ocx, ocy, nx, ny;
  1128 	unsigned int dui;
       
  1129 	Client *c;
  1162 	Client *c;
  1130 	Window dummy;
  1163 	Monitor *m;
  1131 	XEvent ev;
  1164 	XEvent ev;
  1132 
  1165 
  1133 	if(!(c = selmon->sel))
  1166 	if(!(c = selmon->sel))
  1134 		return;
  1167 		return;
  1135 	restack(selmon);
  1168 	restack(selmon);
  1136 	ocx = c->x;
  1169 	ocx = c->x;
  1137 	ocy = c->y;
  1170 	ocy = c->y;
  1138 	if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
  1171 	if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
  1139 	None, cursor[CurMove], CurrentTime) != GrabSuccess)
  1172 	None, cursor[CurMove], CurrentTime) != GrabSuccess)
  1140 		return;
  1173 		return;
  1141 	XQueryPointer(dpy, root, &dummy, &dummy, &x, &y, &di, &di, &dui);
  1174 	if(!getrootpointer(&x, &y))
       
  1175 		return;
  1142 	do {
  1176 	do {
  1143 		XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev);
  1177 		XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev);
  1144 		switch (ev.type) {
  1178 		switch (ev.type) {
  1145 		case ConfigureRequest:
  1179 		case ConfigureRequest:
  1146 		case Expose:
  1180 		case Expose:
  1169 			break;
  1203 			break;
  1170 		}
  1204 		}
  1171 	}
  1205 	}
  1172 	while(ev.type != ButtonRelease);
  1206 	while(ev.type != ButtonRelease);
  1173 	XUngrabPointer(dpy, CurrentTime);
  1207 	XUngrabPointer(dpy, CurrentTime);
       
  1208 	if((m = getmonitorxy(c->x + c->w / 2, c->y + c->h / 2)) != selmon)
       
  1209 		sendmon(c, m);
  1174 }
  1210 }
  1175 
  1211 
  1176 Client *
  1212 Client *
  1177 nexttiled(Client *c) {
  1213 nexttiled(Client *c) {
  1178 	for(; c && (c->isfloating || !ISVISIBLE(c)); c = c->next);
  1214 	for(; c && (c->isfloating || !ISVISIBLE(c)); c = c->next);
  1237 void
  1273 void
  1238 resizemouse(const Arg *arg) {
  1274 resizemouse(const Arg *arg) {
  1239 	int ocx, ocy;
  1275 	int ocx, ocy;
  1240 	int nw, nh;
  1276 	int nw, nh;
  1241 	Client *c;
  1277 	Client *c;
       
  1278 	Monitor *m;
  1242 	XEvent ev;
  1279 	XEvent ev;
  1243 
  1280 
  1244 	if(!(c = selmon->sel))
  1281 	if(!(c = selmon->sel))
  1245 		return;
  1282 		return;
  1246 	restack(selmon);
  1283 	restack(selmon);
  1275 	}
  1312 	}
  1276 	while(ev.type != ButtonRelease);
  1313 	while(ev.type != ButtonRelease);
  1277 	XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1);
  1314 	XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1);
  1278 	XUngrabPointer(dpy, CurrentTime);
  1315 	XUngrabPointer(dpy, CurrentTime);
  1279 	while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
  1316 	while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
       
  1317 	if((m = getmonitorxy(c->x + c->w / 2, c->y + c->h / 2)) != selmon)
       
  1318 		sendmon(c, m);
  1280 }
  1319 }
  1281 
  1320 
  1282 void
  1321 void
  1283 restack(Monitor *m) {
  1322 restack(Monitor *m) {
  1284 	Client *c;
  1323 	Client *c;
  1337 				manage(wins[i], &wa);
  1376 				manage(wins[i], &wa);
  1338 		}
  1377 		}
  1339 		if(wins)
  1378 		if(wins)
  1340 			XFree(wins);
  1379 			XFree(wins);
  1341 	}
  1380 	}
       
  1381 }
       
  1382 
       
  1383 void
       
  1384 sendmon(Client *c, Monitor *m) {
       
  1385 	if(c->mon == m)
       
  1386 		return;
       
  1387 	detach(c);
       
  1388 	detachstack(c);
       
  1389 	c->mon = m;
       
  1390 	c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */
       
  1391 	attach(c);
       
  1392 	attachstack(c);
       
  1393 	focus(NULL);
       
  1394 	arrange();
  1342 }
  1395 }
  1343 
  1396 
  1344 void
  1397 void
  1345 setclientstate(Client *c, long state) {
  1398 setclientstate(Client *c, long state) {
  1346 	long data[] = {state, None};
  1399 	long data[] = {state, None};
  1495 
  1548 
  1496 	if(!(c = selmon->sel))
  1549 	if(!(c = selmon->sel))
  1497 		return;
  1550 		return;
  1498 	for(i = 0, m = mons; m; m = m->next, i++)
  1551 	for(i = 0, m = mons; m; m = m->next, i++)
  1499 		if(i == arg->ui) {
  1552 		if(i == arg->ui) {
  1500 			detach(c);
  1553 			sendmon(c, m);
  1501 			detachstack(c);
       
  1502 			c->mon = m;
       
  1503 			c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */
       
  1504 			attach(c);
       
  1505 			attachstack(c);
       
  1506 			focus(NULL);
       
  1507 			arrange();
       
  1508 			break;
  1554 			break;
  1509 		}
  1555 		}
  1510 }
  1556 }
  1511 #endif /* XINERAMA */
  1557 #endif /* XINERAMA */
  1512 
  1558 
  1674 		m->by = -bh;
  1720 		m->by = -bh;
  1675 }
  1721 }
  1676 
  1722 
  1677 void
  1723 void
  1678 updategeom(void) {
  1724 updategeom(void) {
  1679 	int i, di, n = 1, x, y;
  1725 	int i, n = 1;
  1680 	unsigned int dui;
       
  1681 	Client *c;
  1726 	Client *c;
  1682 	Monitor *newmons = NULL, *m, *tm;
  1727 	Monitor *newmons = NULL, *m, *tm;
  1683 	Window dummy;
       
  1684 
  1728 
  1685 #ifdef XINULATOR
  1729 #ifdef XINULATOR
  1686 	n = 2;
  1730 	n = 2;
  1687 #elif defined(XINERAMA)
  1731 #elif defined(XINERAMA)
  1688 	XineramaScreenInfo *info = NULL;
  1732 	XineramaScreenInfo *info = NULL;
  1761 			attach(c);
  1805 			attach(c);
  1762 			attachstack(c);
  1806 			attachstack(c);
  1763 		}
  1807 		}
  1764 
  1808 
  1765 	/* select focused monitor */
  1809 	/* select focused monitor */
  1766 	selmon = newmons;
       
  1767 	if(XQueryPointer(dpy, root, &dummy, &dummy, &x, &y, &di, &di, &dui)) 
       
  1768 		for(m = newmons; m; m = m->next)
       
  1769 			if(INRECT(x, y, m->wx, m->wy, m->ww, m->wh)) {
       
  1770 				selmon = m;
       
  1771 				break;
       
  1772 			}
       
  1773 
       
  1774 	/* final assignment of new monitors */
       
  1775 	cleanupmons();
  1810 	cleanupmons();
  1776 	mons = newmons;
  1811 	mons = newmons;
       
  1812 	selmon = getmonitor(root);
  1777 }
  1813 }
  1778 
  1814 
  1779 void
  1815 void
  1780 updatenumlockmask(void) {
  1816 updatenumlockmask(void) {
  1781 	unsigned int i, j;
  1817 	unsigned int i, j;
  1846 	if(!gettextprop(c->win, netatom[NetWMName], c->name, sizeof c->name))
  1882 	if(!gettextprop(c->win, netatom[NetWMName], c->name, sizeof c->name))
  1847 		gettextprop(c->win, XA_WM_NAME, c->name, sizeof c->name);
  1883 		gettextprop(c->win, XA_WM_NAME, c->name, sizeof c->name);
  1848 }
  1884 }
  1849 
  1885 
  1850 void
  1886 void
  1851 updatestatus() {
  1887 updatestatus(void) {
  1852 	if(!gettextprop(root, XA_WM_NAME, stext, sizeof(stext)))
  1888 	if(!gettextprop(root, XA_WM_NAME, stext, sizeof(stext)))
  1853 		strcpy(stext, "dwm-"VERSION);
  1889 		strcpy(stext, "dwm-"VERSION);
  1854 	drawbar(selmon);
  1890 	drawbar(selmon);
  1855 }
  1891 }
  1856 
  1892