diff options
author | thankyouverycool <66646555+thankyouverycool@users.noreply.github.com> | 2022-08-27 16:48:11 -0400 |
---|---|---|
committer | Linus Groh <mail@linusgroh.de> | 2022-08-28 16:04:35 +0100 |
commit | 1dd9086e1af170ee5204689b3b6e4c357a6d2986 (patch) | |
tree | b376464e4c711085fead76b2ce2dbe0c26d6716f /Userland/Services | |
parent | b2b68a7551d4a1f45e75a52b5ca33a10a3ecce01 (diff) | |
download | serenity-1dd9086e1af170ee5204689b3b6e4c357a6d2986.zip |
WindowServer: Remove misbehavior conditions for modals
This was too restrictive and there are already UI elements that rely
on this behavior. Now Blocking modals will preempt interaction with
all windows in their modal chain except those descending from them.
Fixes crashing in FilePicker when permission is denied.
Diffstat (limited to 'Userland/Services')
-rw-r--r-- | Userland/Services/WindowServer/ConnectionFromClient.cpp | 4 | ||||
-rw-r--r-- | Userland/Services/WindowServer/Window.cpp | 4 | ||||
-rw-r--r-- | Userland/Services/WindowServer/WindowManager.cpp | 10 | ||||
-rw-r--r-- | Userland/Services/WindowServer/WindowManager.h | 12 | ||||
-rw-r--r-- | Userland/Services/WindowServer/WindowMode.h | 2 |
5 files changed, 14 insertions, 18 deletions
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<typename Callback> Window* for_each_window_in_modal_chain(Window& window, Callback callback) { - Window* maybe_break = nullptr; Function<Window*(Window&)> 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, |