From cb3b7237925a24ba4c5696dd079fdc5d99a48577 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Thu, 15 Dec 2011 14:30:41 +0100 Subject: [PATCH] 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 deletion(-) diff --git a/dlls/user32/hook.c b/dlls/user32/hook.c index 2e36801e3fd..1ba5ddab08e 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 1ffce8d0c3e..d9fb7c065c5 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 7661e3e255d..a38d77b9fce 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 a42efb0a01f..790ba9284f7 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 399974e4679..1a63bad2d7f 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 c6c52b76e6a..8126b31dd9f 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; }