aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/input/windows_vti.rs37
1 files changed, 28 insertions, 9 deletions
diff --git a/src/client/input/windows_vti.rs b/src/client/input/windows_vti.rs
index 2b92c167..0deb3185 100644
--- a/src/client/input/windows_vti.rs
+++ b/src/client/input/windows_vti.rs
@@ -1353,7 +1353,9 @@ fn ctrl_key_code(vk: u16, u: u16, oem: Option<char>) -> Option<crate::protocol::
use crate::protocol::ClientKeyCode;
Some(match (vk, u) {
(0xbf, 0x00) => ClientKeyCode::Char(oem?),
- (_, 0x00) => ClientKeyCode::Char(' '),
+ // Keep Ctrl+Break and Ctrl+Space mappings. Other physical keys carrying
+ // Unicode zero are not evidence of a Space character.
+ (0x03 | 0x20, 0x00) => ClientKeyCode::Char(' '),
(_, 0x1b) => ClientKeyCode::Char('['),
(_, 0x1c) => ClientKeyCode::Char('\\'),
(_, 0x1d) => ClientKeyCode::Char(']'),
@@ -1595,6 +1597,30 @@ mod tests {
.collect()
}
+ #[test]
+ fn vti_ctrl_win_does_not_emit_ctrl_space() {
+ // Exact host sequences captured in issue #4470: Ctrl down, Win down,
+ // Ctrl up, Win up. Non-text keys must not become the Space prefix.
+ let input =
+ "\x1b[17;29;0;1;8;1_\x1b[91;91;0;1;264;1_\x1b[17;29;0;0;0;1_\x1b[91;91;0;0;256;1_";
+ let mut translator = WindowsInputTranslator::default();
+ let events: Vec<_> = input
+ .chars()
+ .flat_map(|ch| translator.translate(key_char(ch)))
+ .collect();
+ assert!(events.is_empty(), "unexpected input events: {events:?}");
+ assert!(translator.idle().is_empty());
+
+ // Ignoring the chord must not consume or defer the following input.
+ for record in [key_char('c'), key_vk_with_utf16_mods(0x20, 0, 0x0008)] {
+ assert_eq!(
+ translator.translate(record),
+ translate_with_provenance([record])
+ );
+ }
+ assert!(translator.idle().is_empty());
+ }
+
#[cfg(windows)]
#[test]
fn windows_input_trace_preserves_mapped_event_groups() {
@@ -1932,6 +1958,7 @@ mod tests {
#[test]
fn vti_control_records_keep_physical_digit_identity() {
let cases = [
+ (0x03, 0x00, ' '),
(0x20, 0x00, ' '),
(0x31, 0x00, '1'),
(0xdc, 0x1c, '\\'),
@@ -2126,14 +2153,6 @@ mod tests {
}
#[test]
- fn vti_ctrl_break_record_keeps_semantic_path() {
- assert!(matches!(
- translate_with_provenance([key_vk(0x03, 0x0008)]).as_slice(),
- [crate::protocol::ClientInputEvent::Key { .. }]
- ));
- }
-
- #[test]
fn vti_ime_virtual_keys_keep_semantic_path() {
for vk in [0xe5, 0xe7] {
assert!(matches!(