diff --git a/config/src/keyassignment.rs b/config/src/keyassignment.rs index 8496a02831a..3d656479559 100644 --- a/config/src/keyassignment.rs +++ b/config/src/keyassignment.rs @@ -333,6 +333,7 @@ impl Default for ClipboardPasteSource { pub enum PaneSelectMode { Activate, SwapWithActive, + SwapWithActiveKeepFocus, MoveToNewTab, MoveToNewWindow, } diff --git a/docs/changelog.md b/docs/changelog.md index b1b6a1ebc63..d8c6635ba05 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -27,9 +27,9 @@ As features stabilize some brief notes about them will accumulate here. their own new Short Codes section. * CharSelect now shows emoji variations such as skin tones * Improved fuzzy matching performance in CharSelect -* [PaneSelect](config/lua/keyassignment/PaneSelect.md) new modes `MoveToNewTab` - and `MoveToNewWindow`, as well as `show_pane_ids=true` to show the pane ids. - #4147 +* [PaneSelect](config/lua/keyassignment/PaneSelect.md) new modes `MoveToNewTab`, + `MoveToNewWindow`, and `SwapWithActiveKeepFocus`, as well as + `show_pane_ids=true` to show the pane ids. #4147 #3014 #### New * [wezterm imgcat](cli/imgcat.md) now has `--position`, `--no-move-cursor` and diff --git a/docs/config/lua/keyassignment/PaneSelect.md b/docs/config/lua/keyassignment/PaneSelect.md index e81409c8f75..722064a40d3 100644 --- a/docs/config/lua/keyassignment/PaneSelect.md +++ b/docs/config/lua/keyassignment/PaneSelect.md @@ -15,16 +15,24 @@ action. The available actions are: * `mode="Activate"` - activate the selected pane. This is the default mode. -* `mode="SwapWithActive"` - swap the position of the active pane with the selected pane +* `mode="SwapWithActive"` - swap the position of the active pane with the + selected pane, switching focus to the selected pane -The selection alphabet defaults to the same value as [quick_select_alphabet](../config/quick_select_alphabet.md), but can be explicitly via the `alphabet` field: +The selection alphabet defaults to the same value as +[quick_select_alphabet](../config/quick_select_alphabet.md), but can be +explicitly via the `alphabet` field: {{since('nightly')}} Additional modes are now supported: -* `mode="MoveToNewTab"` - moves the selected pane into a new tab in the same window, and activates it -* `mode="MoveToNewWindow"` - moves the selected pane into a new window, and activates it +* `mode="MoveToNewTab"` - moves the selected pane into a new tab in the same + window, and activates it +* `mode="MoveToNewWindow"` - moves the selected pane into a new window, and + activates it +* `mode="SwapWithActiveKeepFocus"` - swap the position of the active pane with + the selected pane, retaining focus on the currently active pane but in its + new position You may now also set `show_pane_ids=true` to show the pane id alongside the label. diff --git a/mux/src/tab.rs b/mux/src/tab.rs index 1b46ff170bb..ee891de1208 100644 --- a/mux/src/tab.rs +++ b/mux/src/tab.rs @@ -714,8 +714,10 @@ impl Tab { } /// Swap the active pane with the specified pane_index - pub fn swap_active_with_index(&self, pane_index: usize) -> Option<()> { - self.inner.lock().swap_active_with_index(pane_index) + pub fn swap_active_with_index(&self, pane_index: usize, keep_focus: bool) -> Option<()> { + self.inner + .lock() + .swap_active_with_index(pane_index, keep_focus) } /// Computes the size of the pane that would result if the specified @@ -1776,7 +1778,7 @@ impl TabInner { cell_dimensions(&self.size) } - fn swap_active_with_index(&mut self, pane_index: usize) -> Option<()> { + fn swap_active_with_index(&mut self, pane_index: usize, keep_focus: bool) -> Option<()> { let active_idx = self.get_active_idx(); let mut pane = self.get_active_pane()?; log::trace!( @@ -1822,7 +1824,11 @@ impl TabInner { } // And update focus - self.advise_focus_change(Some(pane)); + if keep_focus { + self.set_active_idx(pane_index); + } else { + self.advise_focus_change(Some(pane)); + } None } diff --git a/wezterm-gui/src/commands.rs b/wezterm-gui/src/commands.rs index 5a7abf6440c..bab431dbfb3 100644 --- a/wezterm-gui/src/commands.rs +++ b/wezterm-gui/src/commands.rs @@ -819,6 +819,17 @@ pub fn derive_command_from_key_assignment(action: &KeyAssignment) -> Option CommandDef { + brief: "Swap a pane with the active pane, keeping focus".into(), + doc: "Activates the pane selection UI".into(), + keys: vec![], // FIXME: find a new assignment + args: &[ArgType::ActivePane], + menubar: &["Window"], + icon: Some("cod_multiple_windows"), + }, PaneSelect(PaneSelectArguments { mode: PaneSelectMode::MoveToNewTab, .. @@ -2017,6 +2028,11 @@ fn compute_default_actions() -> Vec { mode: PaneSelectMode::SwapWithActive, show_pane_ids: false, }), + PaneSelect(PaneSelectArguments { + alphabet: String::new(), + mode: PaneSelectMode::SwapWithActiveKeepFocus, + show_pane_ids: false, + }), PaneSelect(PaneSelectArguments { alphabet: String::new(), mode: PaneSelectMode::MoveToNewTab, diff --git a/wezterm-gui/src/termwindow/paneselect.rs b/wezterm-gui/src/termwindow/paneselect.rs index 2590b912cfa..a0ca05c0cc1 100644 --- a/wezterm-gui/src/termwindow/paneselect.rs +++ b/wezterm-gui/src/termwindow/paneselect.rs @@ -179,8 +179,11 @@ impl PaneSelector { tab.set_active_idx(pane_index); } } - PaneSelectMode::SwapWithActive => { - tab.swap_active_with_index(pane_index); + PaneSelectMode::SwapWithActiveKeepFocus | PaneSelectMode::SwapWithActive => { + tab.swap_active_with_index( + pane_index, + self.mode == PaneSelectMode::SwapWithActiveKeepFocus, + ); } PaneSelectMode::MoveToNewWindow => { if let Some(pos) = panes.iter().find(|p| p.index == pane_index) {