# HG changeset patch # User meillo@marmaro.de # Date 1234777257 -3600 # Node ID 3835ddb75a55efd8c62fee051b854395f2cfd28e # Parent a3399a8964c7f41aff433265df8ddcec9d427816 changed to status text setting through XA_WM_NAME (suggested by Neale Pickett) diff -r a3399a8964c7 -r 3835ddb75a55 aewl.c --- a/aewl.c Mon Feb 16 09:23:57 2009 +0100 +++ b/aewl.c Mon Feb 16 10:40:57 2009 +0100 @@ -8,12 +8,9 @@ * events about window (dis-)appearance. Only one X connection at a time is * allowed to select for this event mask. * - * Calls to fetch an X event from the event queue are blocking. Due reading - * status text from standard input, a select()-driven main loop has been - * implemented which selects for reads on the X connection and STDIN_FILENO to - * handle all data smoothly. The event handlers of dwm are organized in an - * array which is accessed whenever a new event has been fetched. This allows - * event dispatching in O(1) time. + * The event handlers of dwm are organized in an array which is accessed + * whenever a new event has been fetched. This allows event dispatching in O(1) + * time. * * Each child of the root window is called a client, except windows which have * set the override_redirect flag. Clients are organized in a global @@ -46,7 +43,6 @@ #include #include #include -#include #include #include #include @@ -145,7 +141,7 @@ Window root, barwin; static int (*xerrorxlib)(Display *, XErrorEvent *); -static Bool otherwm, readin; +static Bool otherwm; static unsigned int len = 0; @@ -160,13 +156,12 @@ void updatetitle(Client *c); /* update the name of c */ void unmanage(Client *c); /* destroy c */ -void drawstatus(void); /* draw the bar */ +void drawbar(void); /* draw the bar */ unsigned long getcolor(const char *colstr); /* return color of colstr */ void setfont(const char *fontstr); /* set the font for DC */ unsigned int textw(const char *text); /* return the width of text in px*/ void grabkeys(void); /* grab all keys defined in config.h */ -void procevent(void); /* process pending X events */ void sendevent(Window w, Atom a, long value); /* send synthetic event to w */ int xerror(Display *dsply, XErrorEvent *ee); /* X error handler */ @@ -195,6 +190,7 @@ void toggletag(void); /* toggles tag of c */ void spawn(const char* cmd); /* forks a new subprocess with cmd */ +void updatestatus(void); /* update the status text */ RULES @@ -374,7 +370,7 @@ Client *c; XEvent ev; - drawstatus(); + drawbar(); if(!sel) return; if(sel->isfloat) @@ -722,7 +718,7 @@ if(ev->count == 0) { if(barwin == ev->window) - drawstatus(); + drawbar(); } } @@ -783,9 +779,11 @@ Window trans; XPropertyEvent *ev = &e->xproperty; - if(ev->state == PropertyDelete) + if((ev->window == root) && (ev->atom = XA_WM_NAME)) + updatestatus(); + else if(ev->state == PropertyDelete) return; /* ignore */ - if((c = getclient(ev->window))) { + else if((c = getclient(ev->window))) { switch (ev->atom) { default: break; case XA_WM_TRANSIENT_FOR: @@ -800,7 +798,7 @@ if(ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) { updatetitle(c); if(c == sel) - drawstatus(); + drawbar(); } } } @@ -850,17 +848,6 @@ } } -void -procevent(void) { - XEvent ev; - - while(XPending(dpy)) { - XNextEvent(dpy, &ev); - if(handler[ev.type]) - (handler[ev.type])(&ev); /* call handler */ - } -} - /* from draw.c */ unsigned int @@ -920,7 +907,7 @@ } void -drawstatus(void) { +drawbar(void) { int x; unsigned long black[ColLast]; black[ColBG] = getcolor("#000000"); @@ -1112,7 +1099,7 @@ grabbuttons(c, True); } sel = c; - drawstatus(); + drawbar(); if(!selscreen) return; if(c) { @@ -1322,26 +1309,36 @@ void updatetitle(Client *c) { + if (!gettextprop(c->win, netatom[NetWMName], c->name, sizeof c->name)) { + gettextprop(c->win, XA_WM_NAME, c->name, sizeof c->name); + } +} + + +Bool +gettextprop(Window w, Atom atom, char* text, unsigned int size) { char **list = NULL; int n; XTextProperty name; - name.nitems = 0; - c->name[0] = 0; - XGetTextProperty(dpy, c->win, &name, netatom[NetWMName]); + if (!text || size == 0) { + return False; + } + text[0] = '\0'; + XGetTextProperty(dpy, w, &name, atom); if(!name.nitems) - XGetWMName(dpy, c->win, &name); - if(!name.nitems) - return; + return False; if(name.encoding == XA_STRING) - strncpy(c->name, (char *)name.value, sizeof c->name); + strncpy(text, (char *)name.value, size - 1); else { if(XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success && n > 0 && *list) { - strncpy(c->name, *list, sizeof c->name); + strncpy(text, *list, size - 1); XFreeStringList(list); } } + text[size - 1] = '\0'; XFree(name.value); + return True; } void @@ -1370,7 +1367,6 @@ void cleanup(void) { - close(STDIN_FILENO); while(stack) { resize(stack, True); unmanage(stack); @@ -1419,6 +1415,9 @@ XModifierKeymap *modmap; XSetWindowAttributes wa; + screen = DefaultScreen(dpy); + root = RootWindow(dpy, screen); + /* init atoms */ wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False); wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False); @@ -1443,7 +1442,7 @@ XFreeModifiermap(modmap); /* select for events */ wa.event_mask = SubstructureRedirectMask | SubstructureNotifyMask - | EnterWindowMask | LeaveWindowMask; + | EnterWindowMask | LeaveWindowMask | PropertyChangeMask; wa.cursor = cursor[CurNormal]; XChangeWindowAttributes(dpy, root, CWEventMask | CWCursor, &wa); grabkeys(); @@ -1482,6 +1481,8 @@ XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter); /* multihead support */ selscreen = XQueryPointer(dpy, root, &w, &w, &i, &i, &i, &i, &mask); + + updatestatus(); } /* @@ -1510,7 +1511,7 @@ void quit() { - readin = running = False; + running = False; } /* There's no way to check accesses to destroyed windows, thus those cases are @@ -1533,11 +1534,44 @@ return xerrorxlib(dpy, ee); /* may call exit */ } +void +checkotherwm(void) { + otherwm = False; + xerrorxlib = XSetErrorHandler(xerrorstart); + /* this causes an error if some other window manager is running */ + XSelectInput(dpy, DefaultRootWindow(dpy), SubstructureRedirectMask); + XSync(dpy, False); + if(otherwm) { + eprint("aewl: another window manager is already running\n"); + } + + XSetErrorHandler(xerror); + XSync(dpy, False); +} + +void +run(void) { + XEvent ev; + + XSync(dpy, False); + /* main event loop */ + while(running && !XNextEvent(dpy, &ev)) { + if(handler[ev.type]) { + (handler[ev.type])(&ev); /* call handler */ + } + } +} + +void +updatestatus(void) { + if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext))) { + strcpy(stext, "aewl-"VERSION); + } + drawbar(); +} + int main(int argc, char *argv[]) { - char *p; - int r, xfd; - fd_set rd; if(argc == 2 && !strncmp("-v", argv[1], 3)) { fputs("aewl-"VERSION", Copyright 2008 markus schnalke \n", stdout); @@ -1551,63 +1585,13 @@ if(!dpy) { eprint("aewl: cannot open display\n"); } - xfd = ConnectionNumber(dpy); - screen = DefaultScreen(dpy); - root = RootWindow(dpy, screen); - otherwm = False; - XSetErrorHandler(xerrorstart); - /* this causes an error if some other window manager is running */ - XSelectInput(dpy, root, SubstructureRedirectMask); - XSync(dpy, False); - if(otherwm) { - eprint("aewl: another window manager is already running\n"); - } - XSync(dpy, False); - XSetErrorHandler(NULL); - xerrorxlib = XSetErrorHandler(xerror); - XSync(dpy, False); + checkotherwm(); setup(); - drawstatus(); scan(); + run(); + cleanup(); - /* main event loop, also reads status text from stdin */ - XSync(dpy, False); - procevent(); - readin = True; - while(running) { - FD_ZERO(&rd); - if(readin) - FD_SET(STDIN_FILENO, &rd); - FD_SET(xfd, &rd); - if(select(xfd + 1, &rd, NULL, NULL, NULL) == -1) { - if(errno == EINTR) - continue; - eprint("select failed\n"); - } - if(FD_ISSET(STDIN_FILENO, &rd)) { - switch(r = read(STDIN_FILENO, stext, sizeof stext - 1)) { - case -1: - strncpy(stext, strerror(errno), sizeof stext - 1); - stext[sizeof stext - 1] = '\0'; - readin = False; - break; - case 0: - strncpy(stext, "EOF", 4); - readin = False; - break; - default: - for(stext[r] = '\0', p = stext + strlen(stext) - 1; p >= stext && *p == '\n'; *p-- = '\0'); - for(; p >= stext && *p != '\n'; --p); - if(p > stext) - strncpy(stext, p + 1, sizeof stext); - } - drawstatus(); - } - if(FD_ISSET(xfd, &rd)) - procevent(); - } - cleanup(); XCloseDisplay(dpy); return 0; }