diff --git a/Userland/Libraries/LibWeb/DOM/Document.cpp b/Userland/Libraries/LibWeb/DOM/Document.cpp index d6aa370a9fc..863cda59be8 100644 --- a/Userland/Libraries/LibWeb/DOM/Document.cpp +++ b/Userland/Libraries/LibWeb/DOM/Document.cpp @@ -380,9 +380,11 @@ Document::Document(JS::Realm& realm, const URL::URL& url, TemporaryDocumentForFr if (!node) return; - if (auto navigable = this->navigable(); !navigable || !navigable->is_focused()) + auto navigable = this->navigable(); + if (!navigable || !navigable->is_focused()) return; + node->document().invalidate_display_list(); node->document().update_layout(); if (node->paintable()) { @@ -1112,6 +1114,8 @@ void Document::update_layout() if (m_created_for_appropriate_template_contents) return; + invalidate_display_list(); + auto* document_element = this->document_element(); auto viewport_rect = navigable->viewport_rect(); @@ -1250,6 +1254,9 @@ void Document::update_style() style_computer().reset_ancestor_filter(); auto invalidation = update_style_recursively(*this, style_computer()); + if (!invalidation.is_none()) { + invalidate_display_list(); + } if (invalidation.rebuild_layout_tree) { invalidate_layout(); } else { @@ -1266,6 +1273,8 @@ void Document::update_animated_style_if_needed() if (!m_needs_animated_style_update) return; + invalidate_display_list(); + for (auto& timeline : m_associated_animation_timelines) { for (auto& animation : timeline->associated_animations()) { if (auto effect = animation->effect(); effect && effect->target()) @@ -5393,8 +5402,24 @@ void Document::set_needs_display(CSSPixelRect const&) } } +void Document::invalidate_display_list() +{ + m_cached_display_list.clear(); + + auto navigable = this->navigable(); + if (!navigable) + return; + + if (navigable->container()) { + navigable->container()->document().invalidate_display_list(); + } +} + RefPtr Document::record_display_list(PaintConfig config) { + if (m_cached_display_list && m_cached_display_list_paint_config == config) + return m_cached_display_list; + auto display_list = Painting::DisplayList::create(); Painting::DisplayListRecorder display_list_recorder(display_list); @@ -5436,6 +5461,9 @@ RefPtr Document::record_display_list(PaintConfig config) m_needs_repaint = false; + m_cached_display_list = display_list; + m_cached_display_list_paint_config = config; + return display_list; } diff --git a/Userland/Libraries/LibWeb/DOM/Document.h b/Userland/Libraries/LibWeb/DOM/Document.h index 6b2d1bff0de..95938817fa1 100644 --- a/Userland/Libraries/LibWeb/DOM/Document.h +++ b/Userland/Libraries/LibWeb/DOM/Document.h @@ -708,9 +708,13 @@ public: bool should_show_line_box_borders { false }; bool has_focus { false }; Optional canvas_fill_rect {}; + + bool operator==(PaintConfig const& other) const = default; }; RefPtr record_display_list(PaintConfig); + void invalidate_display_list(); + protected: virtual void initialize(JS::Realm&) override; virtual void visit_edges(Cell::Visitor&) override; @@ -986,6 +990,9 @@ private: WeakPtr m_cached_navigable; bool m_needs_repaint { false }; + + Optional m_cached_display_list_paint_config; + RefPtr m_cached_display_list; }; template<> diff --git a/Userland/Libraries/LibWeb/DOM/Range.cpp b/Userland/Libraries/LibWeb/DOM/Range.cpp index 0a4ab926f1d..bf05321ed63 100644 --- a/Userland/Libraries/LibWeb/DOM/Range.cpp +++ b/Userland/Libraries/LibWeb/DOM/Range.cpp @@ -98,6 +98,7 @@ void Range::update_associated_selection() { if (auto* viewport = m_start_container->document().paintable()) { viewport->recompute_selection_states(); + m_start_container->document().invalidate_display_list(); viewport->set_needs_display(); } diff --git a/Userland/Libraries/LibWeb/HTML/CanvasRenderingContext2D.cpp b/Userland/Libraries/LibWeb/HTML/CanvasRenderingContext2D.cpp index 083ac2621ad..484892256d3 100644 --- a/Userland/Libraries/LibWeb/HTML/CanvasRenderingContext2D.cpp +++ b/Userland/Libraries/LibWeb/HTML/CanvasRenderingContext2D.cpp @@ -186,6 +186,7 @@ Gfx::Painter* CanvasRenderingContext2D::painter() if (!canvas_element().bitmap()) { if (!canvas_element().create_bitmap()) return nullptr; + canvas_element().document().invalidate_display_list(); m_painter = make(*canvas_element().bitmap()); } return m_painter.ptr(); diff --git a/Userland/Libraries/LibWeb/HTML/Navigable.h b/Userland/Libraries/LibWeb/HTML/Navigable.h index 3745f171e96..96d4e313d0b 100644 --- a/Userland/Libraries/LibWeb/HTML/Navigable.h +++ b/Userland/Libraries/LibWeb/HTML/Navigable.h @@ -22,6 +22,7 @@ #include #include #include +#include #include #include diff --git a/Userland/Libraries/LibWeb/HTML/TraversableNavigable.cpp b/Userland/Libraries/LibWeb/HTML/TraversableNavigable.cpp index 63d87817b6a..ad966cef041 100644 --- a/Userland/Libraries/LibWeb/HTML/TraversableNavigable.cpp +++ b/Userland/Libraries/LibWeb/HTML/TraversableNavigable.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include namespace Web::HTML { @@ -1193,6 +1194,12 @@ void TraversableNavigable::paint(DevicePixelRect const& content_rect, Painting:: if (!document) return; + for (auto& navigable : all_navigables()) { + if (auto active_document = navigable->active_document(); active_document && active_document->paintable()) { + active_document->paintable()->refresh_scroll_state(); + } + } + DOM::Document::PaintConfig paint_config; paint_config.paint_overlay = paint_options.paint_overlay == PaintOptions::PaintOverlay::Yes; paint_config.should_show_line_box_borders = paint_options.should_show_line_box_borders;