From 5800b7e8845c115844fdee413efa1793f70f1dc9 Mon Sep 17 00:00:00 2001 From: Tim Ledbetter Date: Mon, 2 Sep 2024 16:47:32 +0100 Subject: [PATCH] LibWeb: Invalidate the display list when calling `set_needs_display()` Calls to `Document::set_needs_display()` and `Paintable::set_needs_display()` now invalidate the display list by default. This behavior can be changed by passing `InvalidateDisplayList::No` to the function where invalidating the display list is not necessary. --- Userland/Libraries/LibWeb/DOM/Document.cpp | 19 +++++++++++-------- Userland/Libraries/LibWeb/DOM/Document.h | 5 +++-- Userland/Libraries/LibWeb/DOM/Range.cpp | 1 - Userland/Libraries/LibWeb/Forward.h | 1 + .../LibWeb/HTML/CanvasRenderingContext2D.cpp | 2 +- Userland/Libraries/LibWeb/HTML/Navigable.cpp | 8 ++++---- Userland/Libraries/LibWeb/HTML/Navigable.h | 3 ++- .../Libraries/LibWeb/InvalidateDisplayList.h | 16 ++++++++++++++++ .../Libraries/LibWeb/Painting/Paintable.cpp | 15 +++++++++------ .../Libraries/LibWeb/Painting/Paintable.h | 3 ++- .../LibWeb/Painting/PaintableBox.cpp | 6 +++--- .../Libraries/LibWeb/Painting/PaintableBox.h | 2 +- 12 files changed, 53 insertions(+), 28 deletions(-) create mode 100644 Userland/Libraries/LibWeb/InvalidateDisplayList.h diff --git a/Userland/Libraries/LibWeb/DOM/Document.cpp b/Userland/Libraries/LibWeb/DOM/Document.cpp index 5c3f2e51ad8..fc86215dd0f 100644 --- a/Userland/Libraries/LibWeb/DOM/Document.cpp +++ b/Userland/Libraries/LibWeb/DOM/Document.cpp @@ -384,7 +384,6 @@ Document::Document(JS::Realm& realm, const URL::URL& url, TemporaryDocumentForFr if (!navigable || !navigable->is_focused()) return; - node->document().invalidate_display_list(); node->document().update_layout(); if (node->paintable()) { @@ -5383,18 +5382,22 @@ void Document::set_cached_navigable(JS::GCPtr navigable) m_cached_navigable = navigable.ptr(); } -void Document::set_needs_display() +void Document::set_needs_display(InvalidateDisplayList should_invalidate_display_list) { - set_needs_display(viewport_rect()); + set_needs_display(viewport_rect(), should_invalidate_display_list); } -void Document::set_needs_display(CSSPixelRect const&) +void Document::set_needs_display(CSSPixelRect const&, InvalidateDisplayList should_invalidate_display_list) { // 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 (should_invalidate_display_list == InvalidateDisplayList::Yes) { + invalidate_display_list(); + } + auto navigable = this->navigable(); if (!navigable) return; @@ -5404,8 +5407,8 @@ void Document::set_needs_display(CSSPixelRect const&) return; } - if (navigable->container()) { - navigable->container()->document().set_needs_display(); + if (auto container = navigable->container()) { + container->document().set_needs_display(should_invalidate_display_list); } } @@ -5417,8 +5420,8 @@ void Document::invalidate_display_list() if (!navigable) return; - if (navigable->container()) { - navigable->container()->document().invalidate_display_list(); + if (auto container = navigable->container()) { + container->document().invalidate_display_list(); } } diff --git a/Userland/Libraries/LibWeb/DOM/Document.h b/Userland/Libraries/LibWeb/DOM/Document.h index 95938817fa1..3df25ef5482 100644 --- a/Userland/Libraries/LibWeb/DOM/Document.h +++ b/Userland/Libraries/LibWeb/DOM/Document.h @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -700,8 +701,8 @@ public: void set_cached_navigable(JS::GCPtr); [[nodiscard]] bool needs_repaint() const { return m_needs_repaint; } - void set_needs_display(); - void set_needs_display(CSSPixelRect const&); + void set_needs_display(InvalidateDisplayList = InvalidateDisplayList::Yes); + void set_needs_display(CSSPixelRect const&, InvalidateDisplayList = InvalidateDisplayList::Yes); struct PaintConfig { bool paint_overlay { false }; diff --git a/Userland/Libraries/LibWeb/DOM/Range.cpp b/Userland/Libraries/LibWeb/DOM/Range.cpp index bf05321ed63..0a4ab926f1d 100644 --- a/Userland/Libraries/LibWeb/DOM/Range.cpp +++ b/Userland/Libraries/LibWeb/DOM/Range.cpp @@ -98,7 +98,6 @@ 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/Forward.h b/Userland/Libraries/LibWeb/Forward.h index 1728abd62d4..90c2debc818 100644 --- a/Userland/Libraries/LibWeb/Forward.h +++ b/Userland/Libraries/LibWeb/Forward.h @@ -14,6 +14,7 @@ namespace Web { class DragAndDropEventHandler; class EditEventHandler; class EventHandler; +enum class InvalidateDisplayList; class LoadRequest; class Page; class PageClient; diff --git a/Userland/Libraries/LibWeb/HTML/CanvasRenderingContext2D.cpp b/Userland/Libraries/LibWeb/HTML/CanvasRenderingContext2D.cpp index 0506b941e7c..9ea2de636bf 100644 --- a/Userland/Libraries/LibWeb/HTML/CanvasRenderingContext2D.cpp +++ b/Userland/Libraries/LibWeb/HTML/CanvasRenderingContext2D.cpp @@ -174,7 +174,7 @@ void CanvasRenderingContext2D::did_draw(Gfx::FloatRect const&) // FIXME: Make use of the rect to reduce the invalidated area when possible. if (!canvas_element().paintable()) return; - canvas_element().paintable()->set_needs_display(); + canvas_element().paintable()->set_needs_display(InvalidateDisplayList::No); } Gfx::Painter* CanvasRenderingContext2D::painter() diff --git a/Userland/Libraries/LibWeb/HTML/Navigable.cpp b/Userland/Libraries/LibWeb/HTML/Navigable.cpp index a7c8010e7c6..b5adf8baa2c 100644 --- a/Userland/Libraries/LibWeb/HTML/Navigable.cpp +++ b/Userland/Libraries/LibWeb/HTML/Navigable.cpp @@ -2012,7 +2012,7 @@ void Navigable::set_viewport_size(CSSPixelSize size) } if (auto document = active_document()) { - document->set_needs_display(); + document->set_needs_display(InvalidateDisplayList::No); document->inform_all_viewport_clients_about_the_current_viewport_rect(); @@ -2028,7 +2028,7 @@ void Navigable::perform_scroll_of_viewport(CSSPixelPoint new_position) scroll_offset_did_change(); if (auto document = active_document()) { - document->set_needs_display(); + document->set_needs_display(InvalidateDisplayList::No); document->set_needs_to_refresh_scroll_state(true); document->inform_all_viewport_clients_about_the_current_viewport_rect(); } @@ -2038,10 +2038,10 @@ void Navigable::perform_scroll_of_viewport(CSSPixelPoint new_position) HTML::main_thread_event_loop().schedule(); } -void Navigable::set_needs_display() +void Navigable::set_needs_display(InvalidateDisplayList should_invalidate_display_list) { if (auto document = active_document(); document) { - document->set_needs_display(); + document->set_needs_display(should_invalidate_display_list); } } diff --git a/Userland/Libraries/LibWeb/HTML/Navigable.h b/Userland/Libraries/LibWeb/HTML/Navigable.h index 96d4e313d0b..1fb9bb83926 100644 --- a/Userland/Libraries/LibWeb/HTML/Navigable.h +++ b/Userland/Libraries/LibWeb/HTML/Navigable.h @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -170,7 +171,7 @@ public: void set_viewport_size(CSSPixelSize); void perform_scroll_of_viewport(CSSPixelPoint position); - void set_needs_display(); + void set_needs_display(InvalidateDisplayList = InvalidateDisplayList::Yes); void set_is_popup(TokenizedFeature::Popup is_popup) { m_is_popup = is_popup; } diff --git a/Userland/Libraries/LibWeb/InvalidateDisplayList.h b/Userland/Libraries/LibWeb/InvalidateDisplayList.h new file mode 100644 index 00000000000..52f680d089c --- /dev/null +++ b/Userland/Libraries/LibWeb/InvalidateDisplayList.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2024, Tim Ledbetter + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +namespace Web { + +enum class InvalidateDisplayList { + Yes, + No, +}; + +} diff --git a/Userland/Libraries/LibWeb/Painting/Paintable.cpp b/Userland/Libraries/LibWeb/Painting/Paintable.cpp index 28d8c6169bd..c8574c1913a 100644 --- a/Userland/Libraries/LibWeb/Painting/Paintable.cpp +++ b/Userland/Libraries/LibWeb/Painting/Paintable.cpp @@ -128,24 +128,27 @@ void Paintable::invalidate_stacking_context() m_stacking_context = nullptr; } -void Paintable::set_needs_display() +void Paintable::set_needs_display(InvalidateDisplayList should_invalidate_display_list) { + auto& document = const_cast(this->document()); + if (should_invalidate_display_list == InvalidateDisplayList::Yes) + document.invalidate_display_list(); + auto* containing_block = this->containing_block(); if (!containing_block) return; - auto& document = const_cast(this->document()); - if (is(*this)) { auto const& fragments = static_cast(this)->fragments(); - for (auto const& fragment : fragments) - document.set_needs_display(fragment.absolute_rect()); + for (auto const& fragment : fragments) { + document.set_needs_display(fragment.absolute_rect(), InvalidateDisplayList::No); + } } if (!is(*containing_block)) return; static_cast(*containing_block).for_each_fragment([&](auto& fragment) { - document.set_needs_display(fragment.absolute_rect()); + document.set_needs_display(fragment.absolute_rect(), InvalidateDisplayList::No); return IterationDecision::Continue; }); } diff --git a/Userland/Libraries/LibWeb/Painting/Paintable.h b/Userland/Libraries/LibWeb/Painting/Paintable.h index 2b166ebc095..57cee6e51e7 100644 --- a/Userland/Libraries/LibWeb/Painting/Paintable.h +++ b/Userland/Libraries/LibWeb/Painting/Paintable.h @@ -7,6 +7,7 @@ #pragma once #include +#include #include #include #include @@ -199,7 +200,7 @@ public: JS::GCPtr navigable() const; - virtual void set_needs_display(); + virtual void set_needs_display(InvalidateDisplayList = InvalidateDisplayList::Yes); PaintableBox* containing_block() const { diff --git a/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp b/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp index bb1628d12df..4debff4fc1d 100644 --- a/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp +++ b/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp @@ -125,7 +125,7 @@ void PaintableBox::set_scroll_offset(CSSPixelPoint offset) // 4. Append the element to doc’s pending scroll event targets. document.pending_scroll_event_targets().append(*layout_box().dom_node()); - set_needs_display(); + set_needs_display(InvalidateDisplayList::No); } void PaintableBox::scroll_by(int delta_x, int delta_y) @@ -915,9 +915,9 @@ TraversalDecision PaintableWithLines::hit_test(CSSPixelPoint position, HitTestTy return TraversalDecision::Continue; } -void PaintableBox::set_needs_display() +void PaintableBox::set_needs_display(InvalidateDisplayList should_invalidate_display_list) { - document().set_needs_display(absolute_rect()); + document().set_needs_display(absolute_rect(), should_invalidate_display_list); } Optional PaintableBox::get_masking_area() const diff --git a/Userland/Libraries/LibWeb/Painting/PaintableBox.h b/Userland/Libraries/LibWeb/Painting/PaintableBox.h index b7b00167572..f86b94cb2b3 100644 --- a/Userland/Libraries/LibWeb/Painting/PaintableBox.h +++ b/Userland/Libraries/LibWeb/Painting/PaintableBox.h @@ -128,7 +128,7 @@ public: DOM::Node const* dom_node() const { return layout_box().dom_node(); } DOM::Node* dom_node() { return layout_box().dom_node(); } - virtual void set_needs_display() override; + virtual void set_needs_display(InvalidateDisplayList = InvalidateDisplayList::Yes) override; virtual void apply_scroll_offset(PaintContext&, PaintPhase) const override; virtual void reset_scroll_offset(PaintContext&, PaintPhase) const override;