Handle control characters in VkKeyScanEx similar to what Windows does

Dmitry Timoshkov dmitry at baikal.ru
Mon Mar 28 07:57:44 CST 2005


Hello,

Ulrich Czekalla reported that an application he is working on calls
VkKeyScan(0xa) which fails under Wine. The app uses VkKeyScan to build
INPUT structures for SendInput.

I wrote a simple test app which dumps VkKeyScan output for characters
below 32 and uses MapVirtualKey to verify returned values under WIndows.

for (i = 0; i < 32; i++)
{
    vkey = VkKeyScan(i);
    printf("VkKeyScan(%d) -> 0x%04x\n", i, vkey);
    vkey &= 0xff;
    scan = MapVirtualKey(vkey, 2);
    printf("MapVirtualKey(0x%04x) -> %d (0x%04x)\n", vkey, scan, scan);
}

Windows appears to add 0x240 to each not directly translated to a vkey
passed character. 0x200 aparently indicates a control char. What means 0x40
I don't know, and MSDN doesn't explain it either, perhaps that's just a fixup.

Attached patch seems to produce the results which resemble Windows behaviour
close enough.

Changelog:
    Dmitry Timoshkov <dmitry at codeweavers.com>
    Handle control characters in VkKeyScanEx similar to what Windows does.

--- cvs/hq/wine/dlls/x11drv/keyboard.c	2005-03-23 09:27:48.000000000 +0800
+++ wine/dlls/x11drv/keyboard.c	2005-03-27 14:48:43.000000000 +0900
@@ -1866,6 +1866,9 @@ SHORT X11DRV_VkKeyScanEx(WCHAR wChar, HK
     CHAR cChar;
     SHORT ret;
 
+    /* FIXME: what happens if wChar is not a Latin1 character and CP_UNIXCP
+     * is UTF-8 (multibyte encoding)?
+     */
     if (!WideCharToMultiByte(CP_UNIXCP, 0, &wChar, 1, &cChar, 1, NULL, NULL))
     {
         WARN("no translation from unicode to CP_UNIXCP for 0x%02x\n", wChar);
@@ -1881,7 +1884,15 @@ SHORT X11DRV_VkKeyScanEx(WCHAR wChar, HK
     wine_tsx11_lock();
     keycode = XKeysymToKeycode(display, keysym);  /* keysym -> keycode */
     if (!keycode)
-    { /* It didn't work ... let's try with deadchar code. */
+    {
+        if (keysym >= 0xFF00) /* Windows returns 0x0240 + cChar in this case */
+        {
+            ret = 0x0240 + cChar; /* 0x0200 indicates a control character */
+            TRACE(" ... returning ctrl char %#.2x\n", ret);
+            wine_tsx11_unlock();
+            return ret;
+        }
+        /* It didn't work ... let's try with deadchar code. */
         TRACE("retrying with | 0xFE00\n");
         keycode = XKeysymToKeycode(display, keysym | 0xFE00);
     }






More information about the wine-patches mailing list