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);