WindowServer: Find parent taskbar rect for minimize animation

If a modal window is being minimized, it may not have its own
taskbar rectangle. In that case, try finding a parent in the
modal window stack that does have one, and use that for the
animation.
This commit is contained in:
Tom 2020-08-18 13:33:43 -06:00 committed by Andreas Kling
parent e035640cd5
commit 2552e3be00
Notes: sideshowbarker 2024-07-19 03:25:42 +09:00
4 changed files with 43 additions and 7 deletions

View file

@ -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)

View file

@ -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 };

View file

@ -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;
});
}

View file

@ -182,7 +182,7 @@ public:
void maximize_windows(Window&, bool);
template<typename Function>
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);
}
}