Fix scrollbar regression
This commit is contained in:
@@ -313,9 +313,11 @@ fn layout_element(
|
||||
perf_stats,
|
||||
);
|
||||
let provisional_content_height = content_size.height.max(viewport_rect.size.height);
|
||||
let requested_offset_y = scroll_box.offset_y.max(0.0);
|
||||
let provisional_max_offset_y =
|
||||
(provisional_content_height - viewport_rect.size.height).max(0.0);
|
||||
let mut offset_y = scroll_box.offset_y.max(0.0).min(provisional_max_offset_y);
|
||||
let mut offset_y = requested_offset_y.min(provisional_max_offset_y);
|
||||
let child_scene_start = scene.items.len();
|
||||
|
||||
if viewport_rect.size.width > 0.0 && viewport_rect.size.height > 0.0 {
|
||||
scene.push_clip(viewport_rect, 0.0);
|
||||
@@ -345,7 +347,31 @@ fn layout_element(
|
||||
.max(actual_content_height.ceil())
|
||||
.max(viewport_rect.size.height);
|
||||
let max_offset_y = (content_height - viewport_rect.size.height).max(0.0);
|
||||
offset_y = offset_y.min(max_offset_y);
|
||||
let corrected_offset_y = requested_offset_y.min(max_offset_y);
|
||||
if (corrected_offset_y - offset_y).abs() > f32::EPSILON
|
||||
&& viewport_rect.size.width > 0.0
|
||||
&& viewport_rect.size.height > 0.0
|
||||
{
|
||||
offset_y = corrected_offset_y;
|
||||
scene.items.truncate(child_scene_start);
|
||||
scene.push_clip(viewport_rect, 0.0);
|
||||
interaction.children = layout_container_children(
|
||||
element,
|
||||
Rect::new(
|
||||
viewport_rect.origin.x,
|
||||
viewport_rect.origin.y - offset_y,
|
||||
viewport_rect.size.width,
|
||||
content_height,
|
||||
),
|
||||
&interaction.path,
|
||||
scene,
|
||||
text_system,
|
||||
perf_stats,
|
||||
);
|
||||
scene.pop_clip();
|
||||
} else {
|
||||
offset_y = corrected_offset_y;
|
||||
}
|
||||
interaction.scroll_metrics = Some(ScrollMetrics {
|
||||
viewport_rect,
|
||||
content_height,
|
||||
@@ -1701,6 +1727,41 @@ mod tests {
|
||||
assert!(text_bottom >= viewport_bottom - 1.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn scroll_box_preserves_requested_offset_for_direct_text_children() {
|
||||
let scrollbox_id = ElementId::new(23);
|
||||
let root = Element::column().child(
|
||||
Element::scroll_box(240.0)
|
||||
.id(scrollbox_id)
|
||||
.width(320.0)
|
||||
.height(120.0)
|
||||
.padding(Edges::all(8.0))
|
||||
.child(Element::text(
|
||||
"line 01\nline 02\nline 03\nline 04\nline 05\nline 06\nline 07\nline 08\nline 09\nline 10\nline 11\nline 12\nline 13\nline 14\nline 15\nline 16\nline 17\nline 18\nline 19\nline 20\nline 21\nline 22\nline 23\nline 24\nline 25\nline 26",
|
||||
TextStyle::new(16.0, Color::rgb(0xFF, 0xFF, 0xFF)).with_line_height(20.0),
|
||||
)),
|
||||
);
|
||||
|
||||
let snapshot = layout_snapshot(1, UiSize::new(360.0, 220.0), &root);
|
||||
let scroll_metrics = snapshot
|
||||
.interaction_tree
|
||||
.scroll_metrics_for_element(scrollbox_id)
|
||||
.expect("scroll box should expose scroll metrics");
|
||||
let visible_text = snapshot
|
||||
.scene
|
||||
.items
|
||||
.iter()
|
||||
.find_map(|item| match item {
|
||||
DisplayItem::Text(text) => Some(text),
|
||||
_ => None,
|
||||
})
|
||||
.expect("scroll box should emit direct text children");
|
||||
|
||||
assert!(scroll_metrics.max_offset_y > 240.0);
|
||||
assert_eq!(scroll_metrics.offset_y, 240.0);
|
||||
assert!(visible_text.origin.y < scroll_metrics.viewport_rect.origin.y);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn interaction_tree_hit_test_returns_deepest_pointer_target() {
|
||||
let root = Element::column()
|
||||
|
||||
Reference in New Issue
Block a user