cocoa: Immediately update the mouse focus when showing/hiding a popup menu

When showing or hiding a popup menu, manually check and set the focus if the new topmost window under the cursor is an SDL window. Otherwise, the focus won't be updated until the cursor is actually moved.

(cherry picked from commit 6f5892e543)
This commit is contained in:
Frank Praznik
2025-04-26 03:31:22 -04:00
parent 1a5d1dfef0
commit 01000c73b0

View File

@@ -2115,6 +2115,36 @@ static void Cocoa_SendMouseButtonClicks(SDL_Mouse *mouse, NSEvent *theEvent, SDL
@end
static void Cocoa_UpdateMouseFocus()
{
const NSPoint mouseLocation = [NSEvent mouseLocation];
// Find the topmost window under the pointer and send a motion event if it is an SDL window.
[NSApp enumerateWindowsWithOptions:NSWindowListOrderedFrontToBack
usingBlock:^(NSWindow *nswin, BOOL *stop) {
NSRect r = [nswin contentRectForFrameRect:[nswin frame]];
if (NSPointInRect(mouseLocation, r)) {
SDL_VideoDevice *vid = SDL_GetVideoDevice();
SDL_Window *sdlwindow;
for (sdlwindow = vid->windows; sdlwindow; sdlwindow = sdlwindow->next) {
if (nswin == ((__bridge SDL_CocoaWindowData *)sdlwindow->internal).nswindow) {
break;
}
}
*stop = YES;
if (sdlwindow) {
int wx, wy;
SDL_RelativeToGlobalForWindow(sdlwindow, sdlwindow->x, sdlwindow->y, &wx, &wy);
// Calculate the cursor coordinates relative to the window.
const float dx = mouseLocation.x - wx;
const float dy = (CGDisplayPixelsHigh(kCGDirectMainDisplay) - mouseLocation.y) - wy;
SDL_SendMouseMotion(0, sdlwindow, SDL_GLOBAL_MOUSE_ID, false, dx, dy);
}
}
}];
}
static bool SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, NSWindow *nswindow, NSView *nsview)
{
@autoreleasepool {
@@ -2213,8 +2243,9 @@ static bool SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, NSWindow
if (window->flags & SDL_WINDOW_TOOLTIP) {
[nswindow setIgnoresMouseEvents:YES];
[nswindow setAcceptsMouseMovedEvents:NO];
} else if (window->flags & SDL_WINDOW_POPUP_MENU) {
} else if ((window->flags & SDL_WINDOW_POPUP_MENU) && !(window->flags & SDL_WINDOW_HIDDEN)) {
Cocoa_SetKeyboardFocus(window, window->parent == SDL_GetKeyboardFocus());
Cocoa_UpdateMouseFocus();
}
}
@@ -2599,6 +2630,9 @@ void Cocoa_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window)
[nswindow orderWindow:NSWindowBelow relativeTo:[[NSApp keyWindow] windowNumber]];
}
}
} else if (window->flags & SDL_WINDOW_POPUP_MENU) {
Cocoa_SetKeyboardFocus(window, window->parent == SDL_GetKeyboardFocus());
Cocoa_UpdateMouseFocus();
}
}
[nswindow setIsVisible:YES];
@@ -2646,6 +2680,7 @@ void Cocoa_HideWindow(SDL_VideoDevice *_this, SDL_Window *window)
}
Cocoa_SetKeyboardFocus(new_focus, set_focus);
Cocoa_UpdateMouseFocus();
} else if (window->parent && waskey) {
/* Key status is not automatically set on the parent when a child is hidden. Check if the
* child window was key, and set the first visible parent to be key if so.