SDL: Workaround a macOS cursor-related bug.

From f1690e265e306818882c7c876a9e85492eeefa42 Mon Sep 17 00:00:00 2001
From: Brian Collins <[EMAIL REDACTED]>
Date: Sat, 16 Mar 2024 16:27:14 -0400
Subject: [PATCH] Workaround a macOS cursor-related bug.

This fixes an macOS bug that is only known to occur in fullscreen windows on the built-in displays of newer MacBooks with camera notches. When the mouse is moved near the top of such a window (within about 44 units) and then moved back down, the cursor rects aren't respected. This can cause the default cursor to be visible when it should not be.
---
 src/video/cocoa/SDL_cocoawindow.m | 36 +++++++++++++++++++++----------
 1 file changed, 25 insertions(+), 11 deletions(-)

diff --git a/src/video/cocoa/SDL_cocoawindow.m b/src/video/cocoa/SDL_cocoawindow.m
index b7ff1ca736e48..828366095c5da 100644
--- a/src/video/cocoa/SDL_cocoawindow.m
+++ b/src/video/cocoa/SDL_cocoawindow.m
@@ -460,6 +460,17 @@ static void Cocoa_UpdateClipCursor(SDL_Window * window)
     }
 }
 
+static NSCursor *Cocoa_GetDesiredCursor(void)
+{
+    SDL_Mouse *mouse = SDL_GetMouse();
+
+    if (mouse->cursor_shown && mouse->cur_cursor && !mouse->relative_mode) {
+        return (__bridge NSCursor *)mouse->cur_cursor->driverdata;
+    }
+
+    return [NSCursor invisibleCursor];
+}
+
 
 @implementation Cocoa_WindowListener
 
@@ -1323,6 +1334,7 @@ - (void)mouseMoved:(NSEvent *)theEvent
     NSPoint point;
     int x, y;
     SDL_Window *window;
+    NSView *contentView;
 
     if (!mouse) {
         return;
@@ -1330,6 +1342,17 @@ - (void)mouseMoved:(NSEvent *)theEvent
 
     mouseID = mouse->mouseID;
     window = _data.window;
+    contentView = _data.sdlContentView;
+    point = [theEvent locationInWindow];
+
+    if ([contentView mouse:[contentView convertPoint:point fromView:nil] inRect:[contentView bounds]] &&
+        [NSCursor currentCursor] != Cocoa_GetDesiredCursor()) {
+        // The wrong cursor is on screen, fix it. This fixes an macOS bug that is only known to
+        // occur in fullscreen windows on the built-in displays of newer MacBooks with camera
+        // notches. When the mouse is moved near the top of such a window (within about 44 units)
+        // and then moved back down, the cursor rects aren't respected.
+        [_data.nswindow invalidateCursorRectsForView:contentView];
+    }
 
     if ([self processHitTest:theEvent]) {
         SDL_SendWindowEvent(window, SDL_WINDOWEVENT_HIT_TEST, 0, 0);
@@ -1340,7 +1363,6 @@ - (void)mouseMoved:(NSEvent *)theEvent
         return;
     }
 
-    point = [theEvent locationInWindow];
     x = (int)point.x;
     y = (int)(window->h - point.y);
 
@@ -1590,17 +1612,9 @@ - (BOOL)mouseDownCanMoveWindow
 
 - (void)resetCursorRects
 {
-    SDL_Mouse *mouse;
     [super resetCursorRects];
-    mouse = SDL_GetMouse();
-
-    if (mouse->cursor_shown && mouse->cur_cursor && !mouse->relative_mode) {
-        [self addCursorRect:[self bounds]
-                     cursor:(__bridge NSCursor *)mouse->cur_cursor->driverdata];
-    } else {
-        [self addCursorRect:[self bounds]
-                     cursor:[NSCursor invisibleCursor]];
-    }
+    [self addCursorRect:[self bounds]
+                 cursor:Cocoa_GetDesiredCursor()];
 }
 
 - (BOOL)acceptsFirstMouse:(NSEvent *)theEvent