1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
// Source: ~/claudecode/openclaudecode/src/utils/modifiers.ts
use serde::{Deserialize, Serialize};
/// Modifier key types.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ModifierKey {
Shift,
Command,
Control,
Option,
}
impl ModifierKey {
fn as_str(&self) -> &'static str {
match self {
Self::Shift => "shift",
Self::Command => "command",
Self::Control => "control",
Self::Option => "option",
}
}
}
/// A keyboard modifier.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum Modifier {
Shift,
Ctrl,
Alt,
Meta,
}
impl Modifier {
pub fn as_str(&self) -> &'static str {
match self {
Self::Shift => "shift",
Self::Ctrl => "ctrl",
Self::Alt => "alt",
Self::Meta => "meta",
}
}
}
/// A keyboard shortcut consisting of optional modifiers and a key.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Shortcut {
pub modifiers: Vec<Modifier>,
pub key: String,
}
impl Shortcut {
pub fn new(key: impl Into<String>, modifiers: Vec<Modifier>) -> Self {
Self {
modifiers,
key: key.into(),
}
}
pub fn display(&self) -> String {
let mut parts = Vec::new();
for m in &self.modifiers {
parts.push(match m {
Modifier::Shift => "⇧",
Modifier::Ctrl => "⌃",
Modifier::Alt => "⌥",
Modifier::Meta => "⌘",
});
}
parts.push(&self.key);
parts.join("")
}
}
static PREWARMED: std::sync::atomic::AtomicBool = std::sync::atomic::AtomicBool::new(false);
/// Pre-warm the native module by loading it in advance.
/// Call this early to avoid delay on first use.
/// Note: This is a no-op on non-macOS platforms.
pub fn prewarm_modifiers() {
if PREWARMED.load(std::sync::atomic::Ordering::SeqCst) {
return;
}
// Only on macOS
if !cfg!(target_os = "macos") {
return;
}
PREWARMED.store(true, std::sync::atomic::Ordering::SeqCst);
// In production, this would load the native module
// For now, this is a no-op as we don't have the native bindings
}
/// Check if a specific modifier key is currently pressed.
/// Note: This is a no-op on non-macOS platforms.
pub fn is_modifier_pressed(_modifier: ModifierKey) -> bool {
// Only on macOS
if !cfg!(target_os = "macos") {
return false;
}
// In production, this would call the native module
// For now, always return false as we don't have the native bindings
false
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_prewarm_does_not_panic() {
prewarm_modifiers();
prewarm_modifiers(); // Should be idempotent
}
#[test]
fn test_is_modifier_pressed() {
// On non-macOS this always returns false
// On macOS without native module it also returns false
let _ = is_modifier_pressed(ModifierKey::Shift);
}
}