1use crate::error::WHKError;
6use crate::error::WHKError::RegistrationFailed;
7use crate::hook;
8use crate::hook::{KeyAction, KeyboardEvent};
9use crate::hotkey::Hotkey;
10use crate::state::KeyboardState;
11use crate::VKey;
12use crossbeam_channel::Sender;
13use std::collections::HashMap;
14use std::sync::atomic::{AtomicBool, Ordering};
15use std::sync::Arc;
16
17pub struct HotkeyManager<T> {
25 hotkeys: HashMap<u16, Vec<Hotkey<T>>>,
26 paused_ids: Vec<i32>,
27 paused: Arc<AtomicBool>,
28 interrupt: Arc<AtomicBool>,
29 callback_results_channel: Option<Sender<T>>,
30}
31
32impl<T> Default for HotkeyManager<T> {
33 fn default() -> Self {
34 Self::new()
35 }
36}
37
38impl<T> HotkeyManager<T> {
39 pub fn new() -> HotkeyManager<T> {
40 Self {
41 hotkeys: HashMap::new(),
42 paused_ids: Vec::new(),
43 paused: Arc::new(AtomicBool::new(false)),
44 interrupt: Arc::new(AtomicBool::new(false)),
45 callback_results_channel: None,
46 }
47 }
48
49 pub fn register_hotkey(
51 &mut self,
52 trigger_key: VKey,
53 mod_keys: &[VKey],
54 callback: impl Fn() -> T + Send + 'static,
55 ) -> Result<i32, WHKError> {
56 let hotkey = Hotkey::new(trigger_key, mod_keys, callback);
57 let id = hotkey.generate_id();
58
59 if self
61 .hotkeys
62 .values()
63 .any(|vec| vec.iter().any(|hotkey| hotkey.generate_id() == id))
64 {
65 return Err(RegistrationFailed);
66 }
67
68 self.hotkeys
70 .entry(trigger_key.to_vk_code())
71 .or_default()
72 .push(hotkey);
73 Ok(id)
74 }
75
76 pub fn unregister_hotkey(&mut self, hotkey_id: i32) {
78 for vec in self.hotkeys.values_mut() {
79 vec.retain(|hotkey| hotkey.generate_id() != hotkey_id);
80 }
81 self.paused_ids.retain(|id| *id != hotkey_id);
82 }
83
84 pub fn unregister_all(&mut self) {
86 self.hotkeys.clear();
87 self.paused_ids.clear();
88 }
89
90 pub fn register_pause_hotkey(
94 &mut self,
95 trigger_key: VKey,
96 mod_keys: &[VKey],
97 callback: impl Fn() -> T + Send + 'static,
98 ) -> Result<i32, WHKError> {
99 let paused = Arc::clone(&self.paused);
100 let wrapped_callback = move || {
101 let was_paused = paused.load(Ordering::Relaxed);
102 paused.store(!was_paused, Ordering::Relaxed);
103 callback()
104 };
105 let id = self.register_hotkey(trigger_key, mod_keys, wrapped_callback)?;
106 self.paused_ids.push(id);
107 Ok(id)
108 }
109
110 pub fn register_channel(&mut self, channel: Sender<T>) {
112 self.callback_results_channel = Some(channel);
113 }
114
115 pub fn event_loop(&mut self) {
120 let hook = hook::start();
121 while !self.interrupt.load(Ordering::Relaxed) {
122 if let Ok(event) = hook.recv() {
123 let (key_code, state) = match event {
124 KeyboardEvent::KeyDown {
125 vk_code: key_code,
126 keyboard_state: state,
127 } => (key_code, state),
128 _ => continue,
129 };
130
131 let mut found = false;
132 if let Some(hotkeys) = self.hotkeys.get_mut(&key_code) {
133 for hotkey in hotkeys {
134 if self.paused.load(Ordering::Relaxed)
135 && !self.paused_ids.contains(&hotkey.generate_id())
136 {
137 continue;
138 }
139 if hotkey.is_trigger_state(state) {
140 if state.is_down(VKey::LWin.to_vk_code()) {
141 hook.key_action(KeyAction::Replace);
142 } else {
143 hook.key_action(KeyAction::Block);
144 }
145 let result = hotkey.callback();
146 if let Some(callback_result_channel) = &self.callback_results_channel {
147 callback_result_channel.send(result).unwrap();
148 }
149 found = true;
150 break;
151 }
152 }
153 }
154 if !found {
155 hook.key_action(KeyAction::Allow);
156 }
157 }
158 }
159 hook.exit();
160 }
161
162 pub fn interrupt_handle(&self) -> InterruptHandle {
164 InterruptHandle {
165 interrupt: Arc::clone(&self.interrupt),
166 }
167 }
168
169 pub fn pause_handle(&self) -> PauseHandle {
171 PauseHandle {
172 pause: Arc::clone(&self.paused),
173 }
174 }
175}
176
177#[derive(Debug, Clone)]
183pub struct InterruptHandle {
184 interrupt: Arc<AtomicBool>,
185}
186
187impl InterruptHandle {
188 pub fn interrupt(&self) {
193 use crate::hook::{KeyboardEvent, HOOK_EVENT_TX};
194 let dummy_event = KeyboardEvent::KeyDown {
195 vk_code: 0,
196 keyboard_state: KeyboardState::new(),
197 };
198 self.interrupt.store(true, Ordering::Relaxed);
199 let event_tx = HOOK_EVENT_TX.read().unwrap();
200 if let Some(ke_tx) = &*event_tx {
201 ke_tx.send(dummy_event).unwrap();
202 }
203 }
204}
205
206#[derive(Debug, Clone)]
212pub struct PauseHandle {
213 pause: Arc<AtomicBool>,
214}
215
216impl PauseHandle {
217 pub fn toggle(&self) {
222 self.pause
223 .store(!self.pause.load(Ordering::Relaxed), Ordering::Relaxed);
224 }
225
226 pub fn set(&self, state: bool) {
228 self.pause.store(state, Ordering::Relaxed);
229 }
230
231 pub fn is_paused(&self) -> bool {
236 self.pause.load(Ordering::Relaxed)
237 }
238}