summaryrefslogtreecommitdiff
path: root/Userland/Libraries
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2022-03-21 10:58:51 +0100
committerAndreas Kling <kling@serenityos.org>2022-03-21 13:03:33 +0100
commit8c88ee1165a538600c630f929b0b726d200c7dc7 (patch)
tree345dbf9447fe40d0557abd097b227110ee6ed409 /Userland/Libraries
parent59afdb959ff20ac8516ceb180c68084997538b70 (diff)
downloadserenity-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.json4
-rw-r--r--Userland/Libraries/LibWeb/DOM/Document.cpp6
-rw-r--r--Userland/Libraries/LibWeb/DOM/Document.h1
-rw-r--r--Userland/Libraries/LibWeb/DOM/Element.cpp14
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;
}