aewl

diff aewl.c @ 777:3835ddb75a55

changed to status text setting through XA_WM_NAME (suggested by Neale Pickett)
author meillo@marmaro.de
date Mon, 16 Feb 2009 10:40:57 +0100
parents a3399a8964c7
children 7ea91d4d0882
line diff
     1.1 --- a/aewl.c	Mon Feb 16 09:23:57 2009 +0100
     1.2 +++ b/aewl.c	Mon Feb 16 10:40:57 2009 +0100
     1.3 @@ -8,12 +8,9 @@
     1.4   * events about window (dis-)appearance.  Only one X connection at a time is
     1.5   * allowed to select for this event mask.
     1.6   *
     1.7 - * Calls to fetch an X event from the event queue are blocking.  Due reading
     1.8 - * status text from standard input, a select()-driven main loop has been
     1.9 - * implemented which selects for reads on the X connection and STDIN_FILENO to
    1.10 - * handle all data smoothly. The event handlers of dwm are organized in an
    1.11 - * array which is accessed whenever a new event has been fetched. This allows
    1.12 - * event dispatching in O(1) time.
    1.13 + * The event handlers of dwm are organized in an array which is accessed
    1.14 + * whenever a new event has been fetched. This allows event dispatching in O(1)
    1.15 + * time.
    1.16   *
    1.17   * Each child of the root window is called a client, except windows which have
    1.18   * set the override_redirect flag.  Clients are organized in a global
    1.19 @@ -46,7 +43,6 @@
    1.20  #include <stdlib.h>
    1.21  #include <string.h>
    1.22  #include <unistd.h>
    1.23 -#include <sys/select.h>
    1.24  #include <sys/signal.h>
    1.25  #include <sys/types.h>
    1.26  #include <sys/wait.h>
    1.27 @@ -145,7 +141,7 @@
    1.28  Window root, barwin;
    1.29  
    1.30  static int (*xerrorxlib)(Display *, XErrorEvent *);
    1.31 -static Bool otherwm, readin;
    1.32 +static Bool otherwm;
    1.33  static unsigned int len = 0;
    1.34  
    1.35  
    1.36 @@ -160,13 +156,12 @@
    1.37  void updatetitle(Client *c);		/* update the name of c */
    1.38  void unmanage(Client *c);		/* destroy c */
    1.39  
    1.40 -void drawstatus(void);			/* draw the bar */
    1.41 +void drawbar(void);			/* draw the bar */
    1.42  unsigned long getcolor(const char *colstr);	/* return color of colstr */
    1.43  void setfont(const char *fontstr);	/* set the font for DC */
    1.44  unsigned int textw(const char *text);	/* return the width of text in px*/
    1.45  
    1.46  void grabkeys(void);			/* grab all keys defined in config.h */
    1.47 -void procevent(void);			/* process pending X events */
    1.48  
    1.49  void sendevent(Window w, Atom a, long value);	/* send synthetic event to w */
    1.50  int xerror(Display *dsply, XErrorEvent *ee);	/* X error handler */
    1.51 @@ -195,6 +190,7 @@
    1.52  void toggletag(void);		/* toggles tag of c */
    1.53  void spawn(const char* cmd);			/* forks a new subprocess with cmd */
    1.54  
    1.55 +void updatestatus(void);		/* update the status text */
    1.56  
    1.57  
    1.58  RULES
    1.59 @@ -374,7 +370,7 @@
    1.60  	Client *c;
    1.61  	XEvent ev;
    1.62  
    1.63 -	drawstatus();
    1.64 +	drawbar();
    1.65  	if(!sel)
    1.66  		return;
    1.67  	if(sel->isfloat)
    1.68 @@ -722,7 +718,7 @@
    1.69  
    1.70  	if(ev->count == 0) {
    1.71  		if(barwin == ev->window)
    1.72 -			drawstatus();
    1.73 +			drawbar();
    1.74  	}
    1.75  }
    1.76  
    1.77 @@ -783,9 +779,11 @@
    1.78  	Window trans;
    1.79  	XPropertyEvent *ev = &e->xproperty;
    1.80  
    1.81 -	if(ev->state == PropertyDelete)
    1.82 +	if((ev->window == root) && (ev->atom = XA_WM_NAME))
    1.83 +		updatestatus();
    1.84 +	else if(ev->state == PropertyDelete)
    1.85  		return; /* ignore */
    1.86 -	if((c = getclient(ev->window))) {
    1.87 +	else if((c = getclient(ev->window))) {
    1.88  		switch (ev->atom) {
    1.89  			default: break;
    1.90  			case XA_WM_TRANSIENT_FOR:
    1.91 @@ -800,7 +798,7 @@
    1.92  		if(ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) {
    1.93  			updatetitle(c);
    1.94  			if(c == sel)
    1.95 -				drawstatus();
    1.96 +				drawbar();
    1.97  		}
    1.98  	}
    1.99  }
   1.100 @@ -850,17 +848,6 @@
   1.101  	}
   1.102  }
   1.103  
   1.104 -void
   1.105 -procevent(void) {
   1.106 -	XEvent ev;
   1.107 -
   1.108 -	while(XPending(dpy)) {
   1.109 -		XNextEvent(dpy, &ev);
   1.110 -		if(handler[ev.type])
   1.111 -			(handler[ev.type])(&ev); /* call handler */
   1.112 -	}
   1.113 -}
   1.114 -
   1.115  /* from draw.c */
   1.116  
   1.117  unsigned int
   1.118 @@ -920,7 +907,7 @@
   1.119  }
   1.120  
   1.121  void
   1.122 -drawstatus(void) {
   1.123 +drawbar(void) {
   1.124  	int x;
   1.125  	unsigned long black[ColLast];
   1.126  	black[ColBG] = getcolor("#000000");
   1.127 @@ -1112,7 +1099,7 @@
   1.128  		grabbuttons(c, True);
   1.129  	}
   1.130  	sel = c;
   1.131 -	drawstatus();
   1.132 +	drawbar();
   1.133  	if(!selscreen)
   1.134  		return;
   1.135  	if(c) {
   1.136 @@ -1322,26 +1309,36 @@
   1.137  
   1.138  void
   1.139  updatetitle(Client *c) {
   1.140 +	if (!gettextprop(c->win, netatom[NetWMName], c->name, sizeof c->name)) {
   1.141 +		gettextprop(c->win, XA_WM_NAME, c->name, sizeof c->name);
   1.142 +	}
   1.143 +}
   1.144 +
   1.145 +
   1.146 +Bool
   1.147 +gettextprop(Window w, Atom atom, char* text, unsigned int size) {
   1.148  	char **list = NULL;
   1.149  	int n;
   1.150  	XTextProperty name;
   1.151  
   1.152 -	name.nitems = 0;
   1.153 -	c->name[0] = 0;
   1.154 -	XGetTextProperty(dpy, c->win, &name, netatom[NetWMName]);
   1.155 +	if (!text || size == 0) {
   1.156 +		return False;
   1.157 +	}
   1.158 +	text[0] = '\0';
   1.159 +	XGetTextProperty(dpy, w, &name, atom);
   1.160  	if(!name.nitems)
   1.161 -		XGetWMName(dpy, c->win, &name);
   1.162 -	if(!name.nitems)
   1.163 -		return;
   1.164 +		return False;
   1.165  	if(name.encoding == XA_STRING)
   1.166 -		strncpy(c->name, (char *)name.value, sizeof c->name);
   1.167 +		strncpy(text, (char *)name.value, size - 1);
   1.168  	else {
   1.169  		if(XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success && n > 0 && *list) {
   1.170 -			strncpy(c->name, *list, sizeof c->name);
   1.171 +			strncpy(text, *list, size - 1);
   1.172  			XFreeStringList(list);
   1.173  		}
   1.174  	}
   1.175 +	text[size - 1] = '\0';
   1.176  	XFree(name.value);
   1.177 +	return True;
   1.178  }
   1.179  
   1.180  void
   1.181 @@ -1370,7 +1367,6 @@
   1.182  
   1.183  void
   1.184  cleanup(void) {
   1.185 -	close(STDIN_FILENO);
   1.186  	while(stack) {
   1.187  		resize(stack, True);
   1.188  		unmanage(stack);
   1.189 @@ -1419,6 +1415,9 @@
   1.190  	XModifierKeymap *modmap;
   1.191  	XSetWindowAttributes wa;
   1.192  
   1.193 +	screen = DefaultScreen(dpy);
   1.194 +	root = RootWindow(dpy, screen);
   1.195 +
   1.196  	/* init atoms */
   1.197  	wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False);
   1.198  	wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
   1.199 @@ -1443,7 +1442,7 @@
   1.200  	XFreeModifiermap(modmap);
   1.201  	/* select for events */
   1.202  	wa.event_mask = SubstructureRedirectMask | SubstructureNotifyMask
   1.203 -		| EnterWindowMask | LeaveWindowMask;
   1.204 +		| EnterWindowMask | LeaveWindowMask | PropertyChangeMask;
   1.205  	wa.cursor = cursor[CurNormal];
   1.206  	XChangeWindowAttributes(dpy, root, CWEventMask | CWCursor, &wa);
   1.207  	grabkeys();
   1.208 @@ -1482,6 +1481,8 @@
   1.209  	XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter);
   1.210  	/* multihead support */
   1.211  	selscreen = XQueryPointer(dpy, root, &w, &w, &i, &i, &i, &i, &mask);
   1.212 +
   1.213 +	updatestatus();
   1.214  }
   1.215  
   1.216  /*
   1.217 @@ -1510,7 +1511,7 @@
   1.218  
   1.219  void
   1.220  quit() {
   1.221 -	readin = running = False;
   1.222 +	running = False;
   1.223  }
   1.224  
   1.225  /* There's no way to check accesses to destroyed windows, thus those cases are
   1.226 @@ -1533,11 +1534,44 @@
   1.227  	return xerrorxlib(dpy, ee); /* may call exit */
   1.228  }
   1.229  
   1.230 +void
   1.231 +checkotherwm(void) {
   1.232 +	otherwm = False;
   1.233 +	xerrorxlib = XSetErrorHandler(xerrorstart);
   1.234 +	/* this causes an error if some other window manager is running */
   1.235 +	XSelectInput(dpy, DefaultRootWindow(dpy), SubstructureRedirectMask);
   1.236 +	XSync(dpy, False);
   1.237 +	if(otherwm) {
   1.238 +		eprint("aewl: another window manager is already running\n");
   1.239 +	}
   1.240 +
   1.241 +	XSetErrorHandler(xerror);
   1.242 +	XSync(dpy, False);
   1.243 +}
   1.244 +
   1.245 +void
   1.246 +run(void) {
   1.247 +	XEvent ev;
   1.248 +
   1.249 +	XSync(dpy, False);
   1.250 +	/* main event loop */
   1.251 +	while(running && !XNextEvent(dpy, &ev)) {
   1.252 +		if(handler[ev.type]) {
   1.253 +			(handler[ev.type])(&ev); /* call handler */
   1.254 +		}
   1.255 +	}
   1.256 +}
   1.257 +
   1.258 +void
   1.259 +updatestatus(void) {
   1.260 +	if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext))) {
   1.261 +		strcpy(stext, "aewl-"VERSION);
   1.262 +	}
   1.263 +	drawbar();
   1.264 +}
   1.265 +
   1.266  int
   1.267  main(int argc, char *argv[]) {
   1.268 -	char *p;
   1.269 -	int r, xfd;
   1.270 -	fd_set rd;
   1.271  
   1.272  	if(argc == 2 && !strncmp("-v", argv[1], 3)) {
   1.273  		fputs("aewl-"VERSION", Copyright 2008  markus schnalke <meillo@marmaro.de>\n", stdout);
   1.274 @@ -1551,63 +1585,13 @@
   1.275  	if(!dpy) {
   1.276  		eprint("aewl: cannot open display\n");
   1.277  	}
   1.278 -	xfd = ConnectionNumber(dpy);
   1.279 -	screen = DefaultScreen(dpy);
   1.280 -	root = RootWindow(dpy, screen);
   1.281 -	otherwm = False;
   1.282 -	XSetErrorHandler(xerrorstart);
   1.283 -	/* this causes an error if some other window manager is running */
   1.284 -	XSelectInput(dpy, root, SubstructureRedirectMask);
   1.285 -	XSync(dpy, False);
   1.286 -	if(otherwm) {
   1.287 -		eprint("aewl: another window manager is already running\n");
   1.288 -	}
   1.289  
   1.290 -	XSync(dpy, False);
   1.291 -	XSetErrorHandler(NULL);
   1.292 -	xerrorxlib = XSetErrorHandler(xerror);
   1.293 -	XSync(dpy, False);
   1.294 +	checkotherwm();
   1.295  	setup();
   1.296 -	drawstatus();
   1.297  	scan();
   1.298 +	run();
   1.299 +	cleanup();
   1.300  
   1.301 -	/* main event loop, also reads status text from stdin */
   1.302 -	XSync(dpy, False);
   1.303 -	procevent();
   1.304 -	readin = True;
   1.305 -	while(running) {
   1.306 -		FD_ZERO(&rd);
   1.307 -		if(readin)
   1.308 -			FD_SET(STDIN_FILENO, &rd);
   1.309 -		FD_SET(xfd, &rd);
   1.310 -		if(select(xfd + 1, &rd, NULL, NULL, NULL) == -1) {
   1.311 -			if(errno == EINTR)
   1.312 -				continue;
   1.313 -			eprint("select failed\n");
   1.314 -		}
   1.315 -		if(FD_ISSET(STDIN_FILENO, &rd)) {
   1.316 -			switch(r = read(STDIN_FILENO, stext, sizeof stext - 1)) {
   1.317 -			case -1:
   1.318 -				strncpy(stext, strerror(errno), sizeof stext - 1);
   1.319 -				stext[sizeof stext - 1] = '\0';
   1.320 -				readin = False;
   1.321 -				break;
   1.322 -			case 0:
   1.323 -				strncpy(stext, "EOF", 4);
   1.324 -				readin = False;
   1.325 -				break;
   1.326 -			default:
   1.327 -				for(stext[r] = '\0', p = stext + strlen(stext) - 1; p >= stext && *p == '\n'; *p-- = '\0');
   1.328 -				for(; p >= stext && *p != '\n'; --p);
   1.329 -				if(p > stext)
   1.330 -					strncpy(stext, p + 1, sizeof stext);
   1.331 -			}
   1.332 -			drawstatus();
   1.333 -		}
   1.334 -		if(FD_ISSET(xfd, &rd))
   1.335 -			procevent();
   1.336 -	}
   1.337 -	cleanup();
   1.338  	XCloseDisplay(dpy);
   1.339  	return 0;
   1.340  }