1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-14 09:04:59 +00:00

LibWebView+WebContent: Let the WebView client broadcast when it painted

When the WebContent process has painted to its shared bitmaps, it sends
a synchronous IPC to the browser process to let the chrome paint. It is
synchronous to ensure the WC process doesn't paint onto the backing
bitmap again while it is being displayed.

However, this can cause a crash at exit if the browser process quits
while the WC process is waiting for a response to this IPC.

This patch makes the painting logic asynchronous by letting the browser
process broadcast when it has finished handling the paint IPC. The WC
process will not paint anything again until it receives that message. If
it had tried to repaint while waiting for that message, that paint will
be deferred until it arrives.
This commit is contained in:
Timothy Flynn 2024-01-07 10:35:45 -05:00 committed by Alexander Kalenik
parent 335097e446
commit 8b32f4ae7a
7 changed files with 35 additions and 2 deletions

View file

@ -64,7 +64,9 @@ PageClient::PageClient(PageHost& owner, u64 id)
auto& backing_stores = client().backing_stores();
swap(backing_stores.front_bitmap, backing_stores.back_bitmap);
swap(backing_stores.front_bitmap_id, backing_stores.back_bitmap_id);
client().did_paint(viewport_rect.to_type<int>(), backing_stores.front_bitmap_id);
m_paint_state = PaintState::WaitingForClient;
client().async_did_paint(viewport_rect.to_type<int>(), backing_stores.front_bitmap_id);
});
#ifdef HAS_ACCELERATED_GRAPHICS
@ -76,10 +78,23 @@ PageClient::PageClient(PageHost& owner, u64 id)
void PageClient::schedule_repaint()
{
if (m_paint_state != PaintState::Ready) {
m_paint_state = PaintState::PaintWhenReady;
return;
}
if (!m_repaint_timer->is_active())
m_repaint_timer->start();
}
void PageClient::ready_to_paint()
{
auto old_paint_state = exchange(m_paint_state, PaintState::Ready);
if (old_paint_state == PaintState::PaintWhenReady)
schedule_repaint();
}
void PageClient::visit_edges(JS::Cell::Visitor& visitor)
{
Base::visit_edges(visitor);