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
#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) */
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,
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
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;
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 */
#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
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);
+}