SDL: Fixed leaving the cursor clip set when changing window focus

From ab5351f5d6578206db5ee8784a9cfa18a19728ae Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Mon, 11 Mar 2024 10:58:40 -0700
Subject: [PATCH] Fixed leaving the cursor clip set when changing window focus

While the focus change happens, Windows appears to reset the cursor clip rectangle, and then restore it if the application that has focus has the clip rectangle set.

This fixes resetting the clip rectangle while changing focus between windows in the same application, e.g. the Source 2 editor.
---
 src/video/windows/SDL_windowswindow.c | 29 ++++++++++++++++++---------
 1 file changed, 19 insertions(+), 10 deletions(-)

diff --git a/src/video/windows/SDL_windowswindow.c b/src/video/windows/SDL_windowswindow.c
index 60a2c3c8f0622..30f92628e6999 100644
--- a/src/video/windows/SDL_windowswindow.c
+++ b/src/video/windows/SDL_windowswindow.c
@@ -1568,18 +1568,27 @@ void WIN_UpdateClipCursor(SDL_Window *window)
             }
         }
     } else {
-        POINT first, second;
-
-        first.x = clipped_rect.left;
-        first.y = clipped_rect.top;
-        second.x = clipped_rect.right - 1;
-        second.y = clipped_rect.bottom - 1;
-        if (PtInRect(&data->cursor_clipped_rect, first) &&
-            PtInRect(&data->cursor_clipped_rect, second)) {
+        SDL_bool unclip_cursor = SDL_FALSE;
+
+        /* If the cursor is clipped to the screen, clear the clip state */
+        if (clipped_rect.left == 0 && clipped_rect.top == 0) {
+            unclip_cursor = SDL_TRUE;
+        } else {
+            POINT first, second;
+
+            first.x = clipped_rect.left;
+            first.y = clipped_rect.top;
+            second.x = clipped_rect.right - 1;
+            second.y = clipped_rect.bottom - 1;
+            if (PtInRect(&data->cursor_clipped_rect, first) &&
+                PtInRect(&data->cursor_clipped_rect, second)) {
+                unclip_cursor = SDL_TRUE;
+            }
+        }
+        if (unclip_cursor) {
             ClipCursor(NULL);
+            SDL_zero(data->cursor_clipped_rect);
         }
-        /* Note that we don't have the cursor clipped anymore, even if it's not us that reset it */
-        SDL_zero(data->cursor_clipped_rect);
     }
     data->last_updated_clipcursor = SDL_GetTicks();
 }