summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom <tomut@yahoo.com>2021-06-17 20:16:18 -0600
committerAndreas Kling <kling@serenityos.org>2021-06-20 14:57:26 +0200
commit0547e0329ac9f881b597e822de964f740d890ed3 (patch)
tree23bfb7560a67d7fbbbc9d713a11310034cedb53a
parent229b541e5dc9952fe21114c695ab37f024562664 (diff)
downloadserenity-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.cpp4
-rw-r--r--Userland/Services/WindowServer/WindowFrame.cpp25
-rw-r--r--Userland/Services/WindowServer/WindowFrame.h2
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();