Enable Windows VT input mode
ci / test (push) Canceled after 0s
ci / fuzz-smoke (push) Canceled after 0s
ci / macos-client (macos-aarch64, macos-14) (push) Canceled after 0s
ci / macos-client (macos-x86_64, macos-13) (push) Canceled after 0s
ci / windows-client (push) Canceled after 0s
ci / package-release (linux-x86_64, ubuntu-latest, , , ) (push) Canceled after 0s
ci / package-release (macos-aarch64, macos-14, , , ) (push) Canceled after 0s
ci / package-release (macos-x86_64, macos-13, , , ) (push) Canceled after 0s
ci / package-release (windows-aarch64, windows-latest, aarch64, windows, aarch64-pc-windows-msvc) (push) Canceled after 0s
ci / package-release (windows-x86_64, windows-latest, , , ) (push) Canceled after 0s
ci / remote-bench (push) Canceled after 0s
ci / publish-gitea-release (push) Canceled after 0s

This commit is contained in:
DuProcess
2026-07-16 21:46:30 -04:00
parent 1e5b029731
commit 9f969b795d
+50 -11
View File
@@ -10540,8 +10540,15 @@ fn windows_vt_output_mode(mode: u32) -> u32 {
mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING
} }
#[cfg_attr(not(any(test, windows)), allow(dead_code))]
fn windows_vt_input_mode(mode: u32) -> u32 {
const ENABLE_VIRTUAL_TERMINAL_INPUT: u32 = 0x0200;
mode | ENABLE_VIRTUAL_TERMINAL_INPUT
}
#[cfg(windows)] #[cfg(windows)]
struct WindowsConsoleModeGuard { struct WindowsConsoleModeGuard {
input: Option<(windows_sys::Win32::Foundation::HANDLE, u32)>,
output: Option<(windows_sys::Win32::Foundation::HANDLE, u32)>, output: Option<(windows_sys::Win32::Foundation::HANDLE, u32)>,
} }
@@ -10551,28 +10558,53 @@ impl WindowsConsoleModeGuard {
unsafe { unsafe {
use windows_sys::Win32::Foundation::INVALID_HANDLE_VALUE; use windows_sys::Win32::Foundation::INVALID_HANDLE_VALUE;
use windows_sys::Win32::System::Console::{ use windows_sys::Win32::System::Console::{
GetConsoleMode, GetStdHandle, STD_OUTPUT_HANDLE, SetConsoleMode, GetConsoleMode, GetStdHandle, STD_INPUT_HANDLE, STD_OUTPUT_HANDLE, SetConsoleMode,
}; };
let handle = GetStdHandle(STD_OUTPUT_HANDLE); let input_handle = GetStdHandle(STD_INPUT_HANDLE);
if handle.is_null() || handle == INVALID_HANDLE_VALUE { let input = if input_handle.is_null() || input_handle == INVALID_HANDLE_VALUE {
return Self { output: None }; None
} } else {
let mut original = 0u32; let mut original = 0u32;
if GetConsoleMode(handle, &mut original) == 0 { if GetConsoleMode(input_handle, &mut original) == 0 {
return Self { output: None }; None
} else {
let desired = windows_vt_input_mode(original);
if desired != original {
let _ = SetConsoleMode(input_handle, desired);
} }
Some((input_handle, original))
}
};
let output_handle = GetStdHandle(STD_OUTPUT_HANDLE);
let output = if output_handle.is_null() || output_handle == INVALID_HANDLE_VALUE {
None
} else {
let mut original = 0u32;
if GetConsoleMode(output_handle, &mut original) == 0 {
None
} else {
let desired = windows_vt_output_mode(original); let desired = windows_vt_output_mode(original);
if desired != original { if desired != original {
let _ = SetConsoleMode(handle, desired); let _ = SetConsoleMode(output_handle, desired);
} }
Self { Some((output_handle, original))
output: Some((handle, original)),
} }
};
Self { input, output }
} }
} }
fn restore(&self) { fn restore(&self) {
if let Some((handle, mode)) = self.input {
unsafe {
use windows_sys::Win32::System::Console::SetConsoleMode;
let _ = SetConsoleMode(handle, mode);
}
}
if let Some((handle, mode)) = self.output { if let Some((handle, mode)) = self.output {
unsafe { unsafe {
use windows_sys::Win32::System::Console::SetConsoleMode; use windows_sys::Win32::System::Console::SetConsoleMode;
@@ -10714,7 +10746,7 @@ mod tests {
wake_repaint_retry_deadline, windows_command_word, windows_deferred_update_script, wake_repaint_retry_deadline, windows_command_word, windows_deferred_update_script,
windows_effective_url_script, windows_mode_from_readonly, windows_effective_url_script, windows_mode_from_readonly,
windows_powershell_command_candidates, windows_readonly_from_mode, windows_update_script, windows_powershell_command_candidates, windows_readonly_from_mode, windows_update_script,
windows_url_reachable_script, windows_vt_output_mode, windows_url_reachable_script, windows_vt_input_mode, windows_vt_output_mode,
}; };
use dosh::config::{ClientConfig, CommandExtension, HostConfig}; use dosh::config::{ClientConfig, CommandExtension, HostConfig};
use dosh::native::EnvVar; use dosh::native::EnvVar;
@@ -10846,6 +10878,13 @@ mod tests {
assert_eq!(windows_vt_output_mode(0x0005), 0x0005); assert_eq!(windows_vt_output_mode(0x0005), 0x0005);
} }
#[test]
fn windows_vt_input_mode_enables_escape_sequence_input() {
assert_eq!(windows_vt_input_mode(0), 0x0200);
assert_eq!(windows_vt_input_mode(0x0001), 0x0201);
assert_eq!(windows_vt_input_mode(0x0201), 0x0201);
}
#[test] #[test]
fn cleanup_stream_state_removes_all_per_stream_state_only_for_target() { fn cleanup_stream_state_removes_all_per_stream_state_only_for_target() {
let stream_id = 42; let stream_id = 42;