X-Git-Url: https://git.xinqibao.xyz/dwm.git/blobdiff_plain/a98b5e59359173111322171187ccfd951df85a38..762b66ae7c0cffb51bfbda8c52c4ecc892ae1808:/dwm.c?ds=inline

diff --git a/dwm.c b/dwm.c
index c595a51..88743c5 100644
--- a/dwm.c
+++ b/dwm.c
@@ -17,9 +17,7 @@
  * set the override_redirect flag.  Clients are organized in a global
  * doubly-linked client list, the focus history is remembered through a global
  * stack list. Each client contains an array of Bools of the same size as the
- * global tags array to indicate the tags of a client.  For each client dwm
- * creates a small title window, which is resized whenever the (_NET_)WM_NAME
- * properties are updated or the client is moved/resized.
+ * global tags array to indicate the tags of a client.  
  *
  * Keys and tagging rules are organized as arrays and defined in config.h.
  *
@@ -46,13 +44,16 @@
 /* macros */
 #define BUTTONMASK		(ButtonPressMask | ButtonReleaseMask)
 #define CLEANMASK(mask)		(mask & ~(numlockmask | LockMask))
+#define LENGTH(x)		(sizeof x / sizeof x[0])
+#define MAXTAGLEN		16
 #define MOUSEMASK		(BUTTONMASK | PointerMotionMask)
 
+
 /* enums */
 enum { BarTop, BarBot, BarOff };			/* bar position */
 enum { CurNormal, CurResize, CurMove, CurLast };	/* cursor */
 enum { ColBorder, ColFG, ColBG, ColLast };		/* color */
-enum { NetSupported, NetWMName, NetLast };		/* EWMH atoms */
+enum { NetSupported, NetWMCheck, NetWMName, NetLast };	/* EWMH atoms */
 enum { WMProtocols, WMDelete, WMName, WMState, WMLast };/* default atoms */
 
 /* typedefs */
@@ -143,6 +144,7 @@ unsigned long getcolor(const char *colstr);
 long getstate(Window w);
 Bool gettextprop(Window w, Atom atom, char *text, unsigned int size);
 void grabbuttons(Client *c, Bool focused);
+void grabkeys(void);
 unsigned int idxoftag(const char *tag);
 void initfont(const char *fontstr);
 Bool isoccupied(unsigned int t);
@@ -231,6 +233,8 @@ Regs *regs = NULL;
 /* configuration, allows nested code to access above variables */
 #include "config.h"
 
+Bool prevtags[LENGTH(tags)];
+
 /* function implementations */
 void
 applyrules(Client *c) {
@@ -305,7 +309,7 @@ buttonpress(XEvent *e) {
 	Client *c;
 	XButtonPressedEvent *ev = &e->xbutton;
 
-	if(barwin == ev->window) {
+	if(ev->window == barwin) {
 		x = 0;
 		for(i = 0; i < LENGTH(tags); i++) {
 			x += textw(tags[i]);
@@ -333,7 +337,7 @@ buttonpress(XEvent *e) {
 		if(CLEANMASK(ev->state) != MODKEY)
 			return;
 		if(ev->button == Button1) {
-			if((floating == layout->arrange) || c->isfloating)
+			if((layout->arrange == floating) || c->isfloating)
 				restack();
 			else
 				togglefloating(NULL);
@@ -664,8 +668,8 @@ void
 expose(XEvent *e) {
 	XExposeEvent *ev = &e->xexpose;
 
-	if(0 == ev->count) {
-		if(barwin == ev->window)
+	if(ev->count == 0) {
+		if(ev->window == barwin)
 			drawbar();
 	}
 }
@@ -779,7 +783,7 @@ gettextprop(Window w, Atom atom, char *text, unsigned int size) {
 	int n;
 	XTextProperty name;
 
-	if(!text || 0 == size)
+	if(!text || size == 0)
 		return False;
 	text[0] = '\0';
 	XGetTextProperty(dpy, w, &name, atom);
@@ -789,8 +793,7 @@ gettextprop(Window w, Atom atom, char *text, unsigned int size) {
 		strncpy(text, (char *)name.value, size - 1);
 	else {
 		if(XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success
-		&& n > 0 && *list)
-		{
+		&& n > 0 && *list) {
 			strncpy(text, *list, size - 1);
 			XFreeStringList(list);
 		}
@@ -837,6 +840,25 @@ grabbuttons(Client *c, Bool focused) {
 				GrabModeAsync, GrabModeSync, None, None);
 }
 
+void
+grabkeys(void)  {
+	unsigned int i;
+	KeyCode code;
+
+	XUngrabKey(dpy, AnyKey, AnyModifier, root);
+	for(i = 0; i < LENGTH(keys); i++) {
+		code = XKeysymToKeycode(dpy, keys[i].keysym);
+		XGrabKey(dpy, code, keys[i].mod, root, True,
+				GrabModeAsync, GrabModeAsync);
+		XGrabKey(dpy, code, keys[i].mod | LockMask, root, True,
+				GrabModeAsync, GrabModeAsync);
+		XGrabKey(dpy, code, keys[i].mod | numlockmask, root, True,
+				GrabModeAsync, GrabModeAsync);
+		XGrabKey(dpy, code, keys[i].mod | numlockmask | LockMask, root, True,
+				GrabModeAsync, GrabModeAsync);
+	}
+}
+
 unsigned int
 idxoftag(const char *tag) {
 	unsigned int i;
@@ -924,27 +946,10 @@ isvisible(Client *c) {
 
 void
 keypress(XEvent *e) {
-	KEYS
 	unsigned int i;
-	KeyCode code;
 	KeySym keysym;
 	XKeyEvent *ev;
 
-	if(!e) { /* grabkeys */
-		XUngrabKey(dpy, AnyKey, AnyModifier, root);
-		for(i = 0; i < LENGTH(keys); i++) {
-			code = XKeysymToKeycode(dpy, keys[i].keysym);
-			XGrabKey(dpy, code, keys[i].mod, root, True,
-					GrabModeAsync, GrabModeAsync);
-			XGrabKey(dpy, code, keys[i].mod | LockMask, root, True,
-					GrabModeAsync, GrabModeAsync);
-			XGrabKey(dpy, code, keys[i].mod | numlockmask, root, True,
-					GrabModeAsync, GrabModeAsync);
-			XGrabKey(dpy, code, keys[i].mod | numlockmask | LockMask, root, True,
-					GrabModeAsync, GrabModeAsync);
-		}
-		return;
-	}
 	ev = &e->xkey;
 	keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0);
 	for(i = 0; i < LENGTH(keys); i++)
@@ -1047,7 +1052,7 @@ mappingnotify(XEvent *e) {
 
 	XRefreshKeyboardMapping(ev);
 	if(ev->request == MappingKeyboard)
-		keypress(NULL);
+		grabkeys();
 }
 
 void
@@ -1125,7 +1130,7 @@ propertynotify(XEvent *e) {
 			default: break;
 			case XA_WM_TRANSIENT_FOR:
 				XGetTransientForHint(dpy, c->win, &trans);
-				if(!c->isfloating && (c->isfloating = (NULL != getclient(trans))))
+				if(!c->isfloating && (c->isfloating = (getclient(trans) != NULL)))
 					arrange();
 				break;
 			case XA_WM_NORMAL_HINTS:
@@ -1145,6 +1150,7 @@ quit(const char *arg) {
 	readin = running = False;
 }
 
+
 void
 resize(Client *c, int x, int y, int w, int h, Bool sizehints) {
 	XWindowChanges wc;
@@ -1258,9 +1264,9 @@ restack(void) {
 	drawbar();
 	if(!sel)
 		return;
-	if(sel->isfloating || (floating == layout->arrange))
+	if(sel->isfloating || (layout->arrange == floating))
 		XRaiseWindow(dpy, sel->win);
-	if(floating != layout->arrange) {
+	if(layout->arrange != floating) {
 		wc.stack_mode = Below;
 		wc.sibling = barwin;
 		if(!sel->isfloating) {
@@ -1280,15 +1286,20 @@ restack(void) {
 
 void
 run(void) {
+	char *p;
+	char buf[sizeof stext];
 	fd_set rd;
-	int xfd;
+	int r, xfd;
+	unsigned int len, offset;
 	XEvent ev;
 
 	/* main event loop, also reads status text from stdin */
 	XSync(dpy, False);
 	xfd = ConnectionNumber(dpy);
 	readin = True;
-	stext[sizeof stext - 1] = '\0'; /* 0-terminator is never touched */
+	offset = 0;
+	len = sizeof stext - 1;
+	buf[len] = stext[len] = '\0'; /* 0-terminator is never touched */
 	while(running) {
 		FD_ZERO(&rd);
 		if(readin)
@@ -1300,14 +1311,28 @@ run(void) {
 			eprint("select failed\n");
 		}
 		if(FD_ISSET(STDIN_FILENO, &rd)) {
-			if(stext == fgets(stext, sizeof stext - 1, stdin))
-				stext[strlen(stext) - 1] = '\0'; /* remove tailing '\n' */
-			else {
+			switch((r = read(STDIN_FILENO, buf + offset, len - offset))) {
+			case -1:
+				strncpy(stext, strerror(errno), len);
 				readin = False;
-				if(feof(stdin))
-					strncpy(stext, "EOF", 4);
-				else /* error occured */
-					strncpy(stext, strerror(errno), sizeof stext - 1);
+				break;
+			case 0:
+				strncpy(stext, "EOF", 4);
+				readin = False;
+				break;
+			default:
+				for(p = buf + offset; r > 0; p++, r--, offset++)
+					if(*p == '\n' || *p == '\0') {
+						*p = '\0';
+						strncpy(stext, buf, len);
+						p += r - 1; /* p is buf + offset + r - 1 */
+						for(r = 0; *(p - r) && *(p - r) != '\n'; r++);
+						offset = r;
+						if(r)
+							memmove(buf, p - r + 1, r);
+						break;
+					}
+				break;
 			}
 			drawbar();
 		}
@@ -1383,9 +1408,9 @@ setmwfact(const char *arg) {
 	if(!domwfact)
 		return;
 	/* arg handling, manipulate mwfact */
-	if(NULL == arg)
+	if(arg == NULL)
 		mwfact = MWFACT;
-	else if(1 == sscanf(arg, "%lf", &delta)) {
+	else if(sscanf(arg, "%lf", &delta) == 1) {
 		if(arg[0] == '+' || arg[0] == '-')
 			mwfact += delta;
 		else
@@ -1402,19 +1427,20 @@ void
 setup(void) {
 	int d;
 	unsigned int i, j, mask;
+	Atom utf8string;
 	Window w;
 	XModifierKeymap *modmap;
 	XSetWindowAttributes wa;
 
 	/* init atoms */
+	utf8string = XInternAtom(dpy, "UTF8_STRING", False);
 	wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False);
 	wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
 	wmatom[WMName] = XInternAtom(dpy, "WM_NAME", False);
 	wmatom[WMState] = XInternAtom(dpy, "WM_STATE", False);
 	netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False);
+	netatom[NetWMCheck] = XInternAtom(dpy, "_NET_SUPPORTING_WM_CHECK", False);
 	netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False);
-	XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32,
-			PropModeReplace, (unsigned char *) netatom, NetLast);
 
 	/* init cursors */
 	cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr);
@@ -1444,9 +1470,10 @@ setup(void) {
 	XSelectInput(dpy, root, wa.event_mask);
 
 	/* grab keys */
-	keypress(NULL);
+	grabkeys();
 
 	/* init tags */
+	memcpy(prevtags, seltags, sizeof seltags);
 	compileregs();
 
 	/* init appearance */
@@ -1488,6 +1515,17 @@ setup(void) {
 
 	/* multihead support */
 	selscreen = XQueryPointer(dpy, root, &w, &w, &d, &d, &d, &d, &mask);
+
+	/* EWMH properties */
+	XChangeProperty(dpy, barwin, netatom[NetWMCheck], XA_WINDOW, 32,
+			PropModeReplace, (unsigned char *) &barwin, 1);
+	/* HACK: dwm identifies itself as compiz to workaround the XToolkit bug of Sun JDK */
+	XChangeProperty(dpy, barwin, netatom[NetWMName], utf8string, 8,
+			PropModeReplace, (unsigned char *) "compiz", 7);
+	XChangeProperty(dpy, root, netatom[NetWMCheck], XA_WINDOW, 32,
+			PropModeReplace, (unsigned char *) &barwin, 1);
+	XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32,
+			PropModeReplace, (unsigned char *) netatom, NetLast);
 }
 
 void
@@ -1500,8 +1538,8 @@ spawn(const char *arg) {
 		return;
 	/* The double-fork construct avoids zombie processes and keeps the code
 	 * clean from stupid signal handlers. */
-	if(0 == fork()) {
-		if(0 == fork()) {
+	if(fork() == 0) {
+		if(fork() == 0) {
 			if(dpy)
 				close(ConnectionNumber(dpy));
 			setsid();
@@ -1562,7 +1600,7 @@ tile(void) {
 	nw = 0; /* gcc stupidity requires this */
 	for(i = 0, c = mc = nexttiled(clients); c; c = nexttiled(c->next), i++) {
 		c->ismax = False;
-		if(0 == i) { /* master */
+		if(i == 0) { /* master */
 			nw = mw - 2 * c->border;
 			nh = wah - 2 * c->border;
 		}
@@ -1613,7 +1651,7 @@ togglemax(const char *arg) {
 	if(!sel || sel->isfixed)
 		return;
 	if((sel->ismax = !sel->ismax)) {
-		if((floating == layout->arrange) || sel->isfloating)
+		if((layout->arrange == floating) || sel->isfloating)
 			sel->wasfloating = True;
 		else {
 			togglefloating(NULL);
@@ -1829,11 +1867,11 @@ view(const char *arg) {
 
 void
 viewprevtag(const char *arg) {
-	static Bool tmptags[sizeof tags / sizeof tags[0]];
+	static Bool tmp[LENGTH(tags)];
 
-	memcpy(tmptags, seltags, sizeof seltags);
+	memcpy(tmp, seltags, sizeof seltags);
 	memcpy(seltags, prevtags, sizeof seltags);
-	memcpy(prevtags, tmptags, sizeof seltags);
+	memcpy(prevtags, tmp, sizeof seltags);
 	arrange();
 }
 
@@ -1855,7 +1893,8 @@ zoom(const char *arg) {
 int
 main(int argc, char *argv[]) {
 	if(argc == 2 && !strcmp("-v", argv[1]))
-		eprint("dwm-"VERSION", © 2006-2007 A. R. Garbe, S. van Dijk, J. Salmi, P. Hruby, S. Nagy\n");
+		eprint("dwm-"VERSION", © 2006-2007 Anselm R. Garbe, Sander van Dijk, "
+		       "Jukka Salmi, Premysl Hruby, Szabolcs Nagy\n");
 	else if(argc != 1)
 		eprint("usage: dwm [-v]\n");