gpui: Fix tab jitter from oversized scrolling (#42434)
This commit is contained in:
1 parent
60f1e7e636
commit
369ae38efc
1 file changed
+53
-2
@@ -3193,7 +3193,11 @@ impl ScrollHandle {
|
||||
match active_item.strategy {
|
||||
ScrollStrategy::FirstVisible => {
|
||||
if state.overflow.y == Overflow::Scroll {
|
||||
if bounds.top() + scroll_offset.y < state.bounds.top() {
|
||||
let child_height = bounds.size.height;
|
||||
let viewport_height = state.bounds.size.height;
|
||||
if child_height > viewport_height {
|
||||
scroll_offset.y = state.bounds.top() - bounds.top();
|
||||
} else if bounds.top() + scroll_offset.y < state.bounds.top() {
|
||||
scroll_offset.y = state.bounds.top() - bounds.top();
|
||||
} else if bounds.bottom() + scroll_offset.y > state.bounds.bottom() {
|
||||
scroll_offset.y = state.bounds.bottom() - bounds.bottom();
|
||||
@@ -3206,7 +3210,11 @@ impl ScrollHandle {
|
||||
}
|
||||
|
||||
if state.overflow.x == Overflow::Scroll {
|
||||
if bounds.left() + scroll_offset.x < state.bounds.left() {
|
||||
let child_width = bounds.size.width;
|
||||
let viewport_width = state.bounds.size.width;
|
||||
if child_width > viewport_width {
|
||||
scroll_offset.x = state.bounds.left() - bounds.left();
|
||||
} else if bounds.left() + scroll_offset.x < state.bounds.left() {
|
||||
scroll_offset.x = state.bounds.left() - bounds.left();
|
||||
} else if bounds.right() + scroll_offset.x > state.bounds.right() {
|
||||
scroll_offset.x = state.bounds.right() - bounds.right();
|
||||
@@ -3268,3 +3276,46 @@ impl ScrollHandle {
|
||||
self.0.borrow().child_bounds.len()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn scroll_handle_aligns_wide_children_to_left_edge() {
|
||||
let handle = ScrollHandle::new();
|
||||
{
|
||||
let mut state = handle.0.borrow_mut();
|
||||
state.bounds = Bounds::new(point(px(0.), px(0.)), size(px(80.), px(20.)));
|
||||
state.child_bounds = vec![Bounds::new(point(px(25.), px(0.)), size(px(200.), px(20.)))];
|
||||
state.overflow.x = Overflow::Scroll;
|
||||
state.active_item = Some(ScrollActiveItem {
|
||||
index: 0,
|
||||
strategy: ScrollStrategy::default(),
|
||||
});
|
||||
}
|
||||
|
||||
handle.scroll_to_active_item();
|
||||
|
||||
assert_eq!(handle.offset().x, px(-25.));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn scroll_handle_aligns_tall_children_to_top_edge() {
|
||||
let handle = ScrollHandle::new();
|
||||
{
|
||||
let mut state = handle.0.borrow_mut();
|
||||
state.bounds = Bounds::new(point(px(0.), px(0.)), size(px(20.), px(80.)));
|
||||
state.child_bounds = vec![Bounds::new(point(px(0.), px(25.)), size(px(20.), px(200.)))];
|
||||
state.overflow.y = Overflow::Scroll;
|
||||
state.active_item = Some(ScrollActiveItem {
|
||||
index: 0,
|
||||
strategy: ScrollStrategy::default(),
|
||||
});
|
||||
}
|
||||
|
||||
handle.scroll_to_active_item();
|
||||
|
||||
assert_eq!(handle.offset().y, px(-25.));
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user