@@ -5,6 +5,7 @@ use std::error::Error;
55use std:: fmt:: Debug ;
66#[ cfg( not( any( android_platform, ios_platform) ) ) ]
77use std:: num:: NonZeroU32 ;
8+ use std:: sync:: mpsc:: { self , Receiver , Sender } ;
89use std:: sync:: Arc ;
910use std:: { fmt, mem} ;
1011
@@ -25,6 +26,8 @@ use winit::platform::macos::{OptionAsAlt, WindowAttributesExtMacOS, WindowExtMac
2526use winit:: platform:: startup_notify:: {
2627 self , EventLoopExtStartupNotify , WindowAttributesExtStartupNotify , WindowExtStartupNotify ,
2728} ;
29+ #[ cfg( web_platform) ]
30+ use winit:: platform:: web:: { ActiveEventLoopExtWeb , CustomCursorExtWeb , WindowAttributesExtWeb } ;
2831use winit:: window:: {
2932 Cursor , CursorGrabMode , CustomCursor , CustomCursorSource , Fullscreen , Icon , ResizeDirection ,
3033 Theme , Window , WindowId ,
@@ -43,26 +46,34 @@ fn main() -> Result<(), Box<dyn Error>> {
4346 tracing:: init ( ) ;
4447
4548 let event_loop = EventLoop :: new ( ) ?;
46- let _event_loop_proxy = event_loop . create_proxy ( ) ;
49+ let ( sender , receiver ) = mpsc :: channel ( ) ;
4750
4851 // Wire the user event from another thread.
4952 #[ cfg( not( web_platform) ) ]
50- std:: thread:: spawn ( move || {
51- // Wake up the `event_loop` once every second and dispatch a custom event
52- // from a different thread.
53- info ! ( "Starting to send user event every second" ) ;
54- loop {
55- _event_loop_proxy. wake_up ( ) ;
56- std:: thread:: sleep ( std:: time:: Duration :: from_secs ( 1 ) ) ;
53+ std:: thread:: spawn ( {
54+ let event_loop_proxy = event_loop. create_proxy ( ) ;
55+ let sender = sender. clone ( ) ;
56+ move || {
57+ // Wake up the `event_loop` once every second and dispatch a custom event
58+ // from a different thread.
59+ info ! ( "Starting to send user event every second" ) ;
60+ loop {
61+ let _ = sender. send ( Action :: Message ) ;
62+ event_loop_proxy. wake_up ( ) ;
63+ std:: thread:: sleep ( std:: time:: Duration :: from_secs ( 1 ) ) ;
64+ }
5765 }
5866 } ) ;
5967
60- let app = Application :: new ( & event_loop) ;
68+ let app = Application :: new ( & event_loop, receiver , sender ) ;
6169 Ok ( event_loop. run_app ( app) ?)
6270}
6371
6472/// Application state and event handling.
6573struct Application {
74+ /// Trigger actions through proxy wake up.
75+ receiver : Receiver < Action > ,
76+ sender : Sender < Action > ,
6677 /// Custom cursors assets.
6778 custom_cursors : Vec < CustomCursor > ,
6879 /// Application icon.
@@ -76,7 +87,7 @@ struct Application {
7687}
7788
7889impl Application {
79- fn new ( event_loop : & EventLoop ) -> Self {
90+ fn new ( event_loop : & EventLoop , receiver : Receiver < Action > , sender : Sender < Action > ) -> Self {
8091 // SAFETY: we drop the context right before the event loop is stopped, thus making it safe.
8192 #[ cfg( not( any( android_platform, ios_platform) ) ) ]
8293 let context = Some (
@@ -103,6 +114,8 @@ impl Application {
103114 ] ;
104115
105116 Self {
117+ receiver,
118+ sender,
106119 #[ cfg( not( any( android_platform, ios_platform) ) ) ]
107120 context,
108121 custom_cursors,
@@ -138,7 +151,6 @@ impl Application {
138151
139152 #[ cfg( web_platform) ]
140153 {
141- use winit:: platform:: web:: WindowAttributesExtWeb ;
142154 window_attributes = window_attributes. with_append ( true ) ;
143155 }
144156
@@ -160,7 +172,23 @@ impl Application {
160172 Ok ( window_id)
161173 }
162174
163- fn handle_action ( & mut self , event_loop : & ActiveEventLoop , window_id : WindowId , action : Action ) {
175+ fn handle_action ( & mut self , event_loop : & ActiveEventLoop , action : Action ) {
176+ match action {
177+ Action :: PrintHelp => self . print_help ( ) ,
178+ Action :: DumpMonitors => self . dump_monitors ( event_loop) ,
179+ Action :: Message => {
180+ info ! ( "User wake up" ) ;
181+ } ,
182+ _ => unreachable ! ( "Tried to execute invalid action without `WindowId`" ) ,
183+ }
184+ }
185+
186+ fn handle_action_with_window (
187+ & mut self ,
188+ event_loop : & ActiveEventLoop ,
189+ window_id : WindowId ,
190+ action : Action ,
191+ ) {
164192 // let cursor_position = self.cursor_position;
165193 let window = self . windows . get_mut ( & window_id) . unwrap ( ) ;
166194 info ! ( "Executing action: {action:?}" ) ;
@@ -200,7 +228,6 @@ impl Application {
200228 Action :: DragWindow => window. drag_window ( ) ,
201229 Action :: DragResizeWindow => window. drag_resize_window ( ) ,
202230 Action :: ShowWindowMenu => window. show_menu ( ) ,
203- Action :: PrintHelp => self . print_help ( ) ,
204231 #[ cfg( macos_platform) ]
205232 Action :: CycleOptionAsAlt => window. cycle_option_as_alt ( ) ,
206233 Action :: SetTheme ( theme) => {
@@ -217,6 +244,29 @@ impl Application {
217244 }
218245 } ,
219246 Action :: RequestResize => window. swap_dimensions ( ) ,
247+ Action :: DumpMonitors => {
248+ #[ cfg( web_platform) ]
249+ {
250+ let future = event_loop. request_detailed_monitor_permission ( ) ;
251+ let proxy = event_loop. create_proxy ( ) ;
252+ let sender = self . sender . clone ( ) ;
253+ wasm_bindgen_futures:: spawn_local ( async move {
254+ if let Err ( error) = future. await {
255+ error ! ( "{error}" )
256+ }
257+
258+ let _ = sender. send ( Action :: DumpMonitors ) ;
259+ proxy. wake_up ( ) ;
260+ } ) ;
261+ }
262+ #[ cfg( not( web_platform) ) ]
263+ self . dump_monitors ( event_loop) ;
264+ } ,
265+ Action :: Message => {
266+ self . sender . send ( Action :: Message ) . unwrap ( ) ;
267+ event_loop. create_proxy ( ) . wake_up ( ) ;
268+ } ,
269+ _ => self . handle_action ( event_loop, action) ,
220270 }
221271 }
222272
@@ -300,8 +350,10 @@ impl Application {
300350}
301351
302352impl ApplicationHandler for Application {
303- fn proxy_wake_up ( & mut self , _event_loop : & ActiveEventLoop ) {
304- info ! ( "User wake up" ) ;
353+ fn proxy_wake_up ( & mut self , event_loop : & ActiveEventLoop ) {
354+ while let Ok ( action) = self . receiver . try_recv ( ) {
355+ self . handle_action ( event_loop, action)
356+ }
305357 }
306358
307359 fn window_event (
@@ -369,7 +421,7 @@ impl ApplicationHandler for Application {
369421 } ;
370422
371423 if let Some ( action) = action {
372- self . handle_action ( event_loop, window_id, action) ;
424+ self . handle_action_with_window ( event_loop, window_id, action) ;
373425 }
374426 }
375427 } ,
@@ -378,7 +430,7 @@ impl ApplicationHandler for Application {
378430 if let Some ( action) =
379431 state. is_pressed ( ) . then ( || Self :: process_mouse_binding ( button, & mods) ) . flatten ( )
380432 {
381- self . handle_action ( event_loop, window_id, action) ;
433+ self . handle_action_with_window ( event_loop, window_id, action) ;
382434 }
383435 } ,
384436 WindowEvent :: CursorLeft { .. } => {
@@ -703,8 +755,6 @@ impl WindowState {
703755 ) {
704756 use std:: time:: Duration ;
705757
706- use winit:: platform:: web:: CustomCursorExtWeb ;
707-
708758 let cursors = vec ! [
709759 custom_cursors[ 0 ] . clone( ) ,
710760 custom_cursors[ 1 ] . clone( ) ,
@@ -886,6 +936,8 @@ enum Action {
886936 #[ cfg( macos_platform) ]
887937 CreateNewTab ,
888938 RequestResize ,
939+ DumpMonitors ,
940+ Message ,
889941}
890942
891943impl Action {
@@ -920,6 +972,14 @@ impl Action {
920972 #[ cfg( macos_platform) ]
921973 Action :: CreateNewTab => "Create new tab" ,
922974 Action :: RequestResize => "Request a resize" ,
975+ #[ cfg( not( web_platform) ) ]
976+ Action :: DumpMonitors => "Dump monitor information" ,
977+ #[ cfg( web_platform) ]
978+ Action :: DumpMonitors => {
979+ "Request permission to query detailed monitor information and dump monitor \
980+ information"
981+ } ,
982+ Action :: Message => "Prints a message through a user wake up" ,
923983 }
924984 }
925985}
@@ -942,8 +1002,6 @@ fn decode_cursor(bytes: &[u8]) -> CustomCursorSource {
9421002fn url_custom_cursor ( ) -> CustomCursorSource {
9431003 use std:: sync:: atomic:: { AtomicU64 , Ordering } ;
9441004
945- use winit:: platform:: web:: CustomCursorExtWeb ;
946-
9471005 static URL_COUNTER : AtomicU64 = AtomicU64 :: new ( 0 ) ;
9481006
9491007 CustomCursor :: from_url (
@@ -1041,6 +1099,7 @@ const KEY_BINDINGS: &[Binding<&'static str>] = &[
10411099 Binding :: new ( "R" , ModifiersState :: CONTROL , Action :: ToggleResizable ) ,
10421100 Binding :: new ( "R" , ModifiersState :: ALT , Action :: RequestResize ) ,
10431101 // M.
1102+ Binding :: new ( "M" , ModifiersState :: empty ( ) , Action :: DumpMonitors ) ,
10441103 Binding :: new ( "M" , ModifiersState :: CONTROL , Action :: ToggleMaximize ) ,
10451104 Binding :: new ( "M" , ModifiersState :: ALT , Action :: Minimize ) ,
10461105 // N.
@@ -1069,6 +1128,7 @@ const KEY_BINDINGS: &[Binding<&'static str>] = &[
10691128 Binding :: new ( "T" , ModifiersState :: SUPER , Action :: CreateNewTab ) ,
10701129 #[ cfg( macos_platform) ]
10711130 Binding :: new ( "O" , ModifiersState :: CONTROL , Action :: CycleOptionAsAlt ) ,
1131+ Binding :: new ( "S" , ModifiersState :: empty ( ) , Action :: Message ) ,
10721132] ;
10731133
10741134const MOUSE_BINDINGS : & [ Binding < MouseButton > ] = & [
0 commit comments