diff options
author | Tom <tomut@yahoo.com> | 2021-06-17 20:16:18 -0600 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-06-20 14:57:26 +0200 |
commit | 0547e0329ac9f881b597e822de964f740d890ed3 (patch) | |
tree | 23bfb7560a67d7fbbbc9d713a11310034cedb53a | |
parent | 229b541e5dc9952fe21114c695ab37f024562664 (diff) | |
download | serenity-0547e0329ac9f881b597e822de964f740d890ed3.zip |
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.
-rw-r--r-- | Userland/Services/WindowServer/Window.cpp | 4 | ||||
-rw-r--r-- | Userland/Services/WindowServer/WindowFrame.cpp | 25 | ||||
-rw-r--r-- | Userland/Services/WindowServer/WindowFrame.h | 2 |
3 files changed, 19 insertions, 12 deletions
diff --git a/Userland/Services/WindowServer/Window.cpp b/Userland/Services/WindowServer/Window.cpp index 657605a803..2375061b96 100644 --- a/Userland/Services/WindowServer/Window.cpp +++ b/Userland/Services/WindowServer/Window.cpp @@ -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) diff --git a/Userland/Services/WindowServer/WindowFrame.cpp b/Userland/Services/WindowServer/WindowFrame.cpp index c2cec7ccba..f56b05e7d9 100644 --- a/Userland/Services/WindowServer/WindowFrame.cpp +++ b/Userland/Services/WindowServer/WindowFrame.cpp @@ -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(); diff --git a/Userland/Services/WindowServer/WindowFrame.h b/Userland/Services/WindowServer/WindowFrame.h index b35143378b..457d34afb2 100644 --- a/Userland/Services/WindowServer/WindowFrame.h +++ b/Userland/Services/WindowServer/WindowFrame.h @@ -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(); |