XKB allows a user to define multiple groups (layouts) for their
keyboard, switching between them on the fly. When converting keycodes to
KeySyms one has to be careful about which group they look at. Not every
keycode has to define KeySyms for every available group, and XKB
calculates an "effective" group number in such cases. At the moment
xsetwacom only uses the "current" group number which won't always work.

The following commands exhibit one example of how the bug may be
reproduced:

    $ setxkbmap us,dvorak -option grp:caps_toggle
    $ xsetwacom set <id> button 1 key ctrl
    [ button 1 should work as expected ]
    [ now press CAPSLOCK to switch to Dvorak ]
    $ xsetwacom set <id> button 1 key ctrl
    [ a warning is printed if the bug exists ]

To reset the keyboard back e.g. to the 'us' layout after running the
above commands:

    $ setxkbmap us -option

Fixes: http://sourceforge.net/p/linuxwacom/bugs/269/
Signed-off-by: Jason Gerecke <killert...@gmail.com>
---
 tools/xsetwacom.c | 46 ++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 38 insertions(+), 8 deletions(-)

diff --git a/tools/xsetwacom.c b/tools/xsetwacom.c
index 3d6b417..ec5d24e 100644
--- a/tools/xsetwacom.c
+++ b/tools/xsetwacom.c
@@ -1071,12 +1071,41 @@ static int special_map_button(Display *dpy, int argc, 
char **argv, unsigned long
        return i;
 }
 
-/* Return the first keycode to have the required keysym in the current group.
-   TODOs:
-   - parse other groups as well (do we need this?)
-   - for keysyms not on level 0, return the keycodes for the modifiers as
-     well
-*/
+/**
+ * Return the effective group number for a given keycode and requested
+ * global group number. If the group number is in-range for the keycode,
+ * the returned value will be identical. If the group number is out of
+ * range, the returned value will be wrapped, clamped, or redirected as
+ * necessary.
+ */
+static int keycode_effective_group(XkbDescPtr xkb, int keycode, int group)
+{
+       unsigned char info = XkbKeyGroupInfo(xkb, keycode);
+       unsigned char action = XkbOutOfRangeGroupInfo(info);
+       int n = XkbKeyNumGroups(xkb, keycode);
+
+       if (n <= 0)
+               return 0;
+       else if (group < n && group >= 0)
+               return group;
+       else if (action == XkbRedirectIntoRange)
+               return XkbOutOfRangeGroupNumber(info);
+       else if (action == XkbClampIntoRange)
+               return group < 1 ? 0 : group-1;
+       else /* if XkbWrapIntoRange */
+               return group % n;
+}
+
+/**
+ * Return the first keycode to have the required keysym. The effective
+ * group number is used durring scanning to ensure that an appropriate
+ * keycode is returned even if the active group does not define all
+ * keycodes.
+ *
+ *  TODOs:
+ *  - for keysyms not on level 0, return the keycodes for the modifiers as
+ *    well
+ */
 static int keysym_to_keycode(Display *dpy, KeySym sym)
 {
        static XkbDescPtr xkb = NULL;
@@ -1090,10 +1119,11 @@ static int keysym_to_keycode(Display *dpy, KeySym sym)
 
        for (kc = xkb->min_key_code; kc <= xkb->max_key_code; kc++)
        {
+               int group = keycode_effective_group(xkb, kc, state.group);
                int i;
 
-               for (i = 0; i < XkbKeyGroupWidth(xkb, kc, state.group); i++)
-                       if (XkbKeycodeToKeysym(dpy, kc, state.group, i) == sym)
+               for (i = 0; i < XkbKeyGroupWidth(xkb, kc, group); i++)
+                       if (XkbKeycodeToKeysym(dpy, kc, group, i) == sym)
                                goto out;
        }
 
-- 
2.1.3


------------------------------------------------------------------------------
New Year. New Location. New Benefits. New Data Center in Ashburn, VA.
GigeNET is offering a free month of service with a new server in Ashburn.
Choose from 2 high performing configs, both with 100TB of bandwidth.
Higher redundancy.Lower latency.Increased capacity.Completely compliant.
www.gigenet.com
_______________________________________________
Linuxwacom-devel mailing list
Linuxwacom-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxwacom-devel

Reply via email to