mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 22:17:44 +00:00
LibWeb: Use clip rectangles assigned to paintables in hit-testing
This change makes hit-testing more consistent in the handling of hidden overflow by reusing the same clip-rectangles. Also, it fixes bugs where the box is visible for hit-testing even though it is clipped by the hidden overflow of the containing block.
This commit is contained in:
parent
d3b983b201
commit
16f1962f10
8 changed files with 64 additions and 28 deletions
|
@ -182,6 +182,9 @@ void InlinePaintable::for_each_fragment(Callback callback) const
|
|||
|
||||
Optional<HitTestResult> InlinePaintable::hit_test(CSSPixelPoint position, HitTestType type) const
|
||||
{
|
||||
if (m_clip_rect.has_value() && !m_clip_rect.value().contains(position))
|
||||
return {};
|
||||
|
||||
auto position_adjusted_by_scroll_offset = position;
|
||||
if (m_enclosing_scroll_frame_offset.has_value())
|
||||
position_adjusted_by_scroll_offset.translate_by(-m_enclosing_scroll_frame_offset.value());
|
||||
|
|
|
@ -676,6 +676,9 @@ Layout::BlockContainer& PaintableWithLines::layout_box()
|
|||
|
||||
Optional<HitTestResult> PaintableBox::hit_test(CSSPixelPoint position, HitTestType type) const
|
||||
{
|
||||
if (clip_rect().has_value() && !clip_rect()->contains(position))
|
||||
return {};
|
||||
|
||||
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());
|
||||
|
@ -712,6 +715,9 @@ Optional<HitTestResult> PaintableBox::hit_test(CSSPixelPoint position, HitTestTy
|
|||
|
||||
Optional<HitTestResult> PaintableWithLines::hit_test(CSSPixelPoint position, HitTestType type) const
|
||||
{
|
||||
if (clip_rect().has_value() && !clip_rect()->contains(position))
|
||||
return {};
|
||||
|
||||
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());
|
||||
|
|
|
@ -210,6 +210,7 @@ protected:
|
|||
virtual CSSPixelRect compute_absolute_paint_rect() const;
|
||||
|
||||
Optional<CSSPixelPoint> enclosing_scroll_frame_offset() const { return m_enclosing_scroll_frame_offset; }
|
||||
Optional<CSSPixelRect> clip_rect() const { return m_clip_rect; }
|
||||
|
||||
private:
|
||||
[[nodiscard]] virtual bool is_paintable_box() const final { return true; }
|
||||
|
|
|
@ -372,14 +372,6 @@ Optional<HitTestResult> StackingContext::hit_test(CSSPixelPoint position, HitTes
|
|||
transformed_position.translate_by(-scroll_offset);
|
||||
}
|
||||
|
||||
// FIXME: Support more overflow variations.
|
||||
if (paintable().computed_values().overflow_x() == CSS::Overflow::Hidden && paintable().computed_values().overflow_y() == CSS::Overflow::Hidden) {
|
||||
if (paintable().is_paintable_box()) {
|
||||
if (!paintable_box().absolute_border_box_rect().contains(transformed_position.x(), transformed_position.y()))
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: Hit testing basically happens in reverse painting order.
|
||||
// https://www.w3.org/TR/CSS22/visuren.html#z-index
|
||||
|
||||
|
@ -402,12 +394,6 @@ Optional<HitTestResult> StackingContext::hit_test(CSSPixelPoint position, HitTes
|
|||
|
||||
auto const& paintable_box = verify_cast<PaintableBox>(paintable);
|
||||
|
||||
// FIXME: Support more overflow variations.
|
||||
if (paintable_box.computed_values().overflow_x() == CSS::Overflow::Hidden && paintable_box.computed_values().overflow_y() == CSS::Overflow::Hidden) {
|
||||
if (!paintable_box.absolute_border_box_rect().contains(transformed_position.x(), transformed_position.y()))
|
||||
return TraversalDecision::SkipChildrenAndContinue;
|
||||
}
|
||||
|
||||
auto const& z_index = paintable_box.computed_values().z_index();
|
||||
if (z_index.value_or(0) == 0 && paintable_box.is_positioned() && !paintable_box.stacking_context()) {
|
||||
auto candidate = paintable_box.hit_test(transformed_position, type);
|
||||
|
@ -445,13 +431,6 @@ Optional<HitTestResult> StackingContext::hit_test(CSSPixelPoint position, HitTes
|
|||
return TraversalDecision::Continue;
|
||||
|
||||
auto const& paintable_box = verify_cast<PaintableBox>(paintable);
|
||||
|
||||
// FIXME: Support more overflow variations.
|
||||
if (paintable_box.computed_values().overflow_x() == CSS::Overflow::Hidden && paintable_box.computed_values().overflow_y() == CSS::Overflow::Hidden) {
|
||||
if (!paintable_box.absolute_border_box_rect().contains(transformed_position.x(), transformed_position.y()))
|
||||
return TraversalDecision::SkipChildrenAndContinue;
|
||||
}
|
||||
|
||||
if (paintable_box.is_floating()) {
|
||||
if (auto candidate = paintable_box.hit_test(transformed_position, type); candidate.has_value()) {
|
||||
result = move(candidate);
|
||||
|
@ -470,13 +449,6 @@ Optional<HitTestResult> StackingContext::hit_test(CSSPixelPoint position, HitTes
|
|||
return TraversalDecision::Continue;
|
||||
|
||||
auto const& paintable_box = verify_cast<PaintableBox>(paintable);
|
||||
|
||||
// FIXME: Support more overflow variations.
|
||||
if (paintable_box.computed_values().overflow_x() == CSS::Overflow::Hidden && paintable_box.computed_values().overflow_y() == CSS::Overflow::Hidden) {
|
||||
if (!paintable_box.absolute_border_box_rect().contains(transformed_position.x(), transformed_position.y()))
|
||||
return TraversalDecision::SkipChildrenAndContinue;
|
||||
}
|
||||
|
||||
if (!paintable_box.is_absolutely_positioned() && !paintable_box.is_floating()) {
|
||||
if (auto candidate = paintable_box.hit_test(transformed_position, type); candidate.has_value()) {
|
||||
result = move(candidate);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue