a7n_core/hotkey/
trigger.rs1use super::keys::{key_usage, trigger_name};
4use super::{HotkeyError, Mods, modifier_bit};
5
6pub const HOLD_DEFAULT: u32 = 800;
7pub const HOLD_MIN: u32 = 300;
8pub const HOLD_MAX: u32 = 3000;
9
10#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
11pub enum TriggerMode {
12 #[default]
13 DoubleTap,
14 Hold,
15 Both,
16}
17
18impl TriggerMode {
19 pub fn parse(text: &str) -> Result<Self, HotkeyError> {
22 match text {
23 "double_tap" => Ok(Self::DoubleTap),
24 "hold" => Ok(Self::Hold),
25 "both" => Ok(Self::Both),
26 _ => Err(HotkeyError(format!("unknown trigger mode '{text}'"))),
27 }
28 }
29}
30
31#[derive(Debug, Clone, Copy, PartialEq, Eq)]
33pub struct DoubleTap(TriggerKey);
34
35#[derive(Debug, Clone, Copy, PartialEq, Eq)]
36enum TriggerKey {
37 None,
38 Modifiers(u8),
39 Key(u32),
40}
41
42impl DoubleTap {
43 pub fn parse(text: &str) -> Result<Self, HotkeyError> {
46 let name = text.trim().to_ascii_lowercase();
47 if name == "none" {
48 return Ok(Self(TriggerKey::None));
49 }
50 if let Some(key) = key_usage(&name).filter(|key| trigger_name(*key).is_some()) {
51 return Ok(Self(TriggerKey::Key(key)));
52 }
53 if let Some(modifier) = name.strip_prefix("either_").and_then(Mods::token) {
54 return Ok(Self(TriggerKey::Modifiers(modifier.0 | (modifier.0 << 4))));
55 }
56 Err(HotkeyError(format!("unknown trigger key '{text}'")))
57 }
58
59 #[must_use]
60 pub fn matches(self, usage: u32) -> bool {
61 match self.0 {
62 TriggerKey::None => false,
63 TriggerKey::Key(key) => key == usage,
64 TriggerKey::Modifiers(mask) => modifier_bit(usage).is_some_and(|bit| mask & bit != 0),
65 }
66 }
67
68 #[must_use]
69 pub fn collides(self, chord: super::Chord) -> bool {
70 chord.mods == Mods::default() && self.matches(chord.key)
71 }
72}