From: Hans Lehnert hans.lehnert@gmail.com
If a message is removed from the queue with PeekMessage/GetMessage, the key state should get updated before calling the WH_KEYBOARD hooks. --- dlls/user32/tests/input.c | 43 +++++++++++++++++++++++++++++++++++++++ dlls/win32u/message.c | 5 +++-- 2 files changed, 46 insertions(+), 2 deletions(-)
diff --git a/dlls/user32/tests/input.c b/dlls/user32/tests/input.c index 6a28bd24301..e63855cc7bd 100644 --- a/dlls/user32/tests/input.c +++ b/dlls/user32/tests/input.c @@ -1583,6 +1583,48 @@ done: SetCursorPos(pt_org.x, pt_org.y); }
+static BOOL keyboard_hook_called; +static SHORT expected_key_state; +static LRESULT CALLBACK keyboard_hook( int code, WPARAM wparam, LPARAM lparam ) +{ + SHORT key_state; + + keyboard_hook_called = TRUE; + key_state = GetKeyState(wparam); + ok(expected_key_state == key_state, "Wrong key state. Expected: %hx. Actual %hx\n", expected_key_state, key_state); + + return CallNextHookEx( 0, code, wparam, lparam ); +} + +static void test_keyboard_hook(void) +{ + HWND hwnd; + HHOOK hook; + MSG message; + + hwnd = CreateWindowA("static", "Title", WS_OVERLAPPEDWINDOW | WS_VISIBLE, + 10, 10, 200, 200, NULL, NULL, NULL, NULL); + + hook = SetWindowsHookExA(WH_KEYBOARD, keyboard_hook, GetModuleHandleA(0), GetCurrentThreadId()); + + expected_key_state = GetKeyState(VK_TAB) & 0x01; + + keybd_event(VK_TAB, 0, 0, 0); + WaitMessage(); + + keyboard_hook_called = FALSE; + PeekMessageA(&message, 0, WM_KEYDOWN, WM_KEYDOWN, PM_NOREMOVE); + ok(keyboard_hook_called == TRUE, "Keyboard hook was not called.\n"); + + expected_key_state ^= 0xFF81; + keyboard_hook_called = FALSE; + PeekMessageA(&message, 0, WM_KEYDOWN, WM_KEYDOWN, PM_REMOVE); + ok(keyboard_hook_called == TRUE, "Keyboard hook was not called.\n"); + + UnhookWindowsHookEx(hook); + DestroyWindow(hwnd); +} + static void test_GetMouseMovePointsEx( char **argv ) { #define BUFLIM 64 @@ -5397,6 +5439,7 @@ START_TEST(input) test_Input_mouse(); test_keynames(); test_mouse_ll_hook(); + test_keyboard_hook(); test_key_map(); test_ToUnicode(); test_ToAscii(); diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c index 91f836a60bd..c673034d15f 100644 --- a/dlls/win32u/message.c +++ b/dlls/win32u/message.c @@ -2382,6 +2382,7 @@ static BOOL process_keyboard_message( MSG *msg, UINT hw_id, HWND hwnd_filter, if (msg->wParam == VK_APPS && !is_menu_active()) NtUserPostMessage( msg->hwnd, WM_CONTEXTMENU, (WPARAM)msg->hwnd, -1 ); } + accept_hardware_message( hw_id ); }
if (call_hooks( WH_KEYBOARD, remove ? HC_ACTION : HC_NOREMOVE, @@ -2389,10 +2390,10 @@ static BOOL process_keyboard_message( MSG *msg, UINT hw_id, HWND hwnd_filter, { /* skip this message */ call_hooks( WH_CBT, HCBT_KEYSKIPPED, LOWORD(msg->wParam), msg->lParam, 0 ); - accept_hardware_message( hw_id ); + if (!remove) + accept_hardware_message( hw_id ); return FALSE; } - if (remove) accept_hardware_message( hw_id ); msg->pt = point_phys_to_win_dpi( msg->hwnd, msg->pt );
if (remove && msg->message == WM_KEYDOWN)