From 938b7bb183c74c4fba3e62a35e8d5e0329a139ad Mon Sep 17 00:00:00 2001 From: tims <0xtimsb@gmail.com> Date: Mon, 20 Jan 2025 17:04:18 +0530 Subject: [PATCH] workspace: Add actions for cycling between windows (#23356) Closes #22740 I haven't assigned any default keybindings to these actions because it might conflict with existing OS bindings. Preview: https://github.com/user-attachments/assets/7c62cb34-2747-4674-a278-f0998e7d17f9 Release Notes: - Added `workspace::ActivateNextWindow` and `workspace::ActivatePreviousWindow` actions for cycling between windows. --- crates/workspace/src/workspace.rs | 41 +++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 20b4659c93..b54b797449 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -125,6 +125,8 @@ actions!( [ ActivateNextPane, ActivatePreviousPane, + ActivateNextWindow, + ActivatePreviousWindow, AddFolderToProject, ClearAllNotifications, CloseAllDocks, @@ -4542,6 +4544,12 @@ impl Workspace { .on_action( cx.listener(|workspace, _: &ActivateNextPane, cx| workspace.activate_next_pane(cx)), ) + .on_action(cx.listener(|workspace, _: &ActivateNextWindow, cx| { + workspace.activate_next_window(cx) + })) + .on_action(cx.listener(|workspace, _: &ActivatePreviousWindow, cx| { + workspace.activate_previous_window(cx) + })) .on_action( cx.listener(|workspace, action: &ActivatePaneInDirection, cx| { workspace.activate_pane_in_direction(action.0, cx) @@ -4700,6 +4708,39 @@ impl Workspace { pub fn zoomed_item(&self) -> Option<&AnyWeakView> { self.zoomed.as_ref() } + + pub fn activate_next_window(&mut self, cx: &mut ViewContext) { + let Some(current_window_id) = cx.active_window().map(|a| a.window_id()) else { + return; + }; + let windows = cx.windows(); + let Some(next_window) = windows + .iter() + .cycle() + .skip_while(|window| window.window_id() != current_window_id) + .nth(1) + else { + return; + }; + next_window.update(cx, |_, cx| cx.activate_window()).ok(); + } + + pub fn activate_previous_window(&mut self, cx: &mut ViewContext) { + let Some(current_window_id) = cx.active_window().map(|a| a.window_id()) else { + return; + }; + let windows = cx.windows(); + let Some(prev_window) = windows + .iter() + .rev() + .cycle() + .skip_while(|window| window.window_id() != current_window_id) + .nth(1) + else { + return; + }; + prev_window.update(cx, |_, cx| cx.activate_window()).ok(); + } } fn leader_border_for_pane(