Bläddra i källkod

LibWeb: Treat grid item as it creates stacking context during painting

Grid specification https://www.w3.org/TR/css-grid-2/#z-order defines
special painting order for grid items which should be the same as for
defined for inline-blocks in CSS2.
Aliaksandr Kalenik 1 år sedan
förälder
incheckning
95a8dec373

+ 8 - 0
Tests/LibWeb/Ref/grid-items-painting-order-ref.html

@@ -0,0 +1,8 @@
+<!doctype html><style type="text/css">
+* { outline: 1px solid black; }
+body { display: grid; }
+.bar {
+    grid-area: 1 / 1 / auto / auto;
+    background: orange;
+}
+</style><body><div class="bar">bar</div>

+ 12 - 0
Tests/LibWeb/Ref/grid-items-painting-order.html

@@ -0,0 +1,12 @@
+<!doctype html><style type="text/css">
+* { outline: 1px solid black; }
+body { display: grid; }
+.foo {
+    grid-area: 1 / 1 / auto / auto;
+    background: pink;
+}
+.bar {
+    grid-area: 1 / 1 / auto / auto;
+    background: orange;
+}
+</style><body><div class="foo">foo</div><div class="bar">bar</div>

+ 1 - 0
Tests/LibWeb/Ref/manifest.json

@@ -1,5 +1,6 @@
 {
 {
     "img-srcset-viewport-relative-sizes.html": "img-srcset-viewport-relative-sizes-ref.html",
     "img-srcset-viewport-relative-sizes.html": "img-srcset-viewport-relative-sizes-ref.html",
+    "grid-items-painting-order.html": "grid-items-painting-order-ref.html",
     "square-flex.html": "square-ref.html",
     "square-flex.html": "square-ref.html",
     "separate-borders-inline-table.html": "separate-borders-ref.html",
     "separate-borders-inline-table.html": "separate-borders-ref.html",
     "opacity-stacking.html": "opacity-stacking-ref.html",
     "opacity-stacking.html": "opacity-stacking-ref.html",

+ 1 - 0
Tests/LibWeb/Text/expected/hit_testing/grid.txt

@@ -0,0 +1 @@
+   true

+ 23 - 0
Tests/LibWeb/Text/input/hit_testing/grid.html

@@ -0,0 +1,23 @@
+<!doctype html><style type="text/css">
+* { outline: 1px solid black; }
+body { display: grid; }
+#foo {
+    grid-area: 1 / 1 / auto / auto;
+    background: pink;
+    width: 100px;
+    height: 100px;
+}
+#bar {
+    grid-area: 1 / 1 / auto / auto;
+    background: orange;
+    width: 100px;
+    height: 100px;
+}
+</style>
+<div id="foo"></div><div id="bar"></div>
+<script src="../include.js"></script>
+<script>
+    test(() => {
+        println(internals.hitTest(50, 50).node === document.getElementById("bar"));
+    });
+</script>

+ 28 - 10
Userland/Libraries/LibWeb/Painting/StackingContext.cpp

@@ -72,6 +72,20 @@ static PaintPhase to_paint_phase(StackingContext::StackingContextPaintPhase phas
     }
     }
 }
 }
 
 
+void StackingContext::paint_node_as_stacking_context(Paintable const& paintable, PaintContext& context) const
+{
+    paint_node(paintable, context, PaintPhase::Background);
+    paint_node(paintable, context, PaintPhase::Border);
+    paint_descendants(context, paintable, StackingContextPaintPhase::BackgroundAndBorders);
+    paint_descendants(context, paintable, StackingContextPaintPhase::Floats);
+    paint_descendants(context, paintable, StackingContextPaintPhase::BackgroundAndBordersForInlineLevelAndReplaced);
+    paint_node(paintable, context, PaintPhase::Foreground);
+    paint_descendants(context, paintable, StackingContextPaintPhase::Foreground);
+    paint_node(paintable, context, PaintPhase::Outline);
+    paint_node(paintable, context, PaintPhase::Overlay);
+    paint_descendants(context, paintable, StackingContextPaintPhase::FocusAndOverlay);
+}
+
 void StackingContext::paint_descendants(PaintContext& context, Paintable const& paintable, StackingContextPaintPhase phase) const
 void StackingContext::paint_descendants(PaintContext& context, Paintable const& paintable, StackingContextPaintPhase phase) const
 {
 {
     paintable.before_children_paint(context, to_paint_phase(phase));
     paintable.before_children_paint(context, to_paint_phase(phase));
@@ -99,6 +113,19 @@ void StackingContext::paint_descendants(PaintContext& context, Paintable const&
             return;
             return;
         }
         }
 
 
+        // NOTE: Grid specification https://www.w3.org/TR/css-grid-2/#z-order says that grid items should be treated
+        //       the same way as CSS2 defines for inline-blocks:
+        //       "For each one of these, treat the element as if it created a new stacking context, but any positioned
+        //       descendants and descendants which actually create a new stacking context should be considered part of
+        //       the parent stacking context, not this new one."
+        auto should_be_treated_as_stacking_context = child.layout_node().is_grid_item();
+        if (should_be_treated_as_stacking_context) {
+            // FIXME: This may not be fully correct with respect to the paint phases.
+            if (phase == StackingContextPaintPhase::Foreground)
+                paint_node_as_stacking_context(child, context);
+            return;
+        }
+
         bool child_is_inline_or_replaced = child.is_inline() || is<Layout::ReplacedBox>(child);
         bool child_is_inline_or_replaced = child.is_inline() || is<Layout::ReplacedBox>(child);
         switch (phase) {
         switch (phase) {
         case StackingContextPaintPhase::BackgroundAndBorders:
         case StackingContextPaintPhase::BackgroundAndBorders:
@@ -214,16 +241,7 @@ void StackingContext::paint_internal(PaintContext& context) const
             paint_child(context, *child);
             paint_child(context, *child);
             return TraversalDecision::SkipChildrenAndContinue;
             return TraversalDecision::SkipChildrenAndContinue;
         } else {
         } else {
-            paint_node(paintable, context, PaintPhase::Background);
-            paint_node(paintable, context, PaintPhase::Border);
-            paint_descendants(context, paintable, StackingContextPaintPhase::BackgroundAndBorders);
-            paint_descendants(context, paintable, StackingContextPaintPhase::Floats);
-            paint_descendants(context, paintable, StackingContextPaintPhase::BackgroundAndBordersForInlineLevelAndReplaced);
-            paint_node(paintable, context, PaintPhase::Foreground);
-            paint_descendants(context, paintable, StackingContextPaintPhase::Foreground);
-            paint_node(paintable, context, PaintPhase::Outline);
-            paint_node(paintable, context, PaintPhase::Overlay);
-            paint_descendants(context, paintable, StackingContextPaintPhase::FocusAndOverlay);
+            paint_node_as_stacking_context(paintable, context);
         }
         }
         if (parent_paintable)
         if (parent_paintable)
             parent_paintable->after_children_paint(context, PaintPhase::Foreground);
             parent_paintable->after_children_paint(context, PaintPhase::Foreground);

+ 1 - 0
Userland/Libraries/LibWeb/Painting/StackingContext.h

@@ -29,6 +29,7 @@ public:
         FocusAndOverlay,
         FocusAndOverlay,
     };
     };
 
 
+    void paint_node_as_stacking_context(Paintable const&, PaintContext&) const;
     void paint_descendants(PaintContext&, Paintable const&, StackingContextPaintPhase) const;
     void paint_descendants(PaintContext&, Paintable const&, StackingContextPaintPhase) const;
     void paint(PaintContext&) const;
     void paint(PaintContext&) const;
     Optional<HitTestResult> hit_test(CSSPixelPoint, HitTestType) const;
     Optional<HitTestResult> hit_test(CSSPixelPoint, HitTestType) const;