From 600299a19f36ac43223650c8b47ad827512c957d Mon Sep 17 00:00:00 2001 From: Julien Danjou Date: Tue, 28 Apr 2009 18:17:16 +0200 Subject: [PATCH] key: restore proper support of keysym resolution Signed-off-by: Julien Danjou --- awesome.c | 7 ++++++ common/xutil.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++ common/xutil.h | 4 ++++ event.c | 8 +++++++ key.c | 18 +++++++++------ structs.h | 2 ++ 6 files changed, 94 insertions(+), 7 deletions(-) diff --git a/awesome.c b/awesome.c index 219431af4..530e756bc 100644 --- a/awesome.c +++ b/awesome.c @@ -458,6 +458,8 @@ main(int argc, char **argv) /* Allocate the key symbols */ globalconf.keysyms = xcb_key_symbols_alloc(globalconf.connection); + xcb_get_modifier_mapping_cookie_t xmapping_cookie = + xcb_get_modifier_mapping_unchecked(globalconf.connection); /* init atom cache */ atoms_init(globalconf.connection); @@ -477,6 +479,11 @@ main(int argc, char **argv) for(colors_nbr = 0; colors_nbr < 2; colors_nbr++) xcolor_init_reply(colors_reqs[colors_nbr]); + xutil_lock_mask_get(globalconf.connection, xmapping_cookie, + globalconf.keysyms, &globalconf.numlockmask, + &globalconf.shiftlockmask, &globalconf.capslockmask, + &globalconf.modeswitchmask); + /* do this only for real screen */ for(screen_nbr = 0; screen_nbr < xcb_setup_roots_length(xcb_get_setup(globalconf.connection)); diff --git a/common/xutil.c b/common/xutil.c index cd935ad7c..d62af8eef 100644 --- a/common/xutil.c +++ b/common/xutil.c @@ -19,6 +19,9 @@ * */ +/* XCB doesn't provide keysyms definition */ +#include + #include "common/util.h" #include @@ -82,6 +85,65 @@ xutil_text_prop_get(xcb_connection_t *conn, xcb_window_t w, xcb_atom_t atom, return true; } +/** Get the lock masks (shiftlock, numlock, capslock, modeswitch). + * \param connection The X connection. + * \param cookie The cookie of the request. + * \param keysyms Key symbols. + * \param numlockmask Numlock mask. + * \param shiftlockmask Shiftlock mask. + * \param capslockmask Capslock mask. + * \todo Split this. + */ +void +xutil_lock_mask_get(xcb_connection_t *connection, + xcb_get_modifier_mapping_cookie_t cookie, + xcb_key_symbols_t *keysyms, + uint16_t *numlockmask, + uint16_t *shiftlockmask, + uint16_t *capslockmask, + uint16_t *modeswitchmask) +{ + xcb_get_modifier_mapping_reply_t *modmap_r; + xcb_keycode_t *modmap, kc; + xcb_keycode_t *numlockcodes = xcb_key_symbols_get_keycode(keysyms, XK_Num_Lock); + xcb_keycode_t *shiftlockcodes = xcb_key_symbols_get_keycode(keysyms, XK_Shift_Lock); + xcb_keycode_t *capslockcodes = xcb_key_symbols_get_keycode(keysyms, XK_Caps_Lock); + xcb_keycode_t *modeswitchcodes = xcb_key_symbols_get_keycode(keysyms, XK_Mode_switch); + + modmap_r = xcb_get_modifier_mapping_reply(connection, cookie, NULL); + modmap = xcb_get_modifier_mapping_keycodes(modmap_r); + + /* reset */ + *numlockmask = *shiftlockmask = *capslockmask = *modeswitchmask = 0; + + int i; + for(i = 0; i < 8; i++) + for(int j = 0; j < modmap_r->keycodes_per_modifier; j++) + { + kc = modmap[i * modmap_r->keycodes_per_modifier + j]; + +#define LOOK_FOR(mask, codes) \ + if(*mask == 0 && codes) \ + for(xcb_keycode_t *ktest = codes; *ktest; ktest++) \ + if(*ktest == kc) \ + { \ + *mask = (1 << i); \ + break; \ + } + + LOOK_FOR(numlockmask, numlockcodes) + LOOK_FOR(shiftlockmask, shiftlockcodes) + LOOK_FOR(capslockmask, capslockcodes) + LOOK_FOR(modeswitchmask, modeswitchcodes) +#undef LOOK_FOR + } + p_delete(&numlockcodes); + p_delete(&shiftlockcodes); + p_delete(&capslockcodes); + p_delete(&modeswitchcodes); + p_delete(&modmap_r); +} + /* Number of different errors */ #define ERRORS_NBR 256 diff --git a/common/xutil.h b/common/xutil.h index cd23816c5..6ecc0d311 100644 --- a/common/xutil.h +++ b/common/xutil.h @@ -31,6 +31,10 @@ bool xutil_text_prop_get(xcb_connection_t *, xcb_window_t, xcb_atom_t, char **, ssize_t *); +void xutil_lock_mask_get(xcb_connection_t *, xcb_get_modifier_mapping_cookie_t, + xcb_key_symbols_t *, + uint16_t *, uint16_t *, uint16_t *, uint16_t *); + /** Set the same handler for all errors */ void xutil_error_handler_catch_all_set(xcb_event_handlers_t *, xcb_generic_error_handler_t, void *); diff --git a/event.c b/event.c index 815f23bb8..452107b79 100644 --- a/event.c +++ b/event.c @@ -792,10 +792,18 @@ event_handle_mappingnotify(void *data, if(ev->request == XCB_MAPPING_MODIFIER || ev->request == XCB_MAPPING_KEYBOARD) { + xcb_get_modifier_mapping_cookie_t xmapping_cookie = + xcb_get_modifier_mapping_unchecked(globalconf.connection); + /* Free and then allocate the key symbols */ xcb_key_symbols_free(globalconf.keysyms); globalconf.keysyms = xcb_key_symbols_alloc(globalconf.connection); + xutil_lock_mask_get(globalconf.connection, xmapping_cookie, + globalconf.keysyms, &globalconf.numlockmask, + &globalconf.shiftlockmask, &globalconf.capslockmask, + &globalconf.modeswitchmask); + int nscreen = xcb_setup_roots_length(xcb_get_setup(connection)); /* regrab everything */ diff --git a/key.c b/key.c index 8713ebb31..896d20b9c 100644 --- a/key.c +++ b/key.c @@ -95,9 +95,9 @@ key_getkeysym(xcb_keycode_t detail, uint16_t state) * according to modifier (XCB doesn't provide an equivalent to * XLookupString()). * - * If Mod5 is ON we look into second group. + * If Mode_Switch is ON we look into second group. */ - if(state & XCB_MOD_MASK_5) + if(state & globalconf.modeswitchmask) { k0 = xcb_key_symbols_get_keysym(globalconf.keysyms, detail, 2); k1 = xcb_key_symbols_get_keysym(globalconf.keysyms, detail, 3); @@ -114,11 +114,12 @@ key_getkeysym(xcb_keycode_t detail, uint16_t state) /* The numlock modifier is on and the second KeySym is a keypad * KeySym */ - if((state & XCB_MOD_MASK_2) && xcb_is_keypad_key(k1)) + if((state & globalconf.numlockmask) && xcb_is_keypad_key(k1)) { /* The Shift modifier is on, or if the Lock modifier is on and * is interpreted as ShiftLock, use the first KeySym */ - if((state & XCB_MOD_MASK_SHIFT) || (state & XCB_MOD_MASK_LOCK)) + if((state & XCB_MOD_MASK_SHIFT) + || (state & XCB_MOD_MASK_LOCK && (state & globalconf.shiftlockmask))) return k0; else return k1; @@ -131,7 +132,8 @@ key_getkeysym(xcb_keycode_t detail, uint16_t state) /* The Shift modifier is off and the Lock modifier is on and is * interpreted as CapsLock */ - else if(!(state & XCB_MOD_MASK_SHIFT) && (state & XCB_MOD_MASK_LOCK)) + else if(!(state & XCB_MOD_MASK_SHIFT) + && (state & XCB_MOD_MASK_LOCK && (state & globalconf.capslockmask))) /* The first Keysym is used but if that KeySym is lowercase * alphabetic, then the corresponding uppercase KeySym is used * instead */ @@ -139,7 +141,8 @@ key_getkeysym(xcb_keycode_t detail, uint16_t state) /* The Shift modifier is on, and the Lock modifier is on and is * interpreted as CapsLock */ - else if((state & XCB_MOD_MASK_SHIFT) && (state & XCB_MOD_MASK_LOCK)) + else if((state & XCB_MOD_MASK_SHIFT) + && (state & XCB_MOD_MASK_LOCK && (state & globalconf.capslockmask))) /* The second Keysym is used but if that KeySym is lowercase * alphabetic, then the corresponding uppercase KeySym is used * instead */ @@ -147,7 +150,8 @@ key_getkeysym(xcb_keycode_t detail, uint16_t state) /* The Shift modifer is on, or the Lock modifier is on and is * interpreted as ShiftLock, or both */ - else if((state & XCB_MOD_MASK_SHIFT) || (state & XCB_MOD_MASK_LOCK)) + else if((state & XCB_MOD_MASK_SHIFT) + || (state & XCB_MOD_MASK_LOCK && (state & globalconf.shiftlockmask))) return k1; return XCB_NO_SYMBOL; diff --git a/structs.h b/structs.h index 64d40d954..7da52e414 100644 --- a/structs.h +++ b/structs.h @@ -70,6 +70,8 @@ struct awesome_t key_array_t keys; /** Root window mouse bindings */ button_array_t buttons; + /** Modifiers masks */ + uint16_t numlockmask, shiftlockmask, capslockmask, modeswitchmask; /** Check for XRandR extension */ bool have_randr; /** Check for XTest extension */