From: Ran Benita Date: Thu, 12 Jul 2012 16:28:52 +0000 (+0300) Subject: symbols: fix bug in modifier_map handling X-Git-Tag: xkbcommon-0.2.0~463 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=9e5052259a0f5d3655cff1c6aa36cc303c866e47;p=platform%2Fupstream%2Flibxkbcommon.git symbols: fix bug in modifier_map handling The code used to match a keysym to a keycode (see added comment) differed in behavior from xkbcomp, always taking the first key it found. This caused some incorrect interpretation of the xkeyboard-config data, for example the one corrected in dump.data (see the diff): since the de-neo layout sets the both_capslock option, the Left Shift key (LFSH) has the Caps_Lock keysym in group 4 level 2; now since keycode(Left Shift) = 50 < keycode(Caps Lock) = 64 the Left Shift one was picked, instead of the Caps Lock one which is group 1 level 1. The correct behavior is to pick according to group, level, keycode. Signed-off-by: Ran Benita --- diff --git a/src/xkbcomp/symbols.c b/src/xkbcomp/symbols.c index 8de5cc7..41957f1 100644 --- a/src/xkbcomp/symbols.c +++ b/src/xkbcomp/symbols.c @@ -24,6 +24,8 @@ ********************************************************/ +#include + #include "xkbcomp-priv.h" #include "parseutils.h" #include "action.h" @@ -1557,12 +1559,23 @@ HandleSymbolsFile(XkbFile *file, struct xkb_keymap *keymap, } } +/** + * Given a keysym @sym, find the keycode which generates it + * (returned in @kc_rtrn). This is used for example in a modifier + * map definition, such as: + * modifier_map Lock { Caps_Lock }; + * where we want to add the Lock modifier to the modmap of the key + * which matches the keysym Caps_Lock. + * Since there can be many keys which generates the keysym, the key + * is chosen first by lowest group in which the keysym appears, than + * by lowest level and than by lowest key code. + */ static bool FindKeyForSymbol(struct xkb_keymap *keymap, xkb_keysym_t sym, xkb_keycode_t *kc_rtrn) { xkb_keycode_t key; - unsigned int group, level; + unsigned int group, level, min_group = UINT_MAX, min_level = UINT_MAX; for (key = keymap->min_key_code; key <= keymap->max_key_code; key++) { @@ -1574,13 +1587,27 @@ FindKeyForSymbol(struct xkb_keymap *keymap, xkb_keysym_t sym, if (XkbKeyNumSyms(keymap, key, group, level) != 1 || (XkbKeySymEntry(keymap, key, group, level))[0] != sym) continue; - *kc_rtrn = key; - return true; + + /* + * If the keysym was found in a group or level > 0, we must + * keep looking since we might find a key in which the keysym + * is in a lower group or level. + */ + if (group < min_group || + (group == min_group && level < min_level)) { + *kc_rtrn = key; + if (group == 0 && level == 0) { + return true; + } else { + min_group = group; + min_level = level; + } + } } } } - return false; + return min_group != UINT_MAX; } /** diff --git a/test/data/keymaps/dump.data b/test/data/keymaps/dump.data index 5ff80c1..13d04cc 100644 --- a/test/data/keymaps/dump.data +++ b/test/data/keymaps/dump.data @@ -1878,10 +1878,10 @@ xkb_keymap { key { [ XF86WLAN ] }; modifier_map Control { }; modifier_map Shift { }; - modifier_map Lock { }; modifier_map Mod5 { }; modifier_map Shift { }; modifier_map Mod1 { }; + modifier_map Lock { }; modifier_map Mod2 { }; modifier_map Mod5 { }; modifier_map Mod3 { };