diff --git a/Userland/Services/WindowServer/ConnectionFromClient.cpp b/Userland/Services/WindowServer/ConnectionFromClient.cpp index dcb57422e7..4bac3d938a 100644 --- a/Userland/Services/WindowServer/ConnectionFromClient.cpp +++ b/Userland/Services/WindowServer/ConnectionFromClient.cpp @@ -625,11 +625,6 @@ void ConnectionFromClient::create_window(i32 window_id, Gfx::IntRect const& rect did_misbehave("CreateWindow with bad parent_window_id"); return; } - - if (auto* blocker = parent_window->blocking_modal_window(); blocker && mode == (i32)WindowMode::Blocking) { - did_misbehave("CreateWindow with illegal mode: reciprocally blocked"); - return; - } } if (type < 0 || type >= (i32)WindowType::_Count) { @@ -649,6 +644,11 @@ void ConnectionFromClient::create_window(i32 window_id, Gfx::IntRect const& rect auto window = Window::construct(*this, (WindowType)type, (WindowMode)mode, window_id, minimizable, closeable, frameless, resizable, fullscreen, parent_window); + if (auto* blocker = window->blocking_modal_window(); blocker && mode == to_underlying(WindowMode::Blocking)) { + did_misbehave("CreateWindow with illegal mode: Reciprocally blocked"); + return; + } + window->set_forced_shadow(forced_shadow); if (!launch_origin_rect.is_empty()) @@ -1361,6 +1361,12 @@ void ConnectionFromClient::set_window_parent_from_client(i32 client_id, i32 pare } else { did_misbehave("SetWindowParentFromClient: Window is not stealable"); } + + auto is_also_blocking = to_underlying(child_window->mode()) == to_underlying(WindowMode::Blocking); + if (auto* blocker = child_window->blocking_modal_window(); blocker && is_also_blocking) { + did_misbehave("SetWindowParentFromClient: Reciprocally blocked"); + return; + } } Messages::WindowServer::GetWindowRectFromClientResponse ConnectionFromClient::get_window_rect_from_client(i32 client_id, i32 window_id) diff --git a/Userland/Services/WindowServer/Window.cpp b/Userland/Services/WindowServer/Window.cpp index 809247f2e5..6e0f533111 100644 --- a/Userland/Services/WindowServer/Window.cpp +++ b/Userland/Services/WindowServer/Window.cpp @@ -689,6 +689,8 @@ bool Window::is_active() const Window* Window::blocking_modal_window() { auto maybe_blocker = WindowManager::the().for_each_window_in_modal_chain(*this, [&](auto& window) { + if (parent_window() == window.parent_window() && is_blocking()) + return IterationDecision::Continue; if (is_descendant_of(window)) return IterationDecision::Continue; if (window.is_blocking() && this != &window) diff --git a/Userland/Services/WindowServer/WindowMode.h b/Userland/Services/WindowServer/WindowMode.h index e6c7930adc..c872d62218 100644 --- a/Userland/Services/WindowServer/WindowMode.h +++ b/Userland/Services/WindowServer/WindowMode.h @@ -13,7 +13,7 @@ namespace WindowServer { // - Modeless: No modal effect (default mode for parentless windows) // - Passive: Joins the modal chain but has no modal effect (default mode for child windows) // - RenderAbove: Renders above its parent -// - Blocking: Preempts all interaction with its modal chain excepting descendants and popups (default mode for Dialogs) +// - Blocking: Preempts all interaction with its modal chain excepting descendants, sibling blockers, and popups (default mode for Dialogs) enum class WindowMode { Modeless = 0, Passive,