win_hotkey/
thread_safe.rs1use core::fmt;
2use std::marker::PhantomData;
3use std::sync::mpsc::channel;
4use std::sync::mpsc::Receiver;
5use std::sync::mpsc::Sender;
6use std::thread::spawn;
7use std::thread::JoinHandle;
8
9use crate::error::HotkeyError;
10use crate::keys::ModifiersKey;
11use crate::keys::VirtualKey;
12use crate::single_thread;
13use crate::HotkeyId;
14use crate::HotkeyManagerImpl;
15use crate::InterruptHandle;
16
17pub struct Hotkey<T: 'static> {
18 virtual_key: VirtualKey,
19 modifiers_key: Option<Vec<ModifiersKey>>,
20 extra_keys: Option<Vec<VirtualKey>>,
21 callback: Option<Box<dyn Fn() -> T + Send + 'static>>,
22}
23
24impl<T> fmt::Debug for Hotkey<T>
25where
26 T: fmt::Debug, {
28 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
29 f.debug_struct("Hotkey")
30 .field("virtual_key", &self.virtual_key)
31 .field("modifiers_key", &self.modifiers_key)
32 .field("extra_keys", &self.extra_keys)
33 .field(
34 "callback",
35 &self.callback.as_ref().map_or_else(
36 || "None".to_string(),
37 |_| "Some(Fn() -> T + Send)".to_string(),
38 ),
39 ) .finish()
41 }
42}
43
44#[derive(Debug)]
45enum HotkeyMessage<T: 'static> {
46 Register(Sender<Result<HotkeyId, HotkeyError>>, Hotkey<T>),
47 HandleHotkey(Sender<Option<T>>),
48 Unregister(Sender<Result<(), HotkeyError>>, HotkeyId),
49 UnregisterAll(Sender<Result<(), HotkeyError>>),
50 EventLoop(Sender<()>),
51 InterruptHandle(Sender<InterruptHandle>),
52 Exit(Sender<()>),
53}
54
55#[derive(Debug)]
56pub struct HotkeyManager<T: 'static> {
57 no_repeat: bool,
58 _phantom: PhantomData<T>,
59 sender: Sender<HotkeyMessage<T>>,
60 backend_handle: Option<JoinHandle<()>>,
61}
62
63struct TSHotkeyManagerBackend<T: 'static> {
64 hkm: single_thread::HotkeyManager<T>,
65 receiver: Receiver<HotkeyMessage<T>>,
66}
67
68impl<T: 'static> HotkeyManager<T> {
69 pub fn set_no_repeat(&mut self, no_repeat: bool) {
79 self.no_repeat = no_repeat;
80 }
81}
82
83impl<T> TSHotkeyManagerBackend<T> {
84 fn new(receiver: Receiver<HotkeyMessage<T>>) -> Self {
88 let mut hkm = single_thread::HotkeyManager::new();
89 hkm.set_no_repeat(false);
90 Self { hkm, receiver }
91 }
92
93 fn backend_loop(&mut self) {
94 while let Ok(msg) = self.receiver.recv() {
95 match msg {
96 HotkeyMessage::Register(channel, hotkey) => {
97 let return_value = self.hkm.register_extrakeys(
98 hotkey.virtual_key,
99 hotkey.modifiers_key.as_deref(),
100 hotkey.extra_keys.as_deref(),
101 hotkey.callback,
102 );
103 channel.send(return_value).unwrap();
104 }
105 HotkeyMessage::HandleHotkey(channel) => {
106 let return_value = self.hkm.handle_hotkey();
107 channel.send(return_value).unwrap();
108 }
109 HotkeyMessage::Unregister(channel, hotkey_id) => {
110 let return_value = self.hkm.unregister(hotkey_id);
111 channel.send(return_value).unwrap();
112 }
113 HotkeyMessage::UnregisterAll(channel) => {
114 let return_value = self.hkm.unregister_all();
115 channel.send(return_value).unwrap();
116 }
117 HotkeyMessage::EventLoop(channel) => {
118 self.hkm.event_loop();
119 channel.send(()).unwrap();
120 }
121 HotkeyMessage::InterruptHandle(channel) => {
122 let return_value = self.hkm.interrupt_handle();
123 channel.send(return_value).unwrap();
124 }
125 HotkeyMessage::Exit(channel) => {
126 channel.send(()).unwrap();
127 return;
128 }
129 }
130 }
131 }
132}
133
134impl<T: 'static + Send> HotkeyManagerImpl<T> for HotkeyManager<T> {
135 fn new() -> Self {
136 let (sender, receiver) = channel();
137 let backend_handle = spawn(move || {
138 let mut backend = TSHotkeyManagerBackend::<T>::new(receiver);
139 backend.backend_loop();
140 });
141 Self {
142 no_repeat: true,
143 _phantom: PhantomData,
144 sender,
145 backend_handle: Some(backend_handle),
146 }
147 }
148
149 fn register_extrakeys(
150 &mut self,
151 virtual_key: VirtualKey,
152 modifiers_key: Option<&[ModifiersKey]>,
153 extra_keys: Option<&[VirtualKey]>,
154 callback: Option<impl Fn() -> T + Send + 'static>,
155 ) -> Result<HotkeyId, HotkeyError> {
156 let return_channel = channel();
157
158 let mut modifiers_key = modifiers_key.map(|keys| keys.to_vec());
159
160 if self.no_repeat {
161 modifiers_key
162 .get_or_insert_with(Vec::new)
163 .push(ModifiersKey::NoRepeat);
164 }
165
166 let callback_boxed = callback.map(|cb| Box::new(cb) as Box<dyn Fn() -> T + Send>);
167
168 let hotkey = Hotkey {
169 virtual_key,
170 modifiers_key,
171 extra_keys: extra_keys.map(|keys| keys.to_vec()),
172 callback: callback_boxed,
173 };
174 self.sender
175 .send(HotkeyMessage::Register(return_channel.0, hotkey))
176 .unwrap();
177 return_channel.1.recv().unwrap()
178 }
179
180 fn register(
181 &mut self,
182 virtual_key: VirtualKey,
183 modifiers_key: Option<&[ModifiersKey]>,
184 callback: Option<impl Fn() -> T + Send + 'static>,
185 ) -> Result<HotkeyId, HotkeyError> {
186 self.register_extrakeys(virtual_key, modifiers_key, None, callback)
187 }
188
189 fn unregister(&mut self, id: HotkeyId) -> Result<(), HotkeyError> {
190 let return_channel = channel();
191 self.sender
192 .send(HotkeyMessage::Unregister(return_channel.0, id))
193 .unwrap();
194 return_channel.1.recv().unwrap()
195 }
196
197 fn unregister_all(&mut self) -> Result<(), HotkeyError> {
198 let return_channel = channel();
199 self.sender
200 .send(HotkeyMessage::UnregisterAll(return_channel.0))
201 .unwrap();
202 return_channel.1.recv().unwrap()
203 }
204
205 fn handle_hotkey(&self) -> Option<T> {
206 let return_channel = channel();
207 self.sender
208 .send(HotkeyMessage::HandleHotkey(return_channel.0))
209 .unwrap();
210 return_channel.1.recv().unwrap()
211 }
212
213 fn event_loop(&self) {
214 let return_channel = channel();
215 self.sender
216 .send(HotkeyMessage::EventLoop(return_channel.0))
217 .unwrap();
218 return_channel.1.recv().unwrap()
219 }
220
221 fn interrupt_handle(&self) -> InterruptHandle {
222 let return_channel = channel();
223 self.sender
224 .send(HotkeyMessage::InterruptHandle(return_channel.0))
225 .unwrap();
226 return_channel.1.recv().unwrap()
227 }
228}
229
230impl<T> Drop for HotkeyManager<T> {
231 fn drop(&mut self) {
232 let return_channel = channel();
233 self.sender
234 .send(HotkeyMessage::Exit(return_channel.0))
235 .unwrap();
236 return_channel.1.recv().unwrap();
237 self.backend_handle.take().unwrap().join().unwrap();
238 }
239}