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

WindowServer: Fix clearing area not covered by backing bitmap

We only cleared the area not covered by the backing bitmap if a
rendering rectangle intersected with the backing bitmap. But because
we are potentially calling the render function many times we need
to always clear the area not covered by the backing bitmap, whether
it intersects or not.

Fixes #5291
This commit is contained in:
Tom 2021-02-10 23:08:47 -07:00 committed by Andreas Kling
parent ef9bfbd383
commit dd0833107f

View file

@ -275,7 +275,8 @@ void Compositor::compose()
auto frame_rect = window.frame().render_rect();
if (!frame_rect.intersects(ws.rect()))
return IterationDecision::Continue;
auto frame_rects = frame_rect.shatter(window.rect());
auto window_rect = window.rect();
auto frame_rects = frame_rect.shatter(window_rect);
dbgln_if(COMPOSE_DEBUG, " window {} frame rect: {}", window.title(), frame_rect);
@ -291,9 +292,15 @@ void Compositor::compose()
});
}
auto clear_window_rect = [&](const Gfx::IntRect& clear_rect) {
auto fill_color = wm.palette().window();
if (!window.is_opaque())
fill_color.set_alpha(255 * window.opacity());
painter.fill_rect(clear_rect, fill_color);
};
if (!backing_store) {
if (window.is_opaque())
painter.fill_rect(window.rect().intersected(rect), wm.palette().window());
clear_window_rect(window_rect.intersected(rect));
return;
}
@ -312,44 +319,42 @@ void Compositor::compose()
case ResizeDirection::Right:
case ResizeDirection::Down:
case ResizeDirection::DownRight:
backing_rect.set_location(window.rect().location());
backing_rect.set_location(window_rect.location());
break;
case ResizeDirection::Left:
case ResizeDirection::Up:
case ResizeDirection::UpLeft:
backing_rect.set_right_without_resize(window.rect().right());
backing_rect.set_bottom_without_resize(window.rect().bottom());
backing_rect.set_right_without_resize(window_rect.right());
backing_rect.set_bottom_without_resize(window_rect.bottom());
break;
case ResizeDirection::UpRight:
backing_rect.set_left(window.rect().left());
backing_rect.set_bottom_without_resize(window.rect().bottom());
backing_rect.set_bottom_without_resize(window_rect.bottom());
break;
case ResizeDirection::DownLeft:
backing_rect.set_right_without_resize(window.rect().right());
backing_rect.set_top(window.rect().top());
backing_rect.set_right_without_resize(window_rect.right());
backing_rect.set_top(window_rect.top());
break;
}
Gfx::IntRect dirty_rect_in_backing_coordinates = rect.intersected(window.rect())
Gfx::IntRect dirty_rect_in_backing_coordinates = rect.intersected(window_rect)
.intersected(backing_rect)
.translated(-backing_rect.location());
if (dirty_rect_in_backing_coordinates.is_empty())
return;
auto dst = backing_rect.location().translated(dirty_rect_in_backing_coordinates.location());
if (!dirty_rect_in_backing_coordinates.is_empty()) {
auto dst = backing_rect.location().translated(dirty_rect_in_backing_coordinates.location());
if (window.client() && window.client()->is_unresponsive()) {
painter.blit_filtered(dst, *backing_store, dirty_rect_in_backing_coordinates, [](Color src) {
return src.to_grayscale().darkened(0.75f);
});
} else {
painter.blit(dst, *backing_store, dirty_rect_in_backing_coordinates, window.opacity());
if (window.client() && window.client()->is_unresponsive()) {
painter.blit_filtered(dst, *backing_store, dirty_rect_in_backing_coordinates, [](Color src) {
return src.to_grayscale().darkened(0.75f);
});
} else {
painter.blit(dst, *backing_store, dirty_rect_in_backing_coordinates, window.opacity());
}
}
if (window.is_opaque()) {
for (auto background_rect : window.rect().shatter(backing_rect))
painter.fill_rect(background_rect, wm.palette().window());
}
for (auto background_rect : window_rect.shatter(backing_rect))
clear_window_rect(background_rect);
};
auto& dirty_rects = window.dirty_rects();