LibWeb: Ensure inert elements are not visible for hit testing

This commit is contained in:
Tim Ledbetter 2025-02-05 23:37:21 +00:00 committed by Sam Atkins
commit cb405c773b
Notes: github-actions[bot] 2025-02-21 12:43:19 +00:00
4 changed files with 67 additions and 1 deletions

View file

@ -83,6 +83,17 @@ CSS::ImmutableComputedValues const& Paintable::computed_values() const
return m_layout_node->computed_values(); return m_layout_node->computed_values();
} }
bool Paintable::visible_for_hit_testing() const
{
// https://html.spec.whatwg.org/multipage/interaction.html#inert-subtrees
// When a node is inert:
// - Hit-testing must act as if the 'pointer-events' CSS property were set to 'none'.
if (auto dom_node = this->dom_node(); dom_node && dom_node->is_inert())
return false;
return computed_values().pointer_events() != CSS::PointerEvents::None;
}
void Paintable::set_dom_node(GC::Ptr<DOM::Node> dom_node) void Paintable::set_dom_node(GC::Ptr<DOM::Node> dom_node)
{ {
m_dom_node = dom_node; m_dom_node = dom_node;

View file

@ -109,7 +109,7 @@ public:
CSS::ImmutableComputedValues const& computed_values() const; CSS::ImmutableComputedValues const& computed_values() const;
bool visible_for_hit_testing() const { return computed_values().pointer_events() != CSS::PointerEvents::None; } bool visible_for_hit_testing() const;
GC::Ptr<HTML::Navigable> navigable() const; GC::Ptr<HTML::Navigable> navigable() const;

View file

@ -0,0 +1,6 @@
Harness status: OK
Found 1 tests
1 Pass
Pass inert isn't hit-testable, but that isn't expose in the computed style

View file

@ -0,0 +1,49 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>inert isn't hit-testable, but that isn't expose in the computed style</title>
<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
<link rel="author" title="Mozilla" href="https://mozilla.org">
<script src="../resources/testharness.js"></script>
<script src="../resources/testharnessreport.js"></script>
<style>
body { margin: 0 }
div {
width: 100px;
height: 100px;
position: absolute;
top: 0;
left: 0;
background-color: blue;
}
#nonInert {
background-color: red;
}
</style>
<div id="nonInert"></div>
<div id="inert"></div>
<script>
test(function() {
let inert = document.getElementById("inert");
assert_equals(
document.elementFromPoint(50, 50),
inert,
"not-yet-inert node hit-test before non-inert node",
);
inert.inert = true;
assert_equals(
document.elementFromPoint(50, 50),
nonInert,
"inert node is transparent to events (as pointer-events: none)",
);
assert_equals(
getComputedStyle(inert).pointerEvents,
getComputedStyle(nonInert).pointerEvents,
"inert node doesn't change pointer-events computed value",
);
assert_equals(
getComputedStyle(inert).userSelect,
getComputedStyle(nonInert).userSelect,
"inert node doesn't change user-select computed value",
);
});
</script>