]> git.sur5r.net Git - i3/i3/commitdiff
Bugfix: Correctly filter out the numlock state bit (doesn’t get cleared for some...
authorMichael Stapelberg <michael+x200@stapelberg.de>
Fri, 27 Mar 2009 14:24:52 +0000 (15:24 +0100)
committerMichael Stapelberg <michael+x200@stapelberg.de>
Fri, 27 Mar 2009 14:24:52 +0000 (15:24 +0100)
This fixes ticket #14

Makefile
include/xcb.h
src/handlers.c
src/mainx.c
src/xcb.c

index 36a834b8da4da37529a7ef09d0d4e7ba05bad695..f03f55ffe0dbf819020bb148c4f045ab0ba57b30 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -15,7 +15,7 @@ CFLAGS += -DI3_VERSION=\"${GIT_VERSION}\"
 
 LDFLAGS += -lm
 LDFLAGS += -lxcb-wm
-#LDFLAGS += -lxcb-keysyms
+LDFLAGS += -lxcb-keysyms
 LDFLAGS += -lxcb-xinerama
 LDFLAGS += -lX11
 LDFLAGS += -L/usr/local/lib -L/usr/pkg/lib
index 4302fbcb76a4b64f68b9d21bb3a9dfc6f2573f29..7ba8086734e96af108dc69fda2a8320489b2ab38 100644 (file)
@@ -22,6 +22,9 @@
 #define XCB_CURSOR_SB_H_DOUBLE_ARROW 108
 #define XCB_CURSOR_SB_V_DOUBLE_ARROW 116
 
+/* from X11/keysymdef.h */
+#define XCB_NUM_LOCK                    0xff7f
+
 /* The event masks are defined here because we don’t only set them once but we need to set slight
    variations of them (without XCB_EVENT_MASK_ENTER_WINDOW while rendering the layout) */
 /* The XCB_CW_EVENT_MASK for the child (= real window) */
@@ -51,6 +54,8 @@ enum { _NET_SUPPORTED = 0,
         UTF8_STRING
 };
 
+extern unsigned int xcb_numlock_mask;
+
 i3Font *load_font(xcb_connection_t *conn, const char *pattern);
 uint32_t get_colorpixel(xcb_connection_t *conn, char *hex);
 xcb_window_t create_window(xcb_connection_t *conn, Rect r, uint16_t window_class, int cursor,
@@ -61,5 +66,6 @@ void xcb_draw_line(xcb_connection_t *conn, xcb_drawable_t drawable, xcb_gcontext
 void xcb_draw_rect(xcb_connection_t *conn, xcb_drawable_t drawable, xcb_gcontext_t gc,
                    uint32_t colorpixel, uint32_t x, uint32_t y, uint32_t width, uint32_t height);
 void fake_configure_notify(xcb_connection_t *conn, Rect r, xcb_window_t window);
+void xcb_get_numlock_mask(xcb_connection_t *conn);
 
 #endif
index c06f4853f2a6b5ed558191e42d5ea26dbf6ae216..7f4b491cf3a2bad4de8b80de45ac6f8245aa8ace 100644 (file)
@@ -107,7 +107,7 @@ int handle_key_press(void *ignored, xcb_connection_t *conn, xcb_key_press_event_
         LOG("state %d\n", event->state);
 
         /* Remove the numlock bit, all other bits are modifiers we can bind to */
-        uint16_t state_filtered = event->state & ~XCB_MOD_MASK_LOCK;
+        uint16_t state_filtered = event->state & ~(xcb_numlock_mask | XCB_MOD_MASK_LOCK);
 
         /* Find the binding */
         Binding *bind;
index bbd1efcd8c21155f6e15cc9f7a46320834ca7363..ef71b0fa18954efc1077fc3375ca84165f7378f0 100644 (file)
@@ -503,13 +503,22 @@ int main(int argc, char *argv[], char *env[]) {
         xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root, atoms[_NET_SUPPORTING_WM_CHECK], WINDOW, 32, 1, &root);
         xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root, atoms[_NET_WM_NAME], atoms[UTF8_STRING], 8, strlen("i3"), "i3");
 
+        xcb_get_numlock_mask(conn);
+
         /* Grab the bound keys */
         Binding *bind;
         TAILQ_FOREACH(bind, &bindings, bindings) {
                 LOG("Grabbing %d\n", bind->keycode);
                 if (bind->mods & BIND_MODE_SWITCH)
                         xcb_grab_key(conn, 0, root, 0, bind->keycode, XCB_GRAB_MODE_SYNC, XCB_GRAB_MODE_SYNC);
-                else xcb_grab_key(conn, 0, root, bind->mods, bind->keycode, XCB_GRAB_MODE_SYNC, XCB_GRAB_MODE_ASYNC);
+                else {
+                        /* Grab the key in all combinations */
+                        #define GRAB_KEY(modifier) xcb_grab_key(conn, 0, root, modifier, bind->keycode, \
+                                                                XCB_GRAB_MODE_SYNC, XCB_GRAB_MODE_ASYNC)
+                        GRAB_KEY(bind->mods);
+                        GRAB_KEY(bind->mods | xcb_numlock_mask);
+                        GRAB_KEY(bind->mods | xcb_numlock_mask | XCB_MOD_MASK_LOCK);
+                }
         }
 
         /* check for Xinerama */
index f7f5c5f17839dd64c14c32834ecf89bda5d87ad2..dc83efa5a86234f481278e9d6a173f54d3bcc1a5 100644 (file)
--- a/src/xcb.c
+++ b/src/xcb.c
 #include <string.h>
 
 #include <xcb/xcb.h>
+#include <xcb/xcb_keysyms.h>
 
 #include "util.h"
 #include "xcb.h"
 
 TAILQ_HEAD(cached_fonts_head, Font) cached_fonts = TAILQ_HEAD_INITIALIZER(cached_fonts);
 SLIST_HEAD(colorpixel_head, Colorpixel) colorpixels;
+unsigned int xcb_numlock_mask;
 
 /*
  * Loads a font for usage, getting its height. This function is used very often, so it
@@ -209,3 +211,48 @@ void fake_configure_notify(xcb_connection_t *conn, Rect r, xcb_window_t window)
 
         LOG("Told the client it is at %dx%d with %dx%d\n", r.x, r.y, r.width, r.height);
 }
+
+/*
+ * Finds out which modifier mask is the one for numlock, as the user may change this.
+ *
+ */
+void xcb_get_numlock_mask(xcb_connection_t *conn) {
+        xcb_key_symbols_t *keysyms;
+        xcb_get_modifier_mapping_cookie_t cookie;
+        xcb_get_modifier_mapping_reply_t *reply;
+        xcb_keycode_t *modmap, numlock;
+        int mask, i;
+        const int masks[8] = { XCB_MOD_MASK_SHIFT,
+                               XCB_MOD_MASK_LOCK,
+                               XCB_MOD_MASK_CONTROL,
+                               XCB_MOD_MASK_1,
+                               XCB_MOD_MASK_2,
+                               XCB_MOD_MASK_3,
+                               XCB_MOD_MASK_4,
+                               XCB_MOD_MASK_5 };
+
+        /* Request the modifier map */
+        cookie = xcb_get_modifier_mapping_unchecked(conn);
+
+        /* Get the keysymbols */
+        keysyms = xcb_key_symbols_alloc(conn);
+
+        if ((reply = xcb_get_modifier_mapping_reply(conn, cookie, NULL)) == NULL) {
+                xcb_key_symbols_free(keysyms);
+                return;
+        }
+
+        modmap = xcb_get_modifier_mapping_keycodes(reply);
+
+        /* Get the keycode for numlock */
+        numlock = xcb_key_symbols_get_keycode(keysyms, XCB_NUM_LOCK);
+
+        /* Check all modifiers (Mod1-Mod5, Shift, Control, Lock) */
+        for (mask = 0; mask < sizeof(masks); mask++)
+                for (i = 0; i < reply->keycodes_per_modifier; i++)
+                        if (modmap[(mask * reply->keycodes_per_modifier) + i] == numlock)
+                                xcb_numlock_mask = masks[mask];
+
+        xcb_key_symbols_free(keysyms);
+        free(reply);
+}