SDL: Workaround a macOS cursor-related bug. (560da)

From 560daa07f226c80dcc022a7488558992d12cd45b 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.

(cherry picked from commit f1690e265e306818882c7c876a9e85492eeefa42)
---
 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 03fdfbe1c85cf..e18e4a3f0fdb6 100644
--- a/src/video/cocoa/SDL_cocoawindow.m
+++ b/src/video/cocoa/SDL_cocoawindow.m
@@ -599,6 +599,17 @@ static SDL_bool Cocoa_IsZoomed(SDL_Window *window)
     return ret;
 }
 
+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
 
 - (void)listen:(SDL_CocoaWindowData *)data
@@ -1592,12 +1603,24 @@ - (void)mouseMoved:(NSEvent *)theEvent
     NSPoint point;
     float x, y;
     SDL_Window *window;
+    NSView *contentView;
 
     if (!mouse) {
         return;
     }
 
     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 (window->flags & SDL_WINDOW_TRANSPARENT) {
         [self updateIgnoreMouseState:theEvent];
@@ -1612,7 +1635,6 @@ - (void)mouseMoved:(NSEvent *)theEvent
         return;
     }
 
-    point = [theEvent locationInWindow];
     x = point.x;
     y = (window->h - point.y);
 
@@ -1867,17 +1889,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