mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 23:37:35 +00:00
LibWeb: Change StackingContext::hit_test() to accept callback
This change modifies hit_test() to no longer return the first paintable encountered at a specified position. Instead, this function accepts a callback that is invoked for each paintable located at a position, in hit-testing order. This modification will allow us to reuse this call for `Document.elementsFromPoint()` in upcoming changes.
This commit is contained in:
parent
15d151ee66
commit
9c99182b1e
11 changed files with 120 additions and 104 deletions
|
@ -199,39 +199,42 @@ void InlinePaintable::for_each_fragment(Callback callback) const
|
|||
}
|
||||
}
|
||||
|
||||
Optional<HitTestResult> InlinePaintable::hit_test(CSSPixelPoint position, HitTestType type) const
|
||||
TraversalDecision InlinePaintable::hit_test(CSSPixelPoint position, HitTestType type, Function<TraversalDecision(HitTestResult)> const& callback) const
|
||||
{
|
||||
if (m_clip_rect.has_value() && !m_clip_rect.value().contains(position))
|
||||
return {};
|
||||
return TraversalDecision::Continue;
|
||||
|
||||
auto position_adjusted_by_scroll_offset = position;
|
||||
if (enclosing_scroll_frame_offset().has_value())
|
||||
position_adjusted_by_scroll_offset.translate_by(-enclosing_scroll_frame_offset().value());
|
||||
|
||||
for (auto& fragment : m_fragments) {
|
||||
for (auto const& fragment : m_fragments) {
|
||||
if (fragment.paintable().stacking_context())
|
||||
continue;
|
||||
auto fragment_absolute_rect = fragment.absolute_rect();
|
||||
if (fragment_absolute_rect.contains(position_adjusted_by_scroll_offset)) {
|
||||
if (auto result = fragment.paintable().hit_test(position, type); result.has_value())
|
||||
return result;
|
||||
return HitTestResult { const_cast<Paintable&>(fragment.paintable()),
|
||||
fragment.text_index_at(position_adjusted_by_scroll_offset.x()) };
|
||||
if (fragment.paintable().hit_test(position, type, callback) == TraversalDecision::Break)
|
||||
return TraversalDecision::Break;
|
||||
auto hit_test_result = HitTestResult { const_cast<Paintable&>(fragment.paintable()), fragment.text_index_at(position_adjusted_by_scroll_offset.x()) };
|
||||
if (callback(hit_test_result) == TraversalDecision::Break)
|
||||
return TraversalDecision::Break;
|
||||
}
|
||||
}
|
||||
|
||||
Optional<HitTestResult> hit_test_result;
|
||||
bool should_exit = false;
|
||||
for_each_child([&](Paintable const& child) {
|
||||
if (should_exit)
|
||||
return;
|
||||
if (child.stacking_context())
|
||||
return IterationDecision::Continue;
|
||||
if (auto result = child.hit_test(position, type); result.has_value()) {
|
||||
hit_test_result = result;
|
||||
return IterationDecision::Break;
|
||||
}
|
||||
return IterationDecision::Continue;
|
||||
return;
|
||||
if (child.hit_test(position, type, callback) == TraversalDecision::Break)
|
||||
should_exit = true;
|
||||
});
|
||||
|
||||
return hit_test_result;
|
||||
if (should_exit)
|
||||
return TraversalDecision::Break;
|
||||
|
||||
return TraversalDecision::Continue;
|
||||
}
|
||||
|
||||
CSSPixelRect InlinePaintable::bounding_rect() const
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue