Ken Thomases : winex11: Bias MapVirtualKeyEx(MAPVK_VSC_TO_VK) against numpad vkeys.

Alexandre Julliard julliard at winehq.org
Wed May 21 16:31:52 CDT 2008


Module: wine
Branch: master
Commit: c2bc0e21a2dbca935ef0a80e9e09a3ab301a128d
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=c2bc0e21a2dbca935ef0a80e9e09a3ab301a128d

Author: Ken Thomases <ken at codeweavers.com>
Date:   Fri May 16 10:37:07 2008 -0500

winex11: Bias MapVirtualKeyEx(MAPVK_VSC_TO_VK) against numpad vkeys.

The scan codes for the numeric keypad keys and those for the arrow keys and
keys like Home, End, etc. often match (ignoring the extended key bit).
However, if you map from one of those scan codes to a vkey, Windows reliably
prefers the non-numpad vkey.

---

 dlls/user32/tests/input.c   |   28 ++++++++++++++++++++++++++++
 dlls/winex11.drv/keyboard.c |   14 ++++++++++----
 2 files changed, 38 insertions(+), 4 deletions(-)

diff --git a/dlls/user32/tests/input.c b/dlls/user32/tests/input.c
index dd597d8..e5ac852 100644
--- a/dlls/user32/tests/input.c
+++ b/dlls/user32/tests/input.c
@@ -1115,6 +1115,18 @@ static void test_key_map(void)
 {
     HKL kl = GetKeyboardLayout(0);
     UINT kL, kR, s, sL;
+    int i;
+    static const UINT numpad_collisions[][2] = {
+        { VK_NUMPAD0, VK_INSERT },
+        { VK_NUMPAD1, VK_END },
+        { VK_NUMPAD2, VK_DOWN },
+        { VK_NUMPAD3, VK_NEXT },
+        { VK_NUMPAD4, VK_LEFT },
+        { VK_NUMPAD6, VK_RIGHT },
+        { VK_NUMPAD7, VK_HOME },
+        { VK_NUMPAD8, VK_UP },
+        { VK_NUMPAD9, VK_PRIOR },
+    };
 
     s  = MapVirtualKeyEx(VK_SHIFT,  MAPVK_VK_TO_VSC, kl);
     ok(s != 0, "MapVirtualKeyEx(VK_SHIFT) should return non-zero\n");
@@ -1130,6 +1142,22 @@ static void test_key_map(void)
     ok(kL == VK_LSHIFT, "Scan code -> vKey = %x (not VK_LSHIFT)\n", kL);
     kR = MapVirtualKeyEx(0x36, MAPVK_VSC_TO_VK_EX, kl);
     ok(kR == VK_RSHIFT, "Scan code -> vKey = %x (not VK_RSHIFT)\n", kR);
+
+    /* test that MAPVK_VSC_TO_VK prefers the non-numpad vkey if there's ambiguity */
+    for (i = 0; i < sizeof(numpad_collisions)/sizeof(numpad_collisions[0]); i++)
+    {
+        UINT numpad_scan = MapVirtualKeyEx(numpad_collisions[i][0],  MAPVK_VK_TO_VSC, kl);
+        UINT other_scan  = MapVirtualKeyEx(numpad_collisions[i][1],  MAPVK_VK_TO_VSC, kl);
+
+        /* do they really collide for this layout? */
+        if (numpad_scan && other_scan == numpad_scan)
+        {
+            UINT vkey = MapVirtualKeyEx(numpad_scan, MAPVK_VSC_TO_VK, kl);
+            ok(vkey != numpad_collisions[i][0],
+               "Got numpad vKey %x for scan code %x when there was another choice\n",
+               vkey, numpad_scan);
+        }
+    }
 }
 
 START_TEST(input)
diff --git a/dlls/winex11.drv/keyboard.c b/dlls/winex11.drv/keyboard.c
index 981e4df..d10dc46 100644
--- a/dlls/winex11.drv/keyboard.c
+++ b/dlls/winex11.drv/keyboard.c
@@ -2082,19 +2082,25 @@ UINT X11DRV_MapVirtualKeyEx(UINT wCode, UINT wMapType, HKL hkl)
         case MAPVK_VSC_TO_VK_EX:
         {
             int keyc;
-            UINT vkey;
+            UINT vkey = 0;
 
             /* let's do scan -> keycode -> vkey */
             for (keyc = min_keycode; keyc <= max_keycode; keyc++)
-                if ((keyc2scan[keyc] & 0xFF) == (wCode & 0xFF)) break;
+                if ((keyc2scan[keyc] & 0xFF) == (wCode & 0xFF))
+                {
+                    vkey = keyc2vkey[keyc] & 0xFF;
+                    /* Only stop if it's not a numpad vkey; otherwise keep
+                       looking for a potential better vkey. */
+                    if (vkey && (vkey < VK_NUMPAD0 || VK_DIVIDE < vkey))
+                        break;
+                }
 
-            if (keyc > max_keycode)
+            if (vkey == 0)
             {
                 TRACE("returning no vkey-code.\n");
                 return 0;
             }
 
-            vkey = keyc2vkey[keyc] & 0xFF;
             if (wMapType == MAPVK_VSC_TO_VK)
                 switch (vkey)
                 {




More information about the wine-cvs mailing list