From 89e427bd79cee7e5972a6bff3dd8f239fc5299dc Mon Sep 17 00:00:00 2001 From: Wez Furlong Date: Fri, 6 May 2022 17:57:55 -0700 Subject: [PATCH] overlays: improve key_table handling This commit re-arranges the code so that an overlay can have a local stack of key table activations; this allows copy_mode and search_mode key tables to layer on top of the user's window level key tables. Previously, we'd just stick the search_mode entry on top of the global state, which worked, but had the undesirable side effect of hijacking the Enter key when switching to another tab in the window. refs: https://github.com/wez/wezterm/issues/993 --- wezterm-gui/src/termwindow/keyevent.rs | 38 ++++++++++++++++++----- wezterm-gui/src/termwindow/mod.rs | 42 +++++++++++++++----------- 2 files changed, 55 insertions(+), 25 deletions(-) diff --git a/wezterm-gui/src/termwindow/keyevent.rs b/wezterm-gui/src/termwindow/keyevent.rs index 4d5e0fa5b..de6e50add 100644 --- a/wezterm-gui/src/termwindow/keyevent.rs +++ b/wezterm-gui/src/termwindow/keyevent.rs @@ -82,9 +82,7 @@ impl KeyTableState { return Some((entry, Some(name))); } } - input_map - .lookup_key(key, mods, None) - .map(|entry| (entry, None)) + None } pub fn did_process_key(&mut self) { @@ -148,6 +146,32 @@ impl super::TermWindow { key.encode_win32_input_mode() } + fn lookup_key( + &mut self, + pane: &Rc, + keycode: &KeyCode, + mods: Modifiers, + ) -> Option<(KeyTableEntry, Option)> { + if let Some(overlay) = self.pane_state(pane.pane_id()).overlay.as_mut() { + if let Some((entry, table_name)) = + overlay + .key_table_state + .lookup_key(&self.input_map, keycode, mods) + { + return Some((entry, table_name.map(|s| s.to_string()))); + } + } + if let Some((entry, table_name)) = + self.key_table_state + .lookup_key(&self.input_map, keycode, mods) + { + return Some((entry, table_name.map(|s| s.to_string()))); + } + self.input_map + .lookup_key(keycode, mods, None) + .map(|entry| (entry, None)) + } + fn process_key( &mut self, pane: &Rc, @@ -180,11 +204,9 @@ impl super::TermWindow { } if is_down { - if let Some((entry, table_name)) = self.key_table_state.lookup_key( - &self.input_map, - &keycode, - raw_modifiers | leader_mod, - ) { + if let Some((entry, table_name)) = + self.lookup_key(pane, &keycode, raw_modifiers | leader_mod) + { if self.config.debug_key_events { log::info!( "{}{:?} {:?} -> perform {:?}", diff --git a/wezterm-gui/src/termwindow/mod.rs b/wezterm-gui/src/termwindow/mod.rs index 123b8b11a..1eb96726f 100644 --- a/wezterm-gui/src/termwindow/mod.rs +++ b/wezterm-gui/src/termwindow/mod.rs @@ -161,7 +161,7 @@ pub struct SemanticZoneCache { pub struct OverlayState { pub pane: Rc, - saved_key_table_state: KeyTableState, + key_table_state: KeyTableState, } #[derive(Default)] @@ -2272,8 +2272,17 @@ impl TermWindow { ); self.assign_overlay_for_pane(pane.pane_id(), search); } - self.key_table_state - .activate("search_mode", None, replace_current, false); + self.pane_state(pane.pane_id()) + .overlay + .as_mut() + .map(|overlay| { + overlay.key_table_state.activate( + "search_mode", + None, + replace_current, + false, + ); + }); } } QuickSelect => { @@ -2311,8 +2320,17 @@ impl TermWindow { ); self.assign_overlay_for_pane(pane.pane_id(), copy); } - self.key_table_state - .activate("copy_mode", None, replace_current, false); + self.pane_state(pane.pane_id()) + .overlay + .as_mut() + .map(|overlay| { + overlay.key_table_state.activate( + "copy_mode", + None, + replace_current, + false, + ); + }); } } AdjustPaneSize(direction, amount) => { @@ -2815,14 +2833,9 @@ impl TermWindow { return; } } - let mut key_table = None; if let Some(overlay) = self.tab_state(tab_id).overlay.take() { - key_table.replace(overlay.saved_key_table_state); Mux::get().unwrap().remove_pane(overlay.pane.pane_id()); } - if let Some(key_table) = key_table.take() { - self.key_table_state = key_table; - } if let Some(window) = self.window.as_ref() { window.invalidate(); } @@ -2833,7 +2846,6 @@ impl TermWindow { } fn cancel_overlay_for_pane(&mut self, pane_id: PaneId) { - let mut key_table = None; if let Some(overlay) = self.pane_state(pane_id).overlay.take() { // Ungh, when I built the CopyOverlay, its pane doesn't get // added to the mux and instead it reports the overlaid @@ -2842,10 +2854,6 @@ impl TermWindow { if pane_id != overlay.pane.pane_id() { Mux::get().unwrap().remove_pane(overlay.pane.pane_id()); } - key_table.replace(overlay.saved_key_table_state); - } - if let Some(key_table) = key_table.take() { - self.key_table_state = key_table; } if let Some(window) = self.window.as_ref() { window.invalidate(); @@ -2860,7 +2868,7 @@ impl TermWindow { self.cancel_overlay_for_pane(pane_id); self.pane_state(pane_id).overlay.replace(OverlayState { pane, - saved_key_table_state: self.key_table_state.clone(), + key_table_state: KeyTableState::default(), }); self.update_title(); } @@ -2869,7 +2877,7 @@ impl TermWindow { self.cancel_overlay_for_tab(tab_id, None); self.tab_state(tab_id).overlay.replace(OverlayState { pane: overlay, - saved_key_table_state: self.key_table_state.clone(), + key_table_state: KeyTableState::default(), }); self.update_title(); }