From 4b9f5c6fb839d82a9725a2e6fc011f48caf6525e Mon Sep 17 00:00:00 2001 From: Gingeh <39150378+Gingeh@users.noreply.github.com> Date: Mon, 7 Apr 2025 18:39:32 +1000 Subject: [PATCH] LibWeb: Generate ::backdrop pseudo-elements --- Base/res/ladybird/about-pages/settings.html | 1 - Libraries/LibWeb/CSS/Default.css | 8 ++++ Libraries/LibWeb/DOM/Element.cpp | 2 + Libraries/LibWeb/Layout/TreeBuilder.cpp | 21 +++++++++- .../Layout/expected/dialog-open-modal.txt | 2 + .../Layout/expected/popovertarget-button.txt | 2 + Tests/LibWeb/Layout/expected/top-layer.txt | 2 + .../dialogs-with-no-backdrop-ref.html | 5 +++ .../modal-dialog-backdrop-ref.html | 42 +++++++++++++++++++ .../dialogs-with-no-backdrop.html | 41 ++++++++++++++++++ .../modal-dialog-backdrop.html | 21 ++++++++++ 11 files changed, 145 insertions(+), 2 deletions(-) create mode 100644 Tests/LibWeb/Ref/expected/wpt-import/html/semantics/interactive-elements/the-dialog-element/dialogs-with-no-backdrop-ref.html create mode 100644 Tests/LibWeb/Ref/expected/wpt-import/html/semantics/interactive-elements/the-dialog-element/modal-dialog-backdrop-ref.html create mode 100644 Tests/LibWeb/Ref/input/wpt-import/html/semantics/interactive-elements/the-dialog-element/dialogs-with-no-backdrop.html create mode 100644 Tests/LibWeb/Ref/input/wpt-import/html/semantics/interactive-elements/the-dialog-element/modal-dialog-backdrop.html diff --git a/Base/res/ladybird/about-pages/settings.html b/Base/res/ladybird/about-pages/settings.html index 336e205a84c..bd03eab20b0 100644 --- a/Base/res/ladybird/about-pages/settings.html +++ b/Base/res/ladybird/about-pages/settings.html @@ -152,7 +152,6 @@ } dialog::backdrop { - /* FIXME: This doesn't work in Ladybird. */ background-color: rgba(0, 0, 0, 0.5); } diff --git a/Libraries/LibWeb/CSS/Default.css b/Libraries/LibWeb/CSS/Default.css index 29645daa71d..6cbcfaeb7b6 100644 --- a/Libraries/LibWeb/CSS/Default.css +++ b/Libraries/LibWeb/CSS/Default.css @@ -285,6 +285,14 @@ dialog:popover-open { background-color: transparent; } +/* 4.2. The ::backdrop Pseudo-Element + * https://drafts.csswg.org/css-position-4/#backdrop + */ +::backdrop { + position: fixed; + inset: 0; +} + slot { display: contents; } diff --git a/Libraries/LibWeb/DOM/Element.cpp b/Libraries/LibWeb/DOM/Element.cpp index 08b9e6402ea..c4f9bc70b72 100644 --- a/Libraries/LibWeb/DOM/Element.cpp +++ b/Libraries/LibWeb/DOM/Element.cpp @@ -566,6 +566,8 @@ CSS::RequiredInvalidationAfterStyleChange Element::recompute_style() recompute_pseudo_element_style(CSS::PseudoElement::Before); recompute_pseudo_element_style(CSS::PseudoElement::After); + if (m_rendered_in_top_layer) + recompute_pseudo_element_style(CSS::PseudoElement::Backdrop); if (had_list_marker || m_computed_properties->display().is_list_item()) recompute_pseudo_element_style(CSS::PseudoElement::Marker); diff --git a/Libraries/LibWeb/Layout/TreeBuilder.cpp b/Libraries/LibWeb/Layout/TreeBuilder.cpp index 3a31d8866ff..40f0ba39143 100644 --- a/Libraries/LibWeb/Layout/TreeBuilder.cpp +++ b/Libraries/LibWeb/Layout/TreeBuilder.cpp @@ -567,8 +567,27 @@ void TreeBuilder::update_layout_tree(DOM::Node& dom_node, TreeBuilder::Context& // generate boxes as if they were siblings of the root element. TemporaryChange layout_mask(context.layout_top_layer, true); for (auto const& top_layer_element : document.top_layer_elements()) { - if (top_layer_element->rendered_in_top_layer()) + if (top_layer_element->rendered_in_top_layer()) { + // Each element rendered in the top layer has a ::backdrop pseudo-element, for which it is the originating element. + [&]() { + if (top_layer_element->has_inclusive_ancestor_with_display_none()) + return; + + auto pseudo_element_style = top_layer_element->pseudo_element_computed_properties(CSS::PseudoElement::Backdrop); + if (!pseudo_element_style) + return; + + auto pseudo_element_display = pseudo_element_style->display(); + + auto pseudo_element_node = DOM::Element::create_layout_node_for_display_type(document, pseudo_element_display, *pseudo_element_style, nullptr); + if (!pseudo_element_node) + return; + + top_layer_element->set_pseudo_element_node({}, CSS::PseudoElement::Backdrop, pseudo_element_node); + insert_node_into_inline_or_block_ancestor(*pseudo_element_node, pseudo_element_display, AppendOrPrepend::Append); + }(); update_layout_tree(top_layer_element, context, should_create_layout_node ? MustCreateSubtree::Yes : MustCreateSubtree::No); + } } } pop_parent(); diff --git a/Tests/LibWeb/Layout/expected/dialog-open-modal.txt b/Tests/LibWeb/Layout/expected/dialog-open-modal.txt index e6aa589b670..06c113243c5 100644 --- a/Tests/LibWeb/Layout/expected/dialog-open-modal.txt +++ b/Tests/LibWeb/Layout/expected/dialog-open-modal.txt @@ -2,6 +2,7 @@ Viewport <#document> at (0,0) content-size 800x600 children: not-inline BlockContainer at (0,0) content-size 800x600 [BFC] children: not-inline BlockContainer at (8,8) content-size 784x0 children: inline TextNode <#text> + BlockContainer <(anonymous)> at (0,0) content-size 800x600 positioned [BFC] children: not-inline Box at (358.84375,291.5) content-size 82.3125x17 positioned flex-container(row) [FFC] children: not-inline BlockContainer <(anonymous)> (not painted) [BFC] children: inline TextNode <#text> @@ -15,6 +16,7 @@ Viewport <#document> at (0,0) content-size 800x600 children: not-inline ViewportPaintable (Viewport<#document>) [0,0 800x600] PaintableWithLines (BlockContainer) [0,0 800x600] PaintableWithLines (BlockContainer) [8,8 784x0] + PaintableWithLines (BlockContainer(anonymous)) [0,0 800x600] PaintableBox (Box#modal) [339.84375,272.5 120.3125x55] PaintableWithLines (BlockContainer) [358.84375,291.5 82.3125x17] TextPaintable (TextNode<#text>) diff --git a/Tests/LibWeb/Layout/expected/popovertarget-button.txt b/Tests/LibWeb/Layout/expected/popovertarget-button.txt index a93b32c6eda..afdf5dec98d 100644 --- a/Tests/LibWeb/Layout/expected/popovertarget-button.txt +++ b/Tests/LibWeb/Layout/expected/popovertarget-button.txt @@ -8,6 +8,7 @@ Viewport <#document> at (0,0) content-size 800x600 children: not-inline TextNode <#text> TextNode <#text> TextNode <#text> + BlockContainer <(anonymous)> at (0,0) content-size 800x600 positioned [BFC] children: not-inline BlockContainer at (358.84375,291.5) content-size 82.3125x17 positioned [BFC] children: inline TextNode <#text> InlineNode @@ -22,6 +23,7 @@ ViewportPaintable (Viewport<#document>) [0,0 800x600] PaintableWithLines (BlockContainer