1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 15:07:45 +00:00

WindowServer: Improve screen invalidation on window state changes

Because window states and various flags can affect the windows'
rendered areas it's safer to use the last computed occlusion rectangles
to invalidate areas on the screen that may have to be re-rendered due
to e.g. a window size change.

Fixes #6723
This commit is contained in:
Tom 2021-07-04 15:47:17 -06:00 committed by Andreas Kling
parent 7fdf902e4a
commit fdf701ed96
6 changed files with 85 additions and 45 deletions

View file

@ -141,7 +141,8 @@ void Window::set_rect(const Gfx::IntRect& rect)
}
invalidate(true, old_rect.size() != rect.size());
m_frame.window_rect_changed(old_rect, rect); // recomputes occlusions
m_frame.window_rect_changed(old_rect, rect);
invalidate_last_rendered_screen_rects();
}
void Window::set_rect_without_repaint(const Gfx::IntRect& rect)
@ -161,7 +162,8 @@ void Window::set_rect_without_repaint(const Gfx::IntRect& rect)
}
invalidate(true, old_rect.size() != rect.size());
m_frame.window_rect_changed(old_rect, rect); // recomputes occlusions
m_frame.window_rect_changed(old_rect, rect);
invalidate_last_rendered_screen_rects();
}
bool Window::apply_minimum_size(Gfx::IntRect& rect)
@ -284,12 +286,16 @@ void Window::set_minimized(bool minimized)
return;
m_minimized_state = minimized ? WindowMinimizedState::Minimized : WindowMinimizedState::None;
update_window_menu_items();
Compositor::the().invalidate_occlusions();
Compositor::the().invalidate_screen(frame().render_rect());
if (!blocking_modal_window())
start_minimize_animation();
if (!minimized)
request_update({ {}, size() });
// Since a minimized window won't be visible we need to invalidate the last rendered
// rectangles before the next occlusion calculation
invalidate_last_rendered_screen_rects_now();
WindowManager::the().notify_minimization_state_changed(*this);
}
@ -583,22 +589,24 @@ void Window::set_visible(bool b)
if (!m_visible)
WindowManager::the().check_hide_geometry_overlay(*this);
Compositor::the().invalidate_occlusions();
if (m_visible)
if (m_visible) {
invalidate(true);
else
Compositor::the().invalidate_screen(frame().render_rect());
} else {
// Since the window won't be visible we need to invalidate the last rendered
// rectangles before the next occlusion calculation
invalidate_last_rendered_screen_rects_now();
}
}
void Window::set_frameless(bool frameless)
{
if (m_frameless == frameless)
return;
auto render_rect_before = frame().render_rect();
m_frameless = frameless;
if (m_visible) {
Compositor::the().invalidate_occlusions();
invalidate(true, true);
Compositor::the().invalidate_screen(frameless ? render_rect_before : frame().render_rect());
invalidate_last_rendered_screen_rects();
}
}
@ -651,6 +659,24 @@ bool Window::invalidate_no_notify(const Gfx::IntRect& rect, bool with_frame)
return true;
}
void Window::invalidate_last_rendered_screen_rects()
{
m_invalidate_last_render_rects = true;
Compositor::the().invalidate_occlusions();
}
void Window::invalidate_last_rendered_screen_rects_now()
{
// We can't wait for the next occlusion computation because the window will either no longer
// be around or won't be visible anymore. So we need to invalidate the last rendered rects now.
if (!m_opaque_rects.is_empty())
Compositor::the().invalidate_screen(m_opaque_rects);
if (!m_transparency_rects.is_empty())
Compositor::the().invalidate_screen(m_transparency_rects);
m_invalidate_last_render_rects = false;
Compositor::the().invalidate_occlusions();
}
void Window::refresh_client_size()
{
client()->async_window_resized(m_window_id, m_rect);
@ -686,11 +712,7 @@ void Window::clear_dirty_rects()
bool Window::is_active() const
{
if (!m_window_stack) {
// This may be called while destroying a window as part of
// determining what the render rectangle is!
return false;
}
VERIFY(m_window_stack);
return m_window_stack->active_window() == this;
}
@ -793,8 +815,7 @@ void Window::handle_window_menu_action(WindowMenuAction action)
m_should_show_menubar = item.is_checked();
frame().invalidate();
recalculate_rect();
Compositor::the().invalidate_occlusions();
Compositor::the().invalidate_screen();
invalidate_last_rendered_screen_rects();
break;
}
}