SDL: defer clipcursor refresh unto pump finish (0cd69)

From 0cd6942bfc65cc8e872b25d761dc5d58035a00bb Mon Sep 17 00:00:00 2001
From: expikr <[EMAIL REDACTED]>
Date: Wed, 16 Apr 2025 02:50:00 +0800
Subject: [PATCH] defer clipcursor refresh unto pump finish

(cherry picked from commit dd625a6763b8f33ce8049d2bc874eccad60a4798)
---
 src/video/windows/SDL_windowsevents.c | 35 ++++++++++++++++++---------
 src/video/windows/SDL_windowswindow.c |  2 +-
 src/video/windows/SDL_windowswindow.h |  3 ++-
 3 files changed, 27 insertions(+), 13 deletions(-)

diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c
index a5a17ff62e350..f83dfcc59f4e3 100644
--- a/src/video/windows/SDL_windowsevents.c
+++ b/src/video/windows/SDL_windowsevents.c
@@ -1236,11 +1236,8 @@ LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara
     case WM_NCACTIVATE:
     {
         // Don't immediately clip the cursor in case we're clicking minimize/maximize buttons
-        // This is the only place that this flag is set. This causes all subsequent calls to
-        // WIN_UpdateClipCursor for this window to be no-ops in this frame's message-pumping.
-        // This flag is unset at the end of message pumping each frame for every window, and
-        // should never be carried over between frames.
-        data->skip_update_clipcursor = true;
+        data->postpone_clipcursor = true;
+        data->clipcursor_queued = true;
 
         /* Update the focus here, since it's possible to get WM_ACTIVATE and WM_SETFOCUS without
            actually being the foreground window, but this appears to get called in all cases where
@@ -1409,9 +1406,8 @@ LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara
                 window->flags & (SDL_WINDOW_MOUSE_RELATIVE_MODE | SDL_WINDOW_MOUSE_GRABBED) ||
                 (window->mouse_rect.w > 0 && window->mouse_rect.h > 0)
             );
-            if (wish_clip_cursor) {
-                data->skip_update_clipcursor = false;
-                WIN_UpdateClipCursor(window);
+            if (wish_clip_cursor) { // queue clipcursor refresh on pump finish
+                data->clipcursor_queued = true;
             }
         }
 
@@ -1436,6 +1432,9 @@ LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara
                 SDL_SendMouseMotion(WIN_GetEventTimestamp(), window, SDL_GLOBAL_MOUSE_ID, false, (float)GET_X_LPARAM(lParam), (float)GET_Y_LPARAM(lParam));
             }
         }
+        
+        return 0;
+        
     } break;
 
     case WM_LBUTTONUP:
@@ -2591,13 +2590,27 @@ void WIN_PumpEvents(SDL_VideoDevice *_this)
         }
     }
 
-    // Update the clipping rect in case someone else has stolen it
+    // fire queued clipcursor refreshes
     if (_this) {
         SDL_Window *window = _this->windows;
         while (window) {
+            bool refresh_clipcursor = false;
             SDL_WindowData *data = window->internal;
-            if (data && data->skip_update_clipcursor) {
-                data->skip_update_clipcursor = false;
+            if (data) {
+                refresh_clipcursor = data->clipcursor_queued;
+                data->clipcursor_queued = false;    // Must be cleared unconditionally.
+                data->postpone_clipcursor = false;  // Must be cleared unconditionally.
+                                                    // Must happen before UpdateClipCursor.
+                                                    // Although its occurrence currently
+                                                    // always coincides with the queuing of
+                                                    // clipcursor, it is logically distinct
+                                                    // and this coincidence might no longer
+                                                    // be true in the future.
+                                                    // Ergo this placement concordantly
+                                                    // conveys its unconditionality 
+                                                    // vis-a-vis the queuing of clipcursor.
+            }
+            if (refresh_clipcursor) {
                 WIN_UpdateClipCursor(window);
             }
             window = window->next;
diff --git a/src/video/windows/SDL_windowswindow.c b/src/video/windows/SDL_windowswindow.c
index fe21fa7e9b201..21fba2795d3f8 100644
--- a/src/video/windows/SDL_windowswindow.c
+++ b/src/video/windows/SDL_windowswindow.c
@@ -1599,7 +1599,7 @@ void WIN_UnclipCursorForWindow(SDL_Window *window) {
 void WIN_UpdateClipCursor(SDL_Window *window)
 {
     SDL_WindowData *data = window->internal;
-    if (data->in_title_click || data->focus_click_pending || data->skip_update_clipcursor) {
+    if (data->in_title_click || data->focus_click_pending || data->postpone_clipcursor) {
         return;
     }
 
diff --git a/src/video/windows/SDL_windowswindow.h b/src/video/windows/SDL_windowswindow.h
index 3d1aaed0a24fb..8198b3ad2af01 100644
--- a/src/video/windows/SDL_windowswindow.h
+++ b/src/video/windows/SDL_windowswindow.h
@@ -78,7 +78,8 @@ struct SDL_WindowData
     bool in_border_change;
     bool in_title_click;
     Uint8 focus_click_pending;
-    bool skip_update_clipcursor;
+    bool postpone_clipcursor;
+    bool clipcursor_queued;
     bool windowed_mode_was_maximized;
     bool in_window_deactivation;
     bool force_ws_maximizebox;