[PATCH 3/4] winex11.drv: Recognize the keyboard in a locale-independent way.
Giovanni Mascellani
gmascellani at codeweavers.com
Fri Jan 22 05:28:25 CST 2021
Try to recognize the keyboard comparing keysyms instead of converting
them to multibyte strings, which makes the process locale-dependent and
therefore more fragile.
Unfortunately this means that the layout tables might need to be
updated. However, this change is known to fix the recognitions of a few
keys in the French layout.
Signed-off-by: Giovanni Mascellani <gmascellani at codeweavers.com>
---
dlls/winex11.drv/keyboard.c | 64 ++++++++++++++++++-------------------
1 file changed, 31 insertions(+), 33 deletions(-)
diff --git a/dlls/winex11.drv/keyboard.c b/dlls/winex11.drv/keyboard.c
index d9a6879ee04..fe4a29c4b06 100644
--- a/dlls/winex11.drv/keyboard.c
+++ b/dlls/winex11.drv/keyboard.c
@@ -1417,6 +1417,35 @@ BOOL X11DRV_KeyEvent( HWND hwnd, XEvent *xev )
return TRUE;
}
+/* From the point of view of this function there are two types of
+ * keys: those for which the mapping to vkey and scancode depends on
+ * the keyboard layout (i.e., letters, numbers, punctuation) and those
+ * for which it doesn't (control keys); since this function is used to
+ * recognize the keyboard layout and map keysyms to vkeys and
+ * scancodes, we are only concerned about the first type, and map
+ * everything in the second type to zero.
+ */
+static char keysym_to_char( KeySym keysym )
+{
+ /* Dead keys */
+ if (0xfe50 <= keysym && keysym < 0xfed0)
+ return KEYBOARD_MapDeadKeysym( keysym );
+
+ /* Control keys (there is nothing allocated below 0xfc00, but I
+ take some margin in case something is added in the future) */
+ if (0xf000 <= keysym && keysym < 0x10000)
+ return 0;
+
+ /* XFree86 vendor keys */
+ if (0x10000000 <= keysym)
+ return 0;
+
+ /* "Normal" keys: return last octet, because our tables don't have
+ more than that; it would be better to extend the tables and
+ compare the whole keysym, but it's a lot of work... */
+ return keysym & 0xff;
+}
+
/**********************************************************************
* X11DRV_KEYBOARD_DetectLayout
*
@@ -1447,24 +1476,7 @@ X11DRV_KEYBOARD_DetectLayout( Display *display )
/* get data for keycode from X server */
for (i = 0; i < syms; i++) {
if (!(keysym = keycode_to_keysym (display, keyc, i))) continue;
- /* Allow both one-byte and two-byte national keysyms */
- if ((keysym < 0x8000) && (keysym != ' '))
- {
-#ifdef HAVE_XKB
- if (!use_xkb || !XkbTranslateKeySym(display, &keysym, 0, &ckey[keyc][i], 1, NULL))
-#endif
- {
- TRACE("XKB could not translate keysym %04lx\n", keysym);
- /* FIXME: query what keysym is used as Mode_switch, fill XKeyEvent
- * with appropriate ShiftMask and Mode_switch, use XLookupString
- * to get character in the local encoding.
- */
- ckey[keyc][i] = keysym & 0xFF;
- }
- }
- else {
- ckey[keyc][i] = KEYBOARD_MapDeadKeysym(keysym);
- }
+ ckey[keyc][i] = keysym_to_char(keysym);
}
}
@@ -1713,21 +1725,7 @@ void X11DRV_InitKeyboard( Display *display )
int maxlen=0,maxval=-1,ok;
for (i=0; i<syms; i++) {
keysym = keycode_to_keysym(display, keyc, i);
- if ((keysym<0x8000) && (keysym!=' '))
- {
-#ifdef HAVE_XKB
- if (!use_xkb || !XkbTranslateKeySym(display, &keysym, 0, &ckey[i], 1, NULL))
-#endif
- {
- /* FIXME: query what keysym is used as Mode_switch, fill XKeyEvent
- * with appropriate ShiftMask and Mode_switch, use XLookupString
- * to get character in the local encoding.
- */
- ckey[i] = (keysym <= 0x7F) ? keysym : 0;
- }
- } else {
- ckey[i] = KEYBOARD_MapDeadKeysym(keysym);
- }
+ ckey[i] = keysym_to_char(keysym);
}
/* find key with longest match streak */
for (keyn=0; keyn<MAIN_LEN; keyn++) {
--
2.30.0
More information about the wine-devel
mailing list