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 }