diff --git a/Userland/Services/WindowServer/ConnectionFromClient.cpp b/Userland/Services/WindowServer/ConnectionFromClient.cpp index d49463e242..c702bf5c3c 100644 --- a/Userland/Services/WindowServer/ConnectionFromClient.cpp +++ b/Userland/Services/WindowServer/ConnectionFromClient.cpp @@ -576,10 +576,6 @@ void ConnectionFromClient::create_window(i32 window_id, Gfx::IntRect const& rect did_misbehave("CreateWindow with bad parent_window_id"); return; } - if ((parent_window->is_blocking() && mode != (i32)WindowMode::CaptureInput) || parent_window->is_capturing_input()) { - did_misbehave("CreateWindow with forbidden parent mode"); - return; - } } if (type < 0 || type >= (i32)WindowType::_Count) { diff --git a/Userland/Services/WindowServer/Window.cpp b/Userland/Services/WindowServer/Window.cpp index fab5fc03ab..a24de871f5 100644 --- a/Userland/Services/WindowServer/Window.cpp +++ b/Userland/Services/WindowServer/Window.cpp @@ -442,7 +442,7 @@ void Window::event(Core::Event& event) return; } - if (blocking_modal_window() && !is_capturing_input()) { + if (blocking_modal_window()) { // We still want to handle the WindowDeactivated event below when a new modal is // created to notify its parent window, despite it being "blocked by modal window". if (event.type() != Event::WindowDeactivated) @@ -660,6 +660,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 (is_descendant_of(window)) + return IterationDecision::Continue; if (window.is_blocking() && this != &window) return IterationDecision::Break; return IterationDecision::Continue; diff --git a/Userland/Services/WindowServer/WindowManager.cpp b/Userland/Services/WindowServer/WindowManager.cpp index 860554dc58..c71818c83b 100644 --- a/Userland/Services/WindowServer/WindowManager.cpp +++ b/Userland/Services/WindowServer/WindowManager.cpp @@ -348,8 +348,7 @@ void WindowManager::move_to_front_and_make_active(Window& window) return IterationDecision::Continue; }); - auto* blocker = window.blocking_modal_window(); - if (blocker && !window.is_capturing_input()) { + if (auto* blocker = window.blocking_modal_window()) { blocker->window_stack().move_to_front(*blocker); set_active_window(blocker, true); } else { @@ -1230,7 +1229,7 @@ void WindowManager::process_mouse_event_for_window(HitTestResult& result, MouseE // First check if we should initiate a move or resize (Super+LMB or Super+RMB). // In those cases, the event is swallowed by the window manager. - if ((!blocking_modal_window || window.is_capturing_input()) && window.is_movable()) { + if (!blocking_modal_window && window.is_movable()) { if (!window.is_fullscreen() && m_keyboard_modifiers == Mod_Super && event.type() == Event::MouseDown && event.button() == MouseButton::Primary) { start_window_move(window, event); return; @@ -1248,7 +1247,7 @@ void WindowManager::process_mouse_event_for_window(HitTestResult& result, MouseE set_active_window(&window); } - if (blocking_modal_window && !window.is_capturing_input()) { + if (blocking_modal_window) { if (event.type() == Event::Type::MouseDown) { // We're clicking on something that's blocked by a modal window. // Flash the modal window to let the user know about it. @@ -1835,8 +1834,7 @@ void WindowManager::notify_previous_active_input_window(Window& previous_input_w void WindowManager::set_active_window(Window* new_active_window, bool make_input) { if (new_active_window) { - auto* blocker = new_active_window->blocking_modal_window(); - if (blocker && !new_active_window->is_capturing_input()) { + if (auto* blocker = new_active_window->blocking_modal_window()) { VERIFY(blocker->is_modal()); VERIFY(blocker != new_active_window); new_active_window = blocker; diff --git a/Userland/Services/WindowServer/WindowManager.h b/Userland/Services/WindowServer/WindowManager.h index dad8c6eca7..2b88379074 100644 --- a/Userland/Services/WindowServer/WindowManager.h +++ b/Userland/Services/WindowServer/WindowManager.h @@ -241,24 +241,24 @@ public: template Window* for_each_window_in_modal_chain(Window& window, Callback callback) { - Window* maybe_break = nullptr; Function recurse = [&](Window& w) -> Window* { if (!w.is_modal()) { auto decision = callback(w); if (decision == IterationDecision::Break) - return maybe_break = &w; + return &w; } for (auto& child : w.child_windows()) { if (!child || child->is_destroyed() || !child->is_modal()) continue; auto decision = callback(*child); + if (auto* result = recurse(*child)) + return result; if (decision == IterationDecision::Break) - return maybe_break = child; - recurse(*child); + return child; } - return maybe_break; + return nullptr; }; - if (auto* modeless = window.modeless_ancestor(); modeless) + if (auto* modeless = window.modeless_ancestor()) return recurse(*modeless); return nullptr; } diff --git a/Userland/Services/WindowServer/WindowMode.h b/Userland/Services/WindowServer/WindowMode.h index 8fcd986836..c70e821337 100644 --- a/Userland/Services/WindowServer/WindowMode.h +++ b/Userland/Services/WindowServer/WindowMode.h @@ -14,7 +14,7 @@ namespace WindowServer { // - Passive: Joins the modal chain but has no modal effect (default mode for child windows) // - RenderAbove: Renders above its parent // - CaptureInput: Captures input from its parent -// - Blocking: Preempts all interaction with its modal chain +// - Blocking: Preempts all interaction with its modal chain excepting descendants (default mode for Dialogs) enum class WindowMode { Modeless = 0, Passive,