From 203f55ea38f3fa7c5286b9ab2d1b2f6fc1a1b2fc Mon Sep 17 00:00:00 2001 From: "zed-zippy[bot]" <234243425+zed-zippy[bot]@users.noreply.github.com> Date: Thu, 15 Jan 2026 09:06:47 +0000 Subject: [PATCH] workspace: Fix tab reordering regression (#46872) (cherry-pick to preview) (#46878) Cherry-pick of #46872 to preview ---- Closes [#46864](https://github.com/zed-industries/zed/issues/46864) Initial PR: https://github.com/zed-industries/zed/pull/46573 ## Summary Fix a regression where dragging a tab onto another tab would place it at the end of the tab bar instead of at the target position. The issue was in the `on_drop` handler: it used `this.items.len()` (evaluated at drop time) instead of the captured `ix` index (the position of the tab being dropped onto). Release Notes: - Fixed tab reordering not working correctly when dragging tabs ## Video after fix: - when 'show_pinned_tabs_in_separate_row' is false: https://github.com/user-attachments/assets/1ede0ce5-1161-4209-83f4-33a07572782a - when 'show_pinned_tabs_in_separate_row' is true: https://github.com/user-attachments/assets/d56c0e59-8372-41d4-973b-32a4895ca729 --------- Co-authored-by: Smit Barmase Co-authored-by: Yaroslav Yenkala Co-authored-by: Smit Barmase --- crates/workspace/src/pane.rs | 53 +++++++++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/crates/workspace/src/pane.rs b/crates/workspace/src/pane.rs index 318a790fdfaaaa2dc2d68ccde6d047f08e186a4e..9e24a132b08a666b14f292137b966209af8489af 100644 --- a/crates/workspace/src/pane.rs +++ b/crates/workspace/src/pane.rs @@ -2765,7 +2765,7 @@ impl Pane { .on_drop( cx.listener(move |this, dragged_tab: &DraggedTab, window, cx| { this.drag_split_direction = None; - this.handle_tab_drop(dragged_tab, this.items.len(), window, cx) + this.handle_tab_drop(dragged_tab, ix, window, cx) }), ) .on_drop( @@ -6225,6 +6225,57 @@ mod tests { assert_item_labels(&pane_a, ["C*", "A", "B"], cx); } + #[gpui::test] + async fn test_drag_tab_to_middle_tab_with_mouse_events(cx: &mut TestAppContext) { + use gpui::{Modifiers, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent}; + + init_test(cx); + let fs = FakeFs::new(cx.executor()); + + let project = Project::test(fs, None, cx).await; + let (workspace, cx) = + cx.add_window_view(|window, cx| Workspace::test_new(project.clone(), window, cx)); + let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone()); + + add_labeled_item(&pane, "A", false, cx); + add_labeled_item(&pane, "B", false, cx); + add_labeled_item(&pane, "C", false, cx); + add_labeled_item(&pane, "D", false, cx); + assert_item_labels(&pane, ["A", "B", "C", "D*"], cx); + cx.run_until_parked(); + + let tab_a_bounds = cx + .debug_bounds("TAB-0") + .expect("Tab A (index 0) should have debug bounds"); + let tab_c_bounds = cx + .debug_bounds("TAB-2") + .expect("Tab C (index 2) should have debug bounds"); + + cx.simulate_event(MouseDownEvent { + position: tab_a_bounds.center(), + button: MouseButton::Left, + modifiers: Modifiers::default(), + click_count: 1, + first_mouse: false, + }); + cx.run_until_parked(); + cx.simulate_event(MouseMoveEvent { + position: tab_c_bounds.center(), + pressed_button: Some(MouseButton::Left), + modifiers: Modifiers::default(), + }); + cx.run_until_parked(); + cx.simulate_event(MouseUpEvent { + position: tab_c_bounds.center(), + button: MouseButton::Left, + modifiers: Modifiers::default(), + click_count: 1, + }); + cx.run_until_parked(); + + assert_item_labels(&pane, ["B", "C", "A*", "D"], cx); + } + #[gpui::test] async fn test_add_item_with_new_item(cx: &mut TestAppContext) { init_test(cx);