Skip to main content

winit/platform_impl/windows/
keyboard.rs

1use std::char;
2use std::ffi::OsString;
3use std::mem::MaybeUninit;
4use std::os::windows::ffi::OsStringExt;
5use std::sync::atomic::AtomicU32;
6use std::sync::atomic::Ordering::Relaxed;
7use std::sync::{Mutex, MutexGuard};
8
9use windows_sys::Win32::Foundation::{HWND, LPARAM, WPARAM};
10use windows_sys::Win32::System::SystemServices::LANG_KOREAN;
11use windows_sys::Win32::UI::Input::KeyboardAndMouse::{
12    GetAsyncKeyState, GetKeyState, GetKeyboardLayout, GetKeyboardState, MapVirtualKeyExW,
13    MAPVK_VK_TO_VSC_EX, MAPVK_VSC_TO_VK_EX, VIRTUAL_KEY, VK_ABNT_C2, VK_ADD, VK_CAPITAL, VK_CLEAR,
14    VK_CONTROL, VK_DECIMAL, VK_DELETE, VK_DIVIDE, VK_DOWN, VK_END, VK_F4, VK_HOME, VK_INSERT,
15    VK_LCONTROL, VK_LEFT, VK_LMENU, VK_LSHIFT, VK_LWIN, VK_MENU, VK_MULTIPLY, VK_NEXT, VK_NUMLOCK,
16    VK_NUMPAD0, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3, VK_NUMPAD4, VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7,
17    VK_NUMPAD8, VK_NUMPAD9, VK_PRIOR, VK_RCONTROL, VK_RETURN, VK_RIGHT, VK_RMENU, VK_RSHIFT,
18    VK_RWIN, VK_SCROLL, VK_SHIFT, VK_SUBTRACT, VK_UP,
19};
20use windows_sys::Win32::UI::TextServices::HKL;
21use windows_sys::Win32::UI::WindowsAndMessaging::{
22    PeekMessageW, MSG, PM_NOREMOVE, WM_CHAR, WM_DEADCHAR, WM_KEYDOWN, WM_KEYFIRST, WM_KEYLAST,
23    WM_KEYUP, WM_KILLFOCUS, WM_SETFOCUS, WM_SYSCHAR, WM_SYSDEADCHAR, WM_SYSKEYDOWN, WM_SYSKEYUP,
24};
25
26use smol_str::SmolStr;
27use tracing::{trace, warn};
28use unicode_segmentation::UnicodeSegmentation;
29
30use crate::event::{ElementState, KeyEvent};
31use crate::keyboard::{Key, KeyCode, KeyLocation, NamedKey, NativeKey, NativeKeyCode, PhysicalKey};
32use crate::platform_impl::platform::event_loop::ProcResult;
33use crate::platform_impl::platform::keyboard_layout::{
34    Layout, LayoutCache, WindowsModifiers, LAYOUT_CACHE,
35};
36use crate::platform_impl::platform::{loword, primarylangid, KeyEventExtra};
37
38pub type ExScancode = u16;
39
40pub struct MessageAsKeyEvent {
41    pub event: KeyEvent,
42    pub is_synthetic: bool,
43}
44
45/// Stores information required to make `KeyEvent`s.
46///
47/// A single Winit `KeyEvent` contains information which the Windows API passes to the application
48/// in multiple window messages. In other words: a Winit `KeyEvent` cannot be built from a single
49/// window message. Therefore, this type keeps track of certain information from previous events so
50/// that a `KeyEvent` can be constructed when the last event related to a keypress is received.
51///
52/// `PeekMessage` is sometimes used to determine whether the next window message still belongs to
53/// the current keypress. If it doesn't and the current state represents a key event waiting to be
54/// dispatched, then said event is considered complete and is dispatched.
55///
56/// The sequence of window messages for a key press event is the following:
57/// - Exactly one WM_KEYDOWN / WM_SYSKEYDOWN
58/// - Zero or one WM_DEADCHAR / WM_SYSDEADCHAR
59/// - Zero or more WM_CHAR / WM_SYSCHAR. These messages each come with a UTF-16 code unit which when
60///   put together in the sequence they arrived in, forms the text which is the result of pressing
61///   the key.
62///
63/// Key release messages are a bit different due to the fact that they don't contribute to
64/// text input. The "sequence" only consists of one WM_KEYUP / WM_SYSKEYUP event.
65pub struct KeyEventBuilder {
66    event_info: Mutex<Option<PartialKeyEventInfo>>,
67    pending: PendingEventQueue<MessageAsKeyEvent>,
68}
69impl Default for KeyEventBuilder {
70    fn default() -> Self {
71        KeyEventBuilder { event_info: Mutex::new(None), pending: Default::default() }
72    }
73}
74impl KeyEventBuilder {
75    /// Call this function for every window message.
76    /// Returns Some() if this window message completes a KeyEvent.
77    /// Returns None otherwise.
78    pub(crate) fn process_message(
79        &self,
80        hwnd: HWND,
81        msg_kind: u32,
82        wparam: WPARAM,
83        lparam: LPARAM,
84        result: &mut ProcResult,
85    ) -> Vec<MessageAsKeyEvent> {
86        enum MatchResult {
87            Nothing,
88            TokenToRemove(PendingMessageToken),
89            MessagesToDispatch(Vec<MessageAsKeyEvent>),
90        }
91
92        let mut matcher = || -> MatchResult {
93            match msg_kind {
94                WM_SETFOCUS => {
95                    // synthesize keydown events
96                    let kbd_state = get_async_kbd_state();
97                    let key_events = Self::synthesize_kbd_state(ElementState::Pressed, &kbd_state);
98                    MatchResult::MessagesToDispatch(self.pending.complete_multi(key_events))
99                },
100                WM_KILLFOCUS => {
101                    // synthesize keyup events
102                    let kbd_state = get_kbd_state();
103                    let key_events = Self::synthesize_kbd_state(ElementState::Released, &kbd_state);
104                    MatchResult::MessagesToDispatch(self.pending.complete_multi(key_events))
105                },
106                WM_KEYDOWN | WM_SYSKEYDOWN => {
107                    if msg_kind == WM_SYSKEYDOWN && wparam as VIRTUAL_KEY == VK_F4 {
108                        // Don't dispatch Alt+F4 to the application.
109                        // This is handled in `event_loop.rs`
110                        return MatchResult::Nothing;
111                    }
112                    let pending_token = self.pending.add_pending();
113                    *result = ProcResult::Value(0);
114
115                    let next_msg = next_kbd_msg(hwnd);
116
117                    let mut layouts = LAYOUT_CACHE.lock().unwrap();
118                    let mut finished_event_info = Some(PartialKeyEventInfo::from_message(
119                        wparam,
120                        lparam,
121                        ElementState::Pressed,
122                        &mut layouts,
123                    ));
124                    let mut event_info = self.event_info.lock().unwrap();
125                    *event_info = None;
126                    if let Some(next_msg) = next_msg {
127                        let next_msg_kind = next_msg.message;
128                        let next_belongs_to_this = !matches!(
129                            next_msg_kind,
130                            WM_KEYDOWN | WM_SYSKEYDOWN | WM_KEYUP | WM_SYSKEYUP
131                        );
132                        if next_belongs_to_this {
133                            // The next OS event belongs to this Winit event, so let's just
134                            // store the partial information, and add to it in the upcoming events
135                            *event_info = finished_event_info.take();
136                        } else {
137                            let (_, layout) = layouts.get_current_layout();
138                            let is_fake = {
139                                let curr_event = finished_event_info.as_ref().unwrap();
140                                is_current_fake(curr_event, next_msg, layout)
141                            };
142                            if is_fake {
143                                finished_event_info = None;
144                            }
145                        }
146                    }
147                    if let Some(event_info) = finished_event_info {
148                        let ev = event_info.finalize();
149                        return MatchResult::MessagesToDispatch(self.pending.complete_pending(
150                            pending_token,
151                            MessageAsKeyEvent { event: ev, is_synthetic: false },
152                        ));
153                    }
154                    MatchResult::TokenToRemove(pending_token)
155                },
156                WM_DEADCHAR | WM_SYSDEADCHAR => {
157                    let pending_token = self.pending.add_pending();
158                    *result = ProcResult::Value(0);
159                    // At this point, we know that there isn't going to be any more events related
160                    // to this key press
161                    let event_info = self.event_info.lock().unwrap().take().unwrap();
162                    let ev = event_info.finalize();
163                    MatchResult::MessagesToDispatch(self.pending.complete_pending(
164                        pending_token,
165                        MessageAsKeyEvent { event: ev, is_synthetic: false },
166                    ))
167                },
168                WM_CHAR | WM_SYSCHAR => {
169                    let mut event_info = self.event_info.lock().unwrap();
170                    if event_info.is_none() {
171                        trace!(
172                            "Received a CHAR message but no `event_info` was available. The \
173                             message is probably IME, returning."
174                        );
175                        return MatchResult::Nothing;
176                    }
177                    let pending_token = self.pending.add_pending();
178                    *result = ProcResult::Value(0);
179                    let is_high_surrogate = (0xd800..=0xdbff).contains(&wparam);
180                    let is_low_surrogate = (0xdc00..=0xdfff).contains(&wparam);
181
182                    let is_utf16 = is_high_surrogate || is_low_surrogate;
183
184                    if is_utf16 {
185                        if let Some(ev_info) = event_info.as_mut() {
186                            ev_info.utf16parts.push(wparam as u16);
187                        }
188                    } else {
189                        // In this case, wparam holds a UTF-32 character.
190                        // Let's encode it as UTF-16 and append it to the end of `utf16parts`
191                        let utf16parts = match event_info.as_mut() {
192                            Some(ev_info) => &mut ev_info.utf16parts,
193                            None => {
194                                warn!("The event_info was None when it was expected to be some");
195                                return MatchResult::TokenToRemove(pending_token);
196                            },
197                        };
198                        let start_offset = utf16parts.len();
199                        let new_size = utf16parts.len() + 2;
200                        utf16parts.resize(new_size, 0);
201                        if let Some(ch) = char::from_u32(wparam as u32) {
202                            let encode_len = ch.encode_utf16(&mut utf16parts[start_offset..]).len();
203                            let new_size = start_offset + encode_len;
204                            utf16parts.resize(new_size, 0);
205                        }
206                    }
207                    // It's important that we unlock the mutex, and create the pending event token
208                    // before calling `next_msg`
209                    std::mem::drop(event_info);
210                    let next_msg = next_kbd_msg(hwnd);
211                    let more_char_coming = next_msg
212                        .map(|m| matches!(m.message, WM_CHAR | WM_SYSCHAR))
213                        .unwrap_or(false);
214                    if more_char_coming {
215                        // No need to produce an event just yet, because there are still more
216                        // characters that need to be appended to this keyboard event
217                        MatchResult::TokenToRemove(pending_token)
218                    } else {
219                        let mut event_info = self.event_info.lock().unwrap();
220                        let mut event_info = match event_info.take() {
221                            Some(ev_info) => ev_info,
222                            None => {
223                                warn!("The event_info was None when it was expected to be some");
224                                return MatchResult::TokenToRemove(pending_token);
225                            },
226                        };
227                        let mut layouts = LAYOUT_CACHE.lock().unwrap();
228                        // It's okay to call `ToUnicode` here, because at this point the dead key
229                        // is already consumed by the character.
230                        let kbd_state = get_kbd_state();
231                        let mod_state = WindowsModifiers::active_modifiers(&kbd_state);
232
233                        let (_, layout) = layouts.get_current_layout();
234                        let ctrl_on = if layout.has_alt_graph {
235                            let alt_on = mod_state.contains(WindowsModifiers::ALT);
236                            !alt_on && mod_state.contains(WindowsModifiers::CONTROL)
237                        } else {
238                            mod_state.contains(WindowsModifiers::CONTROL)
239                        };
240
241                        // If Ctrl is not pressed, just use the text with all
242                        // modifiers because that already consumed the dead key. Otherwise,
243                        // we would interpret the character incorrectly, missing the dead key.
244                        if !ctrl_on {
245                            event_info.text = PartialText::System(event_info.utf16parts.clone());
246                        } else {
247                            let mod_no_ctrl = mod_state.remove_only_ctrl();
248                            let num_lock_on = kbd_state[VK_NUMLOCK as usize] & 1 != 0;
249                            let vkey = event_info.vkey;
250                            let physical_key = &event_info.physical_key;
251                            let key = layout.get_key(mod_no_ctrl, num_lock_on, vkey, physical_key);
252                            event_info.text = PartialText::Text(key.to_text().map(SmolStr::new));
253                        }
254                        let ev = event_info.finalize();
255                        MatchResult::MessagesToDispatch(self.pending.complete_pending(
256                            pending_token,
257                            MessageAsKeyEvent { event: ev, is_synthetic: false },
258                        ))
259                    }
260                },
261                WM_KEYUP | WM_SYSKEYUP => {
262                    let pending_token = self.pending.add_pending();
263                    *result = ProcResult::Value(0);
264
265                    let mut layouts = LAYOUT_CACHE.lock().unwrap();
266                    let event_info = PartialKeyEventInfo::from_message(
267                        wparam,
268                        lparam,
269                        ElementState::Released,
270                        &mut layouts,
271                    );
272                    // We MUST release the layout lock before calling `next_kbd_msg`, otherwise it
273                    // may deadlock
274                    drop(layouts);
275                    // It's important that we create the pending token before reading the next
276                    // message.
277                    let next_msg = next_kbd_msg(hwnd);
278                    let mut valid_event_info = Some(event_info);
279                    if let Some(next_msg) = next_msg {
280                        let mut layouts = LAYOUT_CACHE.lock().unwrap();
281                        let (_, layout) = layouts.get_current_layout();
282                        let is_fake = {
283                            let event_info = valid_event_info.as_ref().unwrap();
284                            is_current_fake(event_info, next_msg, layout)
285                        };
286                        if is_fake {
287                            valid_event_info = None;
288                        }
289                    }
290                    if let Some(event_info) = valid_event_info {
291                        let event = event_info.finalize();
292                        return MatchResult::MessagesToDispatch(self.pending.complete_pending(
293                            pending_token,
294                            MessageAsKeyEvent { event, is_synthetic: false },
295                        ));
296                    }
297                    MatchResult::TokenToRemove(pending_token)
298                },
299                _ => MatchResult::Nothing,
300            }
301        };
302        let matcher_result = matcher();
303        match matcher_result {
304            MatchResult::TokenToRemove(t) => self.pending.remove_pending(t),
305            MatchResult::MessagesToDispatch(m) => m,
306            MatchResult::Nothing => Vec::new(),
307        }
308    }
309
310    // Allowing nominimal_bool lint because the `is_key_pressed` macro triggers this warning
311    // and I don't know of another way to resolve it and also keeping the macro
312    #[allow(clippy::nonminimal_bool)]
313    fn synthesize_kbd_state(
314        key_state: ElementState,
315        kbd_state: &[u8; 256],
316    ) -> Vec<MessageAsKeyEvent> {
317        let mut key_events = Vec::new();
318
319        let mut layouts = LAYOUT_CACHE.lock().unwrap();
320        let (locale_id, _) = layouts.get_current_layout();
321
322        macro_rules! is_key_pressed {
323            ($vk:expr) => {
324                kbd_state[$vk as usize] & 0x80 != 0
325            };
326        }
327
328        // Is caps-lock active? Note that this is different from caps-lock
329        // being held down.
330        let caps_lock_on = kbd_state[VK_CAPITAL as usize] & 1 != 0;
331        let num_lock_on = kbd_state[VK_NUMLOCK as usize] & 1 != 0;
332
333        // We are synthesizing the press event for caps-lock first for the following reasons:
334        // 1. If caps-lock is *not* held down but *is* active, then we have to synthesize all
335        //    printable keys, respecting the caps-lock state.
336        // 2. If caps-lock is held down, we could choose to synthesize its keypress after every
337        //    other key, in which case all other keys *must* be synthesized as if the caps-lock
338        //    state was be the opposite of what it currently is.
339        // --
340        // For the sake of simplicity we are choosing to always synthesize
341        // caps-lock first, and always use the current caps-lock state
342        // to determine the produced text
343        if is_key_pressed!(VK_CAPITAL) {
344            let event = Self::create_synthetic(
345                VK_CAPITAL,
346                key_state,
347                caps_lock_on,
348                num_lock_on,
349                locale_id as HKL,
350                &mut layouts,
351            );
352            if let Some(event) = event {
353                key_events.push(event);
354            }
355        }
356        let do_non_modifier = |key_events: &mut Vec<_>, layouts: &mut _| {
357            for vk in 0..256 {
358                match vk {
359                    VK_CONTROL | VK_LCONTROL | VK_RCONTROL | VK_SHIFT | VK_LSHIFT | VK_RSHIFT
360                    | VK_MENU | VK_LMENU | VK_RMENU | VK_CAPITAL => continue,
361                    _ => (),
362                }
363                if !is_key_pressed!(vk) {
364                    continue;
365                }
366                let event = Self::create_synthetic(
367                    vk,
368                    key_state,
369                    caps_lock_on,
370                    num_lock_on,
371                    locale_id as HKL,
372                    layouts,
373                );
374                if let Some(event) = event {
375                    key_events.push(event);
376                }
377            }
378        };
379        let do_modifier = |key_events: &mut Vec<_>, layouts: &mut _| {
380            const CLEAR_MODIFIER_VKS: [VIRTUAL_KEY; 6] =
381                [VK_LCONTROL, VK_LSHIFT, VK_LMENU, VK_RCONTROL, VK_RSHIFT, VK_RMENU];
382            for vk in CLEAR_MODIFIER_VKS.iter() {
383                if is_key_pressed!(*vk) {
384                    let event = Self::create_synthetic(
385                        *vk,
386                        key_state,
387                        caps_lock_on,
388                        num_lock_on,
389                        locale_id as HKL,
390                        layouts,
391                    );
392                    if let Some(event) = event {
393                        key_events.push(event);
394                    }
395                }
396            }
397        };
398
399        // Be cheeky and sequence modifier and non-modifier
400        // key events such that non-modifier keys are not affected
401        // by modifiers (except for caps-lock)
402        match key_state {
403            ElementState::Pressed => {
404                do_non_modifier(&mut key_events, &mut layouts);
405                do_modifier(&mut key_events, &mut layouts);
406            },
407            ElementState::Released => {
408                do_modifier(&mut key_events, &mut layouts);
409                do_non_modifier(&mut key_events, &mut layouts);
410            },
411        }
412
413        key_events
414    }
415
416    fn create_synthetic(
417        vk: VIRTUAL_KEY,
418        key_state: ElementState,
419        caps_lock_on: bool,
420        num_lock_on: bool,
421        locale_id: HKL,
422        layouts: &mut MutexGuard<'_, LayoutCache>,
423    ) -> Option<MessageAsKeyEvent> {
424        let scancode = unsafe { MapVirtualKeyExW(vk as u32, MAPVK_VK_TO_VSC_EX, locale_id) };
425        if scancode == 0 {
426            return None;
427        }
428        let scancode = scancode as ExScancode;
429        let physical_key = scancode_to_physicalkey(scancode as u32);
430        let mods =
431            if caps_lock_on { WindowsModifiers::CAPS_LOCK } else { WindowsModifiers::empty() };
432        let layout = layouts.layouts.get(&(locale_id as u64)).unwrap();
433        let logical_key = layout.get_key(mods, num_lock_on, vk, &physical_key);
434        let key_without_modifiers =
435            layout.get_key(WindowsModifiers::empty(), false, vk, &physical_key);
436        let text = if key_state == ElementState::Pressed {
437            logical_key.to_text().map(SmolStr::new)
438        } else {
439            None
440        };
441        let event_info = PartialKeyEventInfo {
442            vkey: vk,
443            logical_key: PartialLogicalKey::This(logical_key.clone()),
444            key_without_modifiers,
445            key_state,
446            is_repeat: false,
447            physical_key,
448            location: get_location(scancode, locale_id),
449            utf16parts: Vec::with_capacity(8),
450            text: PartialText::Text(text.clone()),
451        };
452
453        let mut event = event_info.finalize();
454        event.logical_key = logical_key;
455        event.platform_specific.text_with_all_modifiers = text;
456        Some(MessageAsKeyEvent { event, is_synthetic: true })
457    }
458}
459
460enum PartialText {
461    // Unicode
462    System(Vec<u16>),
463    Text(Option<SmolStr>),
464}
465
466enum PartialLogicalKey {
467    /// Use the text provided by the WM_CHAR messages and report that as a `Character` variant. If
468    /// the text consists of multiple grapheme clusters (user-perceived characters) that means that
469    /// dead key could not be combined with the second input, and in that case we should fall back
470    /// to using what would have without a dead-key input.
471    TextOr(Key),
472
473    /// Use the value directly provided by this variant
474    This(Key),
475}
476
477struct PartialKeyEventInfo {
478    vkey: VIRTUAL_KEY,
479    key_state: ElementState,
480    is_repeat: bool,
481    physical_key: PhysicalKey,
482    location: KeyLocation,
483    logical_key: PartialLogicalKey,
484
485    key_without_modifiers: Key,
486
487    /// The UTF-16 code units of the text that was produced by the keypress event.
488    /// This take all modifiers into account. Including CTRL
489    utf16parts: Vec<u16>,
490
491    text: PartialText,
492}
493
494impl PartialKeyEventInfo {
495    fn from_message(
496        wparam: WPARAM,
497        lparam: LPARAM,
498        state: ElementState,
499        layouts: &mut MutexGuard<'_, LayoutCache>,
500    ) -> Self {
501        const NO_MODS: WindowsModifiers = WindowsModifiers::empty();
502
503        let (_, layout) = layouts.get_current_layout();
504        let lparam_struct = destructure_key_lparam(lparam);
505        let vkey = wparam as VIRTUAL_KEY;
506        let scancode = if lparam_struct.scancode == 0 {
507            // In some cases (often with media keys) the device reports a scancode of 0 but a
508            // valid virtual key. In these cases we obtain the scancode from the virtual key.
509            unsafe { MapVirtualKeyExW(vkey as u32, MAPVK_VK_TO_VSC_EX, layout.hkl as HKL) as u16 }
510        } else {
511            new_ex_scancode(lparam_struct.scancode, lparam_struct.extended)
512        };
513        let physical_key = scancode_to_physicalkey(scancode as u32);
514        let location = get_location(scancode, layout.hkl as HKL);
515
516        let kbd_state = get_kbd_state();
517        let mods = WindowsModifiers::active_modifiers(&kbd_state);
518        let mods_without_ctrl = mods.remove_only_ctrl();
519        let num_lock_on = kbd_state[VK_NUMLOCK as usize] & 1 != 0;
520
521        // On Windows Ctrl+NumLock = Pause (and apparently Ctrl+Pause -> NumLock). In these cases
522        // the KeyCode still stores the real key, so in the name of consistency across platforms, we
523        // circumvent this mapping and force the key values to match the keycode.
524        // For more on this, read the article by Raymond Chen, titled:
525        // "Why does Ctrl+ScrollLock cancel dialogs?"
526        // https://devblogs.microsoft.com/oldnewthing/20080211-00/?p=23503
527        let code_as_key = if mods.contains(WindowsModifiers::CONTROL) {
528            match physical_key {
529                PhysicalKey::Code(KeyCode::NumLock) => Some(Key::Named(NamedKey::NumLock)),
530                PhysicalKey::Code(KeyCode::Pause) => Some(Key::Named(NamedKey::Pause)),
531                _ => None,
532            }
533        } else {
534            None
535        };
536
537        let preliminary_logical_key =
538            layout.get_key(mods_without_ctrl, num_lock_on, vkey, &physical_key);
539        let key_is_char = matches!(preliminary_logical_key, Key::Character(_));
540        let is_pressed = state == ElementState::Pressed;
541
542        let logical_key = if let Some(key) = code_as_key.clone() {
543            PartialLogicalKey::This(key)
544        } else if is_pressed && key_is_char && !mods.contains(WindowsModifiers::CONTROL) {
545            // In some cases we want to use the UNICHAR text for logical_key in order to allow
546            // dead keys to have an effect on the character reported by `logical_key`.
547            PartialLogicalKey::TextOr(preliminary_logical_key)
548        } else {
549            PartialLogicalKey::This(preliminary_logical_key)
550        };
551        let key_without_modifiers = if let Some(key) = code_as_key {
552            key
553        } else {
554            match layout.get_key(NO_MODS, false, vkey, &physical_key) {
555                // We convert dead keys into their character.
556                // The reason for this is that `key_without_modifiers` is designed for key-bindings,
557                // but the US International layout treats `'` (apostrophe) as a dead key and the
558                // regular US layout treats it a character. In order for a single binding
559                // configuration to work with both layouts, we forward each dead key as a character.
560                Key::Dead(k) => {
561                    if let Some(ch) = k {
562                        // I'm avoiding the heap allocation. I don't want to talk about it :(
563                        let mut utf8 = [0; 4];
564                        let s = ch.encode_utf8(&mut utf8);
565                        Key::Character(SmolStr::new(s))
566                    } else {
567                        Key::Unidentified(NativeKey::Unidentified)
568                    }
569                },
570                key => key,
571            }
572        };
573
574        PartialKeyEventInfo {
575            vkey,
576            key_state: state,
577            logical_key,
578            key_without_modifiers,
579            is_repeat: lparam_struct.is_repeat,
580            physical_key,
581            location,
582            utf16parts: Vec::with_capacity(8),
583            text: PartialText::System(Vec::new()),
584        }
585    }
586
587    fn finalize(self) -> KeyEvent {
588        let mut char_with_all_modifiers = None;
589        if !self.utf16parts.is_empty() {
590            let os_string = OsString::from_wide(&self.utf16parts);
591            if let Ok(string) = os_string.into_string() {
592                char_with_all_modifiers = Some(SmolStr::new(string));
593            }
594        }
595
596        // The text without Ctrl
597        let mut text = None;
598        match self.text {
599            PartialText::System(wide) => {
600                if !wide.is_empty() {
601                    let os_string = OsString::from_wide(&wide);
602                    if let Ok(string) = os_string.into_string() {
603                        text = Some(SmolStr::new(string));
604                    }
605                }
606            },
607            PartialText::Text(s) => {
608                text = s.map(SmolStr::new);
609            },
610        }
611
612        let logical_key = match self.logical_key {
613            PartialLogicalKey::TextOr(fallback) => match text.as_ref() {
614                Some(s) => {
615                    if s.grapheme_indices(true).count() > 1 {
616                        fallback
617                    } else {
618                        Key::Character(s.clone())
619                    }
620                },
621                None => Key::Unidentified(NativeKey::Windows(self.vkey)),
622            },
623            PartialLogicalKey::This(v) => v,
624        };
625
626        KeyEvent {
627            physical_key: self.physical_key,
628            logical_key,
629            text,
630            location: self.location,
631            state: self.key_state,
632            repeat: self.is_repeat,
633            platform_specific: KeyEventExtra {
634                text_with_all_modifiers: char_with_all_modifiers,
635                key_without_modifiers: self.key_without_modifiers,
636            },
637        }
638    }
639}
640
641#[derive(Debug, Copy, Clone)]
642struct KeyLParam {
643    pub scancode: u8,
644    pub extended: bool,
645
646    /// This is `previous_state XOR transition_state`. See the lParam for WM_KEYDOWN and WM_KEYUP
647    /// for further details.
648    pub is_repeat: bool,
649}
650
651fn destructure_key_lparam(lparam: LPARAM) -> KeyLParam {
652    let previous_state = (lparam >> 30) & 0x01;
653    let transition_state = (lparam >> 31) & 0x01;
654    KeyLParam {
655        scancode: ((lparam >> 16) & 0xff) as u8,
656        extended: ((lparam >> 24) & 0x01) != 0,
657        is_repeat: (previous_state ^ transition_state) != 0,
658    }
659}
660
661#[inline]
662fn new_ex_scancode(scancode: u8, extended: bool) -> ExScancode {
663    (scancode as u16) | (if extended { 0xe000 } else { 0 })
664}
665
666#[inline]
667fn ex_scancode_from_lparam(lparam: LPARAM) -> ExScancode {
668    let lparam = destructure_key_lparam(lparam);
669    new_ex_scancode(lparam.scancode, lparam.extended)
670}
671
672/// Gets the keyboard state as reported by messages that have been removed from the event queue.
673/// See also: get_async_kbd_state
674fn get_kbd_state() -> [u8; 256] {
675    unsafe {
676        let mut kbd_state: MaybeUninit<[u8; 256]> = MaybeUninit::uninit();
677        GetKeyboardState(kbd_state.as_mut_ptr() as *mut u8);
678        kbd_state.assume_init()
679    }
680}
681
682/// Gets the current keyboard state regardless of whether the corresponding keyboard events have
683/// been removed from the event queue. See also: get_kbd_state
684#[allow(clippy::uninit_assumed_init)]
685fn get_async_kbd_state() -> [u8; 256] {
686    unsafe {
687        let mut kbd_state: [u8; 256] = [0; 256];
688        for (vk, state) in kbd_state.iter_mut().enumerate() {
689            let vk = vk as VIRTUAL_KEY;
690            let async_state = GetAsyncKeyState(vk as i32);
691            let is_down = (async_state & (1 << 15)) != 0;
692            *state = if is_down { 0x80 } else { 0 };
693
694            if matches!(vk, VK_CAPITAL | VK_NUMLOCK | VK_SCROLL) {
695                // Toggle states aren't reported by `GetAsyncKeyState`
696                let toggle_state = GetKeyState(vk as i32);
697                let is_active = (toggle_state & 1) != 0;
698                *state |= u8::from(is_active);
699            }
700        }
701        kbd_state
702    }
703}
704
705/// On windows, AltGr == Ctrl + Alt
706///
707/// Due to this equivalence, the system generates a fake Ctrl key-press (and key-release) preceding
708/// every AltGr key-press (and key-release). We check if the current event is a Ctrl event and if
709/// the next event is a right Alt (AltGr) event. If this is the case, the current event must be the
710/// fake Ctrl event.
711fn is_current_fake(curr_info: &PartialKeyEventInfo, next_msg: MSG, layout: &Layout) -> bool {
712    let curr_is_ctrl =
713        matches!(curr_info.logical_key, PartialLogicalKey::This(Key::Named(NamedKey::Control)));
714    if layout.has_alt_graph {
715        let next_code = ex_scancode_from_lparam(next_msg.lParam);
716        let next_is_altgr = next_code == 0xe038; // 0xE038 is right alt
717        if curr_is_ctrl && next_is_altgr {
718            return true;
719        }
720    }
721    false
722}
723
724enum PendingMessage<T> {
725    Incomplete,
726    Complete(T),
727}
728struct IdentifiedPendingMessage<T> {
729    token: PendingMessageToken,
730    msg: PendingMessage<T>,
731}
732#[derive(Debug, Clone, Copy, PartialEq, Eq)]
733pub struct PendingMessageToken(u32);
734
735/// While processing keyboard events, we sometimes need
736/// to call `PeekMessageW` (`next_msg`). But `PeekMessageW`
737/// can also call the event handler, which means that the new event
738/// gets processed before finishing to process the one that came before.
739///
740/// This would mean that the application receives events in the wrong order.
741/// To avoid this, we keep track whether we are in the middle of processing
742/// an event. Such an event is an "incomplete pending event". A
743/// "complete pending event" is one that has already finished processing, but
744/// hasn't been dispatched to the application because there still are incomplete
745/// pending events that came before it.
746///
747/// When we finish processing an event, we call `complete_pending`,
748/// which returns an empty array if there are incomplete pending events, but
749/// if all pending events are complete, then it returns all pending events in
750/// the order they were encountered. These can then be dispatched to the application
751pub struct PendingEventQueue<T> {
752    pending: Mutex<Vec<IdentifiedPendingMessage<T>>>,
753    next_id: AtomicU32,
754}
755impl<T> PendingEventQueue<T> {
756    /// Add a new pending event to the "pending queue"
757    pub fn add_pending(&self) -> PendingMessageToken {
758        let token = self.next_token();
759        let mut pending = self.pending.lock().unwrap();
760        pending.push(IdentifiedPendingMessage { token, msg: PendingMessage::Incomplete });
761        token
762    }
763
764    /// Returns all finished pending events
765    ///
766    /// If the return value is non empty, it's guaranteed to contain `msg`
767    ///
768    /// See also: `add_pending`
769    pub fn complete_pending(&self, token: PendingMessageToken, msg: T) -> Vec<T> {
770        let mut pending = self.pending.lock().unwrap();
771        let mut target_is_first = false;
772        for (i, pending_msg) in pending.iter_mut().enumerate() {
773            if pending_msg.token == token {
774                pending_msg.msg = PendingMessage::Complete(msg);
775                if i == 0 {
776                    target_is_first = true;
777                }
778                break;
779            }
780        }
781        if target_is_first {
782            // If the message that we just finished was the first one in the pending queue,
783            // then we can empty the queue, and dispatch all of the messages.
784            Self::drain_pending(&mut *pending)
785        } else {
786            Vec::new()
787        }
788    }
789
790    pub fn complete_multi(&self, msgs: Vec<T>) -> Vec<T> {
791        let mut pending = self.pending.lock().unwrap();
792        if pending.is_empty() {
793            return msgs;
794        }
795        pending.reserve(msgs.len());
796        for msg in msgs {
797            pending.push(IdentifiedPendingMessage {
798                token: self.next_token(),
799                msg: PendingMessage::Complete(msg),
800            });
801        }
802        Vec::new()
803    }
804
805    /// Returns all finished pending events
806    ///
807    /// It's safe to call this even if the element isn't in the list anymore
808    ///
809    /// See also: `add_pending`
810    pub fn remove_pending(&self, token: PendingMessageToken) -> Vec<T> {
811        let mut pending = self.pending.lock().unwrap();
812        let mut was_first = false;
813        if let Some(m) = pending.first() {
814            if m.token == token {
815                was_first = true;
816            }
817        }
818        pending.retain(|m| m.token != token);
819        if was_first {
820            Self::drain_pending(&mut *pending)
821        } else {
822            Vec::new()
823        }
824    }
825
826    fn drain_pending(pending: &mut Vec<IdentifiedPendingMessage<T>>) -> Vec<T> {
827        pending
828            .drain(..)
829            .map(|m| match m.msg {
830                PendingMessage::Complete(msg) => msg,
831                PendingMessage::Incomplete => {
832                    panic!(
833                        "Found an incomplete pending message when collecting messages. This \
834                         indicates a bug in winit."
835                    )
836                },
837            })
838            .collect()
839    }
840
841    fn next_token(&self) -> PendingMessageToken {
842        // It's okay for the u32 to overflow here. Yes, that could mean
843        // that two different messages have the same token,
844        // but that would only happen after having about 4 billion
845        // messages sitting in the pending queue.
846        //
847        // In that case, having two identical tokens is the least of your concerns.
848        let id = self.next_id.fetch_add(1, Relaxed);
849        PendingMessageToken(id)
850    }
851}
852impl<T> Default for PendingEventQueue<T> {
853    fn default() -> Self {
854        PendingEventQueue { pending: Mutex::new(Vec::new()), next_id: AtomicU32::new(0) }
855    }
856}
857
858/// WARNING: Due to using PeekMessage, the event handler
859/// function may get called during this function.
860/// (Re-entrance to the event handler)
861///
862/// This can cause a deadlock if calling this function
863/// while having a mutex locked.
864///
865/// It can also cause code to get executed in a surprising order.
866pub fn next_kbd_msg(hwnd: HWND) -> Option<MSG> {
867    unsafe {
868        let mut next_msg = MaybeUninit::uninit();
869        let peek_retval =
870            PeekMessageW(next_msg.as_mut_ptr(), hwnd, WM_KEYFIRST, WM_KEYLAST, PM_NOREMOVE);
871        (peek_retval != 0).then(|| next_msg.assume_init())
872    }
873}
874
875fn get_location(scancode: ExScancode, hkl: HKL) -> KeyLocation {
876    const ABNT_C2: VIRTUAL_KEY = VK_ABNT_C2 as VIRTUAL_KEY;
877
878    let extension = 0xe000;
879    let extended = (scancode & extension) == extension;
880    let vkey = unsafe { MapVirtualKeyExW(scancode as u32, MAPVK_VSC_TO_VK_EX, hkl) as VIRTUAL_KEY };
881
882    // Use the native VKEY and the extended flag to cover most cases
883    // This is taken from the `druid` GUI library, specifically
884    // druid-shell/src/platform/windows/keyboard.rs
885    match vkey {
886        VK_LSHIFT | VK_LCONTROL | VK_LMENU | VK_LWIN => KeyLocation::Left,
887        VK_RSHIFT | VK_RCONTROL | VK_RMENU | VK_RWIN => KeyLocation::Right,
888        VK_RETURN if extended => KeyLocation::Numpad,
889        VK_INSERT | VK_DELETE | VK_END | VK_DOWN | VK_NEXT | VK_LEFT | VK_CLEAR | VK_RIGHT
890        | VK_HOME | VK_UP | VK_PRIOR => {
891            if extended {
892                KeyLocation::Standard
893            } else {
894                KeyLocation::Numpad
895            }
896        },
897        VK_NUMPAD0 | VK_NUMPAD1 | VK_NUMPAD2 | VK_NUMPAD3 | VK_NUMPAD4 | VK_NUMPAD5
898        | VK_NUMPAD6 | VK_NUMPAD7 | VK_NUMPAD8 | VK_NUMPAD9 | VK_DECIMAL | VK_DIVIDE
899        | VK_MULTIPLY | VK_SUBTRACT | VK_ADD | ABNT_C2 => KeyLocation::Numpad,
900        _ => KeyLocation::Standard,
901    }
902}
903
904pub(crate) fn physicalkey_to_scancode(physical_key: PhysicalKey) -> Option<u32> {
905    // See `scancode_to_physicalkey` for more info
906
907    let hkl = unsafe { GetKeyboardLayout(0) };
908
909    let primary_lang_id = primarylangid(loword(hkl as u32));
910    let is_korean = primary_lang_id as u32 == LANG_KOREAN;
911
912    let code = match physical_key {
913        PhysicalKey::Code(code) => code,
914        PhysicalKey::Unidentified(code) => {
915            return match code {
916                NativeKeyCode::Windows(scancode) => Some(scancode as u32),
917                _ => None,
918            };
919        },
920    };
921
922    match code {
923        KeyCode::Backquote => Some(0x0029),
924        KeyCode::Backslash => Some(0x002b),
925        KeyCode::Backspace => Some(0x000e),
926        KeyCode::BracketLeft => Some(0x001a),
927        KeyCode::BracketRight => Some(0x001b),
928        KeyCode::Comma => Some(0x0033),
929        KeyCode::Digit0 => Some(0x000b),
930        KeyCode::Digit1 => Some(0x0002),
931        KeyCode::Digit2 => Some(0x0003),
932        KeyCode::Digit3 => Some(0x0004),
933        KeyCode::Digit4 => Some(0x0005),
934        KeyCode::Digit5 => Some(0x0006),
935        KeyCode::Digit6 => Some(0x0007),
936        KeyCode::Digit7 => Some(0x0008),
937        KeyCode::Digit8 => Some(0x0009),
938        KeyCode::Digit9 => Some(0x000a),
939        KeyCode::Equal => Some(0x000d),
940        KeyCode::IntlBackslash => Some(0x0056),
941        KeyCode::IntlRo => Some(0x0073),
942        KeyCode::IntlYen => Some(0x007d),
943        KeyCode::KeyA => Some(0x001e),
944        KeyCode::KeyB => Some(0x0030),
945        KeyCode::KeyC => Some(0x002e),
946        KeyCode::KeyD => Some(0x0020),
947        KeyCode::KeyE => Some(0x0012),
948        KeyCode::KeyF => Some(0x0021),
949        KeyCode::KeyG => Some(0x0022),
950        KeyCode::KeyH => Some(0x0023),
951        KeyCode::KeyI => Some(0x0017),
952        KeyCode::KeyJ => Some(0x0024),
953        KeyCode::KeyK => Some(0x0025),
954        KeyCode::KeyL => Some(0x0026),
955        KeyCode::KeyM => Some(0x0032),
956        KeyCode::KeyN => Some(0x0031),
957        KeyCode::KeyO => Some(0x0018),
958        KeyCode::KeyP => Some(0x0019),
959        KeyCode::KeyQ => Some(0x0010),
960        KeyCode::KeyR => Some(0x0013),
961        KeyCode::KeyS => Some(0x001f),
962        KeyCode::KeyT => Some(0x0014),
963        KeyCode::KeyU => Some(0x0016),
964        KeyCode::KeyV => Some(0x002f),
965        KeyCode::KeyW => Some(0x0011),
966        KeyCode::KeyX => Some(0x002d),
967        KeyCode::KeyY => Some(0x0015),
968        KeyCode::KeyZ => Some(0x002c),
969        KeyCode::Minus => Some(0x000c),
970        KeyCode::Period => Some(0x0034),
971        KeyCode::Quote => Some(0x0028),
972        KeyCode::Semicolon => Some(0x0027),
973        KeyCode::Slash => Some(0x0035),
974        KeyCode::AltLeft => Some(0x0038),
975        KeyCode::AltRight => Some(0xe038),
976        KeyCode::CapsLock => Some(0x003a),
977        KeyCode::ContextMenu => Some(0xe05d),
978        KeyCode::ControlLeft => Some(0x001d),
979        KeyCode::ControlRight => Some(0xe01d),
980        KeyCode::Enter => Some(0x001c),
981        KeyCode::SuperLeft => Some(0xe05b),
982        KeyCode::SuperRight => Some(0xe05c),
983        KeyCode::ShiftLeft => Some(0x002a),
984        KeyCode::ShiftRight => Some(0x0036),
985        KeyCode::Space => Some(0x0039),
986        KeyCode::Tab => Some(0x000f),
987        KeyCode::Convert => Some(0x0079),
988        KeyCode::Lang1 => {
989            if is_korean {
990                Some(0xe0f2)
991            } else {
992                Some(0x0072)
993            }
994        },
995        KeyCode::Lang2 => {
996            if is_korean {
997                Some(0xe0f1)
998            } else {
999                Some(0x0071)
1000            }
1001        },
1002        KeyCode::KanaMode => Some(0x0070),
1003        KeyCode::NonConvert => Some(0x007b),
1004        KeyCode::Delete => Some(0xe053),
1005        KeyCode::End => Some(0xe04f),
1006        KeyCode::Home => Some(0xe047),
1007        KeyCode::Insert => Some(0xe052),
1008        KeyCode::PageDown => Some(0xe051),
1009        KeyCode::PageUp => Some(0xe049),
1010        KeyCode::ArrowDown => Some(0xe050),
1011        KeyCode::ArrowLeft => Some(0xe04b),
1012        KeyCode::ArrowRight => Some(0xe04d),
1013        KeyCode::ArrowUp => Some(0xe048),
1014        KeyCode::NumLock => Some(0xe045),
1015        KeyCode::Numpad0 => Some(0x0052),
1016        KeyCode::Numpad1 => Some(0x004f),
1017        KeyCode::Numpad2 => Some(0x0050),
1018        KeyCode::Numpad3 => Some(0x0051),
1019        KeyCode::Numpad4 => Some(0x004b),
1020        KeyCode::Numpad5 => Some(0x004c),
1021        KeyCode::Numpad6 => Some(0x004d),
1022        KeyCode::Numpad7 => Some(0x0047),
1023        KeyCode::Numpad8 => Some(0x0048),
1024        KeyCode::Numpad9 => Some(0x0049),
1025        KeyCode::NumpadAdd => Some(0x004e),
1026        KeyCode::NumpadComma => Some(0x007e),
1027        KeyCode::NumpadDecimal => Some(0x0053),
1028        KeyCode::NumpadDivide => Some(0xe035),
1029        KeyCode::NumpadEnter => Some(0xe01c),
1030        KeyCode::NumpadEqual => Some(0x0059),
1031        KeyCode::NumpadMultiply => Some(0x0037),
1032        KeyCode::NumpadSubtract => Some(0x004a),
1033        KeyCode::Escape => Some(0x0001),
1034        KeyCode::F1 => Some(0x003b),
1035        KeyCode::F2 => Some(0x003c),
1036        KeyCode::F3 => Some(0x003d),
1037        KeyCode::F4 => Some(0x003e),
1038        KeyCode::F5 => Some(0x003f),
1039        KeyCode::F6 => Some(0x0040),
1040        KeyCode::F7 => Some(0x0041),
1041        KeyCode::F8 => Some(0x0042),
1042        KeyCode::F9 => Some(0x0043),
1043        KeyCode::F10 => Some(0x0044),
1044        KeyCode::F11 => Some(0x0057),
1045        KeyCode::F12 => Some(0x0058),
1046        KeyCode::F13 => Some(0x0064),
1047        KeyCode::F14 => Some(0x0065),
1048        KeyCode::F15 => Some(0x0066),
1049        KeyCode::F16 => Some(0x0067),
1050        KeyCode::F17 => Some(0x0068),
1051        KeyCode::F18 => Some(0x0069),
1052        KeyCode::F19 => Some(0x006a),
1053        KeyCode::F20 => Some(0x006b),
1054        KeyCode::F21 => Some(0x006c),
1055        KeyCode::F22 => Some(0x006d),
1056        KeyCode::F23 => Some(0x006e),
1057        KeyCode::F24 => Some(0x0076),
1058        KeyCode::PrintScreen => Some(0xe037),
1059        // KeyCode::PrintScreen => Some(0x0054), // Alt + PrintScreen
1060        KeyCode::ScrollLock => Some(0x0046),
1061        KeyCode::Pause => Some(0x0045),
1062        // KeyCode::Pause => Some(0xE046), // Ctrl + Pause
1063        KeyCode::BrowserBack => Some(0xe06a),
1064        KeyCode::BrowserFavorites => Some(0xe066),
1065        KeyCode::BrowserForward => Some(0xe069),
1066        KeyCode::BrowserHome => Some(0xe032),
1067        KeyCode::BrowserRefresh => Some(0xe067),
1068        KeyCode::BrowserSearch => Some(0xe065),
1069        KeyCode::BrowserStop => Some(0xe068),
1070        KeyCode::LaunchApp1 => Some(0xe06b),
1071        KeyCode::LaunchApp2 => Some(0xe021),
1072        KeyCode::LaunchMail => Some(0xe06c),
1073        KeyCode::MediaPlayPause => Some(0xe022),
1074        KeyCode::MediaSelect => Some(0xe06d),
1075        KeyCode::MediaStop => Some(0xe024),
1076        KeyCode::MediaTrackNext => Some(0xe019),
1077        KeyCode::MediaTrackPrevious => Some(0xe010),
1078        KeyCode::Power => Some(0xe05e),
1079        KeyCode::AudioVolumeDown => Some(0xe02e),
1080        KeyCode::AudioVolumeMute => Some(0xe020),
1081        KeyCode::AudioVolumeUp => Some(0xe030),
1082        _ => None,
1083    }
1084}
1085
1086pub(crate) fn scancode_to_physicalkey(scancode: u32) -> PhysicalKey {
1087    // See: https://www.win.tue.nl/~aeb/linux/kbd/scancodes-1.html
1088    // and: https://www.w3.org/TR/uievents-code/
1089    // and: The widget/NativeKeyToDOMCodeName.h file in the firefox source
1090
1091    PhysicalKey::Code(match scancode {
1092        0x0029 => KeyCode::Backquote,
1093        0x002b => KeyCode::Backslash,
1094        0x000e => KeyCode::Backspace,
1095        0x001a => KeyCode::BracketLeft,
1096        0x001b => KeyCode::BracketRight,
1097        0x0033 => KeyCode::Comma,
1098        0x000b => KeyCode::Digit0,
1099        0x0002 => KeyCode::Digit1,
1100        0x0003 => KeyCode::Digit2,
1101        0x0004 => KeyCode::Digit3,
1102        0x0005 => KeyCode::Digit4,
1103        0x0006 => KeyCode::Digit5,
1104        0x0007 => KeyCode::Digit6,
1105        0x0008 => KeyCode::Digit7,
1106        0x0009 => KeyCode::Digit8,
1107        0x000a => KeyCode::Digit9,
1108        0x000d => KeyCode::Equal,
1109        0x0056 => KeyCode::IntlBackslash,
1110        0x0073 => KeyCode::IntlRo,
1111        0x007d => KeyCode::IntlYen,
1112        0x001e => KeyCode::KeyA,
1113        0x0030 => KeyCode::KeyB,
1114        0x002e => KeyCode::KeyC,
1115        0x0020 => KeyCode::KeyD,
1116        0x0012 => KeyCode::KeyE,
1117        0x0021 => KeyCode::KeyF,
1118        0x0022 => KeyCode::KeyG,
1119        0x0023 => KeyCode::KeyH,
1120        0x0017 => KeyCode::KeyI,
1121        0x0024 => KeyCode::KeyJ,
1122        0x0025 => KeyCode::KeyK,
1123        0x0026 => KeyCode::KeyL,
1124        0x0032 => KeyCode::KeyM,
1125        0x0031 => KeyCode::KeyN,
1126        0x0018 => KeyCode::KeyO,
1127        0x0019 => KeyCode::KeyP,
1128        0x0010 => KeyCode::KeyQ,
1129        0x0013 => KeyCode::KeyR,
1130        0x001f => KeyCode::KeyS,
1131        0x0014 => KeyCode::KeyT,
1132        0x0016 => KeyCode::KeyU,
1133        0x002f => KeyCode::KeyV,
1134        0x0011 => KeyCode::KeyW,
1135        0x002d => KeyCode::KeyX,
1136        0x0015 => KeyCode::KeyY,
1137        0x002c => KeyCode::KeyZ,
1138        0x000c => KeyCode::Minus,
1139        0x0034 => KeyCode::Period,
1140        0x0028 => KeyCode::Quote,
1141        0x0027 => KeyCode::Semicolon,
1142        0x0035 => KeyCode::Slash,
1143        0x0038 => KeyCode::AltLeft,
1144        0xe038 => KeyCode::AltRight,
1145        0x003a => KeyCode::CapsLock,
1146        0xe05d => KeyCode::ContextMenu,
1147        0x001d => KeyCode::ControlLeft,
1148        0xe01d => KeyCode::ControlRight,
1149        0x001c => KeyCode::Enter,
1150        0xe05b => KeyCode::SuperLeft,
1151        0xe05c => KeyCode::SuperRight,
1152        0x002a => KeyCode::ShiftLeft,
1153        0x0036 => KeyCode::ShiftRight,
1154        0x0039 => KeyCode::Space,
1155        0x000f => KeyCode::Tab,
1156        0x0079 => KeyCode::Convert,
1157        0x0072 => KeyCode::Lang1, // for non-Korean layout
1158        0xe0f2 => KeyCode::Lang1, // for Korean layout
1159        0x0071 => KeyCode::Lang2, // for non-Korean layout
1160        0xe0f1 => KeyCode::Lang2, // for Korean layout
1161        0x0070 => KeyCode::KanaMode,
1162        0x007b => KeyCode::NonConvert,
1163        0xe053 => KeyCode::Delete,
1164        0xe04f => KeyCode::End,
1165        0xe047 => KeyCode::Home,
1166        0xe052 => KeyCode::Insert,
1167        0xe051 => KeyCode::PageDown,
1168        0xe049 => KeyCode::PageUp,
1169        0xe050 => KeyCode::ArrowDown,
1170        0xe04b => KeyCode::ArrowLeft,
1171        0xe04d => KeyCode::ArrowRight,
1172        0xe048 => KeyCode::ArrowUp,
1173        0xe045 => KeyCode::NumLock,
1174        0x0052 => KeyCode::Numpad0,
1175        0x004f => KeyCode::Numpad1,
1176        0x0050 => KeyCode::Numpad2,
1177        0x0051 => KeyCode::Numpad3,
1178        0x004b => KeyCode::Numpad4,
1179        0x004c => KeyCode::Numpad5,
1180        0x004d => KeyCode::Numpad6,
1181        0x0047 => KeyCode::Numpad7,
1182        0x0048 => KeyCode::Numpad8,
1183        0x0049 => KeyCode::Numpad9,
1184        0x004e => KeyCode::NumpadAdd,
1185        0x007e => KeyCode::NumpadComma,
1186        0x0053 => KeyCode::NumpadDecimal,
1187        0xe035 => KeyCode::NumpadDivide,
1188        0xe01c => KeyCode::NumpadEnter,
1189        0x0059 => KeyCode::NumpadEqual,
1190        0x0037 => KeyCode::NumpadMultiply,
1191        0x004a => KeyCode::NumpadSubtract,
1192        0x0001 => KeyCode::Escape,
1193        0x003b => KeyCode::F1,
1194        0x003c => KeyCode::F2,
1195        0x003d => KeyCode::F3,
1196        0x003e => KeyCode::F4,
1197        0x003f => KeyCode::F5,
1198        0x0040 => KeyCode::F6,
1199        0x0041 => KeyCode::F7,
1200        0x0042 => KeyCode::F8,
1201        0x0043 => KeyCode::F9,
1202        0x0044 => KeyCode::F10,
1203        0x0057 => KeyCode::F11,
1204        0x0058 => KeyCode::F12,
1205        0x0064 => KeyCode::F13,
1206        0x0065 => KeyCode::F14,
1207        0x0066 => KeyCode::F15,
1208        0x0067 => KeyCode::F16,
1209        0x0068 => KeyCode::F17,
1210        0x0069 => KeyCode::F18,
1211        0x006a => KeyCode::F19,
1212        0x006b => KeyCode::F20,
1213        0x006c => KeyCode::F21,
1214        0x006d => KeyCode::F22,
1215        0x006e => KeyCode::F23,
1216        0x0076 => KeyCode::F24,
1217        0xe037 => KeyCode::PrintScreen,
1218        0x0054 => KeyCode::PrintScreen, // Alt + PrintScreen
1219        0x0046 => KeyCode::ScrollLock,
1220        0x0045 => KeyCode::Pause,
1221        0xe046 => KeyCode::Pause, // Ctrl + Pause
1222        0xe06a => KeyCode::BrowserBack,
1223        0xe066 => KeyCode::BrowserFavorites,
1224        0xe069 => KeyCode::BrowserForward,
1225        0xe032 => KeyCode::BrowserHome,
1226        0xe067 => KeyCode::BrowserRefresh,
1227        0xe065 => KeyCode::BrowserSearch,
1228        0xe068 => KeyCode::BrowserStop,
1229        0xe06b => KeyCode::LaunchApp1,
1230        0xe021 => KeyCode::LaunchApp2,
1231        0xe06c => KeyCode::LaunchMail,
1232        0xe022 => KeyCode::MediaPlayPause,
1233        0xe06d => KeyCode::MediaSelect,
1234        0xe024 => KeyCode::MediaStop,
1235        0xe019 => KeyCode::MediaTrackNext,
1236        0xe010 => KeyCode::MediaTrackPrevious,
1237        0xe05e => KeyCode::Power,
1238        0xe02e => KeyCode::AudioVolumeDown,
1239        0xe020 => KeyCode::AudioVolumeMute,
1240        0xe030 => KeyCode::AudioVolumeUp,
1241        _ => return PhysicalKey::Unidentified(NativeKeyCode::Windows(scancode as u16)),
1242    })
1243}