diff options
| author | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-07-23 03:47:34 +0300 |
|---|---|---|
| committer | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-07-23 03:47:44 +0300 |
| commit | e7fc85bfdb51f89488430adbfe5bbced3be79c2f (patch) | |
| tree | c1c0324f28040c50d0075d6407bdf6ab14d1b8c0 /src/client/input.rs | |
| parent | 2a20e90a026936d0d5b96823d74e2e4fe13a166f (diff) | |
fix: preserve kitty printable key releases
refs #1746
Diffstat (limited to 'src/client/input.rs')
| -rw-r--r-- | src/client/input.rs | 48 |
1 files changed, 42 insertions, 6 deletions
diff --git a/src/client/input.rs b/src/client/input.rs index 1d557543..c37a15c7 100644 --- a/src/client/input.rs +++ b/src/client/input.rs @@ -210,7 +210,7 @@ fn windows_crossterm_reader_loop( tracing::debug!(event = ?event, "windows control key forwarded as semantic input"); } - let Some(event) = crate::protocol::ClientInputEvent::from_crossterm(event) else { + let Some(event) = windows_crossterm_input_event(event) else { continue; }; if event_tx @@ -226,6 +226,21 @@ fn windows_crossterm_reader_loop( } } +#[cfg(any(windows, test))] +fn windows_crossterm_input_event( + event: crossterm::event::Event, +) -> Option<crate::protocol::ClientInputEvent> { + let event = crate::protocol::ClientInputEvent::from_crossterm(event)?; + match event { + crate::protocol::ClientInputEvent::Key { + code: crate::protocol::ClientKeyCode::Char(codepoint), + modifiers: 0, + kind: crate::protocol::ClientKeyKind::Press, + } => Some(crate::protocol::ClientInputEvent::Text { codepoint }), + event => Some(event), + } +} + #[cfg(windows)] fn windows_event_is_control_key(event: &crossterm::event::Event) -> bool { use crossterm::event::{Event, KeyModifiers}; @@ -308,11 +323,22 @@ fn windows_client_input_event_from_raw( event: crate::raw_input::RawInputEvent, ) -> Option<crate::protocol::ClientInputEvent> { match event { - crate::raw_input::RawInputEvent::Key(key) => Some(crate::protocol::ClientInputEvent::Key { - code: crate::protocol::ClientKeyCode::from_crossterm(key.code)?, - modifiers: key.modifiers.bits(), - kind: crate::protocol::ClientKeyKind::from_crossterm(key.kind), - }), + crate::raw_input::RawInputEvent::Key(key) if key.is_text_commit => { + let crossterm::event::KeyCode::Char(codepoint) = key.code else { + return None; + }; + Some(crate::protocol::ClientInputEvent::Text { codepoint }) + } + crate::raw_input::RawInputEvent::Key(key) => { + let code = crate::protocol::ClientKeyCode::from_crossterm(key.code)?; + let modifiers = key.modifiers.bits(); + let kind = crate::protocol::ClientKeyKind::from_crossterm(key.kind); + Some(crate::protocol::ClientInputEvent::Key { + code, + modifiers, + kind, + }) + } crate::raw_input::RawInputEvent::Mouse(mouse) => { Some(crate::protocol::ClientInputEvent::Mouse { kind: crate::protocol::ClientMouseKind::from_crossterm(mouse.kind)?, @@ -474,6 +500,16 @@ mod windows_tests { } #[test] + fn windows_crossterm_printable_press_is_text() { + let event = Event::Key(KeyEvent::new(KeyCode::Char('你'), KeyModifiers::empty())); + + assert_eq!( + windows_crossterm_input_event(event), + Some(crate::protocol::ClientInputEvent::Text { codepoint: '你' }) + ); + } + + #[test] fn windows_ctrl_bracket_starts_raw_escape_sequence() { let ctrl_bracket = Event::Key(KeyEvent::new(KeyCode::Char('['), KeyModifiers::CONTROL)); assert_eq!( |
