LibWeb: Fix unnecessary wheel event consumption with overflow: scroll

Allow wheel event to be consumed by a `overflow: scroll` box only if it
has content that overflows a scrollport.

This fixes the timing issue in the
`Text/input/scroll-window-using-wheel-event.html` test, where a `<body>`
element with `overflow: scroll` was incorrectly consuming wheel events
that should have propagated to the window.
This commit is contained in:
Aliaksandr Kalenik 2025-01-30 15:54:14 +01:00 committed by Jelle Raaijmakers
commit a4c331c199
Notes: github-actions[bot] 2025-01-30 23:39:21 +00:00
3 changed files with 63 additions and 5 deletions

View file

@ -343,9 +343,10 @@ bool PaintableBox::could_be_scrolled_by_wheel_event(ScrollDirection direction) c
return false; return false;
auto scrollable_overflow_size = direction == ScrollDirection::Horizontal ? scrollable_overflow_rect->width() : scrollable_overflow_rect->height(); auto scrollable_overflow_size = direction == ScrollDirection::Horizontal ? scrollable_overflow_rect->width() : scrollable_overflow_rect->height();
auto scrollport_size = direction == ScrollDirection::Horizontal ? absolute_padding_box_rect().width() : absolute_padding_box_rect().height(); auto scrollport_size = direction == ScrollDirection::Horizontal ? absolute_padding_box_rect().width() : absolute_padding_box_rect().height();
if ((is_viewport() && overflow != CSS::Overflow::Hidden) || overflow == CSS::Overflow::Auto) auto overflow_value_allows_scrolling = overflow == CSS::Overflow::Auto || overflow == CSS::Overflow::Scroll;
if ((is_viewport() && overflow != CSS::Overflow::Hidden) || overflow_value_allows_scrolling)
return scrollable_overflow_size > scrollport_size; return scrollable_overflow_size > scrollport_size;
return overflow == CSS::Overflow::Scroll; return false;
} }
bool PaintableBox::could_be_scrolled_by_wheel_event() const bool PaintableBox::could_be_scrolled_by_wheel_event() const
@ -375,7 +376,14 @@ Optional<CSSPixelRect> PaintableBox::scroll_thumb_rect(ScrollDirection direction
Optional<PaintableBox::ScrollbarData> PaintableBox::compute_scrollbar_data(ScrollDirection direction) const Optional<PaintableBox::ScrollbarData> PaintableBox::compute_scrollbar_data(ScrollDirection direction) const
{ {
if (!could_be_scrolled_by_wheel_event(direction)) { bool is_horizontal = direction == ScrollDirection::Horizontal;
bool display_scrollbar = could_be_scrolled_by_wheel_event(direction);
if (is_horizontal) {
display_scrollbar |= computed_values().overflow_x() == CSS::Overflow::Scroll;
} else {
display_scrollbar |= computed_values().overflow_y() == CSS::Overflow::Scroll;
}
if (!display_scrollbar) {
return {}; return {};
} }
@ -383,8 +391,6 @@ Optional<PaintableBox::ScrollbarData> PaintableBox::compute_scrollbar_data(Scrol
return {}; return {};
} }
bool is_horizontal = direction == ScrollDirection::Horizontal;
auto padding_rect = absolute_padding_box_rect(); auto padding_rect = absolute_padding_box_rect();
auto scrollable_overflow_rect = this->scrollable_overflow_rect().value(); auto scrollable_overflow_rect = this->scrollable_overflow_rect().value();
auto scroll_overflow_size = is_horizontal ? scrollable_overflow_rect.width() : scrollable_overflow_rect.height(); auto scroll_overflow_size = is_horizontal ? scrollable_overflow_rect.width() : scrollable_overflow_rect.height();

View file

@ -0,0 +1,51 @@
<!DOCTYPE html>
<html lang="en">
<script src="include.js"></script>
<head>
<style>
body {
margin: 0;
}
.scroll-container {
height: 300px;
width: 300px;
overflow: auto;
border: 2px solid #333;
background-color: #f0f0f0;
}
.box {
overflow: scroll;
}
.nested {
border: 2px solid #777;
background-color: white;
height: 100px;
}
</style>
</head>
<body>
<div class="scroll-container">
<div class="box"><div class="nested">Box 1</div></div>
<div class="box"><div class="nested">Box 2</div></div>
<div class="box"><div class="nested">Box 3</div></div>
<div class="box"><div class="nested">Box 4</div></div>
<div class="box"><div class="nested">Box 5</div></div>
<div class="box"><div class="nested">Box 6</div></div>
<div class="box"><div class="nested">Box 7</div></div>
<div class="box"><div class="nested">Box 8</div></div>
</div>
</body>
<script>
asyncTest(done => {
const container = document.querySelector(".scroll-container");
container.onscroll = () => {
println(`new scrollY: ${container.scrollTop}`);
done();
};
internals.wheel(50, 50, 0, 100);
});
</script>
</html>