Alexandre Julliard : user32: Cache the global key state to avoid performance issues in applications that poll constantly .

Alexandre Julliard julliard at winehq.org
Thu Dec 15 12:47:20 CST 2011


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

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Thu Dec 15 14:30:41 2011 +0100

user32: Cache the global key state to avoid performance issues in applications that poll constantly.

---

 dlls/user32/hook.c         |    4 ++++
 dlls/user32/input.c        |   10 ++++++++++
 dlls/user32/message.c      |    4 ++++
 dlls/user32/user_main.c    |    1 +
 dlls/user32/user_private.h |    4 +++-
 dlls/user32/winstation.c   |    1 +
 6 files changed, 23 insertions(+), 1 deletions(-)

diff --git a/dlls/user32/hook.c b/dlls/user32/hook.c
index 2e36801..1ba5dda 100644
--- a/dlls/user32/hook.c
+++ b/dlls/user32/hook.c
@@ -385,6 +385,10 @@ static LRESULT call_hook( struct hook_info *info, INT code, WPARAM wparam, LPARA
             thread_info->hook_unicode = prev_unicode;
         }
     }
+
+    if (info->id == WH_KEYBOARD_LL || info->id == WH_MOUSE_LL)
+        get_user_thread_info()->key_state_time = 0;  /* force refreshing the key state cache */
+
     return ret;
 }
 
diff --git a/dlls/user32/input.c b/dlls/user32/input.c
index 1ffce8d..d9fb7c0 100644
--- a/dlls/user32/input.c
+++ b/dlls/user32/input.c
@@ -374,21 +374,31 @@ HWND WINAPI GetCapture(void)
  */
 SHORT WINAPI DECLSPEC_HOTPATCH GetAsyncKeyState( INT key )
 {
+    struct user_thread_info *thread_info = get_user_thread_info();
     SHORT ret;
 
     if (key < 0 || key >= 256) return 0;
 
     if ((ret = USER_Driver->pGetAsyncKeyState( key )) == -1)
     {
+        if (thread_info->key_state)
+        {
+            if (GetTickCount() - thread_info->key_state_time < 50)
+                return (thread_info->key_state[key] & 0x80) ? 0x8000 : 0;
+        }
+        else thread_info->key_state = HeapAlloc( GetProcessHeap(), 0, 256 );
+
         ret = 0;
         SERVER_START_REQ( get_key_state )
         {
             req->tid = 0;
             req->key = key;
+            if (thread_info->key_state) wine_server_set_reply( req, thread_info->key_state, 256 );
             if (!wine_server_call( req ))
             {
                 if (reply->state & 0x40) ret |= 0x0001;
                 if (reply->state & 0x80) ret |= 0x8000;
+                thread_info->key_state_time = GetTickCount();
             }
         }
         SERVER_END_REQ;
diff --git a/dlls/user32/message.c b/dlls/user32/message.c
index 7661e3e..a38d77b 100644
--- a/dlls/user32/message.c
+++ b/dlls/user32/message.c
@@ -3112,6 +3112,7 @@ static BOOL send_message( struct send_message_info *info, DWORD_PTR *res_ptr, BO
  */
 NTSTATUS send_hardware_message( HWND hwnd, const INPUT *input, UINT flags )
 {
+    struct user_thread_info *thread_info = get_user_thread_info();
     struct send_message_info info;
     NTSTATUS ret;
     BOOL wait;
@@ -3149,11 +3150,14 @@ NTSTATUS send_hardware_message( HWND hwnd, const INPUT *input, UINT flags )
             req->input.hw.lparam = MAKELONG( input->u.hi.wParamL, input->u.hi.wParamH );
             break;
         }
+        if (thread_info->key_state) wine_server_set_reply( req, thread_info->key_state, 256 );
         ret = wine_server_call( req );
         wait = reply->wait;
     }
     SERVER_END_REQ;
 
+    if (!ret && thread_info->key_state) thread_info->key_state_time = GetTickCount();
+
     if (wait)
     {
         LRESULT ignored;
diff --git a/dlls/user32/user_main.c b/dlls/user32/user_main.c
index a42efb0..790ba92 100644
--- a/dlls/user32/user_main.c
+++ b/dlls/user32/user_main.c
@@ -312,6 +312,7 @@ static void thread_detach(void)
     if (thread_info->msg_window) WIN_DestroyThreadWindows( thread_info->msg_window );
     CloseHandle( thread_info->server_queue );
     HeapFree( GetProcessHeap(), 0, thread_info->wmchar_data );
+    HeapFree( GetProcessHeap(), 0, thread_info->key_state );
 
     exiting_thread_id = 0;
 }
diff --git a/dlls/user32/user_private.h b/dlls/user32/user_private.h
index 399974e..1a63bad 100644
--- a/dlls/user32/user_private.h
+++ b/dlls/user32/user_private.h
@@ -176,10 +176,12 @@ struct user_thread_info
     DWORD                         GetMessagePosVal;       /* Value for GetMessagePos */
     ULONG_PTR                     GetMessageExtraInfoVal; /* Value for GetMessageExtraInfo */
     UINT                          active_hooks;           /* Bitmap of active hooks */
+    UINT                          key_state_time;         /* Time of last key state refresh */
+    BYTE                         *key_state;              /* Cache of global key state */
     HWND                          top_window;             /* Desktop window */
     HWND                          msg_window;             /* HWND_MESSAGE parent window */
 
-    ULONG                         pad[11];                /* Available for more data */
+    ULONG                         pad[9];                 /* Available for more data */
 };
 
 struct hook_extra_info
diff --git a/dlls/user32/winstation.c b/dlls/user32/winstation.c
index c6c52b7..8126b31 100644
--- a/dlls/user32/winstation.c
+++ b/dlls/user32/winstation.c
@@ -401,6 +401,7 @@ BOOL WINAPI SetThreadDesktop( HDESK handle )
         struct user_thread_info *thread_info = get_user_thread_info();
         thread_info->top_window = 0;
         thread_info->msg_window = 0;
+        thread_info->key_state_time = 0;
     }
     return ret;
 }




More information about the wine-cvs mailing list