diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c index 87878dd73..4f914aae6 100644 --- a/src/video/windows/SDL_windowsevents.c +++ b/src/video/windows/SDL_windowsevents.c @@ -432,6 +432,7 @@ LRESULT CALLBACK WIN_KeyboardHookProc(int nCode, WPARAM wParam, LPARAM lParam) { KBDLLHOOKSTRUCT* hookData = (KBDLLHOOKSTRUCT*)lParam; + SDL_VideoData* data = SDL_GetVideoDevice()->driverdata; SDL_Scancode scanCode; if (nCode < 0 || nCode != HC_ACTION) { @@ -474,6 +475,16 @@ WIN_KeyboardHookProc(int nCode, WPARAM wParam, LPARAM lParam) SDL_SendKeyboardKey(SDL_PRESSED, scanCode); } else { SDL_SendKeyboardKey(SDL_RELEASED, scanCode); + + /* If the key was down prior to our hook being installed, allow the + key up message to pass normally the first time. This ensures other + windows have a consistent view of the key state, and avoids keys + being stuck down in those windows if they are down when the grab + happens and raised while grabbed. */ + if (hookData->vkCode <= 0xFF && data->pre_hook_key_state[hookData->vkCode]) { + data->pre_hook_key_state[hookData->vkCode] = 0; + return CallNextHookEx(NULL, nCode, wParam, lParam); + } } return 1; diff --git a/src/video/windows/SDL_windowsvideo.h b/src/video/windows/SDL_windowsvideo.h index cca98c1ea..86fbf3798 100644 --- a/src/video/windows/SDL_windowsvideo.h +++ b/src/video/windows/SDL_windowsvideo.h @@ -186,6 +186,8 @@ typedef struct SDL_VideoData DWORD ime_convmodesinkcookie; TSFSink *ime_uielemsink; TSFSink *ime_ippasink; + + BYTE pre_hook_key_state[256]; } SDL_VideoData; extern SDL_bool g_WindowsEnableMessageLoop; diff --git a/src/video/windows/SDL_windowswindow.c b/src/video/windows/SDL_windowswindow.c index 6eb26ebc7..95ceaf993 100644 --- a/src/video/windows/SDL_windowswindow.c +++ b/src/video/windows/SDL_windowswindow.c @@ -759,6 +759,11 @@ static void WIN_GrabKeyboard(SDL_Window *window) return; } + /* Capture a snapshot of the current keyboard state before the hook */ + if (!GetKeyboardState(data->videodata->pre_hook_key_state)) { + return; + } + /* To grab the keyboard, we have to install a low-level keyboard hook to intercept keys that would normally be captured by the OS. Intercepting all key events on the system is rather invasive, but it's what Microsoft