From 27d452a20f18f8ce7b7c1ad09e2552749fd7b5d7 Mon Sep 17 00:00:00 2001 From: Wez Furlong Date: Thu, 6 Jan 2022 08:38:32 -0700 Subject: [PATCH] input: route key up events to pane on win32 refs: https://github.com/wez/wezterm/issues/1509 --- wezterm-gui/src/termwindow/keyevent.rs | 75 +++++++++++++++----------- wezterm-input-types/src/lib.rs | 6 +-- window/src/os/windows/keycodes.rs | 1 + window/src/os/windows/window.rs | 15 ++++-- 4 files changed, 58 insertions(+), 39 deletions(-) diff --git a/wezterm-gui/src/termwindow/keyevent.rs b/wezterm-gui/src/termwindow/keyevent.rs index 340a635ab..806c23031 100644 --- a/wezterm-gui/src/termwindow/keyevent.rs +++ b/wezterm-gui/src/termwindow/keyevent.rs @@ -52,8 +52,9 @@ impl super::TermWindow { leader_active: bool, leader_mod: Modifiers, only_key_bindings: OnlyKeyBindings, + is_down: bool, ) -> bool { - if !leader_active { + if is_down && !leader_active { // Check to see if this key-press is the leader activating if let Some(duration) = self.input_map.is_leader(&keycode, raw_modifiers) { // Yes; record its expiration @@ -73,27 +74,29 @@ impl super::TermWindow { } } - if let Some(assignment) = self - .input_map - .lookup_key(&keycode, raw_modifiers | leader_mod) - { - if self.config.debug_key_events { - log::info!( - "{:?} {:?} -> perform {:?}", - keycode, - raw_modifiers | leader_mod, - assignment - ); - } - self.perform_key_assignment(&pane, &assignment).ok(); - context.invalidate(); + if is_down { + if let Some(assignment) = self + .input_map + .lookup_key(&keycode, raw_modifiers | leader_mod) + { + if self.config.debug_key_events { + log::info!( + "{:?} {:?} -> perform {:?}", + keycode, + raw_modifiers | leader_mod, + assignment + ); + } + self.perform_key_assignment(&pane, &assignment).ok(); + context.invalidate(); - if leader_active { - // A successful leader key-lookup cancels the leader - // virtual modifier state - self.leader_done(); + if leader_active { + // A successful leader key-lookup cancels the leader + // virtual modifier state + self.leader_done(); + } + return true; } - return true; } // While the leader modifier is active, only registered @@ -138,7 +141,14 @@ impl super::TermWindow { tw_raw_modifiers ); } - if pane.key_down(term_key, tw_raw_modifiers).is_ok() { + + let res = if is_down { + pane.key_down(term_key, tw_raw_modifiers) + } else { + pane.key_up(term_key, tw_raw_modifiers) + }; + + if res.is_ok() { if !keycode.is_modifier() && self.pane_state(pane.pane_id()).overlay.is_none() { @@ -159,10 +169,6 @@ impl super::TermWindow { } pub fn raw_key_event_impl(&mut self, key: RawKeyEvent, context: &dyn WindowOps) { - if !key.key_is_down { - return; - } - if self.config.debug_key_events { log::info!("key_event {:?}", key); } else { @@ -199,6 +205,7 @@ impl super::TermWindow { leader_active, leader_mod, OnlyKeyBindings::Yes, + key.key_is_down, ) { key.set_handled(); return; @@ -218,6 +225,7 @@ impl super::TermWindow { leader_active, leader_mod, OnlyKeyBindings::Yes, + key.key_is_down, ) { key.set_handled(); return; @@ -237,6 +245,7 @@ impl super::TermWindow { leader_active, leader_mod, OnlyKeyBindings::Yes, + key.key_is_down, ) { key.set_handled(); } @@ -280,10 +289,6 @@ impl super::TermWindow { } pub fn key_event_impl(&mut self, window_key: KeyEvent, context: &dyn WindowOps) { - if !window_key.key_is_down { - return; - } - if self.config.debug_key_events { log::info!("key_event {:?}", window_key); } else { @@ -315,6 +320,7 @@ impl super::TermWindow { leader_active, leader_mod, OnlyKeyBindings::No, + window_key.key_is_down, ) { return; } @@ -335,7 +341,13 @@ impl super::TermWindow { log::info!("send to pane key={:?} mods={:?}", key, modifiers); } - if pane.key_down(key, modifiers).is_ok() { + let res = if window_key.key_is_down { + pane.key_down(key, modifiers) + } else { + pane.key_up(key, modifiers) + }; + + if res.is_ok() { if !key.is_modifier() && self.pane_state(pane.pane_id()).overlay.is_none() { self.maybe_scroll_to_bottom_for_input(&pane); } @@ -346,6 +358,9 @@ impl super::TermWindow { } } Key::Composed(s) => { + if !window_key.key_is_down { + return; + } if leader_active { // Leader was pressed and this non-modifier keypress isn't // a registered key binding; swallow this event and cancel diff --git a/wezterm-input-types/src/lib.rs b/wezterm-input-types/src/lib.rs index 05e83b35d..e64d03c58 100644 --- a/wezterm-input-types/src/lib.rs +++ b/wezterm-input-types/src/lib.rs @@ -227,13 +227,13 @@ impl KeyCode { Self::Function(19) => PhysKeyCode::F19, Self::Function(20) => PhysKeyCode::F20, Self::Physical(p) => *p, - Self::LeftShift => PhysKeyCode::LeftShift, + Self::Shift | Self::LeftShift => PhysKeyCode::LeftShift, Self::RightShift => PhysKeyCode::RightShift, Self::Alt | Self::LeftAlt => PhysKeyCode::LeftAlt, Self::RightAlt => PhysKeyCode::RightAlt, Self::LeftWindows => PhysKeyCode::LeftWindows, Self::RightWindows => PhysKeyCode::RightWindows, - Self::LeftControl => PhysKeyCode::LeftControl, + Self::Control | Self::LeftControl => PhysKeyCode::LeftControl, Self::RightControl => PhysKeyCode::RightControl, Self::CapsLock => PhysKeyCode::CapsLock, Self::PageUp => PhysKeyCode::PageUp, @@ -281,9 +281,7 @@ impl KeyCode { | Self::Select | Self::VoidSymbol | Self::Pause - | Self::Shift | Self::Cancel - | Self::Control | Self::Hyper | Self::Super | Self::Meta diff --git a/window/src/os/windows/keycodes.rs b/window/src/os/windows/keycodes.rs index 03c77e7a4..46aac54aa 100644 --- a/window/src/os/windows/keycodes.rs +++ b/window/src/os/windows/keycodes.rs @@ -150,6 +150,7 @@ fn build_map() -> HashMap { (VK_BACK, PhysKeyCode::Backspace), (VK_ESCAPE, PhysKeyCode::Escape), (VK_LWIN, PhysKeyCode::LeftWindows), + (VK_SHIFT, PhysKeyCode::LeftShift), (VK_LSHIFT, PhysKeyCode::LeftShift), (VK_CAPITAL, PhysKeyCode::CapsLock), (VK_MENU, PhysKeyCode::LeftAlt), diff --git a/window/src/os/windows/window.rs b/window/src/os/windows/window.rs index 402b79456..78ce1001f 100644 --- a/window/src/os/windows/window.rs +++ b/window/src/os/windows/window.rs @@ -1770,11 +1770,6 @@ unsafe fn key(hwnd: HWND, msg: UINT, wparam: WPARAM, lparam: LPARAM) -> Option Option Option None, } } else if let Some(c) = inner.keyboard_info.is_dead_key_leader(modifiers, vk) { + if releasing { + // Don't care about key-up events while processing dead keys + return Some(0); + } + // They pressed a dead key. // If they want dead key processing, then record that and // wait for a subsequent keypress.