diff --git a/Meta/Lagom/Tools/CodeGenerators/LibWeb/Generate_CSS_PropertyID_cpp.cpp b/Meta/Lagom/Tools/CodeGenerators/LibWeb/Generate_CSS_PropertyID_cpp.cpp index 5b9a817098..ee24293c38 100644 --- a/Meta/Lagom/Tools/CodeGenerators/LibWeb/Generate_CSS_PropertyID_cpp.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/LibWeb/Generate_CSS_PropertyID_cpp.cpp @@ -155,6 +155,34 @@ bool property_affects_layout(PropertyID property_id) } } +bool property_affects_stacking_context(PropertyID property_id) +{ + switch (property_id) { +)~~~"); + + properties.for_each_member([&](auto& name, auto& value) { + VERIFY(value.is_object()); + + bool affects_layout = true; + if (value.as_object().has("affects-stacking-context")) + affects_layout = value.as_object().get("affects-stacking-context").to_bool(); + + if (affects_layout) { + auto member_generator = generator.fork(); + member_generator.set("name:titlecase", title_casify(name)); + member_generator.append(R"~~~( + case PropertyID::@name:titlecase@: +)~~~"); + } + }); + + generator.append(R"~~~( + return true; + default: + return false; + } +} + NonnullRefPtr property_initial_value(PropertyID property_id) { static Array, to_underlying(last_property_id) + 1> initial_values; diff --git a/Meta/Lagom/Tools/CodeGenerators/LibWeb/Generate_CSS_PropertyID_h.cpp b/Meta/Lagom/Tools/CodeGenerators/LibWeb/Generate_CSS_PropertyID_h.cpp index c3a86fc5d1..813438bc6d 100644 --- a/Meta/Lagom/Tools/CodeGenerators/LibWeb/Generate_CSS_PropertyID_h.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/LibWeb/Generate_CSS_PropertyID_h.cpp @@ -90,6 +90,7 @@ bool property_accepts_value(PropertyID, StyleValue&); size_t property_maximum_value_count(PropertyID); bool property_affects_layout(PropertyID); +bool property_affects_stacking_context(PropertyID); constexpr PropertyID first_property_id = PropertyID::@first_property_id@; constexpr PropertyID last_property_id = PropertyID::@last_property_id@; diff --git a/Userland/Libraries/LibWeb/CSS/Properties.json b/Userland/Libraries/LibWeb/CSS/Properties.json index 6270cbf9ce..7d120038a4 100644 --- a/Userland/Libraries/LibWeb/CSS/Properties.json +++ b/Userland/Libraries/LibWeb/CSS/Properties.json @@ -1034,6 +1034,8 @@ ] }, "opacity": { + "affects-layout": false, + "affects-stacking-context": true, "inherited": false, "initial": "1", "valid-types": [ @@ -1459,6 +1461,8 @@ ] }, "z-index": { + "affects-layout": false, + "affects-stacking-context": true, "inherited": false, "initial": "auto", "valid-types": [ diff --git a/Userland/Libraries/LibWeb/DOM/Document.cpp b/Userland/Libraries/LibWeb/DOM/Document.cpp index b7f357c958..018f6d47c2 100644 --- a/Userland/Libraries/LibWeb/DOM/Document.cpp +++ b/Userland/Libraries/LibWeb/DOM/Document.cpp @@ -1558,4 +1558,10 @@ void Document::decrement_number_of_things_delaying_the_load_event(Badgeclient().page_did_update_resource_count(m_number_of_things_delaying_the_load_event); } +void Document::invalidate_stacking_context_tree() +{ + if (auto* paint_box = this->paint_box()) + const_cast(paint_box)->invalidate_stacking_context(); +} + } diff --git a/Userland/Libraries/LibWeb/DOM/Document.h b/Userland/Libraries/LibWeb/DOM/Document.h index b55f474fda..079d4e95aa 100644 --- a/Userland/Libraries/LibWeb/DOM/Document.h +++ b/Userland/Libraries/LibWeb/DOM/Document.h @@ -148,6 +148,7 @@ public: void set_needs_layout(); void invalidate_layout(); + void invalidate_stacking_context_tree(); virtual bool is_child_allowed(const Node&) const override; diff --git a/Userland/Libraries/LibWeb/DOM/Element.cpp b/Userland/Libraries/LibWeb/DOM/Element.cpp index e562c1db1c..161e178778 100644 --- a/Userland/Libraries/LibWeb/DOM/Element.cpp +++ b/Userland/Libraries/LibWeb/DOM/Element.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -278,12 +279,14 @@ void Element::did_remove_attribute(FlyString const& name) enum class RequiredInvalidation { None, RepaintOnly, + RebuildStackingContextTree, Relayout, }; static RequiredInvalidation compute_required_invalidation(CSS::StyleProperties const& old_style, CSS::StyleProperties const& new_style) { bool requires_repaint = false; + bool requires_stacking_context_tree_rebuild = false; for (auto i = to_underlying(CSS::first_property_id); i <= to_underlying(CSS::last_property_id); ++i) { auto property_id = static_cast(i); auto const& old_value = old_style.properties()[i]; @@ -296,8 +299,12 @@ static RequiredInvalidation compute_required_invalidation(CSS::StyleProperties c continue; if (CSS::property_affects_layout(property_id)) return RequiredInvalidation::Relayout; + if (CSS::property_affects_stacking_context(property_id)) + requires_stacking_context_tree_rebuild = true; requires_repaint = true; } + if (requires_stacking_context_tree_rebuild) + return RequiredInvalidation::RebuildStackingContextTree; if (requires_repaint) return RequiredInvalidation::RepaintOnly; return RequiredInvalidation::None; @@ -325,6 +332,13 @@ Element::NeedsRelayout Element::recompute_style() return NeedsRelayout::No; } + if (required_invalidation == RequiredInvalidation::RebuildStackingContextTree && layout_node()) { + layout_node()->apply_style(*m_computed_css_values); + document().invalidate_stacking_context_tree(); + layout_node()->set_needs_display(); + return NeedsRelayout::No; + } + return NeedsRelayout::Yes; }