From 603c17262c7985b8ef8b0de319e9573b5810ce3f Mon Sep 17 00:00:00 2001 From: Tom Date: Thu, 16 Jul 2020 09:39:52 -0600 Subject: [PATCH] WindowServer: Fix traversing modal stack When walking the modal window stack upwards, we need to check if the top modal window is still a descendant of the window that the parent is blocked by. Fixes not all windows being brought to the front when trying to active a parent in the middle of the modal window stack. --- Services/WindowServer/Window.cpp | 13 +++++++++++++ Services/WindowServer/Window.h | 2 ++ Services/WindowServer/WindowManager.h | 3 ++- 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/Services/WindowServer/Window.cpp b/Services/WindowServer/Window.cpp index e6387014b4..452b28e71f 100644 --- a/Services/WindowServer/Window.cpp +++ b/Services/WindowServer/Window.cpp @@ -634,4 +634,17 @@ void Window::set_progress(int progress) WindowManager::the().notify_progress_changed(*this); } +bool Window::is_descendant_of(Window& window) const +{ + for (auto* parent = parent_window(); parent; parent = parent->parent_window()) { + if (parent == &window) + return true; + for (auto& accessory : parent->accessory_windows()) { + if (accessory == &window) + return true; + } + } + return false; +} + } diff --git a/Services/WindowServer/Window.h b/Services/WindowServer/Window.h index 0fc84bf853..718d238c71 100644 --- a/Services/WindowServer/Window.h +++ b/Services/WindowServer/Window.h @@ -244,6 +244,8 @@ public: Vector>& accessory_windows() { return m_accessory_windows; } const Vector>& accessory_windows() const { return m_accessory_windows; } + bool is_descendant_of(Window&) const; + void set_accessory(bool accessory) { m_accessory = accessory; } bool is_accessory() const; bool is_accessory_of(Window&) const; diff --git a/Services/WindowServer/WindowManager.h b/Services/WindowServer/WindowManager.h index 2fac08daef..f1c351b1da 100644 --- a/Services/WindowServer/WindowManager.h +++ b/Services/WindowServer/WindowManager.h @@ -193,7 +193,8 @@ public: Vector modal_stack; auto* modal_stack_top = blocking_modal_window ? blocking_modal_window : &window; for (auto* parent = modal_stack_top->parent_window(); parent; parent = parent->parent_window()) { - if (parent->is_blocked_by_modal_window() != modal_stack_top) + auto* blocked_by = parent->is_blocked_by_modal_window(); + if (!blocked_by || (blocked_by != modal_stack_top && !modal_stack_top->is_descendant_of(*blocked_by))) break; modal_stack.append(parent); if (!parent->is_modal())