mirror of
https://github.com/libsdl-org/SDL.git
synced 2025-09-05 19:08:12 +00:00
cocoa: Fix SDL_CocoaWindowData keyboard_focus being left pointing to a destroyed SDL window if input focus not previously reset for that window
- If a window being destroyed is a child of an inactive window and was the last keyboard focus of the window, that window will be left with a stale pointer to the destroyed window that it will attempt to restore the next time that window is focused. SDL_DestroyWindow will have already taken care of moving focus if this window is the current SDL keyboard focus so this change intentionally does not set focus. - Like Cocoa_HideWindow, this attempts to move the focus to the closest parent window that is not hidden or destroying.
This commit is contained in:
@@ -546,16 +546,23 @@ static void Cocoa_UpdateClipCursor(SDL_Window *window)
|
||||
}
|
||||
}
|
||||
|
||||
static void Cocoa_SetKeyboardFocus(SDL_Window *window)
|
||||
static SDL_Window *GetTopmostWindow(SDL_Window *window)
|
||||
{
|
||||
SDL_Window *topmost = window;
|
||||
SDL_CocoaWindowData *topmost_data;
|
||||
|
||||
/* Find the topmost parent */
|
||||
while (topmost->parent != NULL) {
|
||||
topmost = topmost->parent;
|
||||
}
|
||||
|
||||
return topmost;
|
||||
}
|
||||
|
||||
static void Cocoa_SetKeyboardFocus(SDL_Window *window)
|
||||
{
|
||||
SDL_Window *topmost = GetTopmostWindow(window);
|
||||
SDL_CocoaWindowData *topmost_data;
|
||||
|
||||
topmost_data = (__bridge SDL_CocoaWindowData *)topmost->driverdata;
|
||||
topmost_data.keyboard_focus = window;
|
||||
SDL_SetKeyboardFocus(window);
|
||||
@@ -2732,6 +2739,22 @@ void Cocoa_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
NSArray *contexts;
|
||||
|
||||
#endif /* SDL_VIDEO_OPENGL */
|
||||
SDL_Window *topmost = GetTopmostWindow(window);
|
||||
SDL_CocoaWindowData *topmost_data = (__bridge SDL_CocoaWindowData *)topmost->driverdata;
|
||||
|
||||
/* Reset the input focus of the root window if this window is still set as keyboard focus.
|
||||
* SDL_DestroyWindow will have already taken care of reassigning focus if this is the SDL
|
||||
* keyboard focus, this ensures that an inactive window with this window set as input focus
|
||||
* does not try to reference it the next time it gains focus.
|
||||
*/
|
||||
if (topmost_data.keyboard_focus == window) {
|
||||
SDL_Window *new_focus = window;
|
||||
while(new_focus->parent && (new_focus->is_hiding || new_focus->is_destroying)) {
|
||||
new_focus = new_focus->parent;
|
||||
}
|
||||
|
||||
topmost_data.keyboard_focus = new_focus;
|
||||
}
|
||||
|
||||
if ([data.listener isInFullscreenSpace]) {
|
||||
[NSMenu setMenuBarVisible:YES];
|
||||
|
Reference in New Issue
Block a user