enum { MOD_Mod1, MOD_Mod4 } modifier = MOD_Mod4;
static char *config_path;
-static xcb_connection_t *conn;
+xcb_connection_t *conn;
static xcb_get_modifier_mapping_reply_t *modmap_reply;
static uint32_t font_id;
static uint32_t font_bold_id;
xcb_get_modifier_mapping_cookie_t modmap_cookie;
modmap_cookie = xcb_get_modifier_mapping(conn);
+ symbols = xcb_key_symbols_alloc(conn);
/* Place requests for the atoms we need as soon as possible */
#define xmacro(atom) \
if (!(modmap_reply = xcb_get_modifier_mapping_reply(conn, modmap_cookie, NULL)))
errx(EXIT_FAILURE, "Could not get modifier mapping\n");
- /* XXX: we should refactor xcb_get_numlock_mask so that it uses the
- * modifier mapping we already have */
- xcb_get_numlock_mask(conn);
-
- symbols = xcb_key_symbols_alloc(conn);
+ xcb_numlock_mask = get_mod_mask_for(XCB_NUM_LOCK, symbols, modmap_reply);
font_id = get_font_id(conn, pattern, &font_height);
font_bold_id = get_font_id(conn, patternbold, &font_bold_height);
return result;
}
-
-/*
- * 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;
- 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 */
-#ifdef OLD_XCB_KEYSYMS_API
- xcb_keycode_t numlock = xcb_key_symbols_get_keycode(keysyms, XCB_NUM_LOCK);
-#else
- /* For now, we only use the first keysymbol. */
- xcb_keycode_t *numlock_syms = xcb_key_symbols_get_keycode(keysyms, XCB_NUM_LOCK);
- if (numlock_syms == NULL)
- return;
- xcb_keycode_t numlock = *numlock_syms;
- free(numlock_syms);
-#endif
-
- /* Check all modifiers (Mod1-Mod5, Shift, Control, Lock) */
- for (mask = 0; mask < 8; 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);
-}
-
xcb_window_t open_input_window(xcb_connection_t *conn, uint32_t width, uint32_t height);
int get_font_id(xcb_connection_t *conn, char *pattern, int *font_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);
#endif
#include <stdarg.h>
#include <xcb/xcb.h>
#include <xcb/xproto.h>
+#include <xcb/xcb_keysyms.h>
/**
* Try to get the socket path from X11 and return NULL if it doesn’t work.
#endif
+/**
+ * All-in-one function which returns the modifier mask (XCB_MOD_MASK_*) for the
+ * given keysymbol, for example for XCB_NUM_LOCK (usually configured to mod2).
+ *
+ * This function initiates one round-trip. Use get_mod_mask_for() directly if
+ * you already have the modifier mapping and key symbols.
+ *
+ */
+uint32_t aio_get_mod_mask_for(uint32_t keysym, xcb_key_symbols_t *symbols);
+
+/**
+ * Returns the modifier mask (XCB_MOD_MASK_*) for the given keysymbol, for
+ * example for XCB_NUM_LOCK (usually configured to mod2).
+ *
+ * This function does not initiate any round-trips.
+ *
+ */
+uint32_t get_mod_mask_for(uint32_t keysym,
+ xcb_key_symbols_t *symbols,
+ xcb_get_modifier_mapping_reply_t *modmap_reply);
+
#endif
*/
void send_take_focus(xcb_window_t window);
-/**
- * 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);
-
/**
* Raises the given window (typically client->frame) above all other windows
*
--- /dev/null
+/*
+ * vim:ts=4:sw=4:expandtab
+ *
+ * i3 - an improved dynamic tiling window manager
+ *
+ * © 2009-2011 Michael Stapelberg and contributors
+ *
+ * See file LICENSE for license information.
+ *
+ */
+#include <stdint.h>
+#include <stdlib.h>
+#include <xcb/xcb.h>
+#include <xcb/xcb_keysyms.h>
+
+#include "libi3.h"
+
+extern xcb_connection_t *conn;
+
+/*
+ * All-in-one function which returns the modifier mask (XCB_MOD_MASK_*) for the
+ * given keysymbol, for example for XCB_NUM_LOCK (usually configured to mod2).
+ *
+ * This function initiates one round-trip. Use get_mod_mask_for() directly if
+ * you already have the modifier mapping and key symbols.
+ *
+ */
+uint32_t aio_get_mod_mask_for(uint32_t keysym, xcb_key_symbols_t *symbols) {
+ xcb_get_modifier_mapping_cookie_t cookie;
+ xcb_get_modifier_mapping_reply_t *modmap_r;
+
+ xcb_flush(conn);
+
+ /* Get the current modifier mapping (this is blocking!) */
+ cookie = xcb_get_modifier_mapping(conn);
+ if (!(modmap_r = xcb_get_modifier_mapping_reply(conn, cookie, NULL)))
+ return 0;
+
+ uint32_t result = get_mod_mask_for(keysym, symbols, modmap_r);
+ free(modmap_r);
+ return result;
+}
+
+/*
+ * Returns the modifier mask (XCB_MOD_MASK_*) for the given keysymbol, for
+ * example for XCB_NUM_LOCK (usually configured to mod2).
+ *
+ * This function does not initiate any round-trips.
+ *
+ */
+uint32_t get_mod_mask_for(uint32_t keysym,
+ xcb_key_symbols_t *symbols,
+ xcb_get_modifier_mapping_reply_t *modmap_reply) {
+ xcb_keycode_t *codes, *modmap;
+ xcb_keycode_t mod_code;
+
+ modmap = xcb_get_modifier_mapping_keycodes(modmap_reply);
+
+ /* Get the list of keycodes for the given symbol */
+ if (!(codes = xcb_key_symbols_get_keycode(symbols, keysym)))
+ return 0;
+
+ /* Loop through all modifiers (Mod1-Mod5, Shift, Control, Lock) */
+ for (int mod = 0; mod < 8; mod++)
+ for (int j = 0; j < modmap_reply->keycodes_per_modifier; j++) {
+ /* Store the current keycode (for modifier 'mod') */
+ mod_code = modmap[(mod * modmap_reply->keycodes_per_modifier) + j];
+ /* Check if that keycode is in the list of previously resolved
+ * keycodes for our symbol. If so, return the modifier mask. */
+ for (xcb_keycode_t *code = codes; *code; code++) {
+ if (*code != mod_code)
+ continue;
+
+ free(codes);
+ /* This corresponds to the XCB_MOD_MASK_* constants */
+ return (1 << mod);
+ }
+ }
+
+ return 0;
+}
DLOG("Received mapping_notify for keyboard or modifier mapping, re-grabbing keys\n");
xcb_refresh_keyboard_mapping(keysyms, event);
- xcb_get_numlock_mask(conn);
+ xcb_numlock_mask = aio_get_mod_mask_for(XCB_NUM_LOCK, keysyms);
ungrab_all_keys(conn);
translate_keysyms();
xcb_key_symbols_free(keysyms);
keysyms = xcb_key_symbols_alloc(conn);
- xcb_get_numlock_mask(conn);
+ xcb_numlock_mask = aio_get_mod_mask_for(XCB_NUM_LOCK, keysyms);
ungrab_all_keys(conn);
DLOG("Re-grabbing...\n");
keysyms = xcb_key_symbols_alloc(conn);
- xcb_get_numlock_mask(conn);
+ xcb_numlock_mask = aio_get_mod_mask_for(XCB_NUM_LOCK, keysyms);
translate_keysyms();
grab_all_keys(conn, false);
free(event);
}
-/*
- * 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;
- 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(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 */
-#ifdef OLD_XCB_KEYSYMS_API
- xcb_keycode_t numlock = xcb_key_symbols_get_keycode(keysyms, XCB_NUM_LOCK);
-#else
- /* For now, we only use the first keysymbol. */
- xcb_keycode_t *numlock_syms = xcb_key_symbols_get_keycode(keysyms, XCB_NUM_LOCK);
- if (numlock_syms == NULL)
- return;
- xcb_keycode_t numlock = *numlock_syms;
- free(numlock_syms);
-#endif
-
- /* Check all modifiers (Mod1-Mod5, Shift, Control, Lock) */
- for (mask = 0; mask < 8; 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);
-}
-
/*
* Raises the given window (typically client->frame) above all other windows
*