Skip to content

Commit d01954d

Browse files
committed
Add keycode_to_key method for getting logical keys from physical
1 parent da62200 commit d01954d

File tree

2 files changed

+51
-0
lines changed

2 files changed

+51
-0
lines changed

winit-win32/src/keyboard_layout.rs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,16 @@ use crate::util::{loword, primarylangid};
4848
pub(crate) static LAYOUT_CACHE: LazyLock<Mutex<LayoutCache>> =
4949
LazyLock::new(|| Mutex::new(LayoutCache::default()));
5050

51+
// high order bit is pressed
5152
fn key_pressed(vkey: VIRTUAL_KEY) -> bool {
5253
unsafe { (GetKeyState(vkey as i32) & (1 << 15)) == (1 << 15) }
5354
}
5455

56+
// low order bit is toggled
57+
fn key_toggled(vkey: VIRTUAL_KEY) -> bool {
58+
unsafe { (GetKeyState(vkey as i32) & 0x01) == 0x01 }
59+
}
60+
5561
const NUMPAD_VKEYS: [VIRTUAL_KEY; 16] = [
5662
VK_NUMPAD0,
5763
VK_NUMPAD1,
@@ -986,3 +992,47 @@ fn vkey_to_non_char_key(
986992
_ => Key::Unidentified(native_code),
987993
}
988994
}
995+
996+
/// Query the logical key that would be produced by a physical key under the
997+
/// current keyboard layout with the given modifier state.
998+
///
999+
/// # Example
1000+
///
1001+
/// ```ignore
1002+
/// use winit::keyboard::{KeyCode, ModifiersState};
1003+
/// use winit_win32::keycode_to_key;
1004+
///
1005+
/// // Get what the 'Q' key produces without modifiers
1006+
/// let key = keycode_to_key(KeyCode::KeyQ, ModifiersState::empty(), false, false);
1007+
///
1008+
/// // Get what Shift+Q produces
1009+
/// let shifted = keycode_to_key(KeyCode::KeyQ, ModifiersState::SHIFT, false, false);
1010+
/// ```
1011+
pub fn keycode_to_key(
1012+
keycode: KeyCode,
1013+
modifiers: ModifiersState,
1014+
caps_lock: bool,
1015+
num_lock: bool,
1016+
) -> Key {
1017+
let mut cache = LAYOUT_CACHE.lock().unwrap();
1018+
let (locale_id, layout) = cache.get_current_layout();
1019+
1020+
let mut win_mods = WindowsModifiers::empty();
1021+
if modifiers.shift_key() {
1022+
win_mods.insert(WindowsModifiers::SHIFT);
1023+
}
1024+
if modifiers.control_key() {
1025+
win_mods.insert(WindowsModifiers::CONTROL);
1026+
}
1027+
if modifiers.alt_key() {
1028+
win_mods.insert(WindowsModifiers::ALT);
1029+
}
1030+
if caps_lock {
1031+
win_mods.insert(WindowsModifiers::CAPS_LOCK);
1032+
}
1033+
1034+
let vkey = keycode_to_vkey(keycode, locale_id);
1035+
let physical_key = PhysicalKey::Code(keycode);
1036+
1037+
layout.get_key(win_mods, num_lock, vkey, &physical_key)
1038+
}

winit-win32/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ use winit_core::window::{PlatformWindowAttributes, Window as CoreWindow};
3737
pub use self::event_loop::{EventLoop, PlatformSpecificEventLoopAttributes};
3838
use self::icon::{RaiiIcon, SelectedCursor};
3939
pub use self::keyboard::{physicalkey_to_scancode, scancode_to_physicalkey};
40+
pub use self::keyboard_layout::keycode_to_key;
4041
pub use self::monitor::{MonitorHandle, VideoModeHandle};
4142
pub use self::window::Window;
4243

0 commit comments

Comments
 (0)