Alexandre Julliard : winex11: Update only the key state on KeymapNotify without sending fake key events.

Alexandre Julliard julliard at winehq.org
Thu Feb 2 12:10:37 CST 2012


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

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Thu Feb  2 17:19:34 2012 +0100

winex11: Update only the key state on KeymapNotify without sending fake key events.

---

 dlls/winex11.drv/keyboard.c    |   54 ++++++++++++++++++++++++++++------------
 include/wine/server_protocol.h |    4 ++-
 server/protocol.def            |    1 +
 server/queue.c                 |    5 +++
 server/request.h               |    3 +-
 server/trace.c                 |    1 +
 6 files changed, 50 insertions(+), 18 deletions(-)

diff --git a/dlls/winex11.drv/keyboard.c b/dlls/winex11.drv/keyboard.c
index 160b986..57deb59 100644
--- a/dlls/winex11.drv/keyboard.c
+++ b/dlls/winex11.drv/keyboard.c
@@ -1176,6 +1176,31 @@ static BOOL get_async_key_state( BYTE state[256] )
 }
 
 /***********************************************************************
+ *           set_async_key_state
+ */
+static void set_async_key_state( const BYTE state[256] )
+{
+    SERVER_START_REQ( set_key_state )
+    {
+        req->tid = GetCurrentThreadId();
+        req->async = 1;
+        wine_server_add_data( req, state, 256 );
+        wine_server_call( req );
+    }
+    SERVER_END_REQ;
+}
+
+static void update_key_state( BYTE *keystate, BYTE key, int down )
+{
+    if (down)
+    {
+        if (!(keystate[key] & 0x80)) keystate[key] ^= 0x01;
+        keystate[key] |= 0x80;
+    }
+    else keystate[key] &= ~0x80;
+}
+
+/***********************************************************************
  *           X11DRV_KeymapNotify
  *
  * Update modifiers state (Ctrl, Alt, Shift) when window is activated.
@@ -1187,12 +1212,11 @@ static BOOL get_async_key_state( BYTE state[256] )
 void X11DRV_KeymapNotify( HWND hwnd, XEvent *event )
 {
     int i, j;
-    DWORD time = GetCurrentTime();
     BYTE keystate[256];
     WORD vkey;
+    BOOL changed = FALSE;
     struct {
         WORD vkey;
-        WORD scan;
         BOOL pressed;
     } modifiers[6]; /* VK_LSHIFT through VK_RMENU are contiguous */
 
@@ -1220,15 +1244,9 @@ void X11DRV_KeymapNotify( HWND hwnd, XEvent *event )
             case VK_LSHIFT:
             case VK_RSHIFT:
                 m = (vkey & 0xff) - VK_LSHIFT;
-                /* Take the vkey and scan from the first keycode we encounter
-                   for this modifier. */
-                if (!modifiers[m].vkey)
-                {
-                    modifiers[m].vkey = vkey;
-                    modifiers[m].scan = keyc2scan[(i * 8) + j];
-                }
-                if (event->xkeymap.key_vector[i] & (1<<j))
-                    modifiers[m].pressed = TRUE;
+                /* Take the vkey from the first keycode we encounter for this modifier */
+                if (!modifiers[m].vkey) modifiers[m].vkey = vkey;
+                if (event->xkeymap.key_vector[i] & (1<<j)) modifiers[m].pressed = TRUE;
                 break;
             }
         }
@@ -1239,16 +1257,20 @@ void X11DRV_KeymapNotify( HWND hwnd, XEvent *event )
         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 );
+            update_key_state( keystate, vkey, modifiers[m].pressed );
+            changed = TRUE;
         }
     }
+
+    if (!changed) return;
+
+    update_key_state( keystate, VK_CONTROL, (keystate[VK_LCONTROL] | keystate[VK_RCONTROL]) & 0x80 );
+    update_key_state( keystate, VK_MENU, (keystate[VK_LMENU] | keystate[VK_RMENU]) & 0x80 );
+    update_key_state( keystate, VK_SHIFT, (keystate[VK_LSHIFT] | keystate[VK_RSHIFT]) & 0x80 );
+    set_async_key_state( keystate );
 }
 
 static void update_lock_state( HWND hwnd, WORD vkey, UINT state, DWORD time )
diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
index fc51291..0e989da 100644
--- a/include/wine/server_protocol.h
+++ b/include/wine/server_protocol.h
@@ -3838,7 +3838,9 @@ struct set_key_state_request
 {
     struct request_header __header;
     thread_id_t    tid;
+    int            async;
     /* VARARG(keystate,bytes); */
+    char __pad_20[4];
 };
 struct set_key_state_reply
 {
@@ -5644,6 +5646,6 @@ union generic_reply
     struct set_suspend_context_reply set_suspend_context_reply;
 };
 
-#define SERVER_PROTOCOL_VERSION 430
+#define SERVER_PROTOCOL_VERSION 431
 
 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */
diff --git a/server/protocol.def b/server/protocol.def
index 73f2d8e..80c0cd3 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -2706,6 +2706,7 @@ enum coords_relative
 /* Set queue keyboard state for a given thread */
 @REQ(set_key_state)
     thread_id_t    tid;           /* id of thread */
+    int            async;         /* whether to change the async state too */
     VARARG(keystate,bytes);       /* state array for all the keys */
 @END
 
diff --git a/server/queue.c b/server/queue.c
index 2cd82b4..4fd32ed 100644
--- a/server/queue.c
+++ b/server/queue.c
@@ -2724,6 +2724,11 @@ DECL_HANDLER(set_key_state)
     {
         if (!(thread = get_thread_from_id( req->tid ))) return;
         if (thread->queue) memcpy( thread->queue->input->keystate, get_req_data(), size );
+        if (req->async && (desktop = get_thread_desktop( thread, 0 )))
+        {
+            memcpy( desktop->keystate, get_req_data(), size );
+            release_object( desktop );
+        }
         release_object( thread );
     }
 }
diff --git a/server/request.h b/server/request.h
index c1cca4c..5b45cf9 100644
--- a/server/request.h
+++ b/server/request.h
@@ -1756,7 +1756,8 @@ C_ASSERT( sizeof(struct get_key_state_request) == 24 );
 C_ASSERT( FIELD_OFFSET(struct get_key_state_reply, state) == 8 );
 C_ASSERT( sizeof(struct get_key_state_reply) == 16 );
 C_ASSERT( FIELD_OFFSET(struct set_key_state_request, tid) == 12 );
-C_ASSERT( sizeof(struct set_key_state_request) == 16 );
+C_ASSERT( FIELD_OFFSET(struct set_key_state_request, async) == 16 );
+C_ASSERT( sizeof(struct set_key_state_request) == 24 );
 C_ASSERT( FIELD_OFFSET(struct set_foreground_window_request, handle) == 12 );
 C_ASSERT( sizeof(struct set_foreground_window_request) == 16 );
 C_ASSERT( FIELD_OFFSET(struct set_foreground_window_reply, previous) == 8 );
diff --git a/server/trace.c b/server/trace.c
index b8dc316..cfef963 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -3162,6 +3162,7 @@ static void dump_get_key_state_reply( const struct get_key_state_reply *req )
 static void dump_set_key_state_request( const struct set_key_state_request *req )
 {
     fprintf( stderr, " tid=%04x", req->tid );
+    fprintf( stderr, ", async=%d", req->async );
     dump_varargs_bytes( ", keystate=", cur_size );
 }
 




More information about the wine-cvs mailing list