From e3e6af39bcf733e779c7ea187e99ff7b235f2022 Mon Sep 17 00:00:00 2001 From: Aliaksandr Kalenik Date: Mon, 18 Mar 2024 20:11:06 +0100 Subject: [PATCH] LibWeb: Add basic implementation of has_a_rendering_opportunity() Return true only if we are ready to repaint. This fixes the issue where requestAnimationFrame() was invoked more than once between repaints. --- Userland/Libraries/LibWeb/HTML/Navigable.cpp | 7 +++++-- Userland/Libraries/LibWeb/Page/Page.h | 1 + Userland/Libraries/LibWeb/SVG/SVGDecodedImageData.cpp | 1 + Userland/Services/WebContent/PageClient.cpp | 5 +++++ Userland/Services/WebContent/PageClient.h | 1 + Userland/Services/WebWorker/PageHost.h | 1 + 6 files changed, 14 insertions(+), 2 deletions(-) diff --git a/Userland/Libraries/LibWeb/HTML/Navigable.cpp b/Userland/Libraries/LibWeb/HTML/Navigable.cpp index 7e442aef09..b70b398c96 100644 --- a/Userland/Libraries/LibWeb/HTML/Navigable.cpp +++ b/Userland/Libraries/LibWeb/HTML/Navigable.cpp @@ -2073,8 +2073,11 @@ bool Navigable::has_a_rendering_opportunity() const // or whether the document's visibility state is "visible". // Rendering opportunities typically occur at regular intervals. - // FIXME: We should at the very least say `false` here if we're an inactive browser tab. - return true; + // FIXME: Return `false` here if we're an inactive browser tab. + auto browsing_context = const_cast(this)->active_browsing_context(); + if (!browsing_context) + return false; + return browsing_context->page().client().is_ready_to_paint(); } // https://html.spec.whatwg.org/multipage/nav-history-apis.html#inform-the-navigation-api-about-aborting-navigation diff --git a/Userland/Libraries/LibWeb/Page/Page.h b/Userland/Libraries/LibWeb/Page/Page.h index 89152869d7..16f08888ca 100644 --- a/Userland/Libraries/LibWeb/Page/Page.h +++ b/Userland/Libraries/LibWeb/Page/Page.h @@ -307,6 +307,7 @@ public: virtual void inspector_did_execute_console_script([[maybe_unused]] String const& script) { } virtual void schedule_repaint() = 0; + virtual bool is_ready_to_paint() const = 0; protected: virtual ~PageClient() = default; diff --git a/Userland/Libraries/LibWeb/SVG/SVGDecodedImageData.cpp b/Userland/Libraries/LibWeb/SVG/SVGDecodedImageData.cpp index cfac8accfa..95cb61d34d 100644 --- a/Userland/Libraries/LibWeb/SVG/SVGDecodedImageData.cpp +++ b/Userland/Libraries/LibWeb/SVG/SVGDecodedImageData.cpp @@ -49,6 +49,7 @@ public: virtual void request_file(FileRequest) override { } virtual void paint(DevicePixelRect const&, Gfx::Bitmap&, Web::PaintOptions = {}) override { } virtual void schedule_repaint() override { } + virtual bool is_ready_to_paint() const override { return true; } private: explicit SVGPageClient(Page& host_page) diff --git a/Userland/Services/WebContent/PageClient.cpp b/Userland/Services/WebContent/PageClient.cpp index 5420ac63e4..51a4039d71 100644 --- a/Userland/Services/WebContent/PageClient.cpp +++ b/Userland/Services/WebContent/PageClient.cpp @@ -96,6 +96,11 @@ void PageClient::schedule_repaint() m_repaint_timer->start(); } +bool PageClient::is_ready_to_paint() const +{ + return m_paint_state == PaintState::Ready; +} + void PageClient::ready_to_paint() { auto old_paint_state = exchange(m_paint_state, PaintState::Ready); diff --git a/Userland/Services/WebContent/PageClient.h b/Userland/Services/WebContent/PageClient.h index fa30eed1e8..82f36e81d7 100644 --- a/Userland/Services/WebContent/PageClient.h +++ b/Userland/Services/WebContent/PageClient.h @@ -30,6 +30,7 @@ public: static void set_use_gpu_painter(); virtual void schedule_repaint() override; + virtual bool is_ready_to_paint() const override; virtual Web::Page& page() override { return *m_page; } virtual Web::Page const& page() const override { return *m_page; } diff --git a/Userland/Services/WebWorker/PageHost.h b/Userland/Services/WebWorker/PageHost.h index 61a2b8ef83..dde2af3bd6 100644 --- a/Userland/Services/WebWorker/PageHost.h +++ b/Userland/Services/WebWorker/PageHost.h @@ -31,6 +31,7 @@ public: virtual void paint(Web::DevicePixelRect const&, Gfx::Bitmap&, Web::PaintOptions = {}) override; virtual void request_file(Web::FileRequest) override; virtual void schedule_repaint() override {}; + virtual bool is_ready_to_paint() const override { return true; } private: explicit PageHost(ConnectionFromClient&);