aboutsummaryrefslogtreecommitdiff
path: root/src/platform
diff options
context:
space:
mode:
authorJJ Liebig <jonathan.liebig@gmail.com>2026-09-03 17:20:57 +0200
committerGitHub <noreply@github.com>2026-09-03 17:20:57 +0200
commit0496636dc75db14a99aa71a7cadb006dc027d5c6 (patch)
tree943d44ed4474ccc9e39ee527a44f00365c81dfbb /src/platform
parent0f8ad128b65869d683253753a477c0ccafca9bf2 (diff)
fix(windows): preserve ctrl+slash key identity (#3578)
refs #2954
Diffstat (limited to 'src/platform')
-rw-r--r--src/platform/windows.rs30
1 files changed, 28 insertions, 2 deletions
diff --git a/src/platform/windows.rs b/src/platform/windows.rs
index b05b9e6f..890c24ca 100644
--- a/src/platform/windows.rs
+++ b/src/platform/windows.rs
@@ -105,8 +105,8 @@ use windows_sys::{
Input::{
Ime::ImmGetDefaultIMEWnd,
KeyboardAndMouse::{
- GetKeyboardLayout, SendInput, INPUT, INPUT_0, INPUT_KEYBOARD, KEYBDINPUT,
- KEYEVENTF_KEYUP,
+ GetKeyboardLayout, SendInput, ToUnicodeEx, INPUT, INPUT_0, INPUT_KEYBOARD,
+ KEYBDINPUT, KEYEVENTF_KEYUP,
},
},
Shell::{
@@ -134,6 +134,32 @@ pub(crate) fn terminal_title_for_presentation(title: &str) -> &str {
title.strip_prefix("Administrator: ").unwrap_or(title)
}
+/// Resolves against the current foreground layout because asynchronous console
+/// records do not retain the layout that was active when the key was pressed.
+pub(crate) fn resolve_base_printable_key(vk: u16, scan: u16) -> Option<char> {
+ // SAFETY: Win32 owns the handles; the fixed buffers match the API lengths.
+ unsafe {
+ let thread_id = GetWindowThreadProcessId(GetForegroundWindow(), null_mut());
+ let layout = GetKeyboardLayout(thread_id);
+
+ let key_state = [0u8; 256];
+ let mut output = [0u16; 2];
+ let written = ToUnicodeEx(
+ vk.into(),
+ scan.into(),
+ key_state.as_ptr(),
+ output.as_mut_ptr(),
+ output.len() as i32,
+ 0x4,
+ layout,
+ );
+ let units = output.get(..usize::try_from(written).ok()?)?;
+ let mut chars = char::decode_utf16(units.iter().copied());
+ let ch = chars.next()?.ok()?;
+ (chars.next().is_none() && !ch.is_control()).then_some(ch)
+ }
+}
+
const MAX_PROCESS_ENVIRONMENT_BYTES: usize = 256 * 1024;
const PROCESS_ENVIRONMENT_READ_CHUNK_BYTES: usize = 16 * 1024;
const PROCESS_RUNTIME_MARKER_CACHE_CAPACITY: usize = 1_024;