mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-09-20 17:58:18 +03:00
LibWeb: Remove is<BlockContainer> check for fragments in hit testing
This change introduces a method for direct access to the paintable of a PaintableFragment. This method is intended to replace the usage of the layout node pointer. Currently, we are only eliminating the use of `layout_node()` in hit testing. Additionally, we no longer check if a fragment's layout node is a `BlockContainer` before recursing into its children during hit testing. This check was likely relevant when all fragments were owned by `PaintableWithLines`, but now it should be safe to remove this check.
This commit is contained in:
parent
09124fc3a5
commit
270bbf43ab
Notes:
sideshowbarker
2024-07-17 04:01:41 +09:00
Author: https://github.com/kalenikaliaksandr Commit: https://github.com/SerenityOS/serenity/commit/270bbf43ab Pull-request: https://github.com/SerenityOS/serenity/pull/22939 Reviewed-by: https://github.com/awesomekling
@ -163,13 +163,13 @@ void InlinePaintable::for_each_fragment(Callback callback) const
|
||||
Optional<HitTestResult> InlinePaintable::hit_test(CSSPixelPoint position, HitTestType type) const
|
||||
{
|
||||
for (auto& fragment : m_fragments) {
|
||||
if (is<Layout::Box>(fragment.layout_node()) && static_cast<Layout::Box const&>(fragment.layout_node()).paintable_box()->stacking_context())
|
||||
if (fragment.paintable().stacking_context())
|
||||
continue;
|
||||
auto fragment_absolute_rect = fragment.absolute_rect();
|
||||
if (fragment_absolute_rect.contains(position)) {
|
||||
if (is<Layout::BlockContainer>(fragment.layout_node()) && fragment.layout_node().paintable())
|
||||
return fragment.layout_node().paintable()->hit_test(position, type);
|
||||
return HitTestResult { const_cast<Paintable&>(const_cast<Paintable&>(*fragment.layout_node().paintable())),
|
||||
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.x()) };
|
||||
}
|
||||
}
|
||||
|
@ -752,17 +752,17 @@ Optional<HitTestResult> PaintableWithLines::hit_test(CSSPixelPoint position, Hit
|
||||
|
||||
Optional<HitTestResult> last_good_candidate;
|
||||
for (auto const& fragment : fragments()) {
|
||||
if (is<Layout::Box>(fragment.layout_node()) && static_cast<Layout::Box const&>(fragment.layout_node()).paintable_box()->stacking_context())
|
||||
if (fragment.paintable().stacking_context())
|
||||
continue;
|
||||
if (!fragment.layout_node().containing_block()) {
|
||||
if (!fragment.paintable().containing_block()) {
|
||||
dbgln("FIXME: PaintableWithLines::hit_test(): Missing containing block on {}", fragment.layout_node().debug_description());
|
||||
continue;
|
||||
}
|
||||
auto fragment_absolute_rect = fragment.absolute_rect();
|
||||
if (fragment_absolute_rect.contains(position)) {
|
||||
if (is<Layout::BlockContainer>(fragment.layout_node()) && fragment.layout_node().paintable())
|
||||
return fragment.layout_node().paintable()->hit_test(position, type);
|
||||
return HitTestResult { const_cast<Paintable&>(const_cast<Paintable&>(*fragment.layout_node().paintable())), fragment.text_index_at(position.x()) };
|
||||
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.x()) };
|
||||
}
|
||||
|
||||
// If we reached this point, the position is not within the fragment. However, the fragment start or end might be the place to place the cursor.
|
||||
@ -771,14 +771,14 @@ Optional<HitTestResult> PaintableWithLines::hit_test(CSSPixelPoint position, Hit
|
||||
// We arbitrarily choose to consider the end of the line above and ignore the beginning of the line below.
|
||||
// If we knew the direction of selection, we could make a better choice.
|
||||
if (fragment_absolute_rect.bottom() - 1 <= position.y()) { // fully below the fragment
|
||||
last_good_candidate = HitTestResult { const_cast<Paintable&>(*fragment.layout_node().paintable()), fragment.start() + fragment.length() };
|
||||
last_good_candidate = HitTestResult { const_cast<Paintable&>(fragment.paintable()), fragment.start() + fragment.length() };
|
||||
} else if (fragment_absolute_rect.top() <= position.y()) { // vertically within the fragment
|
||||
if (position.x() < fragment_absolute_rect.left()) { // left of the fragment
|
||||
if (!last_good_candidate.has_value()) { // first fragment of the line
|
||||
last_good_candidate = HitTestResult { const_cast<Paintable&>(*fragment.layout_node().paintable()), fragment.start() };
|
||||
last_good_candidate = HitTestResult { const_cast<Paintable&>(fragment.paintable()), fragment.start() };
|
||||
}
|
||||
} else { // right of the fragment
|
||||
last_good_candidate = HitTestResult { const_cast<Paintable&>(*fragment.layout_node().paintable()), fragment.start() + fragment.length() };
|
||||
last_good_candidate = HitTestResult { const_cast<Paintable&>(fragment.paintable()), fragment.start() + fragment.length() };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ public:
|
||||
explicit PaintableFragment(Layout::LineBoxFragment const&);
|
||||
|
||||
Layout::Node const& layout_node() const { return m_layout_node; }
|
||||
Paintable const& paintable() const { return *m_layout_node->paintable(); }
|
||||
|
||||
int start() const { return m_start; }
|
||||
int length() const { return m_length; }
|
||||
|
Loading…
Reference in New Issue
Block a user