tMove window creation and event loop outside the main() - xmenu - drop-down menu for X11
 (HTM) git clone git://git.z3bra.org/xmenu.git
 (DIR) Log
 (DIR) Files
 (DIR) Refs
       ---
 (DIR) commit 61c19bc23c3509c5b1e32afe95f335516fd39d32
 (DIR) parent c6811f6a13d0f8b361c2860ae1c38ac88ac341ec
 (HTM) Author: Willy Goiffon <dev@z3bra.org>
       Date:   Wed, 20 Nov 2019 14:04:43 +0100
       
       Move window creation and event loop outside the main()
       
       Diffstat:
         M xmenu.c                             |     132 +++++++++++++++++++------------
       
       1 file changed, 80 insertions(+), 52 deletions(-)
       ---
 (DIR) diff --git a/xmenu.c b/xmenu.c
       t@@ -42,10 +42,9 @@ hilight(xcb_drawable_t xid, int x, int y, int w, int h)
        
                gc = xcb_generate_id(dpy);
        
       -        mask = XCB_GC_FUNCTION | XCB_GC_LINE_WIDTH | XCB_GC_SUBWINDOW_MODE;
       +        mask = XCB_GC_FUNCTION | XCB_GC_SUBWINDOW_MODE;
                val[0] = XCB_GX_INVERT;
       -        val[1] = 0;
       -        val[2] = XCB_SUBWINDOW_MODE_INCLUDE_INFERIORS;
       +        val[1] = XCB_SUBWINDOW_MODE_INCLUDE_INFERIORS;
                xcb_create_gc(dpy, gc, xid, mask, val);
        
                /* draw inverted rectangle */
       t@@ -73,39 +72,9 @@ drawentries()
        }
        
        int
       -main(int argc, char *argv[])
       +popwindow(int w, int h)
        {
       -        char *argv0;
       -        long dpi;
                int mask, val[4];
       -        xcb_generic_event_t *ev = NULL;
       -
       -        ARGBEGIN {
       -        case 'h':
       -                usage(stdout, argv0);
       -                return 0;
       -                break;
       -        case 'v':
       -                verbose++;
       -                break;
       -        default:
       -                usage(stderr, argv0);
       -                return -1;
       -                break;
       -        } ARGEND;
       -
       -        dpy = xcb_connect(NULL, NULL);
       -        if (xcb_connection_has_error(dpy))
       -                return -1;
       -
       -        screen = xcb_setup_roots_iterator(xcb_get_setup(dpy)).data;
       -        if (!screen)
       -                return -1;
       -
       -        /* 1 inch = 25.4 millimeters */
       -        dpi = screen->height_in_pixels/screen->height_in_millimeters * 25.4;
       -
       -        xft_loadfont(font, dpi);
        
                mask = XCB_CW_BACK_PIXEL
                        | XCB_CW_EVENT_MASK;
       t@@ -120,46 +89,56 @@ main(int argc, char *argv[])
                        | XCB_EVENT_MASK_POINTER_MOTION
                        | XCB_EVENT_MASK_STRUCTURE_NOTIFY;
        
       -        for (nent = 0; entries[nent]; nent++) {
       -                maxwidth  = MAX(xft_txtw(entries[nent]), maxwidth);
       -                maxheight = MAX(xft_txth(entries[nent]), maxheight);
       -        }
       -
       -        width = maxwidth * 1.2;
       -        height = maxheight * nent * 2.5;
       -
                wid = xcb_generate_id(dpy);
                xcb_create_window(dpy, screen->root_depth, wid, screen->root,
       -                0, 0, width, height, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT,
       +                0, 0, w, h, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT,
                        screen->root_visual, mask, val);
        
                xcb_map_window(dpy, wid);
       +        xcb_flush(dpy);
       +
       +        return 0;
       +}
        
       +int
       +eventloop()
       +{
                int loop = 1;
       +        xcb_generic_event_t *ev;
       +
                while(loop) {
                        int last = current;
        
       -                xcb_flush(dpy);
                        ev = xcb_wait_for_event(dpy);
                        if (!ev)
                                break;
        
                        switch(ev->response_type & ~0x80) {
                        case XCB_KEY_PRESS:
       -                        if (((xcb_key_press_event_t *)ev)->detail == 9) {
       -                                current = -1;
       -                                loop = 0;
       -                        }
       +                        if (((xcb_key_press_event_t *)ev)->detail == 9)
       +                                return -1;
                                break;
                        case XCB_BUTTON_RELEASE:
                                if (((xcb_button_release_event_t *)ev)->event == wid)
       -                                loop = 0;
       +                                return current;
                                break;
                        case XCB_CONFIGURE_NOTIFY:
                                width =  ((xcb_configure_notify_event_t *)ev)->width;
                                height = ((xcb_configure_notify_event_t *)ev)->height;
                                break;
                        case XCB_EXPOSE:
       +                        /*
       +                         * TODO: clean after someone mess up current entry
       +                         * As the current entry is represented using an
       +                         * XCB_GX_INVERT function, an external program
       +                         * could mess up the display by drawing over
       +                         * the selection using a non-inverting function.
       +                         * Inverting a partially cleared region would
       +                         * end up inverting the artifacts, so we must
       +                         * find a way to clean up this mess somehow.
       +                         *
       +                         * Damn punks.
       +                         */
                                if (last >= 0)
                                        hilight(wid, 0, (height/nent) * last, width, height/nent);
                                drawentries();
       t@@ -168,7 +147,7 @@ main(int argc, char *argv[])
                                break;
                        case XCB_LEAVE_NOTIFY:
                                hilight(wid, 0, (height/nent) * current, width, height/nent);
       -                        current = last = -1;
       +                        current = -1;
                                break;
                        case XCB_MOTION_NOTIFY:
                                /*
       t@@ -191,11 +170,60 @@ main(int argc, char *argv[])
                                break;
                        }
        
       +                xcb_flush(dpy);
                        free(ev);
                }
        
       -        if (current >= 0)
       -                printf("%s\n", entries[current]);
       +        return -1;
       +}
       +
       +int
       +main(int argc, char *argv[])
       +{
       +        int selected = 0;
       +        long dpi;
       +        char *argv0;
       +
       +        ARGBEGIN {
       +        case 'h':
       +                usage(stdout, argv0);
       +                return 0;
       +                break;
       +        case 'v':
       +                verbose++;
       +                break;
       +        default:
       +                usage(stderr, argv0);
       +                return -1;
       +                break;
       +        } ARGEND;
       +
       +        dpy = xcb_connect(NULL, NULL);
       +        if (xcb_connection_has_error(dpy))
       +                return -1;
       +
       +        screen = xcb_setup_roots_iterator(xcb_get_setup(dpy)).data;
       +        if (!screen)
       +                return -1;
       +
       +        /* 1 inch = 25.4 millimeters */
       +        dpi = screen->height_in_pixels/screen->height_in_millimeters * 25.4;
       +
       +        xft_loadfont(font, dpi);
       +
       +        for (nent = 0; entries[nent]; nent++) {
       +                maxwidth  = MAX(xft_txtw(entries[nent]), maxwidth);
       +                maxheight = MAX(xft_txth(entries[nent]), maxheight);
       +        }
       +
       +        width = maxwidth * 1.2;
       +        height = maxheight * nent * 2.5;
       +
       +        popwindow(width, height);
       +        selected = eventloop();
       +
       +        if (selected >= 0)
       +                printf("%s\n", entries[selected]);
        
                xft_unload();
                xcb_disconnect(dpy);