windows_hotkeys/keys/
modkey.rs

1use std::fmt::Display;
2
3use crate::{error::HkError, VKey};
4
5/// Modifier Key for hotkeys.
6///
7/// See: `fsModifiers` from <https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-registerhotkey>
8///
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
10pub enum ModKey {
11    Alt,
12    Ctrl,
13    Shift,
14    Win,
15    /// This is a virtual modifier key that is used to prevent automatically repeating triggers
16    /// when the hotkey is being held down. When converting to a VKey, this is mapped to KeyCode 0
17    NoRepeat,
18}
19
20impl ModKey {
21    /// Take in a string and interpret it as one of the modifier keys.
22    /// Possible values are:
23    /// - ALT
24    /// - CTRL / CONTROL
25    /// - SHIFT
26    /// - WIN / WINDOWS / SUPER
27    /// - NOREPEAT / NO_REPEAT
28    ///
29    pub fn from_keyname(val: &str) -> Result<Self, HkError> {
30        Ok(match val.to_ascii_uppercase().as_ref() {
31            "ALT" => ModKey::Alt,
32            "CTRL" | "CONTROL" => ModKey::Ctrl,
33            "SHIFT" => ModKey::Shift,
34            "WIN" | "WINDOWS" | "SUPER" => ModKey::Win,
35            "NOREPEAT" | "NO_REPEAT" => ModKey::NoRepeat,
36            val => return Err(HkError::InvalidKey(val.to_string())),
37        })
38    }
39
40    /// Obtain the modifier code for the `ModKey`.
41    ///
42    /// See: `fsModifiers` from <https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-registerhotkey>
43    ///
44    pub const fn to_mod_code(&self) -> u32 {
45        use winapi::um::winuser::*;
46
47        match self {
48            ModKey::Alt => MOD_ALT as u32,
49            ModKey::Ctrl => MOD_CONTROL as u32,
50            ModKey::Shift => MOD_SHIFT as u32,
51            ModKey::Win => MOD_WIN as u32,
52            ModKey::NoRepeat => MOD_NOREPEAT as u32,
53        }
54    }
55
56    /// Combine multiple `ModKey`s using bitwise OR
57    ///
58    pub(crate) fn combine(keys: &[ModKey]) -> u32 {
59        keys.iter().fold(0, |a, b| a | b.to_mod_code())
60    }
61}
62
63impl Display for ModKey {
64    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
65        let key = match self {
66            ModKey::Alt => "ALT",
67            ModKey::Ctrl => "CONTROL",
68            ModKey::Shift => "SHIFT",
69            ModKey::Win => "WIN",
70            ModKey::NoRepeat => "NO_REPEAT",
71        };
72        write!(f, "{}", key)
73    }
74}
75
76impl From<ModKey> for VKey {
77    fn from(mk: ModKey) -> VKey {
78        match mk {
79            ModKey::Alt => VKey::Menu,
80            ModKey::Ctrl => VKey::Control,
81            ModKey::Shift => VKey::Shift,
82            ModKey::Win => VKey::LWin,
83            ModKey::NoRepeat => VKey::CustomKeyCode(0),
84        }
85    }
86}