From 34cd33eba76cd4a94bc6106d198fd42c35057224 Mon Sep 17 00:00:00 2001 From: xj Date: Sun, 22 Feb 2026 11:51:42 -0800 Subject: [PATCH 1/2] workspace: Add ActivateLastPane action --- crates/workspace/src/workspace.rs | 62 +++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 4db38daa2ae671..1f650e4013b2e5 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -209,6 +209,8 @@ actions!( ActivateNextPane, /// Activates the previous pane in the workspace. ActivatePreviousPane, + /// Activates the last pane in the workspace. + ActivateLastPane, /// Switches to the next window. ActivateNextWindow, /// Switches to the previous window. @@ -4325,6 +4327,12 @@ impl Workspace { } } + pub fn activate_last_pane(&mut self, window: &mut Window, cx: &mut App) { + if let Some(last_pane) = self.center.panes().last().cloned() { + window.focus(&last_pane.focus_handle(cx), cx); + } + } + pub fn activate_pane_in_direction( &mut self, direction: SplitDirection, @@ -6373,6 +6381,9 @@ impl Workspace { .on_action(cx.listener(|workspace, _: &ActivateNextPane, window, cx| { workspace.activate_next_pane(window, cx) })) + .on_action(cx.listener(|workspace, _: &ActivateLastPane, window, cx| { + workspace.activate_last_pane(window, cx) + })) .on_action( cx.listener(|workspace, _: &ActivateNextWindow, _window, cx| { workspace.activate_next_window(cx) @@ -10468,6 +10479,57 @@ mod tests { }); } + #[gpui::test] + async fn test_activate_last_pane(cx: &mut gpui::TestAppContext) { + init_test(cx); + let fs = FakeFs::new(cx.executor()); + let project = Project::test(fs, [], cx).await; + let (workspace, cx) = + cx.add_window_view(|window, cx| Workspace::test_new(project, window, cx)); + + workspace.update_in(cx, |workspace, window, cx| { + let first_item = cx.new(|cx| { + TestItem::new(cx).with_project_items(&[TestProjectItem::new(1, "1.txt", cx)]) + }); + workspace.add_item_to_active_pane(Box::new(first_item), None, true, window, cx); + workspace.split_pane( + workspace.active_pane().clone(), + SplitDirection::Right, + window, + cx, + ); + workspace.split_pane( + workspace.active_pane().clone(), + SplitDirection::Right, + window, + cx, + ); + }); + + let (first_pane_id, target_last_pane_id) = workspace.update(cx, |workspace, _cx| { + let panes = workspace.center.panes(); + assert!(panes.len() >= 2); + ( + panes.first().expect("at least one pane").entity_id(), + panes.last().expect("at least one pane").entity_id(), + ) + }); + + workspace.update_in(cx, |workspace, window, cx| { + workspace.activate_pane_at_index(&ActivatePane(0), window, cx); + }); + workspace.update(cx, |workspace, _| { + assert_eq!(workspace.active_pane().entity_id(), first_pane_id); + assert_ne!(workspace.active_pane().entity_id(), target_last_pane_id); + }); + + cx.dispatch_action(ActivateLastPane); + + workspace.update(cx, |workspace, _| { + assert_eq!(workspace.active_pane().entity_id(), target_last_pane_id); + }); + } + #[gpui::test] async fn test_toggle_docks_and_panels(cx: &mut gpui::TestAppContext) { init_test(cx); From a266d8a33d8224694ef69ded27629c19188a4842 Mon Sep 17 00:00:00 2001 From: xj Date: Sun, 22 Feb 2026 12:28:58 -0800 Subject: [PATCH 2/2] workspace: Address Copilot review feedback --- crates/workspace/src/workspace.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 1f650e4013b2e5..bca4fafd734606 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -4328,9 +4328,8 @@ impl Workspace { } pub fn activate_last_pane(&mut self, window: &mut Window, cx: &mut App) { - if let Some(last_pane) = self.center.panes().last().cloned() { - window.focus(&last_pane.focus_handle(cx), cx); - } + let last_pane = self.center.last_pane(); + window.focus(&last_pane.focus_handle(cx), cx); } pub fn activate_pane_in_direction( @@ -6406,9 +6405,6 @@ impl Workspace { .on_action(cx.listener(|workspace, _: &ActivatePaneDown, window, cx| { workspace.activate_pane_in_direction(SplitDirection::Down, window, cx) })) - .on_action(cx.listener(|workspace, _: &ActivateNextPane, window, cx| { - workspace.activate_next_pane(window, cx) - })) .on_action(cx.listener( |workspace, action: &MoveItemToPaneInDirection, window, cx| { workspace.move_item_to_pane_in_direction(action, window, cx)