Added dead keys support using X input methods (based on a patch by
Dmitry Timoshkov).
diff --git a/dlls/x11drv/keyboard.c b/dlls/x11drv/keyboard.c
index 13d3dfc..73c67cd 100644
--- a/dlls/x11drv/keyboard.c
+++ b/dlls/x11drv/keyboard.c
@@ -840,11 +840,14 @@
/* Returns the Windows virtual key code associated with the X event <e> */
/* x11 lock must be held */
-static WORD EVENT_event_to_vkey( XKeyEvent *e)
+static WORD EVENT_event_to_vkey( XIC xic, XKeyEvent *e)
{
KeySym keysym;
- XLookupString(e, NULL, 0, &keysym, NULL);
+ if (xic)
+ XmbLookupString(xic, e, NULL, 0, &keysym, NULL);
+ else
+ XLookupString(e, NULL, 0, &keysym, NULL);
if ((keysym >= 0xFFAE) && (keysym <= 0xFFB9) && (keysym != 0xFFAF)
&& (e->state & NumLockMask))
@@ -988,7 +991,7 @@
WORD vkey = 0, bScan;
DWORD dwFlags;
int ascii_chars;
-
+ XIC xic = X11DRV_get_ic( hwnd );
DWORD event_time = event->time - X11DRV_server_startticks;
/* this allows support for dead keys */
@@ -996,18 +999,12 @@
event->keycode=(event->keycode & 0xff);
wine_tsx11_lock();
- ascii_chars = XLookupString(event, Str, sizeof(Str), &keysym, NULL);
+ if (xic)
+ ascii_chars = XmbLookupString(xic, event, Str, sizeof(Str), &keysym, NULL);
+ else
+ ascii_chars = XLookupString(event, Str, sizeof(Str), &keysym, NULL);
wine_tsx11_unlock();
- /* Ignore some unwanted events */
- if (keysym == XK_ISO_Prev_Group ||
- keysym == XK_ISO_Next_Group ||
- keysym == XK_Mode_switch)
- {
- TRACE("Ignoring %s keyboard event\n", TSXKeysymToString(keysym));
- return;
- }
-
TRACE_(key)("state = %X\n", event->state);
/* If XKB extensions are used, the state mask for AltGr will use the group
@@ -1034,7 +1031,9 @@
}
wine_tsx11_lock();
- vkey = EVENT_event_to_vkey(event);
+ vkey = EVENT_event_to_vkey(xic,event);
+ /* X returns keycode 0 for composed characters */
+ if (!vkey && ascii_chars) vkey = VK_NONAME;
wine_tsx11_unlock();
TRACE_(key)("keycode 0x%x converted to vkey 0x%x\n",
@@ -1123,7 +1122,19 @@
keysym = XKeycodeToKeysym (display, keyc, i);
/* Allow both one-byte and two-byte national keysyms */
if ((keysym < 0x8000) && (keysym != ' '))
- ckey[i] = keysym & 0xFF;
+ {
+#ifdef HAVE_XKB
+ if (!is_xkb || !XkbTranslateKeySym(display, &keysym, 0, &ckey[i], 1, NULL))
+#endif
+ {
+ TRACE("XKB could not translate keysym %ld\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[i] = keysym & 0xFF;
+ }
+ }
else {
ckey[i] = KEYBOARD_MapDeadKeysym(keysym);
}
@@ -1277,8 +1288,18 @@
int maxlen=0,maxval=-1,ok;
for (i=0; i<syms; i++) {
keysym = XKeycodeToKeysym(display, keyc, i);
- if ((keysym<0x800) && (keysym!=' ')) {
- ckey[i] = keysym & 0xFF;
+ if ((keysym<0x800) && (keysym!=' '))
+ {
+#ifdef HAVE_XKB
+ if (!is_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 & 0xFF;
+ }
} else {
ckey[i] = KEYBOARD_MapDeadKeysym(keysym);
}
@@ -1507,7 +1528,7 @@
if ((keyc2vkey[keyc] & 0xFF) == wCode)
{ /* We filter the extended bit, we don't know it */
e.keycode = keyc; /* Store it temporarily */
- if ((EVENT_event_to_vkey(&e) & 0xFF) != wCode) {
+ if ((EVENT_event_to_vkey(0,&e) & 0xFF) != wCode) {
e.keycode = 0; /* Wrong one (ex: because of the NumLock
state), so set it to 0, we'll find another one */
}
@@ -1751,16 +1772,27 @@
KeySym keysym;
INT ret;
int keyc;
- BYTE lpChar[2];
+ char lpChar[2];
+ HWND focus;
+ XIC xic;
if (scanCode & 0x8000)
{
TRACE("Key UP, doing nothing\n" );
return 0;
}
+
e.display = display;
e.keycode = 0;
e.state = 0;
+ e.type = KeyPress;
+
+ focus = GetFocus();
+ if (focus) focus = GetAncestor( focus, GA_ROOT );
+ if (!focus) focus = GetActiveWindow();
+ e.window = X11DRV_get_whole_window( focus );
+ xic = X11DRV_get_ic( focus );
+
if (lpKeyState[VK_SHIFT] & 0x80)
{
TRACE("ShiftMask = %04x\n", ShiftMask);
@@ -1795,7 +1827,7 @@
if ((keyc2vkey[keyc] & 0xFF) == virtKey)
{ /* We filter the extended bit, we don't know it */
e.keycode = keyc; /* Store it temporarily */
- if ((EVENT_event_to_vkey(&e) & 0xFF) != virtKey) {
+ if ((EVENT_event_to_vkey(xic,&e) & 0xFF) != virtKey) {
e.keycode = 0; /* Wrong one (ex: because of the NumLock
state), so set it to 0, we'll find another one */
}
@@ -1808,7 +1840,7 @@
if (virtKey==VK_DECIMAL)
e.keycode = XKeysymToKeycode(e.display, XK_KP_Decimal);
- if (!e.keycode)
+ if (!e.keycode && virtKey != VK_NONAME)
{
WARN("Unknown virtual key %X !!! \n",virtKey);
wine_tsx11_unlock();
@@ -1816,7 +1848,10 @@
}
else TRACE("Found keycode %d (0x%2X)\n",e.keycode,e.keycode);
- ret = XLookupString(&e, (LPVOID)lpChar, 2, &keysym, NULL);
+ if (xic)
+ ret = XmbLookupString(xic, &e, lpChar, 2, &keysym, NULL);
+ else
+ ret = XLookupString(&e, lpChar, 2, &keysym, NULL);
wine_tsx11_unlock();
if (ret == 0)
@@ -1852,7 +1887,7 @@
&& (e.state & ShiftMask) /* Shift is pressed */
&& (keysym>=XK_KP_0) && (keysym<=XK_KP_9))
{
- *(char*)lpChar = 0;
+ lpChar[0] = 0;
ret = 0;
}
@@ -1863,7 +1898,7 @@
if (((keysym>=33) && (keysym < 'A')) ||
((keysym > 'Z') && (keysym < 'a')))
{
- *(char*)lpChar = 0;
+ lpChar[0] = 0;
ret = 0;
}
}
@@ -1872,13 +1907,13 @@
extended keyboard. X returns a char for it, but Windows doesn't */
if (keysym == XK_Delete)
{
- *(char*)lpChar = 0;
+ lpChar[0] = 0;
ret = 0;
}
else if((lpKeyState[VK_SHIFT] & 0x80) /* Shift is pressed */
&& (keysym == XK_KP_Decimal))
{
- *(char*)lpChar = 0;
+ lpChar[0] = 0;
ret = 0;
}
@@ -1887,7 +1922,7 @@
{
TRACE_(key)("Translating char 0x%02x from code page %d to unicode\n",
*(BYTE *)lpChar, main_key_tab[kbd_layout].layout_cp);
- ret = MultiByteToWideChar(main_key_tab[kbd_layout].layout_cp, 0, (LPCSTR)lpChar, ret, bufW, bufW_size);
+ ret = MultiByteToWideChar(main_key_tab[kbd_layout].layout_cp, 0, lpChar, ret, bufW, bufW_size);
}
}