dwm.c
changeset 1047 ef0b927bf16c
parent 1046 74aca4c70765
child 1048 98fc0d3c583a
equal deleted inserted replaced
1046:74aca4c70765 1047:ef0b927bf16c
   143 long getstate(Window w);
   143 long getstate(Window w);
   144 Bool gettextprop(Window w, Atom atom, char *text, unsigned int size);
   144 Bool gettextprop(Window w, Atom atom, char *text, unsigned int size);
   145 void grabbuttons(Client *c, Bool focused);
   145 void grabbuttons(Client *c, Bool focused);
   146 unsigned int idxoftag(const char *tag);
   146 unsigned int idxoftag(const char *tag);
   147 void initfont(const char *fontstr);
   147 void initfont(const char *fontstr);
   148 Bool isarrange(void (*func)());
       
   149 Bool isoccupied(unsigned int t);
   148 Bool isoccupied(unsigned int t);
   150 Bool isprotodel(Client *c);
   149 Bool isprotodel(Client *c);
   151 Bool isvisible(Client *c);
   150 Bool isvisible(Client *c);
   152 void keypress(XEvent *e);
   151 void keypress(XEvent *e);
   153 void killclient(const char *arg);
   152 void killclient(const char *arg);
   196 double mwfact;
   195 double mwfact;
   197 int screen, sx, sy, sw, sh, wax, way, waw, wah;
   196 int screen, sx, sy, sw, sh, wax, way, waw, wah;
   198 int (*xerrorxlib)(Display *, XErrorEvent *);
   197 int (*xerrorxlib)(Display *, XErrorEvent *);
   199 unsigned int bh, bpos;
   198 unsigned int bh, bpos;
   200 unsigned int blw = 0;
   199 unsigned int blw = 0;
   201 unsigned int ltidx = 0; /* default */
       
   202 unsigned int nlayouts = 0;
       
   203 unsigned int nrules = 0;
       
   204 unsigned int numlockmask = 0;
   200 unsigned int numlockmask = 0;
   205 void (*handler[LASTEvent]) (XEvent *) = {
   201 void (*handler[LASTEvent]) (XEvent *) = {
   206 	[ButtonPress] = buttonpress,
   202 	[ButtonPress] = buttonpress,
   207 	[ConfigureRequest] = configurerequest,
   203 	[ConfigureRequest] = configurerequest,
   208 	[ConfigureNotify] = configurenotify,
   204 	[ConfigureNotify] = configurenotify,
   215 	[MapRequest] = maprequest,
   211 	[MapRequest] = maprequest,
   216 	[PropertyNotify] = propertynotify,
   212 	[PropertyNotify] = propertynotify,
   217 	[UnmapNotify] = unmapnotify
   213 	[UnmapNotify] = unmapnotify
   218 };
   214 };
   219 Atom wmatom[WMLast], netatom[NetLast];
   215 Atom wmatom[WMLast], netatom[NetLast];
       
   216 Bool domwfact = True;
       
   217 Bool dozoom = True;
   220 Bool otherwm, readin;
   218 Bool otherwm, readin;
   221 Bool running = True;
   219 Bool running = True;
   222 Bool selscreen = True;
   220 Bool selscreen = True;
   223 Client *clients = NULL;
   221 Client *clients = NULL;
   224 Client *sel = NULL;
   222 Client *sel = NULL;
   225 Client *stack = NULL;
   223 Client *stack = NULL;
   226 Cursor cursor[CurLast];
   224 Cursor cursor[CurLast];
   227 Display *dpy;
   225 Display *dpy;
   228 DC dc = {0};
   226 DC dc = {0};
       
   227 Layout *layout = NULL;
   229 Window barwin, root;
   228 Window barwin, root;
   230 Regs *regs = NULL;
   229 Regs *regs = NULL;
   231 
   230 
   232 /* configuration, allows nested code to access above variables */
   231 /* configuration, allows nested code to access above variables */
   233 #include "config.h"
   232 #include "config.h"
   244 	/* rule matching */
   243 	/* rule matching */
   245 	XGetClassHint(dpy, c->win, &ch);
   244 	XGetClassHint(dpy, c->win, &ch);
   246 	snprintf(buf, sizeof buf, "%s:%s:%s",
   245 	snprintf(buf, sizeof buf, "%s:%s:%s",
   247 			ch.res_class ? ch.res_class : "",
   246 			ch.res_class ? ch.res_class : "",
   248 			ch.res_name ? ch.res_name : "", c->name);
   247 			ch.res_name ? ch.res_name : "", c->name);
   249 	for(i = 0; i < nrules; i++)
   248 	for(i = 0; i < NRULES; i++)
   250 		if(regs[i].propregex && !regexec(regs[i].propregex, buf, 1, &tmp, 0)) {
   249 		if(regs[i].propregex && !regexec(regs[i].propregex, buf, 1, &tmp, 0)) {
   251 			c->isfloating = rules[i].isfloating;
   250 			c->isfloating = rules[i].isfloating;
   252 			for(j = 0; regs[i].tagregex && j < NTAGS; j++) {
   251 			for(j = 0; regs[i].tagregex && j < NTAGS; j++) {
   253 				if(!regexec(regs[i].tagregex, tags[j], 1, &tmp, 0)) {
   252 				if(!regexec(regs[i].tagregex, tags[j], 1, &tmp, 0)) {
   254 					matched = True;
   253 					matched = True;
   271 	for(c = clients; c; c = c->next)
   270 	for(c = clients; c; c = c->next)
   272 		if(isvisible(c))
   271 		if(isvisible(c))
   273 			unban(c);
   272 			unban(c);
   274 		else
   273 		else
   275 			ban(c);
   274 			ban(c);
   276 	layouts[ltidx].arrange();
   275 	layout->arrange();
   277 	focus(NULL);
   276 	focus(NULL);
   278 	restack();
   277 	restack();
   279 }
   278 }
   280 
   279 
   281 void
   280 void
   332 	else if((c = getclient(ev->window))) {
   331 	else if((c = getclient(ev->window))) {
   333 		focus(c);
   332 		focus(c);
   334 		if(CLEANMASK(ev->state) != MODKEY)
   333 		if(CLEANMASK(ev->state) != MODKEY)
   335 			return;
   334 			return;
   336 		if(ev->button == Button1) {
   335 		if(ev->button == Button1) {
   337 			if(isarrange(floating) || c->isfloating)
   336 			if((floating == layout->arrange) || c->isfloating)
   338 				restack();
   337 				restack();
   339 			else
   338 			else
   340 				togglefloating(NULL);
   339 				togglefloating(NULL);
   341 			movemouse(c);
   340 			movemouse(c);
   342 		}
   341 		}
   343 		else if(ev->button == Button2) {
   342 		else if(ev->button == Button2) {
   344 			if((ISTILE) && !c->isfixed && c->isfloating)
   343 			if((floating != layout->arrange) && !c->isfixed && c->isfloating)
   345 				togglefloating(NULL);
   344 				togglefloating(NULL);
   346 			else
   345 			else
   347 				zoom(NULL);
   346 				zoom(NULL);
   348 		}
   347 		}
   349 		else if(ev->button == Button3 && !c->isfixed) {
   348 		else if(ev->button == Button3 && !c->isfixed) {
   350 			if(isarrange(floating) || c->isfloating)
   349 			if((floating == layout->arrange) || c->isfloating)
   351 				restack();
   350 				restack();
   352 			else
   351 			else
   353 				togglefloating(NULL);
   352 				togglefloating(NULL);
   354 			resizemouse(c);
   353 			resizemouse(c);
   355 		}
   354 		}
   399 	unsigned int i;
   398 	unsigned int i;
   400 	regex_t *reg;
   399 	regex_t *reg;
   401 
   400 
   402 	if(regs)
   401 	if(regs)
   403 		return;
   402 		return;
   404 	nrules = sizeof rules / sizeof rules[0];
   403 	regs = emallocz(NRULES * sizeof(Regs));
   405 	regs = emallocz(nrules * sizeof(Regs));
   404 	for(i = 0; i < NRULES; i++) {
   406 	for(i = 0; i < nrules; i++) {
       
   407 		if(rules[i].prop) {
   405 		if(rules[i].prop) {
   408 			reg = emallocz(sizeof(regex_t));
   406 			reg = emallocz(sizeof(regex_t));
   409 			if(regcomp(reg, rules[i].prop, REG_EXTENDED))
   407 			if(regcomp(reg, rules[i].prop, REG_EXTENDED))
   410 				free(reg);
   408 				free(reg);
   411 			else
   409 			else
   462 
   460 
   463 	if((c = getclient(ev->window))) {
   461 	if((c = getclient(ev->window))) {
   464 		c->ismax = False;
   462 		c->ismax = False;
   465 		if(ev->value_mask & CWBorderWidth)
   463 		if(ev->value_mask & CWBorderWidth)
   466 			c->border = ev->border_width;
   464 			c->border = ev->border_width;
   467 		if(c->isfixed || c->isfloating || isarrange(floating)) {
   465 		if(c->isfixed || c->isfloating || (floating == layout->arrange)) {
   468 			if(ev->value_mask & CWX)
   466 			if(ev->value_mask & CWX)
   469 				c->x = ev->x;
   467 				c->x = ev->x;
   470 			if(ev->value_mask & CWY)
   468 			if(ev->value_mask & CWY)
   471 				c->y = ev->y;
   469 				c->y = ev->y;
   472 			if(ev->value_mask & CWWidth)
   470 			if(ev->value_mask & CWWidth)
   543 			drawsquare(sel && sel->tags[i], isoccupied(i), dc.norm);
   541 			drawsquare(sel && sel->tags[i], isoccupied(i), dc.norm);
   544 		}
   542 		}
   545 		dc.x += dc.w;
   543 		dc.x += dc.w;
   546 	}
   544 	}
   547 	dc.w = blw;
   545 	dc.w = blw;
   548 	drawtext(layouts[ltidx].symbol, dc.norm);
   546 	drawtext(layout->symbol, dc.norm);
   549 	x = dc.x + dc.w;
   547 	x = dc.x + dc.w;
   550 	dc.w = textw(stext);
   548 	dc.w = textw(stext);
   551 	dc.x = sw - dc.w;
   549 	dc.x = sw - dc.w;
   552 	if(dc.x < x) {
   550 	if(dc.x < x) {
   553 		dc.x = x;
   551 		dc.x = x;
   674 
   672 
   675 void
   673 void
   676 floating(void) { /* default floating layout */
   674 floating(void) { /* default floating layout */
   677 	Client *c;
   675 	Client *c;
   678 
   676 
       
   677 	domwfact = dozoom = False;
   679 	for(c = clients; c; c = c->next)
   678 	for(c = clients; c; c = c->next)
   680 		if(isvisible(c))
   679 		if(isvisible(c))
   681 			resize(c, c->x, c->y, c->w, c->h, True);
   680 			resize(c, c->x, c->y, c->w, c->h, True);
   682 }
   681 }
   683 
   682 
   887 	}
   886 	}
   888 	dc.font.height = dc.font.ascent + dc.font.descent;
   887 	dc.font.height = dc.font.ascent + dc.font.descent;
   889 }
   888 }
   890 
   889 
   891 Bool
   890 Bool
   892 isarrange(void (*func)())
       
   893 {
       
   894 	return func == layouts[ltidx].arrange;
       
   895 }
       
   896 
       
   897 Bool
       
   898 isoccupied(unsigned int t) {
   891 isoccupied(unsigned int t) {
   899 	Client *c;
   892 	Client *c;
   900 
   893 
   901 	for(c = clients; c; c = c->next)
   894 	for(c = clients; c; c = c->next)
   902 		if(c->tags[t])
   895 		if(c->tags[t])
   930 }
   923 }
   931 
   924 
   932 void
   925 void
   933 keypress(XEvent *e) {
   926 keypress(XEvent *e) {
   934 	KEYS
   927 	KEYS
   935 	unsigned int len = sizeof keys / sizeof keys[0];
       
   936 	unsigned int i;
   928 	unsigned int i;
   937 	KeyCode code;
   929 	KeyCode code;
   938 	KeySym keysym;
   930 	KeySym keysym;
   939 	XKeyEvent *ev;
   931 	XKeyEvent *ev;
   940 
   932 
   941 	if(!e) { /* grabkeys */
   933 	if(!e) { /* grabkeys */
   942 		XUngrabKey(dpy, AnyKey, AnyModifier, root);
   934 		XUngrabKey(dpy, AnyKey, AnyModifier, root);
   943 		for(i = 0; i < len; i++) {
   935 		for(i = 0; i < NKEYS; i++) {
   944 			code = XKeysymToKeycode(dpy, keys[i].keysym);
   936 			code = XKeysymToKeycode(dpy, keys[i].keysym);
   945 			XGrabKey(dpy, code, keys[i].mod, root, True,
   937 			XGrabKey(dpy, code, keys[i].mod, root, True,
   946 					GrabModeAsync, GrabModeAsync);
   938 					GrabModeAsync, GrabModeAsync);
   947 			XGrabKey(dpy, code, keys[i].mod | LockMask, root, True,
   939 			XGrabKey(dpy, code, keys[i].mod | LockMask, root, True,
   948 					GrabModeAsync, GrabModeAsync);
   940 					GrabModeAsync, GrabModeAsync);
   953 		}
   945 		}
   954 		return;
   946 		return;
   955 	}
   947 	}
   956 	ev = &e->xkey;
   948 	ev = &e->xkey;
   957 	keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0);
   949 	keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0);
   958 	for(i = 0; i < len; i++)
   950 	for(i = 0; i < NKEYS; i++)
   959 		if(keysym == keys[i].keysym
   951 		if(keysym == keys[i].keysym
   960 		&& CLEANMASK(keys[i].mod) == CLEANMASK(ev->state))
   952 		&& CLEANMASK(keys[i].mod) == CLEANMASK(ev->state))
   961 		{
   953 		{
   962 			if(keys[i].func)
   954 			if(keys[i].func)
   963 				keys[i].func(keys[i].arg);
   955 				keys[i].func(keys[i].arg);
  1264 	XWindowChanges wc;
  1256 	XWindowChanges wc;
  1265 
  1257 
  1266 	drawbar();
  1258 	drawbar();
  1267 	if(!sel)
  1259 	if(!sel)
  1268 		return;
  1260 		return;
  1269 	if(sel->isfloating || isarrange(floating))
  1261 	if(sel->isfloating || (floating == layout->arrange))
  1270 		XRaiseWindow(dpy, sel->win);
  1262 		XRaiseWindow(dpy, sel->win);
  1271 	if(!isarrange(floating)) {
  1263 	if(floating != layout->arrange) {
  1272 		wc.stack_mode = Below;
  1264 		wc.stack_mode = Below;
  1273 		wc.sibling = barwin;
  1265 		wc.sibling = barwin;
  1274 		if(!sel->isfloating) {
  1266 		if(!sel->isfloating) {
  1275 			XConfigureWindow(dpy, sel->win, CWSibling | CWStackMode, &wc);
  1267 			XConfigureWindow(dpy, sel->win, CWSibling | CWStackMode, &wc);
  1276 			wc.sibling = sel->win;
  1268 			wc.sibling = sel->win;
  1372 void
  1364 void
  1373 setlayout(const char *arg) {
  1365 setlayout(const char *arg) {
  1374 	unsigned int i;
  1366 	unsigned int i;
  1375 
  1367 
  1376 	if(!arg) {
  1368 	if(!arg) {
  1377 		if(++ltidx == nlayouts)
  1369 		if(++layout == &layouts[NLAYOUTS])
  1378 			ltidx = 0;;
  1370 			layout = &layouts[0];
  1379 	}
  1371 	}
  1380 	else {
  1372 	else {
  1381 		for(i = 0; i < nlayouts; i++)
  1373 		for(i = 0; i < NLAYOUTS; i++)
  1382 			if(!strcmp(arg, layouts[i].symbol))
  1374 			if(!strcmp(arg, layouts[i].symbol))
  1383 				break;
  1375 				break;
  1384 		if(i == nlayouts)
  1376 		if(i == NLAYOUTS)
  1385 			return;
  1377 			return;
  1386 		ltidx = i;
  1378 		layout = &layouts[i];
  1387 	}
  1379 	}
  1388 	if(sel)
  1380 	if(sel)
  1389 		arrange();
  1381 		arrange();
  1390 	else
  1382 	else
  1391 		drawbar();
  1383 		drawbar();
  1393 
  1385 
  1394 void
  1386 void
  1395 setmwfact(const char *arg) {
  1387 setmwfact(const char *arg) {
  1396 	double delta;
  1388 	double delta;
  1397 
  1389 
  1398 	if(!(ISTILE))
  1390 	if(!domwfact)
  1399 		return;
  1391 		return;
  1400 	/* arg handling, manipulate mwfact */
  1392 	/* arg handling, manipulate mwfact */
  1401 	if(NULL == arg)
  1393 	if(NULL == arg)
  1402 		mwfact = MWFACT;
  1394 		mwfact = MWFACT;
  1403 	else if(1 == sscanf(arg, "%lf", &delta)) {
  1395 	else if(1 == sscanf(arg, "%lf", &delta)) {
  1474 	initfont(FONT);
  1466 	initfont(FONT);
  1475 	dc.h = bh = dc.font.height + 2;
  1467 	dc.h = bh = dc.font.height + 2;
  1476 
  1468 
  1477 	/* init layouts */
  1469 	/* init layouts */
  1478 	mwfact = MWFACT;
  1470 	mwfact = MWFACT;
  1479 	nlayouts = sizeof layouts / sizeof layouts[0];
  1471 	layout = &layouts[0];
  1480 	for(blw = i = 0; i < nlayouts; i++) {
  1472 	for(blw = i = 0; i < NLAYOUTS; i++) {
  1481 		j = textw(layouts[i].symbol);
  1473 		j = textw(layouts[i].symbol);
  1482 		if(j > blw)
  1474 		if(j > blw)
  1483 			blw = j;
  1475 			blw = j;
  1484 	}
  1476 	}
  1485 
  1477 
  1560 void
  1552 void
  1561 tile(void) {
  1553 tile(void) {
  1562 	unsigned int i, n, nx, ny, nw, nh, mw, th;
  1554 	unsigned int i, n, nx, ny, nw, nh, mw, th;
  1563 	Client *c, *mc;
  1555 	Client *c, *mc;
  1564 
  1556 
       
  1557 	domwfact = dozoom = True;
  1565 	for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next))
  1558 	for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next))
  1566 		n++;
  1559 		n++;
  1567 
  1560 
  1568 	/* window geoms */
  1561 	/* window geoms */
  1569 	mw = (n == 1) ? waw : mwfact * waw;
  1562 	mw = (n == 1) ? waw : mwfact * waw;
  1625 	XEvent ev;
  1618 	XEvent ev;
  1626 
  1619 
  1627 	if(!sel || sel->isfixed)
  1620 	if(!sel || sel->isfixed)
  1628 		return;
  1621 		return;
  1629 	if((sel->ismax = !sel->ismax)) {
  1622 	if((sel->ismax = !sel->ismax)) {
  1630 		if(isarrange(floating) || sel->isfloating)
  1623 		if((floating == layout->arrange) || sel->isfloating)
  1631 			sel->wasfloating = True;
  1624 			sel->wasfloating = True;
  1632 		else {
  1625 		else {
  1633 			togglefloating(NULL);
  1626 			togglefloating(NULL);
  1634 			sel->wasfloating = False;
  1627 			sel->wasfloating = False;
  1635 		}
  1628 		}
  1853 
  1846 
  1854 void
  1847 void
  1855 zoom(const char *arg) {
  1848 zoom(const char *arg) {
  1856 	Client *c;
  1849 	Client *c;
  1857 
  1850 
  1858 	if(!sel || !(ISTILE) || sel->isfloating)
  1851 	if(!sel || !dozoom || sel->isfloating)
  1859 		return;
  1852 		return;
  1860 	if((c = sel) == nexttiled(clients))
  1853 	if((c = sel) == nexttiled(clients))
  1861 		if(!(c = nexttiled(c->next)))
  1854 		if(!(c = nexttiled(c->next)))
  1862 			return;
  1855 			return;
  1863 	detach(c);
  1856 	detach(c);