1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
|
From b1ca9ad99eaa709198ac3bdb34ae2c62fe1f87c0 Mon Sep 17 00:00:00 2001
From: Giovanni Mascellani <gmascellani@codeweavers.com>
Date: Mon, 7 Dec 2020 09:31:52 +0100
Subject: [PATCH] winex11.drv: Recognize the keyboard in a locale-independent
way.
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.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=30984
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=45605
CW-Bug-Id: #16793
---
dlls/winex11.drv/keyboard.c | 62 +++++++++++++++++++------------------
1 file changed, 32 insertions(+), 30 deletions(-)
diff --git a/dlls/winex11.drv/keyboard.c b/dlls/winex11.drv/keyboard.c
index 731adc0265b..b561bd997b6 100644
--- a/dlls/winex11.drv/keyboard.c
+++ b/dlls/winex11.drv/keyboard.c
@@ -1440,6 +1440,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
*
@@ -1470,22 +1499,7 @@ X11DRV_KEYBOARD_DetectLayout( Display *display )
/* get data for keycode from X server */
for (i = 0; i < syms; i++) {
if (!(keysym = XkbKeycodeToKeysym( display, keyc, 0, i ))) continue;
- /* Allow both one-byte and two-byte national keysyms */
- if ((keysym < 0x8000) && (keysym != ' '))
- {
- if (!XkbTranslateKeySym(display, &keysym, 0, &ckey[keyc][i], 1, NULL))
- {
- 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);
}
}
@@ -1660,20 +1674,8 @@ void X11DRV_InitKeyboard( Display *display )
/* we seem to need to search the layout-dependent scancodes */
int maxlen=0,maxval=-1,ok;
for (i=0; i<syms; i++) {
- keysym = XkbKeycodeToKeysym( display, keyc, 0, i );
- if ((keysym<0x8000) && (keysym!=' '))
- {
- if (!XkbTranslateKeySym(display, &keysym, 0, &ckey[i], 1, NULL))
- {
- /* 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);
- }
+ keysym = XkbKeycodeToKeysym( display, keyc, 0, i );
+ ckey[i] = keysym_to_char(keysym);
}
/* find key with longest match streak */
for (keyn=0; keyn<MAIN_LEN; keyn++) {
|