From 447519f6783456c239c6c78acb2ff3503fb45b18 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Sun, 23 Oct 2022 18:18:58 +0200 Subject: [PATCH] LibWeb: Paint positioned descendants with `z-index: auto` This "worked" before because all positioned elements would create their own stacking context. When we stopped doing this, there was nobody to actually paint positioned descendants with `z-index: auto`. This patch splits up steps 8 and 9 of the paint order algorithm and implements step 8 as a paint tree traversal. There's more to step 8 than I've implemented here, so I've left a FIXME for our future selves. --- .../LibWeb/Painting/StackingContext.cpp | 37 +++++++++++++++++-- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/Userland/Libraries/LibWeb/Painting/StackingContext.cpp b/Userland/Libraries/LibWeb/Painting/StackingContext.cpp index d28929c41e..8d50b2183c 100644 --- a/Userland/Libraries/LibWeb/Painting/StackingContext.cpp +++ b/Userland/Libraries/LibWeb/Painting/StackingContext.cpp @@ -153,11 +153,40 @@ void StackingContext::paint_internal(PaintContext& context) const paint_descendants(context, m_box, StackingContextPaintPhase::BackgroundAndBordersForInlineLevelAndReplaced); paint_node(m_box, context, PaintPhase::Foreground); paint_descendants(context, m_box, StackingContextPaintPhase::Foreground); - // Draw other positioned descendants (steps 8, 9) + + // Draw positioned descendants with z-index `0` or `auto` in tree order. (step 8) + // FIXME: There's more to this step that we have yet to understand and implement. + m_box.paint_box()->for_each_in_subtree_of_type([&](PaintableBox const& paint_box) { + if (!paint_box.layout_box().is_positioned()) + return TraversalDecision::Continue; + auto const& z_index = paint_box.computed_values().z_index(); + if (z_index.has_value() && z_index.value() != 0) + return TraversalDecision::Continue; + if (auto* child = paint_box.stacking_context()) { + paint_child(child); + return TraversalDecision::SkipChildrenAndContinue; + } + // At this point, `paint_box` is a positioned descendant with z-index: auto + // but no stacking context of its own. + // FIXME: This is basically duplicating logic found elsewhere in this same function. Find a way to make this more elegant. + paint_node(paint_box.layout_box(), context, PaintPhase::Background); + paint_node(paint_box.layout_box(), context, PaintPhase::Border); + paint_descendants(context, paint_box.layout_box(), StackingContextPaintPhase::BackgroundAndBorders); + paint_descendants(context, paint_box.layout_box(), StackingContextPaintPhase::Floats); + paint_descendants(context, paint_box.layout_box(), StackingContextPaintPhase::BackgroundAndBordersForInlineLevelAndReplaced); + paint_node(paint_box.layout_box(), context, PaintPhase::Foreground); + paint_descendants(context, paint_box.layout_box(), StackingContextPaintPhase::Foreground); + paint_node(paint_box.layout_box(), context, PaintPhase::FocusOutline); + paint_node(paint_box.layout_box(), context, PaintPhase::Overlay); + paint_descendants(context, paint_box.layout_box(), StackingContextPaintPhase::FocusAndOverlay); + + return TraversalDecision::Continue; + }); + + // Draw other positioned descendants (step 9) for (auto* child : m_children) { - if (child->m_box.computed_values().z_index().has_value() && child->m_box.computed_values().z_index().value() < 0) - continue; - paint_child(child); + if (child->m_box.computed_values().z_index().has_value() && child->m_box.computed_values().z_index().value() >= 1) + paint_child(child); } paint_node(m_box, context, PaintPhase::FocusOutline);