mirror of
https://github.com/zed-industries/zed.git
synced 2026-05-26 07:24:46 +00:00
gpui: Recalculate list layout after the window has been resized (#51414)
Closes #51417 I noticed this bug in the settings menu where when I opened the settings menu, I could not scroll down through all the available options, eg. on the initial page I wasn't able to scroll down to privacy. When I saw that no one else had reported this issue, I figured it may be due to my setup, and it turns out that using Aerospace, the window manager I use, was what made this bug visible to me. Because aerospace resizes the window right after it launches, the originally computed heights for the list are incorrect, meaning the scroll bar is the wrong size as well. in the relevant code there was a comment that says "If the width of the list has changed, invalidate all cached item heights" which wasn't incorrect per-se, but it just invalidated them without triggering any re-computation, causing incorrect scroll bars. My intuition is that window resizes/events that change the width of the list bounds are fairly rare, so there shouldn't be a large performance hit from the change. Also implemented a test that directly showcases the behavior, if you run the test without the change it fails, as the max_offset_for_scrollbar will be wrong. Videos: Before https://github.com/user-attachments/assets/2b680222-7071-4098-863f-519361f0756a After: https://github.com/user-attachments/assets/1222a299-23d7-4007-8e88-55d2daccce64 [x] Tests [x] Video of behavior Release Notes: - gpui: fixed list height re-computation when the list width changes.
This commit is contained in:
parent
d4bb640555
commit
7b9afc8c45
1 changed files with 36 additions and 0 deletions
|
|
@ -1103,6 +1103,7 @@ impl Element for List {
|
|||
);
|
||||
|
||||
state.items = new_items;
|
||||
state.measuring_behavior.reset();
|
||||
}
|
||||
|
||||
let padding = style
|
||||
|
|
@ -1348,6 +1349,41 @@ mod test {
|
|||
assert_eq!(offset.offset_in_item, px(0.));
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
fn test_measure_all_after_width_change(cx: &mut TestAppContext) {
|
||||
let cx = cx.add_empty_window();
|
||||
|
||||
let state = ListState::new(10, crate::ListAlignment::Top, px(0.)).measure_all();
|
||||
|
||||
struct TestView(ListState);
|
||||
impl Render for TestView {
|
||||
fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
|
||||
list(self.0.clone(), |_, _, _| {
|
||||
div().h(px(50.)).w_full().into_any()
|
||||
})
|
||||
.w_full()
|
||||
.h_full()
|
||||
}
|
||||
}
|
||||
|
||||
let view = cx.update(|_, cx| cx.new(|_| TestView(state.clone())));
|
||||
|
||||
// First draw at width 100: all 10 items measured (total 500px).
|
||||
// Viewport is 200px, so max scroll offset should be 300px.
|
||||
cx.draw(point(px(0.), px(0.)), size(px(100.), px(200.)), |_, _| {
|
||||
view.clone().into_any_element()
|
||||
});
|
||||
assert_eq!(state.max_offset_for_scrollbar().y, px(300.));
|
||||
|
||||
// Second draw at a different width: items get invalidated.
|
||||
// Without the fix, max_offset would drop because unmeasured items
|
||||
// contribute 0 height.
|
||||
cx.draw(point(px(0.), px(0.)), size(px(200.), px(200.)), |_, _| {
|
||||
view.into_any_element()
|
||||
});
|
||||
assert_eq!(state.max_offset_for_scrollbar().y, px(300.));
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
fn test_remeasure(cx: &mut TestAppContext) {
|
||||
let cx = cx.add_empty_window();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue