use super::keys::{key_usage, trigger_name};
use super::{HotkeyError, Mods, modifier_bit};
pub const HOLD_DEFAULT: u32 = 800;
pub const HOLD_MIN: u32 = 300;
pub const HOLD_MAX: u32 = 3000;
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub enum TriggerMode {
#[default]
DoubleTap,
Hold,
Both,
}
impl TriggerMode {
pub fn parse(text: &str) -> Result<Self, HotkeyError> {
match text {
"double_tap" => Ok(Self::DoubleTap),
"hold" => Ok(Self::Hold),
"both" => Ok(Self::Both),
_ => Err(HotkeyError(format!("unknown trigger mode '{text}'"))),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct DoubleTap(TriggerKey);
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum TriggerKey {
None,
Modifiers(u8),
Key(u32),
}
impl DoubleTap {
pub fn parse(text: &str) -> Result<Self, HotkeyError> {
let name = text.trim().to_ascii_lowercase();
if name == "none" {
return Ok(Self(TriggerKey::None));
}
if let Some(key) = key_usage(&name).filter(|key| trigger_name(*key).is_some()) {
return Ok(Self(TriggerKey::Key(key)));
}
if let Some(modifier) = name.strip_prefix("either_").and_then(Mods::token) {
return Ok(Self(TriggerKey::Modifiers(modifier.0 | (modifier.0 << 4))));
}
Err(HotkeyError(format!("unknown trigger key '{text}'")))
}
#[must_use]
pub fn matches(self, usage: u32) -> bool {
match self.0 {
TriggerKey::None => false,
TriggerKey::Key(key) => key == usage,
TriggerKey::Modifiers(mask) => modifier_bit(usage).is_some_and(|bit| mask & bit != 0),
}
}
#[must_use]
pub fn collides(self, chord: super::Chord) -> bool {
chord.mods == Mods::default() && self.matches(chord.key)
}
}