diff --git a/src/video/cocoa/SDL_cocoawindow.m b/src/video/cocoa/SDL_cocoawindow.m index 4f51a514fe..cfc1d23159 100644 --- a/src/video/cocoa/SDL_cocoawindow.m +++ b/src/video/cocoa/SDL_cocoawindow.m @@ -634,7 +634,7 @@ static SDL_Window *GetParentToplevelWindow(SDL_Window *window) return toplevel; } -static void Cocoa_SetKeyboardFocus(SDL_Window *window) +static void Cocoa_SetKeyboardFocus(SDL_Window *window, bool set_active_focus) { SDL_Window *toplevel = GetParentToplevelWindow(window); SDL_CocoaWindowData *toplevel_data; @@ -642,7 +642,7 @@ static void Cocoa_SetKeyboardFocus(SDL_Window *window) toplevel_data = (__bridge SDL_CocoaWindowData *)toplevel->internal; toplevel_data.keyboard_focus = window; - if (!window->is_hiding && !window->is_destroying) { + if (set_active_focus && !window->is_hiding && !window->is_destroying) { SDL_SetKeyboardFocus(window); } } @@ -1175,7 +1175,7 @@ static NSCursor *Cocoa_GetDesiredCursor(void) // We're going to get keyboard events, since we're key. // This needs to be done before restoring the relative mouse mode. - Cocoa_SetKeyboardFocus(_data.keyboard_focus ? _data.keyboard_focus : window); + Cocoa_SetKeyboardFocus(_data.keyboard_focus ? _data.keyboard_focus : window, true); // If we just gained focus we need the updated mouse position if (!(window->flags & SDL_WINDOW_MOUSE_RELATIVE_MODE)) { @@ -2131,15 +2131,13 @@ static bool SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, NSWindow if (!SDL_WINDOW_IS_POPUP(window)) { if ([nswindow isKeyWindow]) { window->flags |= SDL_WINDOW_INPUT_FOCUS; - Cocoa_SetKeyboardFocus(data.window); + Cocoa_SetKeyboardFocus(data.window, true); } } else { if (window->flags & SDL_WINDOW_TOOLTIP) { [nswindow setIgnoresMouseEvents:YES]; } else if (window->flags & SDL_WINDOW_POPUP_MENU) { - if (window->parent == SDL_GetKeyboardFocus()) { - Cocoa_SetKeyboardFocus(window); - } + Cocoa_SetKeyboardFocus(window, window->parent == SDL_GetKeyboardFocus()); } } @@ -2555,16 +2553,20 @@ void Cocoa_HideWindow(SDL_VideoDevice *_this, SDL_Window *window) // Transfer keyboard focus back to the parent when closing a popup menu if (window->flags & SDL_WINDOW_POPUP_MENU) { - if (window == SDL_GetKeyboardFocus()) { - SDL_Window *new_focus = window->parent; + SDL_Window *new_focus = window->parent; + bool set_focus = window == SDL_GetKeyboardFocus(); - // Find the highest level window, up to the next toplevel, that isn't being hidden or destroyed. - while (SDL_WINDOW_IS_POPUP(new_focus) && (new_focus->is_hiding || new_focus->is_destroying)) { - new_focus = new_focus->parent; + // Find the highest level window, up to the toplevel parent, that isn't being hidden or destroyed. + while (SDL_WINDOW_IS_POPUP(new_focus) && (new_focus->is_hiding || new_focus->is_destroying)) { + new_focus = new_focus->parent; + + // If some window in the chain currently had focus, set it to the new lowest-level window. + if (!set_focus) { + set_focus = new_focus == SDL_GetKeyboardFocus(); } - - Cocoa_SetKeyboardFocus(new_focus); } + + Cocoa_SetKeyboardFocus(new_focus, set_focus); } 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. diff --git a/src/video/wayland/SDL_waylandwindow.c b/src/video/wayland/SDL_waylandwindow.c index 75e80af4ee..6d463b3bdb 100644 --- a/src/video/wayland/SDL_waylandwindow.c +++ b/src/video/wayland/SDL_waylandwindow.c @@ -1629,7 +1629,7 @@ static const struct frog_color_managed_surface_listener frog_surface_listener = frog_preferred_metadata_handler }; -static void SetKeyboardFocus(SDL_Window *window) +static void SetKeyboardFocus(SDL_Window *window, bool set_focus) { SDL_Window *toplevel = window; @@ -1640,7 +1640,7 @@ static void SetKeyboardFocus(SDL_Window *window) toplevel->internal->keyboard_focus = window; - if (!window->is_hiding && !window->is_destroying) { + if (set_focus && !window->is_hiding && !window->is_destroying) { SDL_SetKeyboardFocus(window); } } @@ -1895,9 +1895,7 @@ void Wayland_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window) wl_surface_set_input_region(data->surface, region); wl_region_destroy(region); } else if (window->flags & SDL_WINDOW_POPUP_MENU) { - if (window->parent == SDL_GetKeyboardFocus()) { - SetKeyboardFocus(window); - } + SetKeyboardFocus(window, window->parent == SDL_GetKeyboardFocus()); } SDL_SetPointerProperty(props, SDL_PROP_WINDOW_WAYLAND_XDG_POPUP_POINTER, data->shell_surface.xdg.popup.xdg_popup); @@ -2042,16 +2040,20 @@ static void Wayland_ReleasePopup(SDL_VideoDevice *_this, SDL_Window *popup) } if (popup->flags & SDL_WINDOW_POPUP_MENU) { - if (popup == SDL_GetKeyboardFocus()) { - SDL_Window *new_focus = popup->parent; + SDL_Window *new_focus = popup->parent; + bool set_focus = popup == SDL_GetKeyboardFocus(); - // Find the highest level window, up to the toplevel parent, that isn't being hidden or destroyed. - while (SDL_WINDOW_IS_POPUP(new_focus) && new_focus->parent && (new_focus->is_hiding || new_focus->is_destroying)) { - new_focus = new_focus->parent; + // Find the highest level window, up to the toplevel parent, that isn't being hidden or destroyed. + while (SDL_WINDOW_IS_POPUP(new_focus) && (new_focus->is_hiding || new_focus->is_destroying)) { + new_focus = new_focus->parent; + + // If some window in the chain currently had focus, set it to the new lowest-level window. + if (!set_focus) { + set_focus = new_focus == SDL_GetKeyboardFocus(); } - - SetKeyboardFocus(new_focus); } + + SetKeyboardFocus(new_focus, set_focus); } xdg_popup_destroy(popupdata->shell_surface.xdg.popup.xdg_popup); diff --git a/src/video/windows/SDL_windowswindow.c b/src/video/windows/SDL_windowswindow.c index d4456cab3b..459f23d875 100644 --- a/src/video/windows/SDL_windowswindow.c +++ b/src/video/windows/SDL_windowswindow.c @@ -723,7 +723,7 @@ static void WIN_ConstrainPopup(SDL_Window *window, bool output_to_pending) } } -static void WIN_SetKeyboardFocus(SDL_Window *window) +static void WIN_SetKeyboardFocus(SDL_Window *window, bool set_active_focus) { SDL_Window *toplevel = window; @@ -734,7 +734,7 @@ static void WIN_SetKeyboardFocus(SDL_Window *window) toplevel->internal->keyboard_focus = window; - if (!window->is_hiding && !window->is_destroying) { + if (set_active_focus && !window->is_hiding && !window->is_destroying) { SDL_SetKeyboardFocus(window); } } @@ -1097,9 +1097,7 @@ void WIN_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window) } if (window->flags & SDL_WINDOW_POPUP_MENU && bActivate) { - if (window->parent == SDL_GetKeyboardFocus()) { - WIN_SetKeyboardFocus(window); - } + WIN_SetKeyboardFocus(window, window->parent == SDL_GetKeyboardFocus()); } if (window->flags & SDL_WINDOW_MODAL) { WIN_SetWindowModal(_this, window, true); @@ -1118,16 +1116,20 @@ void WIN_HideWindow(SDL_VideoDevice *_this, SDL_Window *window) // Transfer keyboard focus back to the parent if (window->flags & SDL_WINDOW_POPUP_MENU) { - if (window == SDL_GetKeyboardFocus()) { - SDL_Window *new_focus = window->parent; + SDL_Window *new_focus = window->parent; + bool set_focus = window == SDL_GetKeyboardFocus(); - // Find the highest level window, up to the toplevel parent, that isn't being hidden or destroyed. - while (SDL_WINDOW_IS_POPUP(new_focus) && (new_focus->is_hiding || new_focus->is_destroying)) { - new_focus = new_focus->parent; + // Find the highest level window, up to the toplevel parent, that isn't being hidden or destroyed. + while (SDL_WINDOW_IS_POPUP(new_focus) && (new_focus->is_hiding || new_focus->is_destroying)) { + new_focus = new_focus->parent; + + // If some window in the chain currently had keyboard focus, set it to the new lowest-level window. + if (!set_focus) { + set_focus = new_focus == SDL_GetKeyboardFocus(); } - - WIN_SetKeyboardFocus(new_focus); } + + WIN_SetKeyboardFocus(new_focus, set_focus); } } @@ -1165,9 +1167,7 @@ void WIN_RaiseWindow(SDL_VideoDevice *_this, SDL_Window *window) if (bActivate) { SetForegroundWindow(hwnd); if (window->flags & SDL_WINDOW_POPUP_MENU) { - if (window->parent == SDL_GetKeyboardFocus()) { - WIN_SetKeyboardFocus(window); - } + WIN_SetKeyboardFocus(window, window->parent == SDL_GetKeyboardFocus()); } } else { SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, data->copybits_flag | SWP_NOMOVE | SWP_NOSIZE | SWP_NOOWNERZORDER | SWP_NOACTIVATE); diff --git a/src/video/x11/SDL_x11window.c b/src/video/x11/SDL_x11window.c index 791d515e19..81b8434a26 100644 --- a/src/video/x11/SDL_x11window.c +++ b/src/video/x11/SDL_x11window.c @@ -240,7 +240,7 @@ static void X11_ConstrainPopup(SDL_Window *window, bool output_to_pending) } } -static void X11_SetKeyboardFocus(SDL_Window *window) +static void X11_SetKeyboardFocus(SDL_Window *window, bool set_active_focus) { SDL_Window *toplevel = window; @@ -251,7 +251,7 @@ static void X11_SetKeyboardFocus(SDL_Window *window) toplevel->internal->keyboard_focus = window; - if (!window->is_hiding && !window->is_destroying) { + if (set_active_focus && !window->is_hiding && !window->is_destroying) { SDL_SetKeyboardFocus(window); } } @@ -1474,9 +1474,7 @@ void X11_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window) // Popup menus grab the keyboard if (window->flags & SDL_WINDOW_POPUP_MENU) { - if (window->parent == SDL_GetKeyboardFocus()) { - X11_SetKeyboardFocus(window); - } + X11_SetKeyboardFocus(window, window->parent == SDL_GetKeyboardFocus()); } // Get some valid border values, if we haven't received them yet @@ -1532,16 +1530,20 @@ void X11_HideWindow(SDL_VideoDevice *_this, SDL_Window *window) // Transfer keyboard focus back to the parent if (window->flags & SDL_WINDOW_POPUP_MENU) { - if (window == SDL_GetKeyboardFocus()) { - SDL_Window *new_focus = window->parent; + SDL_Window *new_focus = window->parent; + bool set_focus = window == SDL_GetKeyboardFocus(); - // Find the highest level window that isn't being hidden or destroyed. - while (SDL_WINDOW_IS_POPUP(new_focus) && (new_focus->is_hiding || new_focus->is_destroying)) { - new_focus = new_focus->parent; + // Find the highest level window, up to the toplevel parent, that isn't being hidden or destroyed. + while (SDL_WINDOW_IS_POPUP(new_focus) && (new_focus->is_hiding || new_focus->is_destroying)) { + new_focus = new_focus->parent; + + // If some window in the chain currently had focus, set it to the new lowest-level window. + if (!set_focus) { + set_focus = new_focus == SDL_GetKeyboardFocus(); } - - X11_SetKeyboardFocus(new_focus); } + + X11_SetKeyboardFocus(new_focus, set_focus); } X11_XSync(display, False);