diff --git a/Services/WindowServer/Window.cpp b/Services/WindowServer/Window.cpp index 8617af6b41..ab785e3162 100644 --- a/Services/WindowServer/Window.cpp +++ b/Services/WindowServer/Window.cpp @@ -243,6 +243,36 @@ void Window::set_minimizable(bool minimizable) // TODO: Hide/show (or alternatively change enabled state of) window minimize button dynamically depending on value of m_minimizable } +void Window::set_taskbar_rect(const Gfx::IntRect& rect) +{ + m_taskbar_rect = rect; + m_have_taskbar_rect = !m_taskbar_rect.is_empty(); +} + +void Window::start_minimize_animation() +{ + if (!m_have_taskbar_rect) { + // If this is a modal window, it may not have its own taskbar + // button, so there is no rectangle. In that case, walk the + // modal stack until we find a window that may have one + WindowManager::the().for_each_window_in_modal_stack(*this, [&](Window& w, bool) { + if (w.has_taskbar_rect()) { + // We purposely do NOT set m_have_taskbar_rect to true here + // because we want to only copy the rectangle from the + // window that has it, but since this window wouldn't receive + // any updates down the road we want to query it again + // next time we want to start the animation + m_taskbar_rect = w.taskbar_rect(); + + ASSERT(!m_have_taskbar_rect); // should remain unset! + return IterationDecision::Break; + }; + return IterationDecision::Continue; + }); + } + m_minimize_animation_step = 0; +} + void Window::set_opacity(float opacity) { if (m_opacity == opacity) diff --git a/Services/WindowServer/Window.h b/Services/WindowServer/Window.h index 5a92d8453f..cdf7c0ce05 100644 --- a/Services/WindowServer/Window.h +++ b/Services/WindowServer/Window.h @@ -153,7 +153,7 @@ public: void set_rect(int x, int y, int width, int height) { set_rect({ x, y, width, height }); } void set_rect_without_repaint(const Gfx::IntRect&); - void set_taskbar_rect(const Gfx::IntRect& rect) { m_taskbar_rect = rect; } + void set_taskbar_rect(const Gfx::IntRect&); const Gfx::IntRect& taskbar_rect() const { return m_taskbar_rect; } void move_to(const Gfx::IntPoint& position) { set_rect({ position, size() }); } @@ -221,11 +221,11 @@ public: void request_update(const Gfx::IntRect&, bool ignore_occlusion = false); Gfx::DisjointRectSet take_pending_paint_rects() { return move(m_pending_paint_rects); } + bool has_taskbar_rect() const { return m_have_taskbar_rect; }; bool in_minimize_animation() const { return m_minimize_animation_step != -1; } - int minimize_animation_index() const { return m_minimize_animation_step; } void step_minimize_animation() { m_minimize_animation_step += 1; } - void start_minimize_animation() { m_minimize_animation_step = 0; } + void start_minimize_animation(); void end_minimize_animation() { m_minimize_animation_step = -1; } Gfx::IntRect tiled_rect(WindowTileType) const; @@ -321,6 +321,7 @@ private: bool m_accessory { false }; bool m_destroyed { false }; bool m_default_positioned { false }; + bool m_have_taskbar_rect { false }; bool m_invalidated { true }; bool m_invalidated_all { true }; bool m_invalidated_frame { true }; diff --git a/Services/WindowServer/WindowManager.cpp b/Services/WindowServer/WindowManager.cpp index 777ff8ac08..b907b7e586 100644 --- a/Services/WindowServer/WindowManager.cpp +++ b/Services/WindowServer/WindowManager.cpp @@ -228,6 +228,7 @@ void WindowManager::move_to_front_and_make_active(Window& window) // active input from any accessory window) for_each_window_in_modal_stack(window, [&](auto& w, bool is_stack_top) { move_window_to_front(w, is_stack_top, is_stack_top); + return IterationDecision::Continue; }); Compositor::the().invalidate_occlusions(); @@ -1416,6 +1417,7 @@ void WindowManager::minimize_windows(Window& window, bool minimized) { for_each_window_in_modal_stack(window, [&](auto& w, bool) { w.set_minimized(minimized); + return IterationDecision::Continue; }); } @@ -1426,6 +1428,7 @@ void WindowManager::maximize_windows(Window& window, bool maximized) w.set_maximized(maximized); if (w.is_minimized()) w.set_minimized(false); + return IterationDecision::Continue; }); } diff --git a/Services/WindowServer/WindowManager.h b/Services/WindowServer/WindowManager.h index eeece8f29a..86e33f2b0a 100644 --- a/Services/WindowServer/WindowManager.h +++ b/Services/WindowServer/WindowManager.h @@ -182,7 +182,7 @@ public: void maximize_windows(Window&, bool); template - void for_each_window_in_modal_stack(Window& window, Function f) + IterationDecision for_each_window_in_modal_stack(Window& window, Function f) { auto* blocking_modal_window = window.is_blocked_by_modal_window(); if (blocking_modal_window || window.is_modal()) { @@ -198,13 +198,15 @@ public: } if (!modal_stack.is_empty()) { for (size_t i = modal_stack.size(); i > 0; i--) { - f(*modal_stack[i - 1], false); + IterationDecision decision = f(*modal_stack[i - 1], false); + if (decision != IterationDecision::Continue) + return decision; } } - f(*modal_stack_top, true); + return f(*modal_stack_top, true); } else { // Not a modal window stack, just "iterate" over this window - f(window, true); + return f(window, true); } }