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.
This commit is contained in:
parent
b4064320bd
commit
95a8dec373
Notes:
sideshowbarker
2024-07-17 18:38:54 +09:00
Author: https://github.com/kalenikaliaksandr Commit: https://github.com/SerenityOS/serenity/commit/95a8dec373 Pull-request: https://github.com/SerenityOS/serenity/pull/20688 Reviewed-by: https://github.com/awesomekling
7 changed files with 74 additions and 10 deletions
8
Tests/LibWeb/Ref/grid-items-painting-order-ref.html
Normal file
8
Tests/LibWeb/Ref/grid-items-painting-order-ref.html
Normal file
|
@ -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
Tests/LibWeb/Ref/grid-items-painting-order.html
Normal file
12
Tests/LibWeb/Ref/grid-items-painting-order.html
Normal file
|
@ -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,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
Tests/LibWeb/Text/expected/hit_testing/grid.txt
Normal file
1
Tests/LibWeb/Text/expected/hit_testing/grid.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
true
|
23
Tests/LibWeb/Text/input/hit_testing/grid.html
Normal file
23
Tests/LibWeb/Text/input/hit_testing/grid.html
Normal file
|
@ -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>
|
|
@ -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_as_stacking_context(paintable, context);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
if (parent_paintable)
|
if (parent_paintable)
|
||||||
parent_paintable->after_children_paint(context, PaintPhase::Foreground);
|
parent_paintable->after_children_paint(context, PaintPhase::Foreground);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Add table
Reference in a new issue