dwm.c
changeset 1104 167446962e09
parent 1103 94af6c83cad2
child 1106 084b17f96d9b
equal deleted inserted replaced
1103:94af6c83cad2 1104:167446962e09
   104 	void (*arrange)(View *);
   104 	void (*arrange)(View *);
   105 } Layout;
   105 } Layout;
   106 
   106 
   107 typedef struct {
   107 typedef struct {
   108 	const char *prop;
   108 	const char *prop;
   109 	const char *tags;
   109 	const char *tag;
   110 	Bool isfloating;
   110 	Bool isfloating;
   111 } Rule;
   111 } Rule;
   112 
       
   113 typedef struct {
       
   114 	regex_t *propregex;
       
   115 	regex_t *tagregex;
       
   116 } Regs;
       
   117 
   112 
   118 struct View {
   113 struct View {
   119 	int id;
   114 	int id;
   120 	int x, y, w, h, wax, way, wah, waw;
   115 	int x, y, w, h, wax, way, wah, waw;
   121 	double mwfact;
   116 	double mwfact;
   130 void attachstack(Client *c);
   125 void attachstack(Client *c);
   131 void ban(Client *c);
   126 void ban(Client *c);
   132 void buttonpress(XEvent *e);
   127 void buttonpress(XEvent *e);
   133 void checkotherwm(void);
   128 void checkotherwm(void);
   134 void cleanup(void);
   129 void cleanup(void);
   135 void compileregs(void);
       
   136 void configure(Client *c);
   130 void configure(Client *c);
   137 void configurenotify(XEvent *e);
   131 void configurenotify(XEvent *e);
   138 void configurerequest(XEvent *e);
   132 void configurerequest(XEvent *e);
   139 void destroynotify(XEvent *e);
   133 void destroynotify(XEvent *e);
   140 void detach(Client *c);
   134 void detach(Client *c);
   208 int xerrorstart(Display *dpy, XErrorEvent *ee);
   202 int xerrorstart(Display *dpy, XErrorEvent *ee);
   209 void zoom(const char *arg);
   203 void zoom(const char *arg);
   210 void selectview(const char *arg);
   204 void selectview(const char *arg);
   211 
   205 
   212 /* variables */
   206 /* variables */
   213 char stext[256];
   207 char stext[256], buf[256];
   214 int nviews = 1;
   208 int nviews = 1;
   215 View *selview;
   209 View *selview;
   216 int screen;
   210 int screen;
   217 int *seltags;
   211 int *seltags;
   218 int *prevtags;
   212 int *prevtags;
   244 Client *sel = NULL;
   238 Client *sel = NULL;
   245 Client *stack = NULL;
   239 Client *stack = NULL;
   246 Cursor cursor[CurLast];
   240 Cursor cursor[CurLast];
   247 Display *dpy;
   241 Display *dpy;
   248 DC dc = {0};
   242 DC dc = {0};
   249 Regs *regs = NULL;
       
   250 View *views;
   243 View *views;
   251 Window root;
   244 Window root;
   252 
   245 
   253 /* configuration, allows nested code to access above variables */
   246 /* configuration, allows nested code to access above variables */
   254 #include "config.h"
   247 #include "config.h"
   255 
   248 
   256 /* function implementations */
   249 /* function implementations */
   257 void
   250 void
   258 applyrules(Client *c) {
   251 applyrules(Client *c) {
   259 	static char buf[512];
   252 	unsigned int i;
   260 	unsigned int i, j;
       
   261 	regmatch_t tmp;
       
   262 	Bool matched_tag = False;
   253 	Bool matched_tag = False;
       
   254 	Rule *r;
   263 	XClassHint ch = { 0 };
   255 	XClassHint ch = { 0 };
   264 
   256 
   265 	/* rule matching */
   257 	/* rule matching */
   266 	XGetClassHint(dpy, c->win, &ch);
   258 	XGetClassHint(dpy, c->win, &ch);
   267 	snprintf(buf, sizeof buf, "%s:%s:%s",
   259 	snprintf(buf, sizeof buf, "%s:%s:%s",
   268 			ch.res_class ? ch.res_class : "",
   260 			ch.res_class ? ch.res_class : "",
   269 			ch.res_name ? ch.res_name : "", c->name);
   261 			ch.res_name ? ch.res_name : "", c->name);
   270 	for(i = 0; i < LENGTH(rules); i++)
   262 	for(i = 0; i < LENGTH(rules); i++) {
   271 		if(regs[i].propregex && !regexec(regs[i].propregex, buf, 1, &tmp, 0)) {
   263 		r = &rules[i];
   272 			c->isfloating = rules[i].isfloating;
   264 		if(strstr(c->name, r->prop)
   273 			for(j = 0; regs[i].tagregex && j < LENGTH(tags); j++) {
   265 		|| (ch.res_class && strstr(ch.res_class, r->prop))
   274 				if(!regexec(regs[i].tagregex, tags[j], 1, &tmp, 0)) {
   266 		|| (ch.res_name && strstr(ch.res_name, r->prop)))
   275 					matched_tag = True;
   267 		{
   276 					c->tags[j] = selview->id;
   268 			c->isfloating = r->isfloating;
   277 				}
   269 			if(r->tag) {
       
   270 				matched_tag = True;
       
   271 				c->tags[idxoftag(r->tag)] = selview->id;
   278 			}
   272 			}
   279 		}
   273 		}
       
   274 	}
   280 	if(ch.res_class)
   275 	if(ch.res_class)
   281 		XFree(ch.res_class);
   276 		XFree(ch.res_class);
   282 	if(ch.res_name)
   277 	if(ch.res_name)
   283 		XFree(ch.res_name);
   278 		XFree(ch.res_name);
   284 	if(!matched_tag)
   279 	if(!matched_tag)
   416 	XFreeCursor(dpy, cursor[CurMove]);
   411 	XFreeCursor(dpy, cursor[CurMove]);
   417 	for(i = 0; i < nviews; i++)
   412 	for(i = 0; i < nviews; i++)
   418 		XDestroyWindow(dpy, views[i].barwin);
   413 		XDestroyWindow(dpy, views[i].barwin);
   419 	XSync(dpy, False);
   414 	XSync(dpy, False);
   420 	XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
   415 	XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
   421 }
       
   422 
       
   423 void
       
   424 compileregs(void) {
       
   425 	unsigned int i;
       
   426 	regex_t *reg;
       
   427 
       
   428 	if(regs)
       
   429 		return;
       
   430 	regs = emallocz(LENGTH(rules) * sizeof(Regs));
       
   431 	for(i = 0; i < LENGTH(rules); i++) {
       
   432 		if(rules[i].prop) {
       
   433 			reg = emallocz(sizeof(regex_t));
       
   434 			if(regcomp(reg, rules[i].prop, REG_EXTENDED))
       
   435 				free(reg);
       
   436 			else
       
   437 				regs[i].propregex = reg;
       
   438 		}
       
   439 		if(rules[i].tags) {
       
   440 			reg = emallocz(sizeof(regex_t));
       
   441 			if(regcomp(reg, rules[i].tags, REG_EXTENDED))
       
   442 				free(reg);
       
   443 			else
       
   444 				regs[i].tagregex = reg;
       
   445 		}
       
   446 	}
       
   447 }
   416 }
   448 
   417 
   449 void
   418 void
   450 configure(Client *c) {
   419 configure(Client *c) {
   451 	XConfigureEvent ce;
   420 	XConfigureEvent ce;
   622 }
   591 }
   623 
   592 
   624 void
   593 void
   625 drawtext(View *v, const char *text, unsigned long col[ColLast], Bool invert) {
   594 drawtext(View *v, const char *text, unsigned long col[ColLast], Bool invert) {
   626 	int x, y, w, h;
   595 	int x, y, w, h;
   627 	static char buf[256];
       
   628 	unsigned int len, olen;
   596 	unsigned int len, olen;
   629 	XRectangle r = { dc.x, dc.y, dc.w, dc.h };
   597 	XRectangle r = { dc.x, dc.y, dc.w, dc.h };
   630 
   598 
   631 	XSetForeground(dpy, dc.gc, col[invert ? ColFG : ColBG]);
   599 	XSetForeground(dpy, dc.gc, col[invert ? ColFG : ColBG]);
   632 	XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1);
   600 	XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1);
  1143 		return;
  1111 		return;
  1144 	if(wa.override_redirect)
  1112 	if(wa.override_redirect)
  1145 		return;
  1113 		return;
  1146 	if(!getclient(ev->window))
  1114 	if(!getclient(ev->window))
  1147 		manage(ev->window, &wa);
  1115 		manage(ev->window, &wa);
  1148 }
       
  1149 
       
  1150 View *
       
  1151 viewat() {
       
  1152 	int i, x, y;
       
  1153 	Window win;
       
  1154 	unsigned int mask;
       
  1155 
       
  1156 	XQueryPointer(dpy, root, &win, &win, &x, &y, &i, &i, &mask);
       
  1157 	for(i = 0; i < nviews; i++) {
       
  1158 		if((x >= views[i].x && x < views[i].x + views[i].w)
       
  1159 		&& (y >= views[i].y && y < views[i].y + views[i].h))
       
  1160 			return &views[i];
       
  1161 	}
       
  1162 	return NULL;
       
  1163 }
  1116 }
  1164 
  1117 
  1165 void
  1118 void
  1166 movemouse(Client *c) {
  1119 movemouse(Client *c) {
  1167 	int x1, y1, ocx, ocy, di, nx, ny;
  1120 	int x1, y1, ocx, ocy, di, nx, ny;
  1404 }
  1357 }
  1405 
  1358 
  1406 void
  1359 void
  1407 run(void) {
  1360 run(void) {
  1408 	char *p;
  1361 	char *p;
  1409 	char buf[sizeof stext];
  1362 	char sbuf[sizeof stext];
  1410 	fd_set rd;
  1363 	fd_set rd;
  1411 	int r, xfd;
  1364 	int r, xfd;
  1412 	unsigned int len, offset;
  1365 	unsigned int len, offset;
  1413 	XEvent ev;
  1366 	XEvent ev;
  1414 
  1367 
  1416 	XSync(dpy, False);
  1369 	XSync(dpy, False);
  1417 	xfd = ConnectionNumber(dpy);
  1370 	xfd = ConnectionNumber(dpy);
  1418 	readin = True;
  1371 	readin = True;
  1419 	offset = 0;
  1372 	offset = 0;
  1420 	len = sizeof stext - 1;
  1373 	len = sizeof stext - 1;
  1421 	buf[len] = stext[len] = '\0'; /* 0-terminator is never touched */
  1374 	sbuf[len] = stext[len] = '\0'; /* 0-terminator is never touched */
  1422 	while(running) {
  1375 	while(running) {
  1423 		FD_ZERO(&rd);
  1376 		FD_ZERO(&rd);
  1424 		if(readin)
  1377 		if(readin)
  1425 			FD_SET(STDIN_FILENO, &rd);
  1378 			FD_SET(STDIN_FILENO, &rd);
  1426 		FD_SET(xfd, &rd);
  1379 		FD_SET(xfd, &rd);
  1428 			if(errno == EINTR)
  1381 			if(errno == EINTR)
  1429 				continue;
  1382 				continue;
  1430 			eprint("select failed\n");
  1383 			eprint("select failed\n");
  1431 		}
  1384 		}
  1432 		if(FD_ISSET(STDIN_FILENO, &rd)) {
  1385 		if(FD_ISSET(STDIN_FILENO, &rd)) {
  1433 			switch((r = read(STDIN_FILENO, buf + offset, len - offset))) {
  1386 			switch((r = read(STDIN_FILENO, sbuf + offset, len - offset))) {
  1434 			case -1:
  1387 			case -1:
  1435 				strncpy(stext, strerror(errno), len);
  1388 				strncpy(stext, strerror(errno), len);
  1436 				readin = False;
  1389 				readin = False;
  1437 				break;
  1390 				break;
  1438 			case 0:
  1391 			case 0:
  1439 				strncpy(stext, "EOF", 4);
  1392 				strncpy(stext, "EOF", 4);
  1440 				readin = False;
  1393 				readin = False;
  1441 				break;
  1394 				break;
  1442 			default:
  1395 			default:
  1443 				for(p = buf + offset; r > 0; p++, r--, offset++)
  1396 				for(p = sbuf + offset; r > 0; p++, r--, offset++)
  1444 					if(*p == '\n' || *p == '\0') {
  1397 					if(*p == '\n' || *p == '\0') {
  1445 						*p = '\0';
  1398 						*p = '\0';
  1446 						strncpy(stext, buf, len);
  1399 						strncpy(stext, sbuf, len);
  1447 						p += r - 1; /* p is buf + offset + r - 1 */
  1400 						p += r - 1; /* p is sbuf + offset + r - 1 */
  1448 						for(r = 0; *(p - r) && *(p - r) != '\n'; r++);
  1401 						for(r = 0; *(p - r) && *(p - r) != '\n'; r++);
  1449 						offset = r;
  1402 						offset = r;
  1450 						if(r)
  1403 						if(r)
  1451 							memmove(buf, p - r + 1, r);
  1404 							memmove(sbuf, p - r + 1, r);
  1452 						break;
  1405 						break;
  1453 					}
  1406 					}
  1454 				break;
  1407 				break;
  1455 			}
  1408 			}
  1456 			drawbar(selview);
  1409 			drawbar(selview);
  1663 	if(info)
  1616 	if(info)
  1664 		XFree(info);
  1617 		XFree(info);
  1665 
  1618 
  1666 	/* grab keys */
  1619 	/* grab keys */
  1667 	grabkeys();
  1620 	grabkeys();
  1668 
       
  1669 	/* init tags */
       
  1670 	compileregs();
       
  1671 
  1621 
  1672 	selview = &views[0];
  1622 	selview = &views[0];
  1673 }
  1623 }
  1674 
  1624 
  1675 void
  1625 void
  1948 		c->isurgent = (wmh->flags & XUrgencyHint) ? True : False;
  1898 		c->isurgent = (wmh->flags & XUrgencyHint) ? True : False;
  1949 		XFree(wmh);
  1899 		XFree(wmh);
  1950 	}
  1900 	}
  1951 }
  1901 }
  1952 
  1902 
       
  1903 void
       
  1904 view(const char *arg) {
       
  1905 	unsigned int i;
       
  1906 	int tmp[LENGTH(tags)];
       
  1907 
       
  1908 	for(i = 0; i < LENGTH(tags); i++)
       
  1909 		tmp[i] = (NULL == arg) ? selview->id : 0;
       
  1910 	tmp[idxoftag(arg)] = selview->id;
       
  1911 	if(memcmp(seltags, tmp, sizeof initags) != 0) {
       
  1912 		memcpy(prevtags, seltags, sizeof initags);
       
  1913 		memcpy(seltags, tmp, sizeof initags);
       
  1914 		arrange();
       
  1915 	}
       
  1916 }
       
  1917 
       
  1918 View *
       
  1919 viewat() {
       
  1920 	int i, x, y;
       
  1921 	Window win;
       
  1922 	unsigned int mask;
       
  1923 
       
  1924 	XQueryPointer(dpy, root, &win, &win, &x, &y, &i, &i, &mask);
       
  1925 	for(i = 0; i < nviews; i++) {
       
  1926 		if((x >= views[i].x && x < views[i].x + views[i].w)
       
  1927 		&& (y >= views[i].y && y < views[i].y + views[i].h))
       
  1928 			return &views[i];
       
  1929 	}
       
  1930 	return NULL;
       
  1931 }
       
  1932 
       
  1933 void
       
  1934 viewprevtag(const char *arg) {
       
  1935 	static Bool tmp[LENGTH(tags)];
       
  1936 
       
  1937 	memcpy(tmp, seltags, sizeof initags);
       
  1938 	memcpy(seltags, prevtags, sizeof initags);
       
  1939 	memcpy(prevtags, tmp, sizeof initags);
       
  1940 	arrange();
       
  1941 }
       
  1942 
  1953 /* There's no way to check accesses to destroyed windows, thus those cases are
  1943 /* There's no way to check accesses to destroyed windows, thus those cases are
  1954  * ignored (especially on UnmapNotify's).  Other types of errors call Xlibs
  1944  * ignored (especially on UnmapNotify's).  Other types of errors call Xlibs
  1955  * default error handler, which may call exit.  */
  1945  * default error handler, which may call exit.  */
  1956 int
  1946 int
  1957 xerror(Display *dpy, XErrorEvent *ee) {
  1947 xerror(Display *dpy, XErrorEvent *ee) {
  1981 	otherwm = True;
  1971 	otherwm = True;
  1982 	return -1;
  1972 	return -1;
  1983 }
  1973 }
  1984 
  1974 
  1985 void
  1975 void
  1986 view(const char *arg) {
       
  1987 	unsigned int i;
       
  1988 	int tmp[LENGTH(tags)];
       
  1989 
       
  1990 	for(i = 0; i < LENGTH(tags); i++)
       
  1991 		tmp[i] = (NULL == arg) ? selview->id : 0;
       
  1992 	tmp[idxoftag(arg)] = selview->id;
       
  1993 	if(memcmp(seltags, tmp, sizeof initags) != 0) {
       
  1994 		memcpy(prevtags, seltags, sizeof initags);
       
  1995 		memcpy(seltags, tmp, sizeof initags);
       
  1996 		arrange();
       
  1997 	}
       
  1998 }
       
  1999 
       
  2000 void
       
  2001 viewprevtag(const char *arg) {
       
  2002 	static Bool tmp[LENGTH(tags)];
       
  2003 
       
  2004 	memcpy(tmp, seltags, sizeof initags);
       
  2005 	memcpy(seltags, prevtags, sizeof initags);
       
  2006 	memcpy(prevtags, tmp, sizeof initags);
       
  2007 	arrange();
       
  2008 }
       
  2009 
       
  2010 void
       
  2011 zoom(const char *arg) {
  1976 zoom(const char *arg) {
  2012 	Client *c = sel;
  1977 	Client *c = sel;
  2013 
  1978 
  2014 	if(!sel || !dozoom || sel->isfloating)
  1979 	if(!sel || !dozoom || sel->isfloating)
  2015 		return;
  1980 		return;
  2020 	attach(c);
  1985 	attach(c);
  2021 	focus(c);
  1986 	focus(c);
  2022 	arrange();
  1987 	arrange();
  2023 }
  1988 }
  2024 
  1989 
  2025 void
       
  2026 selectview(const char *arg) {
       
  2027 	int i;
       
  2028 	View *v;
       
  2029 
       
  2030 	if(!arg)
       
  2031 		return;
       
  2032 	if(arg)
       
  2033 		i = atoi(arg);
       
  2034 	v = &views[i % nviews];
       
  2035 	XWarpPointer(dpy, None, root, 0, 0, 0, 0, v->wax+v->waw/2, v->way+v->wah/2);
       
  2036 	focus(NULL);
       
  2037 }
       
  2038 
       
  2039 
       
  2040 int
  1990 int
  2041 main(int argc, char *argv[]) {
  1991 main(int argc, char *argv[]) {
  2042 	if(argc == 2 && !strcmp("-v", argv[1]))
  1992 	if(argc == 2 && !strcmp("-v", argv[1]))
  2043 		eprint("dwm-"VERSION", © 2006-2008 dwm engineers, see LICENSE for details\n");
  1993 		eprint("dwm-"VERSION", © 2006-2008 dwm engineers, see LICENSE for details\n");
  2044 	else if(argc != 1)
  1994 	else if(argc != 1)