SDL: Guarantee that we don't dispatch any mouse motion from before or including the last mouse warp

From 16aeb8d0f5e550ac124096c7b5e03ce756762e12 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Thu, 7 Oct 2021 15:04:06 -0700
Subject: [PATCH] Guarantee that we don't dispatch any mouse motion from before
 or including the last mouse warp

---
 src/video/windows/SDL_windowsevents.c | 10 ++++++++++
 src/video/windows/SDL_windowsmouse.c  | 14 +++++---------
 src/video/windows/SDL_windowsmouse.h  |  1 +
 3 files changed, 16 insertions(+), 9 deletions(-)

diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c
index bb8504c460..a099fa6319 100644
--- a/src/video/windows/SDL_windowsevents.c
+++ b/src/video/windows/SDL_windowsevents.c
@@ -1550,6 +1550,16 @@ WIN_PumpEvents(_THIS)
                 g_WindowsMessageHook(g_WindowsMessageHookData, msg.hwnd, msg.message, msg.wParam, msg.lParam);
             }
 
+            /* Don't dispatch any mouse motion queued prior to or including the last mouse warp */
+            if (msg.message == WM_MOUSEMOVE && SDL_last_warp_time) {
+                if (!SDL_TICKS_PASSED(msg.time, (SDL_last_warp_time + 1))) {
+                    continue;
+                }
+
+                /* This mouse message happened after the warp */
+                SDL_last_warp_time = 0;
+            }
+
             /* Always translate the message in case it's a non-SDL window (e.g. with Qt integration) */
             TranslateMessage(&msg);
             DispatchMessage(&msg);
diff --git a/src/video/windows/SDL_windowsmouse.c b/src/video/windows/SDL_windowsmouse.c
index 2492243cd0..dd34bdcf78 100644
--- a/src/video/windows/SDL_windowsmouse.c
+++ b/src/video/windows/SDL_windowsmouse.c
@@ -27,6 +27,7 @@
 #include "../../events/SDL_mouse_c.h"
 
 
+DWORD SDL_last_warp_time = 0;
 HCURSOR SDL_cursor = NULL;
 static SDL_Cursor *SDL_blank_cursor = NULL;
 
@@ -253,16 +254,11 @@ WIN_WarpMouse(SDL_Window * window, int x, int y)
     SetCursorPos(pt.x, pt.y);
 
     /* Flush any pending mouse motion and simulate motion for this warp */
-    {
-        SDL_Mouse *mouse = SDL_GetMouse();
-        const SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
-        MSG msg;
-
-        while (PeekMessage(&msg, data->hwnd, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_REMOVE)) {
-            continue;
-        }
-        SDL_SendMouseMotion(window, mouse->mouseID, 0, x, y);
+    SDL_last_warp_time = GetTickCount();
+    if (!SDL_last_warp_time) {
+        SDL_last_warp_time = 1;
     }
+    SDL_SendMouseMotion(window, SDL_GetMouse()->mouseID, 0, x, y);
 }
 
 static int
diff --git a/src/video/windows/SDL_windowsmouse.h b/src/video/windows/SDL_windowsmouse.h
index f89a20b2d3..68279a685e 100644
--- a/src/video/windows/SDL_windowsmouse.h
+++ b/src/video/windows/SDL_windowsmouse.h
@@ -23,6 +23,7 @@
 #ifndef SDL_windowsmouse_h_
 #define SDL_windowsmouse_h_
 
+extern DWORD SDL_last_warp_time;
 extern HCURSOR SDL_cursor;
 
 extern void WIN_InitMouse(_THIS);