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.
This commit is contained in:
tims 2025-01-20 17:04:18 +05:30 committed by GitHub
parent 0ff803fe10
commit 938b7bb183
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -125,6 +125,8 @@ actions!(
[ [
ActivateNextPane, ActivateNextPane,
ActivatePreviousPane, ActivatePreviousPane,
ActivateNextWindow,
ActivatePreviousWindow,
AddFolderToProject, AddFolderToProject,
ClearAllNotifications, ClearAllNotifications,
CloseAllDocks, CloseAllDocks,
@ -4542,6 +4544,12 @@ impl Workspace {
.on_action( .on_action(
cx.listener(|workspace, _: &ActivateNextPane, cx| workspace.activate_next_pane(cx)), 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( .on_action(
cx.listener(|workspace, action: &ActivatePaneInDirection, cx| { cx.listener(|workspace, action: &ActivatePaneInDirection, cx| {
workspace.activate_pane_in_direction(action.0, cx) workspace.activate_pane_in_direction(action.0, cx)
@ -4700,6 +4708,39 @@ impl Workspace {
pub fn zoomed_item(&self) -> Option<&AnyWeakView> { pub fn zoomed_item(&self) -> Option<&AnyWeakView> {
self.zoomed.as_ref() self.zoomed.as_ref()
} }
pub fn activate_next_window(&mut self, cx: &mut ViewContext<Self>) {
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<Self>) {
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( fn leader_border_for_pane(