SDL: win32: Invalidate window message mouse button flags when reading buttons from raw input or GameInput

From 6aedc488d3f4b2c1c42dd486f634eeb9ea403a5a Mon Sep 17 00:00:00 2001
From: Josh Dowell <[EMAIL REDACTED]>
Date: Sat, 21 Jun 2025 09:57:34 +0100
Subject: [PATCH] win32: Invalidate window message mouse button flags when
 reading buttons from raw input or GameInput

SDL2 would set a high bit in the mouse button flags to indicate when raw input had been read from, without this, if you hold down a mouse button and left raw input mode (leaving relative mode) the button would remain partially stuck, and would require two clicks to start producing mouse down events again.
SDL3's raw input code was refactored to not use the mouse button flags, but forgot to invalidate the flags, causing this bug to manifest.
---
 src/video/windows/SDL_windowsevents.c      | 4 ++++
 src/video/windows/SDL_windowsgameinput.cpp | 6 ++++++
 2 files changed, 10 insertions(+)

diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c
index ad55c6711f445..58fafd38e5868 100644
--- a/src/video/windows/SDL_windowsevents.c
+++ b/src/video/windows/SDL_windowsevents.c
@@ -701,6 +701,10 @@ static void WIN_HandleRawMouseInput(Uint64 timestamp, SDL_VideoData *data, HANDL
             float fAmount = (float)amount / WHEEL_DELTA;
             SDL_SendMouseWheel(WIN_GetEventTimestamp(), window, mouseID, fAmount, 0.0f, SDL_MOUSEWHEEL_NORMAL);
         }
+
+        /* Invalidate the mouse button flags. If we don't do this then disabling raw input
+           will cause held down mouse buttons to persist when released. */
+        windowdata->mouse_button_flags = (WPARAM)-1;
     }
 }
 
diff --git a/src/video/windows/SDL_windowsgameinput.cpp b/src/video/windows/SDL_windowsgameinput.cpp
index 084b93c34e23f..265cb6dd25762 100644
--- a/src/video/windows/SDL_windowsgameinput.cpp
+++ b/src/video/windows/SDL_windowsgameinput.cpp
@@ -279,6 +279,9 @@ static void GAMEINPUT_InitialMouseReading(WIN_GameInputData *data, SDL_Window *w
             bool down = ((state.buttons & mask) != 0);
             SDL_SendMouseButton(timestamp, window, mouseID, GAMEINPUT_button_map[i], down);
         }
+
+        // Invalidate mouse button flags
+        window->internal->mouse_button_flags = (WPARAM)-1;
     }
 }
 
@@ -308,6 +311,9 @@ static void GAMEINPUT_HandleMouseDelta(WIN_GameInputData *data, SDL_Window *wind
                     SDL_SendMouseButton(timestamp, window, mouseID, GAMEINPUT_button_map[i], down);
                 }
             }
+
+            // Invalidate mouse button flags
+            window->internal->mouse_button_flags = (WPARAM)-1;
         }
         if (delta.wheelX || delta.wheelY) {
             float fAmountX = (float)delta.wheelX / WHEEL_DELTA;