Ver código fonte

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.
Tim Ledbetter 11 meses atrás
pai
commit
5800b7e884

+ 11 - 8
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<HTML::Navigable> 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();
     }
 }
 

+ 3 - 2
Userland/Libraries/LibWeb/DOM/Document.h

@@ -35,6 +35,7 @@
 #include <LibWeb/HTML/SandboxingFlagSet.h>
 #include <LibWeb/HTML/Scripting/Environments.h>
 #include <LibWeb/HTML/VisibilityState.h>
+#include <LibWeb/InvalidateDisplayList.h>
 #include <LibWeb/WebIDL/ExceptionOr.h>
 #include <LibWeb/WebIDL/ObservableArray.h>
 
@@ -700,8 +701,8 @@ public:
     void set_cached_navigable(JS::GCPtr<HTML::Navigable>);
 
     [[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 };

+ 0 - 1
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();
     }
 

+ 1 - 0
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;

+ 1 - 1
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()

+ 4 - 4
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);
     }
 }
 

+ 2 - 1
Userland/Libraries/LibWeb/HTML/Navigable.h

@@ -21,6 +21,7 @@
 #include <LibWeb/HTML/SourceSnapshotParams.h>
 #include <LibWeb/HTML/StructuredSerialize.h>
 #include <LibWeb/HTML/TokenizedFeatures.h>
+#include <LibWeb/InvalidateDisplayList.h>
 #include <LibWeb/Page/EventHandler.h>
 #include <LibWeb/Painting/DisplayList.h>
 #include <LibWeb/PixelUnits.h>
@@ -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; }
 

+ 16 - 0
Userland/Libraries/LibWeb/InvalidateDisplayList.h

@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2024, Tim Ledbetter <tim.ledbetter@ladybird.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+namespace Web {
+
+enum class InvalidateDisplayList {
+    Yes,
+    No,
+};
+
+}

+ 9 - 6
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<DOM::Document&>(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<DOM::Document&>(this->document());
-
     if (is<Painting::InlinePaintable>(*this)) {
         auto const& fragments = static_cast<Painting::InlinePaintable const*>(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<Painting::PaintableWithLines>(*containing_block))
         return;
     static_cast<Painting::PaintableWithLines const&>(*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;
     });
 }

+ 2 - 1
Userland/Libraries/LibWeb/Painting/Paintable.h

@@ -7,6 +7,7 @@
 #pragma once
 
 #include <AK/NonnullOwnPtr.h>
+#include <LibWeb/InvalidateDisplayList.h>
 #include <LibWeb/Layout/Box.h>
 #include <LibWeb/Layout/LineBox.h>
 #include <LibWeb/Layout/TextNode.h>
@@ -199,7 +200,7 @@ public:
 
     JS::GCPtr<HTML::Navigable> navigable() const;
 
-    virtual void set_needs_display();
+    virtual void set_needs_display(InvalidateDisplayList = InvalidateDisplayList::Yes);
 
     PaintableBox* containing_block() const
     {

+ 3 - 3
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<CSSPixelRect> PaintableBox::get_masking_area() const

+ 1 - 1
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;