@@ -13,8 +13,8 @@ use tauri_runtime::{
1313 dpi:: { LogicalPosition , LogicalSize , PhysicalPosition , PhysicalSize , Position , Size } ,
1414 DetachedWindow , PendingWindow , WindowEvent ,
1515 } ,
16- Dispatch , Error , GlobalShortcutManager , Icon , Params , Result , RunEvent , RunIteration , Runtime ,
17- RuntimeHandle , UserAttentionType ,
16+ ClipboardManager , Dispatch , Error , GlobalShortcutManager , Icon , Params , Result , RunEvent ,
17+ RunIteration , Runtime , RuntimeHandle , UserAttentionType ,
1818} ;
1919
2020#[ cfg( feature = "menu" ) ]
@@ -33,6 +33,7 @@ use uuid::Uuid;
3333use wry:: {
3434 application:: {
3535 accelerator:: { Accelerator , AcceleratorId } ,
36+ clipboard:: Clipboard ,
3637 dpi:: {
3738 LogicalPosition as WryLogicalPosition , LogicalSize as WryLogicalSize ,
3839 PhysicalPosition as WryPhysicalPosition , PhysicalSize as WryPhysicalSize ,
@@ -97,7 +98,7 @@ macro_rules! dispatcher_getter {
9798 } } ;
9899}
99100
100- macro_rules! shortcut_getter {
101+ macro_rules! getter {
101102 ( $self: ident, $rx: expr, $message: expr) => { {
102103 if current_thread( ) . id( ) == $self. context. main_thread_id
103104 && !$self. context. is_event_loop_running. load( Ordering :: Relaxed )
@@ -113,30 +114,30 @@ macro_rules! shortcut_getter {
113114 } } ;
114115}
115116
116- #[ derive( Debug , Clone ) ]
117- struct GlobalShortcutWrapper ( GlobalShortcut ) ;
118-
119- unsafe impl Send for GlobalShortcutWrapper { }
120-
121117#[ derive( Clone ) ]
122- struct GlobalShortcutManagerContext {
118+ struct EventLoopContext {
123119 main_thread_id : ThreadId ,
124120 is_event_loop_running : Arc < AtomicBool > ,
125121 proxy : EventLoopProxy < Message > ,
126122}
127123
124+ #[ derive( Debug , Clone ) ]
125+ struct GlobalShortcutWrapper ( GlobalShortcut ) ;
126+
127+ unsafe impl Send for GlobalShortcutWrapper { }
128+
128129/// Wrapper around [`WryShortcutManager`].
129130#[ derive( Clone ) ]
130131pub struct GlobalShortcutManagerHandle {
131- context : GlobalShortcutManagerContext ,
132+ context : EventLoopContext ,
132133 shortcuts : HashMap < String , ( AcceleratorId , GlobalShortcutWrapper ) > ,
133134 listeners : GlobalShortcutListeners ,
134135}
135136
136137impl GlobalShortcutManager for GlobalShortcutManagerHandle {
137138 fn is_registered ( & self , accelerator : & str ) -> Result < bool > {
138139 let ( tx, rx) = channel ( ) ;
139- Ok ( shortcut_getter ! (
140+ Ok ( getter ! (
140141 self ,
141142 rx,
142143 Message :: GlobalShortcut ( GlobalShortcutMessage :: IsRegistered (
@@ -150,7 +151,7 @@ impl GlobalShortcutManager for GlobalShortcutManagerHandle {
150151 let wry_accelerator: Accelerator = accelerator. parse ( ) . expect ( "invalid accelerator" ) ;
151152 let id = wry_accelerator. clone ( ) . id ( ) ;
152153 let ( tx, rx) = channel ( ) ;
153- let shortcut = shortcut_getter ! (
154+ let shortcut = getter ! (
154155 self ,
155156 rx,
156157 Message :: GlobalShortcut ( GlobalShortcutMessage :: Register ( wry_accelerator, tx) )
@@ -164,7 +165,7 @@ impl GlobalShortcutManager for GlobalShortcutManagerHandle {
164165
165166 fn unregister_all ( & mut self ) -> Result < ( ) > {
166167 let ( tx, rx) = channel ( ) ;
167- shortcut_getter ! (
168+ getter ! (
168169 self ,
169170 rx,
170171 Message :: GlobalShortcut ( GlobalShortcutMessage :: UnregisterAll ( tx) )
@@ -177,20 +178,43 @@ impl GlobalShortcutManager for GlobalShortcutManagerHandle {
177178 fn unregister ( & mut self , accelerator : & str ) -> Result < ( ) > {
178179 if let Some ( ( accelerator_id, shortcut) ) = self . shortcuts . remove ( accelerator) {
179180 let ( tx, rx) = channel ( ) ;
180- shortcut_getter ! (
181+ getter ! (
181182 self ,
182183 rx,
183- Message :: GlobalShortcut ( GlobalShortcutMessage :: Unregister (
184- GlobalShortcutWrapper ( shortcut. 0 ) ,
185- tx
186- ) )
184+ Message :: GlobalShortcut ( GlobalShortcutMessage :: Unregister ( shortcut, tx) )
187185 ) ?;
188186 self . listeners . lock ( ) . unwrap ( ) . remove ( & accelerator_id) ;
189187 }
190188 Ok ( ( ) )
191189 }
192190}
193191
192+ #[ derive( Clone ) ]
193+ pub struct ClipboardManagerWrapper {
194+ context : EventLoopContext ,
195+ }
196+
197+ impl ClipboardManager for ClipboardManagerWrapper {
198+ fn read_text ( & self ) -> Result < Option < String > > {
199+ let ( tx, rx) = channel ( ) ;
200+ Ok ( getter ! (
201+ self ,
202+ rx,
203+ Message :: Clipboard ( ClipboardMessage :: ReadText ( tx) )
204+ ) )
205+ }
206+
207+ fn write_text < T : Into < String > > ( & mut self , text : T ) -> Result < ( ) > {
208+ let ( tx, rx) = channel ( ) ;
209+ getter ! (
210+ self ,
211+ rx,
212+ Message :: Clipboard ( ClipboardMessage :: WriteText ( text. into( ) , tx) )
213+ ) ;
214+ Ok ( ( ) )
215+ }
216+ }
217+
194218/// Wrapper around a [`wry::application::window::Icon`] that can be created from an [`Icon`].
195219pub struct WryIcon ( WindowIcon ) ;
196220
@@ -650,6 +674,12 @@ pub(crate) enum GlobalShortcutMessage {
650674 UnregisterAll ( Sender < Result < ( ) > > ) ,
651675}
652676
677+ #[ derive( Clone ) ]
678+ pub ( crate ) enum ClipboardMessage {
679+ WriteText ( String , Sender < ( ) > ) ,
680+ ReadText ( Sender < Option < String > > ) ,
681+ }
682+
653683#[ derive( Clone ) ]
654684pub ( crate ) enum Message {
655685 Task ( MainTask ) ,
@@ -659,6 +689,7 @@ pub(crate) enum Message {
659689 Tray ( TrayMessage ) ,
660690 CreateWebview ( Arc < Mutex < Option < CreateWebviewHandler > > > , Sender < WindowId > ) ,
661691 GlobalShortcut ( GlobalShortcutMessage ) ,
692+ Clipboard ( ClipboardMessage ) ,
662693}
663694
664695#[ derive( Clone ) ]
@@ -1099,6 +1130,8 @@ pub struct Wry {
10991130 main_thread_id : ThreadId ,
11001131 global_shortcut_manager : Arc < Mutex < WryShortcutManager > > ,
11011132 global_shortcut_manager_handle : GlobalShortcutManagerHandle ,
1133+ clipboard_manager : Arc < Mutex < Clipboard > > ,
1134+ clipboard_manager_handle : ClipboardManagerWrapper ,
11021135 is_event_loop_running : Arc < AtomicBool > ,
11031136 event_loop : EventLoop < Message > ,
11041137 webviews : Arc < Mutex < HashMap < WindowId , WebviewWrapper > > > ,
@@ -1159,28 +1192,39 @@ impl Runtime for Wry {
11591192 type Dispatcher = WryDispatcher ;
11601193 type Handle = WryHandle ;
11611194 type GlobalShortcutManager = GlobalShortcutManagerHandle ;
1195+ type ClipboardManager = ClipboardManagerWrapper ;
11621196 #[ cfg( feature = "system-tray" ) ]
11631197 type TrayHandler = SystemTrayHandle ;
11641198
11651199 fn new ( ) -> Result < Self > {
11661200 let event_loop = EventLoop :: < Message > :: with_user_event ( ) ;
1167- let global_shortcut_manager = WryShortcutManager :: new ( & event_loop) ;
1168- let global_shortcut_listeners = GlobalShortcutListeners :: default ( ) ;
11691201 let proxy = event_loop. create_proxy ( ) ;
11701202 let main_thread_id = current_thread ( ) . id ( ) ;
11711203 let is_event_loop_running = Arc :: new ( AtomicBool :: default ( ) ) ;
1204+
1205+ let event_loop_context = EventLoopContext {
1206+ main_thread_id,
1207+ is_event_loop_running : is_event_loop_running. clone ( ) ,
1208+ proxy,
1209+ } ;
1210+
1211+ let global_shortcut_manager = WryShortcutManager :: new ( & event_loop) ;
1212+ let global_shortcut_listeners = GlobalShortcutListeners :: default ( ) ;
1213+ let clipboard_manager = Clipboard :: new ( ) ;
1214+ let clipboard_manager_handle = ClipboardManagerWrapper {
1215+ context : event_loop_context. clone ( ) ,
1216+ } ;
1217+
11721218 Ok ( Self {
11731219 main_thread_id,
11741220 global_shortcut_manager : Arc :: new ( Mutex :: new ( global_shortcut_manager) ) ,
11751221 global_shortcut_manager_handle : GlobalShortcutManagerHandle {
1176- context : GlobalShortcutManagerContext {
1177- main_thread_id,
1178- is_event_loop_running : is_event_loop_running. clone ( ) ,
1179- proxy,
1180- } ,
1222+ context : event_loop_context,
11811223 shortcuts : Default :: default ( ) ,
11821224 listeners : global_shortcut_listeners,
11831225 } ,
1226+ clipboard_manager : Arc :: new ( Mutex :: new ( clipboard_manager) ) ,
1227+ clipboard_manager_handle,
11841228 is_event_loop_running,
11851229 event_loop,
11861230 webviews : Default :: default ( ) ,
@@ -1209,6 +1253,10 @@ impl Runtime for Wry {
12091253 self . global_shortcut_manager_handle . clone ( )
12101254 }
12111255
1256+ fn clipboard_manager ( & self ) -> Self :: ClipboardManager {
1257+ self . clipboard_manager_handle . clone ( )
1258+ }
1259+
12121260 fn create_window < P : Params < Runtime = Self > > (
12131261 & self ,
12141262 pending : PendingWindow < P > ,
@@ -1298,6 +1346,7 @@ impl Runtime for Wry {
12981346 let tray_context = self . tray_context . clone ( ) ;
12991347 let global_shortcut_manager = self . global_shortcut_manager . clone ( ) ;
13001348 let global_shortcut_manager_handle = self . global_shortcut_manager_handle . clone ( ) ;
1349+ let clipboard_manager = self . clipboard_manager . clone ( ) ;
13011350
13021351 let mut iteration = RunIteration :: default ( ) ;
13031352
@@ -1318,6 +1367,7 @@ impl Runtime for Wry {
13181367 window_event_listeners : window_event_listeners. clone ( ) ,
13191368 global_shortcut_manager : global_shortcut_manager. clone ( ) ,
13201369 global_shortcut_manager_handle : global_shortcut_manager_handle. clone ( ) ,
1370+ clipboard_manager : clipboard_manager. clone ( ) ,
13211371 #[ cfg( feature = "menu" ) ]
13221372 menu_event_listeners : menu_event_listeners. clone ( ) ,
13231373 #[ cfg( feature = "system-tray" ) ]
@@ -1340,6 +1390,7 @@ impl Runtime for Wry {
13401390 let tray_context = self . tray_context ;
13411391 let global_shortcut_manager = self . global_shortcut_manager . clone ( ) ;
13421392 let global_shortcut_manager_handle = self . global_shortcut_manager_handle . clone ( ) ;
1393+ let clipboard_manager = self . clipboard_manager . clone ( ) ;
13431394
13441395 self . event_loop . run ( move |event, event_loop, control_flow| {
13451396 handle_event_loop (
@@ -1352,6 +1403,7 @@ impl Runtime for Wry {
13521403 window_event_listeners : window_event_listeners. clone ( ) ,
13531404 global_shortcut_manager : global_shortcut_manager. clone ( ) ,
13541405 global_shortcut_manager_handle : global_shortcut_manager_handle. clone ( ) ,
1406+ clipboard_manager : clipboard_manager. clone ( ) ,
13551407 #[ cfg( feature = "menu" ) ]
13561408 menu_event_listeners : menu_event_listeners. clone ( ) ,
13571409 #[ cfg( feature = "system-tray" ) ]
@@ -1368,6 +1420,7 @@ struct EventLoopIterationContext<'a> {
13681420 window_event_listeners : WindowEventListeners ,
13691421 global_shortcut_manager : Arc < Mutex < WryShortcutManager > > ,
13701422 global_shortcut_manager_handle : GlobalShortcutManagerHandle ,
1423+ clipboard_manager : Arc < Mutex < Clipboard > > ,
13711424 #[ cfg( feature = "menu" ) ]
13721425 menu_event_listeners : MenuEventListeners ,
13731426 #[ cfg( feature = "system-tray" ) ]
@@ -1386,6 +1439,7 @@ fn handle_event_loop(
13861439 window_event_listeners,
13871440 global_shortcut_manager,
13881441 global_shortcut_manager_handle,
1442+ clipboard_manager,
13891443 #[ cfg( feature = "menu" ) ]
13901444 menu_event_listeners,
13911445 #[ cfg ( feature = "system-tray" ) ]
@@ -1689,6 +1743,15 @@ fn handle_event_loop(
16891743 )
16901744 . unwrap ( ) ,
16911745 } ,
1746+ Message :: Clipboard ( message) => match message {
1747+ ClipboardMessage :: WriteText ( text, tx) => {
1748+ clipboard_manager. lock ( ) . unwrap ( ) . write_text ( text) ;
1749+ tx. send ( ( ) ) . unwrap ( ) ;
1750+ }
1751+ ClipboardMessage :: ReadText ( tx) => tx
1752+ . send ( clipboard_manager. lock ( ) . unwrap ( ) . read_text ( ) )
1753+ . unwrap ( ) ,
1754+ } ,
16921755 } ,
16931756 _ => ( ) ,
16941757 }
0 commit comments