mirror of
https://github.com/libsdl-org/SDL.git
synced 2026-05-31 05:46:43 +08:00
video: Fix focus when non-focused popup windows are hidden
Fix focus issues when a popup that is the child of a window that does not currently have keyboard focus is hidden or destroyed.
This commit is contained in:
@@ -634,7 +634,7 @@ static SDL_Window *GetParentToplevelWindow(SDL_Window *window)
|
|||||||
return toplevel;
|
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_Window *toplevel = GetParentToplevelWindow(window);
|
||||||
SDL_CocoaWindowData *toplevel_data;
|
SDL_CocoaWindowData *toplevel_data;
|
||||||
@@ -642,7 +642,7 @@ static void Cocoa_SetKeyboardFocus(SDL_Window *window)
|
|||||||
toplevel_data = (__bridge SDL_CocoaWindowData *)toplevel->internal;
|
toplevel_data = (__bridge SDL_CocoaWindowData *)toplevel->internal;
|
||||||
toplevel_data.keyboard_focus = window;
|
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);
|
SDL_SetKeyboardFocus(window);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1175,7 +1175,7 @@ static NSCursor *Cocoa_GetDesiredCursor(void)
|
|||||||
|
|
||||||
// We're going to get keyboard events, since we're key.
|
// We're going to get keyboard events, since we're key.
|
||||||
// This needs to be done before restoring the relative mouse mode.
|
// 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 we just gained focus we need the updated mouse position
|
||||||
if (!(window->flags & SDL_WINDOW_MOUSE_RELATIVE_MODE)) {
|
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 (!SDL_WINDOW_IS_POPUP(window)) {
|
||||||
if ([nswindow isKeyWindow]) {
|
if ([nswindow isKeyWindow]) {
|
||||||
window->flags |= SDL_WINDOW_INPUT_FOCUS;
|
window->flags |= SDL_WINDOW_INPUT_FOCUS;
|
||||||
Cocoa_SetKeyboardFocus(data.window);
|
Cocoa_SetKeyboardFocus(data.window, true);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (window->flags & SDL_WINDOW_TOOLTIP) {
|
if (window->flags & SDL_WINDOW_TOOLTIP) {
|
||||||
[nswindow setIgnoresMouseEvents:YES];
|
[nswindow setIgnoresMouseEvents:YES];
|
||||||
} else if (window->flags & SDL_WINDOW_POPUP_MENU) {
|
} else if (window->flags & SDL_WINDOW_POPUP_MENU) {
|
||||||
if (window->parent == SDL_GetKeyboardFocus()) {
|
Cocoa_SetKeyboardFocus(window, window->parent == SDL_GetKeyboardFocus());
|
||||||
Cocoa_SetKeyboardFocus(window);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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
|
// Transfer keyboard focus back to the parent when closing a popup menu
|
||||||
if (window->flags & SDL_WINDOW_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.
|
// 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)) {
|
while (SDL_WINDOW_IS_POPUP(new_focus) && (new_focus->is_hiding || new_focus->is_destroying)) {
|
||||||
new_focus = new_focus->parent;
|
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) {
|
} else if (window->parent && waskey) {
|
||||||
/* Key status is not automatically set on the parent when a child is hidden. Check if the
|
/* 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.
|
* child window was key, and set the first visible parent to be key if so.
|
||||||
|
|||||||
@@ -1629,7 +1629,7 @@ static const struct frog_color_managed_surface_listener frog_surface_listener =
|
|||||||
frog_preferred_metadata_handler
|
frog_preferred_metadata_handler
|
||||||
};
|
};
|
||||||
|
|
||||||
static void SetKeyboardFocus(SDL_Window *window)
|
static void SetKeyboardFocus(SDL_Window *window, bool set_focus)
|
||||||
{
|
{
|
||||||
SDL_Window *toplevel = window;
|
SDL_Window *toplevel = window;
|
||||||
|
|
||||||
@@ -1640,7 +1640,7 @@ static void SetKeyboardFocus(SDL_Window *window)
|
|||||||
|
|
||||||
toplevel->internal->keyboard_focus = 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);
|
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_surface_set_input_region(data->surface, region);
|
||||||
wl_region_destroy(region);
|
wl_region_destroy(region);
|
||||||
} else if (window->flags & SDL_WINDOW_POPUP_MENU) {
|
} else if (window->flags & SDL_WINDOW_POPUP_MENU) {
|
||||||
if (window->parent == SDL_GetKeyboardFocus()) {
|
SetKeyboardFocus(window, window->parent == SDL_GetKeyboardFocus());
|
||||||
SetKeyboardFocus(window);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_SetPointerProperty(props, SDL_PROP_WINDOW_WAYLAND_XDG_POPUP_POINTER, data->shell_surface.xdg.popup.xdg_popup);
|
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->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.
|
// 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)) {
|
while (SDL_WINDOW_IS_POPUP(new_focus) && (new_focus->is_hiding || new_focus->is_destroying)) {
|
||||||
new_focus = new_focus->parent;
|
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);
|
xdg_popup_destroy(popupdata->shell_surface.xdg.popup.xdg_popup);
|
||||||
|
|||||||
@@ -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;
|
SDL_Window *toplevel = window;
|
||||||
|
|
||||||
@@ -734,7 +734,7 @@ static void WIN_SetKeyboardFocus(SDL_Window *window)
|
|||||||
|
|
||||||
toplevel->internal->keyboard_focus = 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);
|
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->flags & SDL_WINDOW_POPUP_MENU && bActivate) {
|
||||||
if (window->parent == SDL_GetKeyboardFocus()) {
|
WIN_SetKeyboardFocus(window, window->parent == SDL_GetKeyboardFocus());
|
||||||
WIN_SetKeyboardFocus(window);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (window->flags & SDL_WINDOW_MODAL) {
|
if (window->flags & SDL_WINDOW_MODAL) {
|
||||||
WIN_SetWindowModal(_this, window, true);
|
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
|
// Transfer keyboard focus back to the parent
|
||||||
if (window->flags & SDL_WINDOW_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 toplevel parent, that isn't being hidden or destroyed.
|
// 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)) {
|
while (SDL_WINDOW_IS_POPUP(new_focus) && (new_focus->is_hiding || new_focus->is_destroying)) {
|
||||||
new_focus = new_focus->parent;
|
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) {
|
if (bActivate) {
|
||||||
SetForegroundWindow(hwnd);
|
SetForegroundWindow(hwnd);
|
||||||
if (window->flags & SDL_WINDOW_POPUP_MENU) {
|
if (window->flags & SDL_WINDOW_POPUP_MENU) {
|
||||||
if (window->parent == SDL_GetKeyboardFocus()) {
|
WIN_SetKeyboardFocus(window, window->parent == SDL_GetKeyboardFocus());
|
||||||
WIN_SetKeyboardFocus(window);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, data->copybits_flag | SWP_NOMOVE | SWP_NOSIZE | SWP_NOOWNERZORDER | SWP_NOACTIVATE);
|
SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, data->copybits_flag | SWP_NOMOVE | SWP_NOSIZE | SWP_NOOWNERZORDER | SWP_NOACTIVATE);
|
||||||
|
|||||||
@@ -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;
|
SDL_Window *toplevel = window;
|
||||||
|
|
||||||
@@ -251,7 +251,7 @@ static void X11_SetKeyboardFocus(SDL_Window *window)
|
|||||||
|
|
||||||
toplevel->internal->keyboard_focus = 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);
|
SDL_SetKeyboardFocus(window);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1474,9 +1474,7 @@ void X11_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window)
|
|||||||
|
|
||||||
// Popup menus grab the keyboard
|
// Popup menus grab the keyboard
|
||||||
if (window->flags & SDL_WINDOW_POPUP_MENU) {
|
if (window->flags & SDL_WINDOW_POPUP_MENU) {
|
||||||
if (window->parent == SDL_GetKeyboardFocus()) {
|
X11_SetKeyboardFocus(window, window->parent == SDL_GetKeyboardFocus());
|
||||||
X11_SetKeyboardFocus(window);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get some valid border values, if we haven't received them yet
|
// 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
|
// Transfer keyboard focus back to the parent
|
||||||
if (window->flags & SDL_WINDOW_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 that isn't being hidden or destroyed.
|
// 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)) {
|
while (SDL_WINDOW_IS_POPUP(new_focus) && (new_focus->is_hiding || new_focus->is_destroying)) {
|
||||||
new_focus = new_focus->parent;
|
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);
|
X11_XSync(display, False);
|
||||||
|
|||||||
Reference in New Issue
Block a user