summaryrefslogtreecommitdiff
path: root/Userland/Services
diff options
context:
space:
mode:
authorthankyouverycool <66646555+thankyouverycool@users.noreply.github.com>2022-08-27 16:48:11 -0400
committerLinus Groh <mail@linusgroh.de>2022-08-28 16:04:35 +0100
commit1dd9086e1af170ee5204689b3b6e4c357a6d2986 (patch)
treeb376464e4c711085fead76b2ce2dbe0c26d6716f /Userland/Services
parentb2b68a7551d4a1f45e75a52b5ca33a10a3ecce01 (diff)
downloadserenity-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.cpp4
-rw-r--r--Userland/Services/WindowServer/Window.cpp4
-rw-r--r--Userland/Services/WindowServer/WindowManager.cpp10
-rw-r--r--Userland/Services/WindowServer/WindowManager.h12
-rw-r--r--Userland/Services/WindowServer/WindowMode.h2
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,