1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 01:27:34 +00:00

WindowServer: Fix artifacts after window resize in some cases

We were calculating the old window rectangle after changing window
states that may affect these calculations, which sometimes resulted
in artifacts left on the screen, particularily when tiling a window
as this now also constrains rendering to one screen.

Instead, just calculate the new rectangle and use the window's
occlusion information to figure out what areas need to be invalidated.
This commit is contained in:
Tom 2021-06-17 20:16:18 -06:00 committed by Andreas Kling
parent 229b541e5d
commit 0547e0329a
3 changed files with 19 additions and 12 deletions

View file

@ -139,7 +139,7 @@ void Window::set_rect(const Gfx::IntRect& rect)
}
invalidate(true, old_rect.size() != rect.size());
m_frame.notify_window_rect_changed(old_rect, rect); // recomputes occlusions
m_frame.window_rect_changed(old_rect, rect); // recomputes occlusions
}
void Window::set_rect_without_repaint(const Gfx::IntRect& rect)
@ -159,7 +159,7 @@ void Window::set_rect_without_repaint(const Gfx::IntRect& rect)
}
invalidate(true, old_rect.size() != rect.size());
m_frame.notify_window_rect_changed(old_rect, rect); // recomputes occlusions
m_frame.window_rect_changed(old_rect, rect); // recomputes occlusions
}
bool Window::apply_minimum_size(Gfx::IntRect& rect)

View file

@ -619,19 +619,26 @@ void WindowFrame::invalidate(Gfx::IntRect relative_rect)
m_window.invalidate(relative_rect, true);
}
void WindowFrame::notify_window_rect_changed(const Gfx::IntRect& old_rect, const Gfx::IntRect& new_rect)
void WindowFrame::window_rect_changed(const Gfx::IntRect& old_rect, const Gfx::IntRect& new_rect)
{
layout_buttons();
auto old_frame_rect = inflated_for_shadow(frame_rect_for_window(m_window, old_rect));
auto new_frame_rect = inflated_for_shadow(frame_rect_for_window(m_window, new_rect));
if (old_frame_rect.size() != new_frame_rect.size())
set_dirty(true);
auto new_frame_rect = constrained_render_rect_to_screen(frame_rect_for_window(m_window, new_rect));
set_dirty(true);
auto& compositor = Compositor::the();
for (auto& dirty : old_frame_rect.shatter(new_frame_rect))
compositor.invalidate_screen(dirty);
if (!m_window.is_opaque())
compositor.invalidate_screen(new_frame_rect);
{
// Invalidate the areas outside of the new rect. Use the last computed occlusions for this purpose
// as we can't reliably calculate the previous frame rect anymore. The window state (e.g. maximized
// or tiled) may affect the calculations and it may have already been changed by the time we get
// called here.
auto invalidate_opaque = m_window.opaque_rects().shatter(new_frame_rect);
for (auto& rect : invalidate_opaque.rects())
compositor.invalidate_screen(rect);
auto invalidate_transparent = m_window.transparency_rects().shatter(new_frame_rect);
for (auto& rect : invalidate_transparent.rects())
compositor.invalidate_screen(rect);
}
compositor.invalidate_occlusions();

View file

@ -67,7 +67,7 @@ public:
bool handle_titlebar_icon_mouse_event(MouseEvent const&);
void handle_border_mouse_event(MouseEvent const&);
void notify_window_rect_changed(const Gfx::IntRect& old_rect, const Gfx::IntRect& new_rect);
void window_rect_changed(const Gfx::IntRect& old_rect, const Gfx::IntRect& new_rect);
void invalidate_titlebar();
void invalidate(Gfx::IntRect relative_rect);
void invalidate();