Pārlūkot izejas kodu

cocoa: clear mouse focus based on NSEventTypeMouseExited events (#11991)

We can't directly set the mouse focus since we may get spammed by entered/exited events,
but we can process the current focus later in the mouseMoved handler in line with the
mouse motion event sequence.

Fixes https://github.com/libsdl-org/SDL/issues/8188
Sam Lantinga 3 mēneši atpakaļ
vecāks
revīzija
ea642fe9ff

+ 2 - 0
src/video/cocoa/SDL_cocoaevents.m

@@ -76,6 +76,8 @@ static void Cocoa_DispatchEvent(NSEvent *theEvent)
     case NSEventTypeOtherMouseDragged: // usually middle mouse dragged
     case NSEventTypeMouseMoved:
     case NSEventTypeScrollWheel:
+    case NSEventTypeMouseEntered:
+    case NSEventTypeMouseExited:
         Cocoa_HandleMouseEvent(_this, theEvent);
         break;
     case NSEventTypeKeyDown:

+ 1 - 0
src/video/cocoa/SDL_cocoamouse.h

@@ -26,6 +26,7 @@
 #include "SDL_cocoavideo.h"
 
 extern bool Cocoa_InitMouse(SDL_VideoDevice *_this);
+extern NSWindow *Cocoa_GetMouseFocus();
 extern void Cocoa_HandleMouseEvent(SDL_VideoDevice *_this, NSEvent *event);
 extern void Cocoa_HandleMouseWheel(SDL_Window *window, NSEvent *event);
 extern void Cocoa_HandleMouseWarp(CGFloat x, CGFloat y);

+ 22 - 6
src/video/cocoa/SDL_cocoamouse.m

@@ -27,7 +27,9 @@
 
 #include "../../events/SDL_mouse_c.h"
 
-// #define DEBUG_COCOAMOUSE
+#if 0
+#define DEBUG_COCOAMOUSE
+#endif
 
 #ifdef DEBUG_COCOAMOUSE
 #define DLog(fmt, ...) printf("%s: " fmt "\n", __func__, ##__VA_ARGS__)
@@ -230,11 +232,11 @@ static bool Cocoa_ShowCursor(SDL_Cursor *cursor)
         SDL_VideoDevice *device = SDL_GetVideoDevice();
         SDL_Window *window = (device ? device->windows : NULL);
         for (; window != NULL; window = window->next) {
-            SDL_CocoaWindowData *internal = (__bridge SDL_CocoaWindowData *)window->internal;
-            if (internal) {
-                [internal.nswindow performSelectorOnMainThread:@selector(invalidateCursorRectsForView:)
-                                                      withObject:[internal.nswindow contentView]
-                                                   waitUntilDone:NO];
+            SDL_CocoaWindowData *data = (__bridge SDL_CocoaWindowData *)window->internal;
+            if (data) {
+                [data.nswindow performSelectorOnMainThread:@selector(invalidateCursorRectsForView:)
+                                                withObject:[data.nswindow contentView]
+                                             waitUntilDone:NO];
             }
         }
         return true;
@@ -428,6 +430,13 @@ static void Cocoa_HandleTitleButtonEvent(SDL_VideoDevice *_this, NSEvent *event)
     }
 }
 
+static NSWindow *Cocoa_MouseFocus;
+
+NSWindow *Cocoa_GetMouseFocus()
+{
+    return Cocoa_MouseFocus;
+}
+
 void Cocoa_HandleMouseEvent(SDL_VideoDevice *_this, NSEvent *event)
 {
     SDL_MouseID mouseID = SDL_DEFAULT_MOUSE_ID;
@@ -437,7 +446,14 @@ void Cocoa_HandleMouseEvent(SDL_VideoDevice *_this, NSEvent *event)
     CGFloat lastMoveX, lastMoveY;
     float deltaX, deltaY;
     bool seenWarp;
+
     switch ([event type]) {
+    case NSEventTypeMouseEntered:
+        Cocoa_MouseFocus = [event window];
+        return;
+    case NSEventTypeMouseExited:
+        Cocoa_MouseFocus = NULL;
+        return;
     case NSEventTypeMouseMoved:
     case NSEventTypeLeftMouseDragged:
     case NSEventTypeRightMouseDragged:

+ 6 - 0
src/video/cocoa/SDL_cocoawindow.m

@@ -1776,6 +1776,12 @@ static void Cocoa_SendMouseButtonClicks(SDL_Mouse *mouse, NSEvent *theEvent, SDL
         return;
     }
 
+    if (!Cocoa_GetMouseFocus()) {
+        // The mouse is no longer over any window in the application
+        SDL_SetMouseFocus(NULL);
+        return;
+    }
+
     window = _data.window;
     contentView = _data.sdlContentView;
     point = [theEvent locationInWindow];