@@ -5,7 +5,7 @@ use std::sync::mpsc::{Receiver, Sender, SyncSender};
55use std:: thread;
66use std:: time:: { Duration , Instant } ;
77use winit:: application:: ApplicationHandler ;
8- use winit:: dpi:: PhysicalSize ;
8+ use winit:: dpi:: { PhysicalPosition , PhysicalSize } ;
99use winit:: event:: { ButtonSource , ElementState , MouseButton , WindowEvent } ;
1010use winit:: event_loop:: { ActiveEventLoop , ControlFlow } ;
1111use winit:: window:: WindowId ;
@@ -27,6 +27,8 @@ pub(crate) struct App {
2727 window_size : PhysicalSize < u32 > ,
2828 window_maximized : bool ,
2929 window_fullscreen : bool ,
30+ pointer_position : PhysicalPosition < f64 > ,
31+ pointer_lock_position : Option < PhysicalPosition < f64 > > ,
3032 ui_scale : f64 ,
3133 app_event_receiver : Receiver < AppEvent > ,
3234 app_event_scheduler : AppEventScheduler ,
@@ -84,6 +86,8 @@ impl App {
8486 window_size : PhysicalSize { width : 0 , height : 0 } ,
8587 window_maximized : false ,
8688 window_fullscreen : false ,
89+ pointer_position : Default :: default ( ) ,
90+ pointer_lock_position : Default :: default ( ) ,
8791 ui_scale : 1. ,
8892 app_event_receiver,
8993 app_event_scheduler,
@@ -329,6 +333,12 @@ impl App {
329333 window. clipboard_write ( content) ;
330334 }
331335 }
336+ DesktopFrontendMessage :: PointerLock => {
337+ self . pointer_lock_position = Some ( self . pointer_position ) ;
338+ if let Some ( window) = & self . window {
339+ window. start_pointer_lock ( ) ;
340+ }
341+ }
332342 DesktopFrontendMessage :: WindowClose => {
333343 self . app_event_scheduler . schedule ( AppEvent :: CloseWindow ) ;
334344 }
@@ -480,6 +490,26 @@ impl ApplicationHandler for App {
480490 }
481491
482492 fn window_event ( & mut self , event_loop : & dyn ActiveEventLoop , _window_id : WindowId , event : WindowEvent ) {
493+ // Handle pointer lock release
494+ if let Some ( pointer_lock_position) = self . pointer_lock_position
495+ && let WindowEvent :: PointerButton {
496+ state : ElementState :: Released ,
497+ button : ButtonSource :: Mouse ( MouseButton :: Left ) ,
498+ ..
499+ } = event
500+ {
501+ self . pointer_lock_position = None ;
502+ if let Some ( window) = & self . window {
503+ window. end_pointer_lock ( ) ;
504+ }
505+ self . cef_context . handle_window_event ( & WindowEvent :: PointerMoved {
506+ device_id : None ,
507+ position : pointer_lock_position,
508+ primary : true ,
509+ source : winit:: event:: PointerSource :: Mouse ,
510+ } ) ;
511+ }
512+
483513 self . cef_context . handle_window_event ( & event) ;
484514
485515 match event {
@@ -556,13 +586,29 @@ impl ApplicationHandler for App {
556586 self . app_event_scheduler . schedule ( AppEvent :: DesktopWrapperMessage ( message) ) ;
557587 }
558588 }
589+
590+ WindowEvent :: PointerMoved { position, .. } | WindowEvent :: PointerLeft { position : Some ( position) , .. } | WindowEvent :: PointerEntered { position, .. }
591+ if self . pointer_lock_position . is_none ( ) =>
592+ {
593+ self . pointer_position = position;
594+ }
595+
559596 _ => { }
560597 }
561598
562599 // Notify cef of possible input events
563600 self . cef_context . work ( ) ;
564601 }
565602
603+ fn device_event ( & mut self , _event_loop : & dyn ActiveEventLoop , _device_id : Option < winit:: event:: DeviceId > , event : winit:: event:: DeviceEvent ) {
604+ if self . pointer_lock_position . is_some ( )
605+ && let winit:: event:: DeviceEvent :: PointerMotion { delta : ( x, y) } = event
606+ {
607+ let message = DesktopWrapperMessage :: PointerLockMove { x, y } ;
608+ self . app_event_scheduler . schedule ( AppEvent :: DesktopWrapperMessage ( message) ) ;
609+ }
610+ }
611+
566612 fn about_to_wait ( & mut self , event_loop : & dyn ActiveEventLoop ) {
567613 // Set a timeout in case we miss any cef schedule requests
568614 let timeout = Instant :: now ( ) + Duration :: from_millis ( 10 ) ;
0 commit comments