diff --git a/platform/macos/display_server_macos.h b/platform/macos/display_server_macos.h index 1cb4abc2052..39b84adf1ab 100644 --- a/platform/macos/display_server_macos.h +++ b/platform/macos/display_server_macos.h @@ -215,7 +215,7 @@ private: Callable system_theme_changed; WindowID _create_window(WindowMode p_mode, VSyncMode p_vsync_mode, const Rect2i &p_rect); - void _update_window_style(WindowData p_wd); + void _update_window_style(WindowData p_wd, WindowID p_window); void _update_displays_arrangement() const; Point2i _get_native_screen_position(int p_screen) const; @@ -265,6 +265,8 @@ public: void mouse_exit_window(WindowID p_window); void update_presentation_mode(); + bool is_always_on_top_recursive(WindowID p_window) const; + void window_destroy(WindowID p_window); void window_resize(WindowID p_window, int p_width, int p_height); void window_set_custom_window_buttons(WindowData &p_wd, bool p_enabled); diff --git a/platform/macos/display_server_macos.mm b/platform/macos/display_server_macos.mm index 476e508a554..5b625ef590d 100644 --- a/platform/macos/display_server_macos.mm +++ b/platform/macos/display_server_macos.mm @@ -211,7 +211,7 @@ DisplayServerMacOS::WindowID DisplayServerMacOS::_create_window(WindowMode p_mod return id; } -void DisplayServerMacOS::_update_window_style(WindowData p_wd) { +void DisplayServerMacOS::_update_window_style(WindowData p_wd, WindowID p_window) { bool borderless_full = false; if (p_wd.borderless) { @@ -231,7 +231,7 @@ void DisplayServerMacOS::_update_window_style(WindowData p_wd) { [(NSWindow *)p_wd.window_object setHidesOnDeactivate:YES]; } else { // Reset these when our window is not a borderless window that covers up the screen. - if (p_wd.on_top && !p_wd.fullscreen) { + if (is_always_on_top_recursive(p_window) && !p_wd.fullscreen) { [(NSWindow *)p_wd.window_object setLevel:NSFloatingWindowLevel]; } else { [(NSWindow *)p_wd.window_object setLevel:NSNormalWindowLevel]; @@ -240,6 +240,21 @@ void DisplayServerMacOS::_update_window_style(WindowData p_wd) { } } +bool DisplayServerMacOS::is_always_on_top_recursive(WindowID p_window) const { + ERR_FAIL_COND_V(!windows.has(p_window), false); + + const WindowData &wd = windows[p_window]; + if (wd.on_top) { + return true; + } + + if (wd.transient_parent != INVALID_WINDOW_ID) { + return is_always_on_top_recursive(wd.transient_parent); + } + + return false; +} + void DisplayServerMacOS::set_window_per_pixel_transparency_enabled(bool p_enabled, WindowID p_window) { ERR_FAIL_COND(!windows.has(p_window)); WindowData &wd = windows[p_window]; @@ -2049,7 +2064,7 @@ void DisplayServerMacOS::window_set_position(const Point2i &p_position, WindowID [wd.window_object setFrameTopLeftPoint:NSMakePoint(position.x - offset.x, position.y - offset.y)]; - _update_window_style(wd); + _update_window_style(wd, p_window); update_mouse_pos(wd, [wd.window_object mouseLocationOutsideOfEventStream]); } @@ -2187,7 +2202,7 @@ void DisplayServerMacOS::window_set_size(const Size2i p_size, WindowID p_window) [wd.window_object setFrame:new_frame display:YES]; - _update_window_style(wd); + _update_window_style(wd, p_window); } Size2i DisplayServerMacOS::window_get_size(WindowID p_window) const { @@ -2484,7 +2499,7 @@ void DisplayServerMacOS::window_set_flag(WindowFlags p_flag, bool p_enabled, Win [wd.window_object setFrame:NSMakeRect(frameRect.origin.x, frameRect.origin.y, frameRect.size.width + 1, frameRect.size.height) display:NO]; [wd.window_object setFrame:frameRect display:NO]; } - _update_window_style(wd); + _update_window_style(wd, p_window); if (was_visible || [wd.window_object isVisible]) { if ([wd.window_object isMiniaturized]) { return; @@ -2561,11 +2576,7 @@ bool DisplayServerMacOS::window_get_flag(WindowFlags p_flag, WindowID p_window) return [wd.window_object styleMask] == NSWindowStyleMaskBorderless; } break; case WINDOW_FLAG_ALWAYS_ON_TOP: { - if (wd.fullscreen) { - return wd.on_top; - } else { - return [(NSWindow *)wd.window_object level] == NSFloatingWindowLevel; - } + return wd.on_top; } break; case WINDOW_FLAG_TRANSPARENT: { return wd.layered_window; diff --git a/platform/macos/godot_window_delegate.mm b/platform/macos/godot_window_delegate.mm index 7749debfd6d..35c053dca5d 100644 --- a/platform/macos/godot_window_delegate.mm +++ b/platform/macos/godot_window_delegate.mm @@ -194,7 +194,7 @@ } // Restore on-top state. - if (wd.on_top) { + if (ds->is_always_on_top_recursive(window_id)) { [wd.window_object setLevel:NSFloatingWindowLevel]; } diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp index 271a93b122f..1ca1b9d1948 100644 --- a/platform/windows/display_server_windows.cpp +++ b/platform/windows/display_server_windows.cpp @@ -1542,6 +1542,21 @@ DisplayServer::WindowID DisplayServerWindows::create_sub_window(WindowMode p_mod return window_id; } +bool DisplayServerWindows::_is_always_on_top_recursive(WindowID p_window) const { + ERR_FAIL_COND_V(!windows.has(p_window), false); + + const WindowData &wd = windows[p_window]; + if (wd.always_on_top) { + return true; + } + + if (wd.transient_parent != INVALID_WINDOW_ID) { + return _is_always_on_top_recursive(wd.transient_parent); + } + + return false; +} + void DisplayServerWindows::show_window(WindowID p_id) { ERR_FAIL_COND(!windows.has(p_id)); @@ -1569,7 +1584,7 @@ void DisplayServerWindows::show_window(WindowID p_id) { SetForegroundWindow(wd.hWnd); // Slightly higher priority. SetFocus(wd.hWnd); // Set keyboard focus. } - if (wd.always_on_top) { + if (_is_always_on_top_recursive(p_id)) { SetWindowPos(wd.hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | ((wd.no_focus || wd.is_popup) ? SWP_NOACTIVATE : 0)); } } @@ -2192,7 +2207,7 @@ void DisplayServerWindows::_update_window_style(WindowID p_window, bool p_repain set_icon(icon); } - SetWindowPos(wd.hWnd, wd.always_on_top ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | ((wd.no_focus || wd.is_popup) ? SWP_NOACTIVATE : 0)); + SetWindowPos(wd.hWnd, _is_always_on_top_recursive(p_window) ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | ((wd.no_focus || wd.is_popup) ? SWP_NOACTIVATE : 0)); if (p_repaint) { RECT rect; diff --git a/platform/windows/display_server_windows.h b/platform/windows/display_server_windows.h index c6b8693a9d5..b5d14233dc6 100644 --- a/platform/windows/display_server_windows.h +++ b/platform/windows/display_server_windows.h @@ -628,6 +628,8 @@ class DisplayServerWindows : public DisplayServer { void _drag_event(WindowID p_window, float p_x, float p_y, int idx); void _touch_event(WindowID p_window, bool p_pressed, float p_x, float p_y, int idx); + bool _is_always_on_top_recursive(WindowID p_window) const; + void _update_window_style(WindowID p_window, bool p_repaint = true); void _update_window_mouse_passthrough(WindowID p_window);