Skip to content

Commit

Permalink
cocoa: clear mouse focus based on NSEventTypeMouseExited events (libs…
Browse files Browse the repository at this point in the history
…dl-org#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 libsdl-org#8188
  • Loading branch information
slouken authored Jan 16, 2025
1 parent 5f4696c commit ea642fe
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 6 deletions.
2 changes: 2 additions & 0 deletions src/video/cocoa/SDL_cocoaevents.m
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
1 change: 1 addition & 0 deletions src/video/cocoa/SDL_cocoamouse.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
28 changes: 22 additions & 6 deletions src/video/cocoa/SDL_cocoamouse.m
Original file line number Diff line number Diff line change
Expand Up @@ -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__)
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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:
Expand Down
6 changes: 6 additions & 0 deletions src/video/cocoa/SDL_cocoawindow.m
Original file line number Diff line number Diff line change
Expand Up @@ -1776,6 +1776,12 @@ - (void)mouseMoved:(NSEvent *)theEvent
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];
Expand Down

0 comments on commit ea642fe

Please sign in to comment.