From b31fb36ed368158ee8e6c92d138f978b28ffe3c8 Mon Sep 17 00:00:00 2001 From: Aliaksandr Kalenik Date: Sun, 24 Mar 2024 13:22:01 +0100 Subject: [PATCH] LibWeb: Reschedule repaint for navigables with ongoing painting Fixes delayed repainting in the following case: 1. Style or layout invalidation triggers html event loop processing. 2. Event loop processing does nothing because there is no rendering opportunity. 3. Style or layout change won't be reflected until something else triggers event loop processing --- .../LibWeb/HTML/EventLoop/EventLoop.cpp | 16 ++++++++++++++++ Userland/Services/WebContent/PageClient.cpp | 7 +++++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp b/Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp index cb583a7db95..9461fb47bd9 100644 --- a/Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp +++ b/Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp @@ -196,6 +196,22 @@ void EventLoop::process() } }; + // AD-HOC: Since event loop processing steps do not constantly running in parallel, and + // something must trigger them, we need to manually schedule a repaint for all + // navigables that do not have a rendering opportunity at this event loop iteration. + // Otherwise their repaint will be delayed until something else will trigger event + // loop processing. + for_each_fully_active_document_in_docs([&](DOM::Document& document) { + auto navigable = document.navigable(); + if (navigable && navigable->has_a_rendering_opportunity()) + return; + auto* browsing_context = document.browsing_context(); + if (!browsing_context) + return; + auto& page = browsing_context->page(); + page.client().schedule_repaint(); + }); + // 2. Rendering opportunities: Remove from docs all Document objects whose node navigables do not have a rendering opportunity. docs.remove_all_matching([&](auto& document) { auto navigable = document->navigable(); diff --git a/Userland/Services/WebContent/PageClient.cpp b/Userland/Services/WebContent/PageClient.cpp index 51a4039d71b..0ea02a26d05 100644 --- a/Userland/Services/WebContent/PageClient.cpp +++ b/Userland/Services/WebContent/PageClient.cpp @@ -105,8 +105,11 @@ void PageClient::ready_to_paint() { auto old_paint_state = exchange(m_paint_state, PaintState::Ready); - if (old_paint_state == PaintState::PaintWhenReady) - schedule_repaint(); + if (old_paint_state == PaintState::PaintWhenReady) { + // NOTE: Repainting always has to be scheduled from HTML event loop processing steps + // to make sure style and layout are up-to-date. + page().top_level_traversable()->set_needs_display(); + } } void PageClient::add_backing_store(i32 front_bitmap_id, Gfx::ShareableBitmap const& front_bitmap, i32 back_bitmap_id, Gfx::ShareableBitmap const& back_bitmap)