code cleaning, windows are properly closed on exit; if last client quits, exit - ttabbed - Simple tabbing application for X11.
       
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit 89622e41b248eb18ee7b36aa3f95f9eb4b4ad4a0
 (DIR) parent 9f9e39604dc3dbcc8b6b56b421a110548ec608fb
 (HTM) 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:
         config.def.h                        |       4 +---
         tabbed.c                            |      57 ++++++++++++++++---------------
       
       2 files changed, 31 insertions(+), 30 deletions(-)
       ---
 (DIR) 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 } },
 (DIR) 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 */
        
        ttypedef 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);