@@ -20,11 +20,11 @@ use std::{
2020 sync:: { Arc , Mutex } ,
2121} ;
2222
23+ use global_hotkey:: GlobalHotKeyEvent ;
2324pub use global_hotkey:: {
2425 hotkey:: { Code , HotKey as Shortcut , Modifiers } ,
2526 GlobalHotKeyEvent as ShortcutEvent , HotKeyState as ShortcutState ,
2627} ;
27- use global_hotkey:: { GlobalHotKeyEvent , GlobalHotKeyManager } ;
2828use serde:: Serialize ;
2929use tauri:: {
3030 ipc:: Channel ,
@@ -60,13 +60,33 @@ struct RegisteredShortcut<R: Runtime> {
6060 handler : Option < Arc < HandlerFn < R > > > ,
6161}
6262
63+ struct GlobalHotKeyManager ( global_hotkey:: GlobalHotKeyManager ) ;
64+
65+ /// SAFETY: we ensure it is run on main thread only
66+ unsafe impl Send for GlobalHotKeyManager { }
67+ /// SAFETY: we ensure it is run on main thread only
68+ unsafe impl Sync for GlobalHotKeyManager { }
69+
6370pub struct GlobalShortcut < R : Runtime > {
6471 #[ allow( dead_code) ]
6572 app : AppHandle < R > ,
66- manager : GlobalHotKeyManager ,
73+ manager : Arc < GlobalHotKeyManager > ,
6774 shortcuts : Arc < Mutex < HashMap < HotKeyId , RegisteredShortcut < R > > > > ,
6875}
6976
77+ macro_rules! run_main_thread {
78+ ( $handle: expr, $manager: expr, |$m: ident| $ex: expr) => { {
79+ let ( tx, rx) = std:: sync:: mpsc:: channel( ) ;
80+ let manager = $manager. clone( ) ;
81+ let task = move || {
82+ let f = |$m: & GlobalHotKeyManager | $ex;
83+ let _ = tx. send( f( & * manager) ) ;
84+ } ;
85+ $handle. run_on_main_thread( task) ?;
86+ rx. recv( ) ?
87+ } } ;
88+ }
89+
7090impl < R : Runtime > GlobalShortcut < R > {
7191 fn register_internal < F : Fn ( & AppHandle < R > , & Shortcut , ShortcutEvent ) + Send + Sync + ' static > (
7292 & self ,
@@ -75,8 +95,7 @@ impl<R: Runtime> GlobalShortcut<R> {
7595 ) -> Result < ( ) > {
7696 let id = shortcut. id ( ) ;
7797 let handler = handler. map ( |h| Arc :: new ( Box :: new ( h) as HandlerFn < R > ) ) ;
78-
79- self . manager . register ( shortcut) ?;
98+ run_main_thread ! ( self . app, self . manager, |m| m. 0 . register( shortcut) ) ?;
8099 self . shortcuts
81100 . lock ( )
82101 . unwrap ( )
@@ -95,7 +114,7 @@ impl<R: Runtime> GlobalShortcut<R> {
95114
96115 let mut shortcuts = self . shortcuts . lock ( ) . unwrap ( ) ;
97116 for shortcut in hotkeys {
98- self . manager . register ( shortcut) ?;
117+ run_main_thread ! ( self . app , self . manager, |m| m . 0 . register( shortcut) ) ?;
99118 shortcuts. insert (
100119 shortcut. id ( ) ,
101120 RegisteredShortcut {
@@ -167,7 +186,7 @@ impl<R: Runtime> GlobalShortcut<R> {
167186 S :: Error : std:: error:: Error ,
168187 {
169188 let shortcut = try_into_shortcut ( shortcut) ?;
170- self . manager . unregister ( shortcut) ?;
189+ run_main_thread ! ( self . app , self . manager, |m| m . 0 . unregister( shortcut) ) ?;
171190 self . shortcuts . lock ( ) . unwrap ( ) . remove ( & shortcut. id ( ) ) ;
172191 Ok ( ( ) )
173192 }
@@ -180,15 +199,19 @@ impl<R: Runtime> GlobalShortcut<R> {
180199 where
181200 T :: Error : std:: error:: Error ,
182201 {
183- let mut s = Vec :: new ( ) ;
202+ let mut mapped_shortcuts = Vec :: new ( ) ;
184203 for shortcut in shortcuts {
185- s . push ( try_into_shortcut ( shortcut) ?) ;
204+ mapped_shortcuts . push ( try_into_shortcut ( shortcut) ?) ;
186205 }
187206
188- self . manager . unregister_all ( & s) ?;
207+ {
208+ let mapped_shortcuts = mapped_shortcuts. clone ( ) ;
209+ #[ rustfmt:: skip]
210+ run_main_thread ! ( self . app, self . manager, |m| m. 0 . unregister_all( & mapped_shortcuts) ) ?;
211+ }
189212
190213 let mut shortcuts = self . shortcuts . lock ( ) . unwrap ( ) ;
191- for s in s {
214+ for s in mapped_shortcuts {
192215 shortcuts. remove ( & s. id ( ) ) ;
193216 }
194217
@@ -200,9 +223,9 @@ impl<R: Runtime> GlobalShortcut<R> {
200223 let mut shortcuts = self . shortcuts . lock ( ) . unwrap ( ) ;
201224 let hotkeys = std:: mem:: take ( & mut * shortcuts) ;
202225 let hotkeys = hotkeys. values ( ) . map ( |s| s. shortcut ) . collect :: < Vec < _ > > ( ) ;
203- self . manager
204- . unregister_all ( hotkeys. as_slice ( ) )
205- . map_err ( Into :: into)
226+ # [ rustfmt :: skip ]
227+ let res = run_main_thread ! ( self . app , self . manager , |m| m . 0 . unregister_all( hotkeys. as_slice( ) ) ) ;
228+ res . map_err ( Into :: into)
206229 }
207230
208231 /// Determines whether the given shortcut is registered by this application or not.
@@ -375,7 +398,7 @@ impl<R: Runtime> Builder<R> {
375398 is_registered,
376399 ] )
377400 . setup ( move |app, _api| {
378- let manager = GlobalHotKeyManager :: new ( ) ?;
401+ let manager = global_hotkey :: GlobalHotKeyManager :: new ( ) ?;
379402 let mut store = HashMap :: < HotKeyId , RegisteredShortcut < R > > :: new ( ) ;
380403 for shortcut in shortcuts {
381404 manager. register ( shortcut) ?;
@@ -405,7 +428,7 @@ impl<R: Runtime> Builder<R> {
405428
406429 app. manage ( GlobalShortcut {
407430 app : app. clone ( ) ,
408- manager,
431+ manager : Arc :: new ( GlobalHotKeyManager ( manager ) ) ,
409432 shortcuts,
410433 } ) ;
411434 Ok ( ( ) )
0 commit comments