From 91134f75c0c99581dd7c4e7aaeabcff673fafc5b Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Sun, 23 Oct 2011 21:26:15 +0100 Subject: [PATCH] Move get_mod_mask to libi3, use it in i3 and i3-config-wizard Also, the API changed a bit. There are two functions now, both assume you already got the keysyms (which is the case for i3 and i3-config-wizard), one gets the modifier mapping for you (aio_get_mod_mask_for) while the other assumes you also got that. No roundtrips are required for the latter. --- i3-config-wizard/main.c | 9 ++--- i3-config-wizard/xcb.c | 55 ---------------------------- i3-config-wizard/xcb.h | 5 --- include/libi3.h | 22 +++++++++++ include/xcb.h | 7 ---- libi3/get_mod_mask.c | 81 +++++++++++++++++++++++++++++++++++++++++ src/handlers.c | 2 +- src/main.c | 4 +- src/xcb.c | 54 --------------------------- 9 files changed, 109 insertions(+), 130 deletions(-) create mode 100644 libi3/get_mod_mask.c diff --git a/i3-config-wizard/main.c b/i3-config-wizard/main.c index 09320dfb..fb916daf 100644 --- a/i3-config-wizard/main.c +++ b/i3-config-wizard/main.c @@ -57,7 +57,7 @@ enum { STEP_WELCOME, STEP_GENERATE } current_step = STEP_WELCOME; 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; @@ -424,6 +424,7 @@ int main(int argc, char *argv[]) { 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) \ @@ -437,11 +438,7 @@ int main(int argc, char *argv[]) { 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); diff --git a/i3-config-wizard/xcb.c b/i3-config-wizard/xcb.c index 4f8eb4da..753568e3 100644 --- a/i3-config-wizard/xcb.c +++ b/i3-config-wizard/xcb.c @@ -104,58 +104,3 @@ int get_font_id(xcb_connection_t *conn, char *pattern, int *font_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); -} - diff --git a/i3-config-wizard/xcb.h b/i3-config-wizard/xcb.h index c2ecedf8..1e5d2d2a 100644 --- a/i3-config-wizard/xcb.h +++ b/i3-config-wizard/xcb.h @@ -12,10 +12,5 @@ extern unsigned int xcb_numlock_mask; 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 diff --git a/include/libi3.h b/include/libi3.h index f4cd2160..ecb72cb5 100644 --- a/include/libi3.h +++ b/include/libi3.h @@ -8,6 +8,7 @@ #include #include #include +#include /** * Try to get the socket path from X11 and return NULL if it doesn’t work. @@ -121,4 +122,25 @@ char *strndup(const char *str, size_t n); #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 diff --git a/include/xcb.h b/include/xcb.h index 9660939d..3670bbcd 100644 --- a/include/xcb.h +++ b/include/xcb.h @@ -97,13 +97,6 @@ void fake_absolute_configure_notify(Con *con); */ 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 * diff --git a/libi3/get_mod_mask.c b/libi3/get_mod_mask.c new file mode 100644 index 00000000..76549220 --- /dev/null +++ b/libi3/get_mod_mask.c @@ -0,0 +1,81 @@ +/* + * 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 +#include +#include +#include + +#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; +} diff --git a/src/handlers.c b/src/handlers.c index 0695f2d0..29dcdc70 100644 --- a/src/handlers.c +++ b/src/handlers.c @@ -286,7 +286,7 @@ static int handle_mapping_notify(xcb_mapping_notify_event_t *event) { 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(); diff --git a/src/main.c b/src/main.c index 958ea653..52c9e2cd 100644 --- a/src/main.c +++ b/src/main.c @@ -178,7 +178,7 @@ static void xkb_got_event(EV_P_ struct ev_io *w, int revents) { 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"); @@ -520,7 +520,7 @@ int main(int argc, char *argv[]) { 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); diff --git a/src/xcb.c b/src/xcb.c index 587f18b3..d9891bfc 100644 --- a/src/xcb.c +++ b/src/xcb.c @@ -173,60 +173,6 @@ void send_take_focus(xcb_window_t window) { 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 *