Ken Thomases : winex11.drv: Fix X11DRV_KeymapNotify when multiple keycodes map to same vkey.

Alexandre Julliard julliard at winehq.org
Wed Jul 13 12:16:33 CDT 2011


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

Author: Ken Thomases <ken at codeweavers.com>
Date:   Wed Jul 13 06:03:43 2011 -0500

winex11.drv: Fix X11DRV_KeymapNotify when multiple keycodes map to same vkey.

---

 dlls/winex11.drv/keyboard.c |   46 ++++++++++++++++++++++++++++++++----------
 1 files changed, 35 insertions(+), 11 deletions(-)

diff --git a/dlls/winex11.drv/keyboard.c b/dlls/winex11.drv/keyboard.c
index 42ca462..5648d79 100644
--- a/dlls/winex11.drv/keyboard.c
+++ b/dlls/winex11.drv/keyboard.c
@@ -1189,9 +1189,17 @@ void X11DRV_KeymapNotify( HWND hwnd, XEvent *event )
     int i, j;
     DWORD time = GetCurrentTime();
     BYTE keystate[256];
+    WORD vkey;
+    struct {
+        WORD vkey;
+        WORD scan;
+        BOOL pressed;
+    } modifiers[6]; /* VK_LSHIFT through VK_RMENU are contiguous */
 
     if (!get_async_key_state( keystate )) return;
 
+    memset(modifiers, 0, sizeof(modifiers));
+
     /* the minimum keycode is always greater or equal to 8, so we can
      * skip the first 8 values, hence start at 1
      */
@@ -1199,7 +1207,9 @@ void X11DRV_KeymapNotify( HWND hwnd, XEvent *event )
     {
         for (j = 0; j < 8; j++)
         {
-            WORD vkey = keyc2vkey[(i * 8) + j];
+            int m;
+
+            vkey = keyc2vkey[(i * 8) + j];
 
             switch(vkey & 0xff)
             {
@@ -1209,22 +1219,36 @@ void X11DRV_KeymapNotify( HWND hwnd, XEvent *event )
             case VK_RCONTROL:
             case VK_LSHIFT:
             case VK_RSHIFT:
-                if (!(keystate[vkey & 0xff] & 0x80) != !(event->xkeymap.key_vector[i] & (1<<j)))
+                m = (vkey & 0xff) - VK_LSHIFT;
+                /* Take the vkey and scan from the first keycode we encounter
+                   for this modifier. */
+                if (!modifiers[m].vkey)
                 {
-                    WORD scan = keyc2scan[(i * 8) + j];
-                    DWORD flags = vkey & 0x100 ? KEYEVENTF_EXTENDEDKEY : 0;
-                    if (!(event->xkeymap.key_vector[i] & (1<<j))) flags |= KEYEVENTF_KEYUP;
-
-                    TRACE( "Adjusting state for vkey %#.2x. State before %#.2x\n",
-                           vkey, keystate[vkey & 0xff]);
-
-                    /* Fake key being pressed inside wine */
-                    X11DRV_send_keyboard_input( hwnd, vkey & 0xff, scan & 0xff, flags, time );
+                    modifiers[m].vkey = vkey;
+                    modifiers[m].scan = keyc2scan[(i * 8) + j];
                 }
+                if (event->xkeymap.key_vector[i] & (1<<j))
+                    modifiers[m].pressed = TRUE;
                 break;
             }
         }
     }
+
+    for (vkey = VK_LSHIFT; vkey <= VK_RMENU; vkey++)
+    {
+        int m = vkey - VK_LSHIFT;
+        if (modifiers[m].vkey && !(keystate[vkey] & 0x80) != !modifiers[m].pressed)
+        {
+            DWORD flags = modifiers[m].vkey & 0x100 ? KEYEVENTF_EXTENDEDKEY : 0;
+            if (!modifiers[m].pressed) flags |= KEYEVENTF_KEYUP;
+
+            TRACE( "Adjusting state for vkey %#.2x. State before %#.2x\n",
+                   modifiers[m].vkey, keystate[vkey]);
+
+            /* Fake key being pressed inside wine */
+            X11DRV_send_keyboard_input( hwnd, vkey, modifiers[m].scan & 0xff, flags, time );
+        }
+    }
 }
 
 static void update_lock_state( HWND hwnd, WORD vkey, UINT state, DWORD time )




More information about the wine-cvs mailing list