windows_hotkeys/
threadsafe.rs1use std::{
2 marker::PhantomData,
3 sync::mpsc::{channel, Receiver, Sender},
4 thread::{spawn, JoinHandle},
5};
6
7use crate::{
8 error::HkError,
9 keys::{ModKey, VKey},
10 singlethreaded, HotkeyId, HotkeyManagerImpl, InterruptHandle,
11};
12
13struct Hotkey<T: 'static> {
14 key: VKey,
15 key_modifiers: Vec<ModKey>,
16 extra_keys: Vec<VKey>,
17 callback: Box<dyn Fn() -> T + Send + 'static>,
18}
19
20enum HkMsg<T: 'static> {
21 Register(Sender<Result<HotkeyId, HkError>>, Hotkey<T>),
22 HandleHotkey(Sender<Option<T>>),
23 Unregister(Sender<Result<(), HkError>>, HotkeyId),
24 UnregisterAll(Sender<Result<(), HkError>>),
25 EventLoop(Sender<()>),
26 InterruptHandle(Sender<InterruptHandle>),
27 Exit(Sender<()>),
28}
29
30pub struct HotkeyManager<T: 'static> {
31 no_repeat: bool,
32 _phantom: PhantomData<T>,
33 snd: Sender<HkMsg<T>>,
34 backend_handle: Option<JoinHandle<()>>,
35}
36
37struct TSHotkeyManagerBackend<T: 'static> {
38 hkm: singlethreaded::HotkeyManager<T>,
39 rec: Receiver<HkMsg<T>>,
40}
41
42impl<T: 'static> HotkeyManager<T> {
43 pub fn set_no_repeat(&mut self, no_repeat: bool) {
53 self.no_repeat = no_repeat;
54 }
55}
56
57impl<T> TSHotkeyManagerBackend<T> {
58 fn new(rec: Receiver<HkMsg<T>>) -> Self {
62 let mut hkm = singlethreaded::HotkeyManager::new();
63 hkm.set_no_repeat(false);
64 Self { hkm, rec }
65 }
66
67 fn backend_loop(&mut self) {
68 while let Ok(msg) = self.rec.recv() {
69 match msg {
70 HkMsg::Register(chan_ret, hk) => {
71 let ret_val = self.hkm.register_extrakeys(
72 hk.key,
73 &hk.key_modifiers,
74 &hk.extra_keys,
75 hk.callback,
76 );
77 chan_ret.send(ret_val).unwrap();
78 }
79 HkMsg::HandleHotkey(chan_ret) => {
80 let ret_val = self.hkm.handle_hotkey();
81 chan_ret.send(ret_val).unwrap();
82 }
83 HkMsg::Unregister(chan_ret, hkid) => {
84 let ret_val = self.hkm.unregister(hkid);
85 chan_ret.send(ret_val).unwrap();
86 }
87 HkMsg::UnregisterAll(chan_ret) => {
88 let ret_val = self.hkm.unregister_all();
89 chan_ret.send(ret_val).unwrap();
90 }
91 HkMsg::EventLoop(chan_ret) => {
92 self.hkm.event_loop();
93 chan_ret.send(()).unwrap();
94 }
95 HkMsg::InterruptHandle(chan_ret) => {
96 let ret_val = self.hkm.interrupt_handle();
97 chan_ret.send(ret_val).unwrap();
98 }
99 HkMsg::Exit(chan_ret) => {
100 chan_ret.send(()).unwrap();
101 return;
102 }
103 }
104 }
105 }
106}
107
108impl<T: 'static + Send> HotkeyManagerImpl<T> for HotkeyManager<T> {
109 fn new() -> Self {
110 let (snd, rec) = channel();
111 let backend_handle = spawn(move || {
112 let mut backend = TSHotkeyManagerBackend::<T>::new(rec);
113 backend.backend_loop();
114 });
115
116 Self {
117 no_repeat: true,
118 _phantom: PhantomData,
119 snd,
120 backend_handle: Some(backend_handle),
121 }
122 }
123
124 fn register(
125 &mut self,
126 key: VKey,
127 key_modifiers: &[ModKey],
128 callback: impl Fn() -> T + Send + 'static,
129 ) -> Result<HotkeyId, HkError> {
130 self.register_extrakeys(key, key_modifiers, &[], callback)
131 }
132
133 fn register_extrakeys(
134 &mut self,
135 key: VKey,
136 key_modifiers: &[ModKey],
137 extra_keys: &[VKey],
138 callback: impl Fn() -> T + Send + 'static,
139 ) -> Result<HotkeyId, HkError> {
140 let ret_ch = channel();
141
142 let mut key_modifiers = key_modifiers.to_vec();
143 if self.no_repeat {
144 key_modifiers.push(ModKey::NoRepeat);
145 }
146
147 let hk = Hotkey {
148 key,
149 key_modifiers,
150 extra_keys: extra_keys.to_vec(),
151 callback: Box::new(callback),
152 };
153 self.snd.send(HkMsg::Register(ret_ch.0, hk)).unwrap();
154 ret_ch.1.recv().unwrap()
155 }
156
157 fn unregister(&mut self, id: HotkeyId) -> Result<(), HkError> {
158 let ret_ch = channel();
159 self.snd.send(HkMsg::Unregister(ret_ch.0, id)).unwrap();
160 ret_ch.1.recv().unwrap()
161 }
162
163 fn unregister_all(&mut self) -> Result<(), HkError> {
164 let ret_ch = channel();
165 self.snd.send(HkMsg::UnregisterAll(ret_ch.0)).unwrap();
166 ret_ch.1.recv().unwrap()
167 }
168
169 fn handle_hotkey(&self) -> Option<T> {
170 let ret_ch = channel();
171 self.snd.send(HkMsg::HandleHotkey(ret_ch.0)).unwrap();
172 ret_ch.1.recv().unwrap()
173 }
174
175 fn event_loop(&self) {
176 let ret_ch = channel();
177 self.snd.send(HkMsg::EventLoop(ret_ch.0)).unwrap();
178 ret_ch.1.recv().unwrap()
179 }
180
181 fn interrupt_handle(&self) -> InterruptHandle {
182 let ret_ch = channel();
183 self.snd.send(HkMsg::InterruptHandle(ret_ch.0)).unwrap();
184 ret_ch.1.recv().unwrap()
185 }
186}
187
188impl<T> Drop for HotkeyManager<T> {
189 fn drop(&mut self) {
190 let ret_ch = channel();
191 self.snd.send(HkMsg::Exit(ret_ch.0)).unwrap();
192 ret_ch.1.recv().unwrap();
193 self.backend_handle.take().unwrap().join().unwrap();
194 }
195}