Sfoglia il codice sorgente

LibWeb: Only propagate CSS overflow to the viewport once per tree build

Before this change, we were doing it after every layout, which meant
that already-propagated overflow could be propagated again, which led to
incorrect scrolling behavior.
Andreas Kling 1 anno fa
parent
commit
f9cab320e6

+ 1 - 1
Tests/LibWeb/Layout/expected/replaced-within-max-content.txt

@@ -8,7 +8,7 @@ Viewport <#document> at (0,0) content-size 800x600 children: not-inline
           frag 0 from ImageBox start: 0, length: 0, rect: [8,8 150x150]
         ImageBox <img.replaced> at (8,8) content-size 150x150 children: not-inline
           (SVG-as-image isolated context)
-          Viewport <#document> at (0,0) content-size 150x150 children: inline
+          Viewport <#document> at (0,0) content-size 150x150 [BFC] children: inline
             SVGSVGBox <svg> at (0,0) content-size 150x150 [SVG] children: not-inline
               SVGGeometryBox <path> at (0,0) content-size 150x150 children: not-inline
         TextNode <#text>

+ 1 - 1
Tests/LibWeb/Layout/expected/svg/svg-as-image-implicit-viewbox.txt

@@ -3,7 +3,7 @@ Viewport <#document> at (0,0) content-size 800x600 children: not-inline
     BlockContainer <body> at (8,8) content-size 784x100 children: not-inline
       ImageBox <img> at (8,8) content-size 50x100 children: not-inline
         (SVG-as-image isolated context)
-        Viewport <#document> at (0,0) content-size 50x100 children: inline
+        Viewport <#document> at (0,0) content-size 50x100 [BFC] children: inline
           SVGSVGBox <svg> at (0,0) content-size 50x100 [SVG] children: not-inline
             SVGGeometryBox <rect> at (0,0) content-size 50x100 children: not-inline
 

+ 1 - 1
Tests/LibWeb/Layout/expected/svg/svg-as-image.txt

@@ -3,7 +3,7 @@ Viewport <#document> at (0,0) content-size 800x600 children: not-inline
     BlockContainer <body> at (8,8) content-size 784x1568 children: not-inline
       ImageBox <img> at (8,8) content-size 784x1568 children: not-inline
         (SVG-as-image isolated context)
-        Viewport <#document> at (0,0) content-size 784x1568 children: inline
+        Viewport <#document> at (0,0) content-size 784x1568 [BFC] children: inline
           SVGSVGBox <svg> at (0,0) content-size 784x1568 [SVG] children: inline
             TextNode <#text>
             SVGGeometryBox <rect> at (0,0) content-size 784x1568 children: not-inline

+ 3 - 3
Userland/Libraries/LibWeb/DOM/Document.cpp

@@ -984,10 +984,10 @@ void Document::update_layout()
     if (!m_layout_root) {
         Layout::TreeBuilder tree_builder;
         m_layout_root = verify_cast<Layout::Viewport>(*tree_builder.build(*this));
-    }
 
-    if (auto* document_element = this->document_element()) {
-        propagate_overflow_to_viewport(*document_element, *m_layout_root);
+        if (auto* document_element = this->document_element()) {
+            propagate_overflow_to_viewport(*document_element, *m_layout_root);
+        }
     }
 
     Layout::LayoutState layout_state;

+ 7 - 0
Userland/Libraries/LibWeb/DOM/Element.cpp

@@ -542,6 +542,13 @@ static Element::RequiredInvalidationAfterStyleChange compute_required_invalidati
             return Element::RequiredInvalidationAfterStyleChange::full();
         }
 
+        // NOTE: If one of the overflow properties change, we rebuild the entire layout tree.
+        //       This ensures that overflow propagation from root/body to viewport happens correctly.
+        //       In the future, we can make this invalidation narrower.
+        if (property_id == CSS::PropertyID::OverflowX || property_id == CSS::PropertyID::OverflowY) {
+            return Element::RequiredInvalidationAfterStyleChange::full();
+        }
+
         // OPTIMIZATION: Special handling for CSS `visibility`:
         if (property_id == CSS::PropertyID::Visibility) {
             // We don't need to relayout if the visibility changes from visible to hidden or vice versa. Only collapse requires relayout.