tabbed

tab interface for application supporting Xembed
git clone git://git.suckless.org/tabbed
Log | Files | Refs | README | LICENSE

commit 89622e41b248eb18ee7b36aa3f95f9eb4b4ad4a0
parent 9f9e39604dc3dbcc8b6b56b421a110548ec608fb
Author: Enno Boland (tox) <tox@s01.de>
Date:   Mon, 26 Oct 2009 16:50:38 +0100

code cleaning, windows are properly closed on exit; if last client quits, exit
Diffstat:
Mconfig.def.h | 4+---
Mtabbed.c | 57++++++++++++++++++++++++++++++---------------------------
2 files changed, 31 insertions(+), 30 deletions(-)

diff --git a/config.def.h b/config.def.h @@ -7,12 +7,10 @@ static const int tabwidth = 200; static const char before[] = "<"; static const char after[] = ">"; -#define EXEC "surf", "-e", winid #define MODKEY ControlMask static Key keys[] = { \ /* modifier key function argument */ - { MODKEY|ShiftMask, XK_Return, spawn, { .v = (char*[]){ EXEC, NULL} } }, - { MODKEY|ShiftMask, XK_t, spawn, { .v = (char*[]){ EXEC, NULL} } }, + { MODKEY|ShiftMask, XK_Return, spawn, { .v = (char*[]){ "surf", "-e", winid, NULL} } }, { MODKEY|ShiftMask, XK_l, rotate, { .i = +1 } }, { MODKEY|ShiftMask, XK_h, rotate, { .i = -1 } }, { MODKEY, XK_1, move, { .i = 1 } }, diff --git a/tabbed.c b/tabbed.c @@ -47,11 +47,9 @@ #define LENGTH(x) (sizeof x / sizeof x[0]) #define CLEANMASK(mask) (mask & ~(numlockmask|LockMask)) #define TEXTW(x) (textnw(x, strlen(x)) + dc.font.height) -#define XEMBED_EMBEDDED_NOTIFY 0 enum { ColFG, ColBG, ColLast }; /* color */ -enum { NetSupported, NetWMName, NetLast }; /* EWMH atoms */ -enum { WMProtocols, WMDelete, WMState, WMLast }; /* default atoms */ +enum { WMProtocols, WMDelete, WMLast }; /* default atoms */ typedef union { int i; @@ -147,10 +145,10 @@ static void (*handler[LASTEvent]) (const XEvent *) = { }; static int bh, wx, wy, ww, wh; static unsigned int numlockmask = 0; -static Bool running = True, badwindow = False; +static Bool running = True, hadclients = False; static Display *dpy; static DC dc; -static Atom wmatom[WMLast], netatom[NetLast], xembedatom; +static Atom wmatom[WMLast], xembedatom; static Window root, win; static Client *clients = NULL, *sel = NULL; static int (*xerrorxlib)(Display *, XErrorEvent *); @@ -177,6 +175,15 @@ buttonpress(const XEvent *e) { void cleanup(void) { + Client *c, *n; + + for(c = clients; c; c = n) { + killclient(NULL); + focus(c); + XReparentWindow(dpy, c->win, root, 0, 0); + n = c->next; + unmanage(c); + } if(dc.font.set) XFreeFontSet(dpy, dc.font.set); else @@ -191,9 +198,9 @@ void clientmessage(const XEvent *e) { const XClientMessageEvent *ev = &e->xclient; - if(ev->message_type == xembedatom) { - printf("%ld %ld %ld %ld %ld\n", ev->data.l[0], ev->data.l[1], ev->data.l[2], ev->data.l[3], ev->data.l[4]); - } + if(ev->message_type == wmatom[WMProtocols] + && ev->data.l[0] == wmatom[WMDelete]) + running = False; } void @@ -552,14 +559,11 @@ manage(Window w) { Client *c; XEvent e; + hadclients = True; XWithdrawWindow(dpy, w, 0); XReparentWindow(dpy, w, win, 0, bh); XSelectInput(dpy, w, PropertyChangeMask|StructureNotifyMask|EnterWindowMask); XSync(dpy, False); - if(badwindow) { - badwindow = False; - return; - } for(i = 0; i < LENGTH(keys); i++) { if((code = XKeysymToKeycode(dpy, keys[i].keysym))) for(j = 0; j < LENGTH(modifiers); j++) @@ -679,9 +683,6 @@ setup(void) { /* init atoms */ wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False); wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False); - wmatom[WMState] = XInternAtom(dpy, "WM_STATE", False); - netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False); - netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False); xembedatom = XInternAtom(dpy, "_XEMBED", False); /* init appearance */ wx = 0; @@ -701,12 +702,13 @@ setup(void) { XMapRaised(dpy, win); XSelectInput(dpy, win, SubstructureNotifyMask|FocusChangeMask| ButtonPressMask|ExposureMask|KeyPressMask| - StructureNotifyMask); + StructureNotifyMask|SubstructureRedirectMask); xerrorxlib = XSetErrorHandler(xerror); XClassHint class_hint; class_hint.res_name = "tabbed"; class_hint.res_class = "Tabbed"; XSetClassHint(dpy, win, &class_hint); + XSetWMProtocols(dpy, win, &wmatom[WMDelete], 1); snprintf(winid, LENGTH(winid), "%u", (int)win); focus(clients); } @@ -749,14 +751,16 @@ unmanage(Client *c) { if(!clients) return; else if(c == clients) - clients = c->next; + pc = clients = c->next; else { for(pc = clients; pc && pc->next && pc->next != c; pc = pc->next); pc->next = c->next; } + focus(c->next ? c->next : pc); free(c); - focus(clients); XSync(dpy, False); + if(hadclients && !clients) + running = False; } void @@ -798,10 +802,6 @@ updatetitle(Client *c) { * default error handler, which may call exit. */ int xerror(Display *dpy, XErrorEvent *ee) { - if(ee->error_code == BadWindow) { - badwindow = True; - return 0; - } fprintf(stderr, "tabbed: fatal error: request code=%d, error code=%d\n", ee->request_code, ee->error_code); return xerrorxlib(dpy, ee); /* may call exit */ @@ -825,12 +825,15 @@ main(int argc, char *argv[]) { setup(); printf("%i\n", (int)win); fflush(NULL); - if(detach && fork() != 0) { - if(dpy) - close(ConnectionNumber(dpy)); - return EXIT_SUCCESS; + if(detach) { + if(fork() == 0) + fclose(stdout); + else { + if(dpy) + close(ConnectionNumber(dpy)); + return EXIT_SUCCESS; + } } - fclose(stdout); run(); cleanup(); XCloseDisplay(dpy);