]> git.sur5r.net Git - i3/i3/commitdiff
Implement hide-on-modifier
authorAxel Wagner <mail@merovius.de>
Wed, 25 Aug 2010 14:23:30 +0000 (16:23 +0200)
committerAxel Wagner <mail@merovius.de>
Wed, 25 Aug 2010 16:11:06 +0000 (18:11 +0200)
i3bar/common.mk
i3bar/src/xcb.c

index 655883144a66e7132cb38ee1af4ad0ca5ce3cbac..1df1f6fb1210a491c9a40f35bc508b96a78e18f5 100644 (file)
@@ -15,6 +15,7 @@ LDFLAGS += -lev
 LDFLAGS += -lyajl
 LDFLAGS += -lxcb
 LDFLAGS += -lxcb-atom
+LDFLAGS += -lX11
 LDFLAGS += -L/usr/local/lib
 
 ifeq ($(DEBUG),1)
index a11a4e9acad42fc3a03d283ab670a03885716c5d..45ed79cc51c7428b96e2d147c811d92c6a9c1f73 100644 (file)
 #include <xcb/xcb_event.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
 #include <string.h>
 #include <i3/ipc.h>
 #include <ev.h>
 
+#include <X11/Xlib.h>
+#include <X11/XKBlib.h>
+#include <X11/extensions/XKB.h>
+
 #include "common.h"
 
 /* We save the Atoms in an easy to access array, indexed by an enum */
@@ -36,10 +42,15 @@ xcb_screen_t     *xcb_screens;
 xcb_window_t     xcb_root;
 xcb_font_t       xcb_font;
 
+Display          *xkb_dpy;
+int              xkb_event_base;
+int              mod_pressed;
+
 /* Event-Watchers, to interact with the user */
 ev_prepare *xcb_prep;
 ev_check   *xcb_chk;
 ev_io      *xcb_io;
+ev_io      *xkb_io;
 
 /*
  * Converts a colorstring to a colorpixel as expected from xcb_change_gc.
@@ -56,6 +67,54 @@ uint32_t get_colorpixel(const char *s) {
     return (r << 16 | g << 8 | b);
 }
 
+/*
+ * Hides all bars (unmaps them)
+ *
+ */
+void hide_bars() {
+    i3_output *walk;
+    SLIST_FOREACH(walk, outputs, slist) {
+        xcb_unmap_window(xcb_connection, walk->bar);
+    }
+}
+
+/*
+ * Unhides all bars (maps them)
+ *
+ */
+void unhide_bars() {
+    i3_output           *walk;
+    xcb_void_cookie_t   cookie;
+    xcb_generic_error_t *err;
+    uint32_t            mask;
+    uint32_t            values[4];
+
+    SLIST_FOREACH(walk, outputs, slist) {
+        if (walk->bar == XCB_NONE) {
+            continue;
+        }
+        mask = XCB_CONFIG_WINDOW_X |
+               XCB_CONFIG_WINDOW_Y |
+               XCB_CONFIG_WINDOW_WIDTH |
+               XCB_CONFIG_WINDOW_HEIGHT;
+        values[0] = walk->rect.x;
+        values[1] = walk->rect.y + walk->rect.h - font_height - 6;
+        values[2] = walk->rect.w;
+        values[3] = font_height + 6;
+        printf("Reconfiguring Window for output %s to %d,%d\n", walk->name, values[0], values[1]);
+        cookie = xcb_configure_window_checked(xcb_connection,
+                                              walk->bar,
+                                              mask,
+                                              values);
+
+        if ((err = xcb_request_check(xcb_connection, cookie)) != NULL) {
+            printf("ERROR: Could not reconfigure window. XCB-errorcode: %d\n", err->error_code);
+            exit(EXIT_FAILURE);
+        }
+        xcb_map_window(xcb_connection, walk->bar);
+    }
+}
+
 /*
  * Handle a button-press-event (i.c. a mouse click on one of our bars).
  * We determine, wether the click occured on a ws-button or if the scroll-
@@ -175,6 +234,45 @@ void xcb_chk_cb(struct ev_loop *loop, ev_check *watcher, int revents) {
 void xcb_io_cb(struct ev_loop *loop, ev_io *watcher, int revents) {
 }
 
+/*
+ * We need to bind to the modifier per XKB. Sadly, XCB does not implement this
+ *
+ */
+void xkb_io_cb(struct ev_loop *loop, ev_io *watcher, int revents) {
+    XkbEvent ev;
+    int modstate;
+
+    printf("Got XKB-Event!\n");
+
+    while (XPending(xkb_dpy)) {
+        XNextEvent(xkb_dpy, (XEvent*)&ev);
+
+        if (ev.type != xkb_event_base) {
+            printf("ERROR: No Xkb-Event!\n");
+            continue;
+        }
+
+        if (ev.any.xkb_type != XkbStateNotify) {
+            printf("ERROR: No State Notify!\n");
+            continue;
+        }
+
+        unsigned int mods = ev.state.mods;
+        modstate = mods & Mod4Mask;
+    }
+
+    if (modstate != mod_pressed) {
+        if (modstate == 0) {
+            printf("Mod4 got released!\n");
+            hide_bars();
+        } else {
+            printf("Mod4 got pressed!\n");
+            unhide_bars();
+        }
+        mod_pressed = modstate;
+    }
+}
+
 /*
  * Calculate the rendered width of a string with the configured font.
  * The string has to be encoded in ucs2 and glyph_len has to be the length
@@ -242,18 +340,55 @@ void init_xcb(char *fontname) {
                                                 strlen(fontname),
                                                 fontname);
 
+    int xkb_major, xkb_minor, xkb_errbase, xkb_err;
+    xkb_major = XkbMajorVersion;
+    xkb_minor = XkbMinorVersion;
+
+    xkb_dpy = XkbOpenDisplay(":0",
+                             &xkb_event_base,
+                             &xkb_errbase,
+                             &xkb_major,
+                             &xkb_minor,
+                             &xkb_err);
+
+    if (xkb_dpy == NULL) {
+        printf("ERROR: No XKB!\n");
+        exit(EXIT_FAILURE);
+    }
+
+    if (fcntl(ConnectionNumber(xkb_dpy), F_SETFD, FD_CLOEXEC) == -1) {
+        fprintf(stderr, "Could not set FD_CLOEXEC on xkbdpy\n");
+        exit(EXIT_FAILURE);
+    }
+
+    int i1;
+    if (!XkbQueryExtension(xkb_dpy, &i1, &xkb_event_base, &xkb_errbase, &xkb_major, &xkb_minor)) {
+        printf("ERROR: XKB not supported by X-server!\n");
+        exit(EXIT_FAILURE);
+    }
+
+    if (!XkbSelectEvents(xkb_dpy, XkbUseCoreKbd, XkbStateNotifyMask, XkbStateNotifyMask)) {
+        printf("Could not grab Key!\n");
+        exit(EXIT_FAILURE);
+    }
+
     /* The varios Watchers to communicate with xcb */
     xcb_io = malloc(sizeof(ev_io));
     xcb_prep = malloc(sizeof(ev_prepare));
     xcb_chk = malloc(sizeof(ev_check));
+    xkb_io = malloc(sizeof(ev_io));
 
     ev_io_init(xcb_io, &xcb_io_cb, xcb_get_file_descriptor(xcb_connection), EV_READ);
     ev_prepare_init(xcb_prep, &xcb_prep_cb);
     ev_check_init(xcb_chk, &xcb_chk_cb);
+    ev_io_init(xkb_io, &xkb_io_cb, ConnectionNumber(xkb_dpy), EV_READ);
 
     ev_io_start(main_loop, xcb_io);
     ev_prepare_start(main_loop, xcb_prep);
     ev_check_start(main_loop, xcb_chk);
+    ev_io_start(main_loop, xkb_io);
+
+    XFlush(xkb_dpy);
 
     /* Now we get the atoms and save them in a nice data-structure */
     get_atoms();