SDL: windows: Fix GUI key state when grabbing the keyboard

From 715d481271eafa047a2e610399aeee1df7b91a22 Mon Sep 17 00:00:00 2001
From: Cameron Gutman <[EMAIL REDACTED]>
Date: Mon, 29 Nov 2021 22:43:25 +0300
Subject: [PATCH] windows: Fix GUI key state when grabbing the keyboard

When our keyboard grab hook is installed, GetKeyState() will return 0 for the
GUI keys even when they are pressed. This leads to spurious key up events when
holding down the GUI keys and the inability to use any key combos involving
those modifier keys.
---
 src/video/windows/SDL_windowsevents.c | 19 +++++++++++++------
 1 file changed, 13 insertions(+), 6 deletions(-)

diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c
index d784c31c5e..880653535d 100644
--- a/src/video/windows/SDL_windowsevents.c
+++ b/src/video/windows/SDL_windowsevents.c
@@ -1476,6 +1476,7 @@ WIN_PumpEvents(_THIS)
     MSG msg;
     DWORD end_ticks = GetTickCount() + 1;
     int new_messages = 0;
+    SDL_Window *focusWindow;
 
     if (g_WindowsEnableMessageLoop) {
         while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
@@ -1523,12 +1524,18 @@ WIN_PumpEvents(_THIS)
     if ((keystate[SDL_SCANCODE_RSHIFT] == SDL_PRESSED) && !(GetKeyState(VK_RSHIFT) & 0x8000)) {
         SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_RSHIFT);
     }
-    /* The Windows key state gets lost when using Windows+Space or Windows+G shortcuts */
-    if ((keystate[SDL_SCANCODE_LGUI] == SDL_PRESSED) && !(GetKeyState(VK_LWIN) & 0x8000)) {
-        SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_LGUI);
-    }
-    if ((keystate[SDL_SCANCODE_RGUI] == SDL_PRESSED) && !(GetKeyState(VK_RWIN) & 0x8000)) {
-        SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_RGUI);
+
+    /* The Windows key state gets lost when using Windows+Space or Windows+G shortcuts and
+       not grabbing the keyboard. Note: If we *are* grabbing the keyboard, GetKeyState()
+       will return inaccurate results for VK_LWIN and VK_RWIN but we don't need it anyway. */
+    focusWindow = SDL_GetKeyboardFocus();
+    if (!focusWindow || !(focusWindow->flags & SDL_WINDOW_KEYBOARD_GRABBED)) {
+        if ((keystate[SDL_SCANCODE_LGUI] == SDL_PRESSED) && !(GetKeyState(VK_LWIN) & 0x8000)) {
+            SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_LGUI);
+        }
+        if ((keystate[SDL_SCANCODE_RGUI] == SDL_PRESSED) && !(GetKeyState(VK_RWIN) & 0x8000)) {
+            SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_RGUI);
+        }
     }
 
     /* Update the clipping rect in case someone else has stolen it */