From d01954d5d27d396ed8d893dd758d3a29c58499d7 Mon Sep 17 00:00:00 2001 From: Aceeri Date: Mon, 29 Dec 2025 16:43:26 -0800 Subject: [PATCH 1/2] Add `keycode_to_key` method for getting logical keys from physical --- winit-win32/src/keyboard_layout.rs | 50 ++++++++++++++++++++++++++++++ winit-win32/src/lib.rs | 1 + 2 files changed, 51 insertions(+) diff --git a/winit-win32/src/keyboard_layout.rs b/winit-win32/src/keyboard_layout.rs index 7b6a370fdb..6213ea9dea 100644 --- a/winit-win32/src/keyboard_layout.rs +++ b/winit-win32/src/keyboard_layout.rs @@ -48,10 +48,16 @@ use crate::util::{loword, primarylangid}; pub(crate) static LAYOUT_CACHE: LazyLock> = LazyLock::new(|| Mutex::new(LayoutCache::default())); +// high order bit is pressed fn key_pressed(vkey: VIRTUAL_KEY) -> bool { unsafe { (GetKeyState(vkey as i32) & (1 << 15)) == (1 << 15) } } +// low order bit is toggled +fn key_toggled(vkey: VIRTUAL_KEY) -> bool { + unsafe { (GetKeyState(vkey as i32) & 0x01) == 0x01 } +} + const NUMPAD_VKEYS: [VIRTUAL_KEY; 16] = [ VK_NUMPAD0, VK_NUMPAD1, @@ -986,3 +992,47 @@ fn vkey_to_non_char_key( _ => Key::Unidentified(native_code), } } + +/// Query the logical key that would be produced by a physical key under the +/// current keyboard layout with the given modifier state. +/// +/// # Example +/// +/// ```ignore +/// use winit::keyboard::{KeyCode, ModifiersState}; +/// use winit_win32::keycode_to_key; +/// +/// // Get what the 'Q' key produces without modifiers +/// let key = keycode_to_key(KeyCode::KeyQ, ModifiersState::empty(), false, false); +/// +/// // Get what Shift+Q produces +/// let shifted = keycode_to_key(KeyCode::KeyQ, ModifiersState::SHIFT, false, false); +/// ``` +pub fn keycode_to_key( + keycode: KeyCode, + modifiers: ModifiersState, + caps_lock: bool, + num_lock: bool, +) -> Key { + let mut cache = LAYOUT_CACHE.lock().unwrap(); + let (locale_id, layout) = cache.get_current_layout(); + + let mut win_mods = WindowsModifiers::empty(); + if modifiers.shift_key() { + win_mods.insert(WindowsModifiers::SHIFT); + } + if modifiers.control_key() { + win_mods.insert(WindowsModifiers::CONTROL); + } + if modifiers.alt_key() { + win_mods.insert(WindowsModifiers::ALT); + } + if caps_lock { + win_mods.insert(WindowsModifiers::CAPS_LOCK); + } + + let vkey = keycode_to_vkey(keycode, locale_id); + let physical_key = PhysicalKey::Code(keycode); + + layout.get_key(win_mods, num_lock, vkey, &physical_key) +} diff --git a/winit-win32/src/lib.rs b/winit-win32/src/lib.rs index 569d1f32c1..a5619206e2 100644 --- a/winit-win32/src/lib.rs +++ b/winit-win32/src/lib.rs @@ -37,6 +37,7 @@ use winit_core::window::{PlatformWindowAttributes, Window as CoreWindow}; pub use self::event_loop::{EventLoop, PlatformSpecificEventLoopAttributes}; use self::icon::{RaiiIcon, SelectedCursor}; pub use self::keyboard::{physicalkey_to_scancode, scancode_to_physicalkey}; +pub use self::keyboard_layout::keycode_to_key; pub use self::monitor::{MonitorHandle, VideoModeHandle}; pub use self::window::Window; From d3dca9dd82d77f868192b7d5e95f98a29eddad7e Mon Sep 17 00:00:00 2001 From: Aceeri Date: Mon, 29 Dec 2025 16:53:54 -0800 Subject: [PATCH 2/2] Remove unnecessary changes --- winit-win32/src/keyboard_layout.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/winit-win32/src/keyboard_layout.rs b/winit-win32/src/keyboard_layout.rs index 6213ea9dea..368737d8c3 100644 --- a/winit-win32/src/keyboard_layout.rs +++ b/winit-win32/src/keyboard_layout.rs @@ -48,16 +48,10 @@ use crate::util::{loword, primarylangid}; pub(crate) static LAYOUT_CACHE: LazyLock> = LazyLock::new(|| Mutex::new(LayoutCache::default())); -// high order bit is pressed fn key_pressed(vkey: VIRTUAL_KEY) -> bool { unsafe { (GetKeyState(vkey as i32) & (1 << 15)) == (1 << 15) } } -// low order bit is toggled -fn key_toggled(vkey: VIRTUAL_KEY) -> bool { - unsafe { (GetKeyState(vkey as i32) & 0x01) == 0x01 } -} - const NUMPAD_VKEYS: [VIRTUAL_KEY; 16] = [ VK_NUMPAD0, VK_NUMPAD1,