diff --git a/Libraries/LibWeb/DOM/Document.cpp b/Libraries/LibWeb/DOM/Document.cpp index 4dd82316abc..1ebdc2e687c 100644 --- a/Libraries/LibWeb/DOM/Document.cpp +++ b/Libraries/LibWeb/DOM/Document.cpp @@ -5315,7 +5315,7 @@ GC::RootVector> Document::elements_from_point(double x, double if (auto const* paintable_box = this->paintable_box(); paintable_box) { (void)paintable_box->hit_test(position, Painting::HitTestType::Exact, [&](Painting::HitTestResult result) { auto* dom_node = result.dom_node(); - if (dom_node && dom_node->is_element()) + if (dom_node && dom_node->is_element() && result.paintable->visible_for_hit_testing()) sequence.append(*static_cast(dom_node)); return TraversalDecision::Continue; }); diff --git a/Libraries/LibWeb/Painting/PaintableBox.cpp b/Libraries/LibWeb/Painting/PaintableBox.cpp index 3f092a04138..63ba7ffe015 100644 --- a/Libraries/LibWeb/Painting/PaintableBox.cpp +++ b/Libraries/LibWeb/Painting/PaintableBox.cpp @@ -965,9 +965,6 @@ TraversalDecision PaintableBox::hit_test(CSSPixelPoint position, HitTestType typ return TraversalDecision::Break; } - if (!visible_for_hit_testing()) - return TraversalDecision::Continue; - if (!absolute_border_box_rect().contains(position_adjusted_by_scroll_offset)) return TraversalDecision::Continue; @@ -978,18 +975,38 @@ Optional PaintableBox::hit_test(CSSPixelPoint position, HitTestTy { Optional result; (void)PaintableBox::hit_test(position, type, [&](HitTestResult candidate) { - if (candidate.paintable->visible_for_hit_testing()) { - if (!result.has_value() - || candidate.vertical_distance.value_or(CSSPixels::max_integer_value) < result->vertical_distance.value_or(CSSPixels::max_integer_value) - || candidate.horizontal_distance.value_or(CSSPixels::max_integer_value) < result->horizontal_distance.value_or(CSSPixels::max_integer_value)) { - result = move(candidate); - } + if (!result.has_value() + || candidate.vertical_distance.value_or(CSSPixels::max_integer_value) < result->vertical_distance.value_or(CSSPixels::max_integer_value) + || candidate.horizontal_distance.value_or(CSSPixels::max_integer_value) < result->horizontal_distance.value_or(CSSPixels::max_integer_value)) { + result = move(candidate); } if (result.has_value() && (type == HitTestType::Exact || (result->vertical_distance == 0 && result->horizontal_distance == 0))) return TraversalDecision::Break; return TraversalDecision::Continue; }); + + // If our hit-testing has resulted in a hit on a paintable, we know that it is the most specific hit. If that + // paintable turns out to be invisible for hit-testing, we need to traverse up the paintable tree to find the next + // paintable that is visible for hit-testing. This implements the behavior expected for pointer-events. + while (result.has_value() && !result->paintable->visible_for_hit_testing()) { + result->index_in_node = result->paintable->dom_node() ? result->paintable->dom_node()->index() : 0; + result->paintable = result->paintable->parent(); + + // If the new parent is an anonymous box part of a continuation, we need to follow the chain to the inline node + // that spawned the anonymous "middle" part of the continuation, since that inline node is the actual parent. + if (is(*result->paintable)) { + auto const& box_layout_node = static_cast(*result->paintable).layout_node_with_style_and_box_metrics(); + if (box_layout_node.is_anonymous() && box_layout_node.continuation_of_node()) { + auto const* original_inline_node = &box_layout_node; + while (original_inline_node->continuation_of_node()) + original_inline_node = original_inline_node->continuation_of_node(); + + result->paintable = const_cast(original_inline_node->first_paintable()); + } + } + } + return result; } diff --git a/Tests/LibWeb/Text/expected/hit_testing/pointer-events.txt b/Tests/LibWeb/Text/expected/hit_testing/pointer-events.txt new file mode 100644 index 00000000000..4d5daec9517 --- /dev/null +++ b/Tests/LibWeb/Text/expected/hit_testing/pointer-events.txt @@ -0,0 +1,12 @@ +
+ +--- +
+
+--- + + +--- + + +--- diff --git a/Tests/LibWeb/Text/input/hit_testing/pointer-events.html b/Tests/LibWeb/Text/input/hit_testing/pointer-events.html new file mode 100644 index 00000000000..ee567380e47 --- /dev/null +++ b/Tests/LibWeb/Text/input/hit_testing/pointer-events.html @@ -0,0 +1,37 @@ + + + +
+
+
+ + +
+
+
+
+
+ + +
+
+
+ + + foo
bar
bazlorem
+ +