diff options
author | Andreas Kling <kling@serenityos.org> | 2022-03-21 10:58:51 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2022-03-21 13:03:33 +0100 |
commit | 8c88ee1165a538600c630f929b0b726d200c7dc7 (patch) | |
tree | 345dbf9447fe40d0557abd097b227110ee6ed409 /Userland/Libraries | |
parent | 59afdb959ff20ac8516ceb180c68084997538b70 (diff) | |
download | serenity-8c88ee1165a538600c630f929b0b726d200c7dc7.zip |
LibWeb: Only invalidate stacking context tree for opacity/z-index change
I came across some websites that change an elements CSS "opacity" in
their :hover selectors. That caused us to relayout on hover, which we'd
like to avoid.
With this patch, we now check if a property only affects the stacking
context tree, and if nothing layout-affecting has changed, we only
invalidate the stacking context tree, causing it to be rebuilt on next
paint or hit test.
This makes :hover { opacity: ... } rules much faster. :^)
Diffstat (limited to 'Userland/Libraries')
-rw-r--r-- | Userland/Libraries/LibWeb/CSS/Properties.json | 4 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/DOM/Document.cpp | 6 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/DOM/Document.h | 1 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/DOM/Element.cpp | 14 |
4 files changed, 25 insertions, 0 deletions
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(Badge<Document page->client().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<Painting::PaintableBox*>(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 <LibWeb/HTML/EventLoop/EventLoop.h> #include <LibWeb/HTML/Parser/HTMLParser.h> #include <LibWeb/Layout/BlockContainer.h> +#include <LibWeb/Layout/InitialContainingBlock.h> #include <LibWeb/Layout/InlineNode.h> #include <LibWeb/Layout/ListItemBox.h> #include <LibWeb/Layout/TableBox.h> @@ -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<CSS::PropertyID>(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; } |