diff --git a/Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp b/Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp
index 85442591d6..f60ea51c64 100644
--- a/Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp
+++ b/Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp
@@ -256,9 +256,11 @@ void EventLoop::process()
// 16. For each fully active Document in docs, update the rendering or user interface of that Document and its browsing context to reflect the current state.
for_each_fully_active_document_in_docs([&](DOM::Document& document) {
- auto* browsing_context = document.browsing_context();
- auto& page = browsing_context->page();
- page.client().schedule_repaint();
+ if (document.navigable() && document.navigable()->needs_repaint()) {
+ auto* browsing_context = document.browsing_context();
+ auto& page = browsing_context->page();
+ page.client().schedule_repaint();
+ }
});
// 13. If all of the following are true
diff --git a/Userland/Libraries/LibWeb/HTML/Navigable.cpp b/Userland/Libraries/LibWeb/HTML/Navigable.cpp
index e9f73bed96..555b3e1772 100644
--- a/Userland/Libraries/LibWeb/HTML/Navigable.cpp
+++ b/Userland/Libraries/LibWeb/HTML/Navigable.cpp
@@ -1980,12 +1980,14 @@ void Navigable::set_viewport_rect(CSSPixelRect const& rect)
document->set_needs_layout();
}
did_change = true;
+ m_needs_repaint = true;
}
if (m_viewport_scroll_offset != rect.location()) {
m_viewport_scroll_offset = rect.location();
scroll_offset_did_change();
did_change = true;
+ m_needs_repaint = true;
}
if (did_change && active_document()) {
@@ -2036,6 +2038,8 @@ void Navigable::set_needs_display(CSSPixelRect const& rect)
// FIXME: Ignore updates outside the visible viewport rect.
// This requires accounting for fixed-position elements in the input rect, which we don't do yet.
+ m_needs_repaint = true;
+
if (is(*this)) {
static_cast(this)->page().client().page_did_invalidate(to_top_level_rect(rect));
return;
@@ -2128,6 +2132,8 @@ void Navigable::paint(Painting::RecordingPainter& recording_painter, PaintConfig
}
recording_painter.commands_list().apply_scroll_offsets(scroll_offsets_by_frame_id);
}
+
+ m_needs_repaint = false;
}
// https://html.spec.whatwg.org/multipage/browsing-the-web.html#event-uni
diff --git a/Userland/Libraries/LibWeb/HTML/Navigable.h b/Userland/Libraries/LibWeb/HTML/Navigable.h
index 7c9554284f..5c3bdfd56d 100644
--- a/Userland/Libraries/LibWeb/HTML/Navigable.h
+++ b/Userland/Libraries/LibWeb/HTML/Navigable.h
@@ -173,6 +173,8 @@ public:
[[nodiscard]] TargetSnapshotParams snapshot_target_snapshot_params();
+ [[nodiscard]] bool needs_repaint() const { return m_needs_repaint; }
+
struct PaintConfig {
bool paint_overlay { false };
bool should_show_line_box_borders { false };
@@ -221,6 +223,8 @@ private:
CSSPixelSize m_size;
CSSPixelPoint m_viewport_scroll_offset;
+
+ bool m_needs_repaint { false };
};
HashTable& all_navigables();
diff --git a/Userland/Services/WebContent/PageClient.cpp b/Userland/Services/WebContent/PageClient.cpp
index faf1f24b1c..9fc012c270 100644
--- a/Userland/Services/WebContent/PageClient.cpp
+++ b/Userland/Services/WebContent/PageClient.cpp
@@ -222,7 +222,6 @@ void PageClient::paint(Web::DevicePixelRect const& content_rect, Gfx::Bitmap& ta
void PageClient::set_viewport_rect(Web::DevicePixelRect const& rect)
{
page().top_level_traversable()->set_viewport_rect(page().device_to_css_rect(rect));
- Web::HTML::main_thread_event_loop().schedule();
}
void PageClient::page_did_invalidate(Web::CSSPixelRect const&)