key_names/
lib.rs

1//! Platform-aware keyboard key name handling for Rust applications.
2
3#![warn(missing_docs)]
4
5use winit::keyboard::{Key, NativeKey, NativeKeyCode, PhysicalKey};
6
7#[cfg(target_os = "linux")]
8mod linux;
9#[cfg(target_os = "macos")]
10mod macos;
11#[cfg(target_arch = "wasm32")]
12mod web;
13#[cfg(windows)]
14mod windows;
15
16#[cfg(target_os = "linux")]
17use linux as os;
18#[cfg(target_os = "macos")]
19use macos as os;
20#[cfg(target_arch = "wasm32")]
21use web as os;
22#[cfg(windows)]
23use windows as os;
24
25/// OS's conventional modifiers order, represented as an ASCII string containing
26/// the characters `csam` for `CTRL`, `SHIFT`, `ALT`, and `META`/`LOGO`
27/// respectively in some order.
28pub const MODIFIERS_ORDER: &str = os::MODIFIERS_ORDER;
29
30/// OS's conventional name for the <key>Ctrl</key> modifier.
31pub const CTRL_STR: &str = "Ctrl";
32/// OS's conventional name for the <key>Shift</key> modifier.
33pub const SHIFT_STR: &str = "Shift";
34/// OS's conventional name for the <key>Alt</key> modifier.
35pub const ALT_STR: &str = os::ALT_STR;
36/// OS's conventional name for the logo modifier.
37pub const LOGO_STR: &str = os::LOGO_STR;
38
39/// Returns a string representing modifiers using the OS's conventional names
40/// and ordering. For example, on Windows this function might produce "Ctrl +
41/// Shift + Alt + Win + " while on macOS it might produce "Ctrl + Option + Shift
42/// + Cmd + ".
43pub fn mods_prefix_string(shift: bool, ctrl: bool, alt: bool, logo: bool) -> String {
44    let mut ret = String::new();
45    for ch in MODIFIERS_ORDER.chars() {
46        match ch {
47            's' if shift => {
48                ret += SHIFT_STR;
49                ret += " + ";
50            }
51            'c' if ctrl => {
52                ret += CTRL_STR;
53                ret += " + ";
54            }
55            'a' if alt => {
56                ret += ALT_STR;
57                ret += " + ";
58            }
59            'm' if logo => {
60                ret += LOGO_STR;
61                ret += " + ";
62            }
63            _ => (),
64        }
65    }
66    ret
67}
68
69/// Returns a human-friendly name for a physical key using the operating
70/// system's API when possible.
71///
72/// On Windows and Linux, this queries the user's keyboard layout. On macOS and
73/// web, hard-coded key names are used.
74pub fn physical_key_name(physical_key: PhysicalKey) -> String {
75    os::try_physical_key_name(physical_key).unwrap_or_else(|| match physical_key {
76        PhysicalKey::Code(key_code) => format!("{key_code:?}"),
77        PhysicalKey::Unidentified(native_key_code) => match native_key_code {
78            NativeKeyCode::Unidentified => "<unknown>".to_string(),
79            NativeKeyCode::Android(sc) => format!("SC{sc}"),
80            NativeKeyCode::MacOS(sc) => format!("SC{sc}"),
81            NativeKeyCode::Windows(sc) => format!("SC{sc}"),
82            NativeKeyCode::Xkb(sc) => format!("SC{sc}"),
83        },
84    })
85}
86
87/// Returns a human-friendly name for a virtual key.
88///
89/// Letters are uppercased and some special keys are given OS-specific names
90/// (such as "Win" on Windows vs. "Super" on Linux vs. "Command" on macOS).
91pub fn key_name(key: Key) -> String {
92    match key {
93        Key::Named(named_key) => match os::os_specific_key_name(named_key) {
94            Some(name) => name.to_string(),
95            None => format!("{named_key:?}"),
96        },
97        Key::Character(c) => c.to_ascii_uppercase(),
98        Key::Unidentified(native_key) => match native_key {
99            NativeKey::Unidentified => "<unknown>".to_string(),
100            NativeKey::Android(sc) => format!("SC{sc}"),
101            NativeKey::MacOS(sc) => format!("SC{sc}"),
102            NativeKey::Windows(sc) => format!("SC{sc}"),
103            NativeKey::Xkb(sc) => format!("SC{sc}"),
104            NativeKey::Web(smol_str) => format!("{smol_str}"),
105        },
106        Key::Dead(None) => "<unknown>".to_string(),
107        Key::Dead(Some(c)) => c.into(),
108    }
109}