@@ -8,14 +8,14 @@ use winapi::um::winuser::{
88 AdjustWindowRectEx , CreateWindowExW , DefWindowProcW , DestroyWindow , DispatchMessageW ,
99 GetDpiForWindow , GetMessageW , GetWindowLongPtrW , LoadCursorW , PostMessageW , RegisterClassW ,
1010 ReleaseCapture , SetCapture , SetProcessDpiAwarenessContext , SetTimer , SetWindowLongPtrW ,
11- SetWindowPos , TranslateMessage , UnregisterClassW , CS_OWNDC , GET_XBUTTON_WPARAM , GWLP_USERDATA ,
12- IDC_ARROW , MSG , SWP_NOMOVE , SWP_NOZORDER , WHEEL_DELTA , WM_CHAR , WM_CLOSE , WM_CREATE ,
13- WM_DPICHANGED , WM_INPUTLANGCHANGE , WM_KEYDOWN , WM_KEYUP , WM_LBUTTONDOWN , WM_LBUTTONUP ,
14- WM_MBUTTONDOWN , WM_MBUTTONUP , WM_MOUSEHWHEEL , WM_MOUSEMOVE , WM_MOUSEWHEEL , WM_NCDESTROY ,
15- WM_RBUTTONDOWN , WM_RBUTTONUP , WM_SHOWWINDOW , WM_SIZE , WM_SYSCHAR , WM_SYSKEYDOWN , WM_SYSKEYUP ,
16- WM_TIMER , WM_USER , WM_XBUTTONDOWN , WM_XBUTTONUP , WNDCLASSW , WS_CAPTION , WS_CHILD ,
17- WS_CLIPSIBLINGS , WS_MAXIMIZEBOX , WS_MINIMIZEBOX , WS_POPUPWINDOW , WS_SIZEBOX , WS_VISIBLE ,
18- XBUTTON1 , XBUTTON2 ,
11+ SetWindowPos , TrackMouseEvent , TranslateMessage , UnregisterClassW , CS_OWNDC ,
12+ GET_XBUTTON_WPARAM , GWLP_USERDATA , IDC_ARROW , MSG , SWP_NOMOVE , SWP_NOZORDER , TRACKMOUSEEVENT ,
13+ WHEEL_DELTA , WM_CHAR , WM_CLOSE , WM_CREATE , WM_DPICHANGED , WM_INPUTLANGCHANGE , WM_KEYDOWN ,
14+ WM_KEYUP , WM_LBUTTONDOWN , WM_LBUTTONUP , WM_MBUTTONDOWN , WM_MBUTTONUP , WM_MOUSEHWHEEL ,
15+ WM_MOUSELEAVE , WM_MOUSEMOVE , WM_MOUSEWHEEL , WM_NCDESTROY , WM_RBUTTONDOWN , WM_RBUTTONUP ,
16+ WM_SHOWWINDOW , WM_SIZE , WM_SYSCHAR , WM_SYSKEYDOWN , WM_SYSKEYUP , WM_TIMER , WM_USER ,
17+ WM_XBUTTONDOWN , WM_XBUTTONUP , WNDCLASSW , WS_CAPTION , WS_CHILD , WS_CLIPSIBLINGS , WS_MAXIMIZEBOX ,
18+ WS_MINIMIZEBOX , WS_POPUPWINDOW , WS_SIZEBOX , WS_VISIBLE , XBUTTON1 , XBUTTON2 ,
1919} ;
2020
2121use std:: cell:: { Cell , Ref , RefCell , RefMut } ;
@@ -170,21 +170,47 @@ unsafe fn wnd_proc_inner(
170170 WM_MOUSEMOVE => {
171171 let mut window = crate :: Window :: new ( window_state. create_window ( ) ) ;
172172
173+ let mut mouse_was_outside_window = window_state. mouse_was_outside_window . borrow_mut ( ) ;
174+ if * mouse_was_outside_window {
175+ // this makes Windows track whether the mouse leaves the window.
176+ // When the mouse leaves it results in a `WM_MOUSELEAVE` event.
177+ let mut track_mouse =TRACKMOUSEEVENT {
178+ cbSize : std:: mem:: size_of :: < TRACKMOUSEEVENT > ( ) as u32 ,
179+ dwFlags : winapi:: um:: winuser:: TME_LEAVE ,
180+ hwndTrack : hwnd,
181+ dwHoverTime : winapi:: um:: winuser:: HOVER_DEFAULT ,
182+ } ;
183+ // Couldn't find a good way to track whether the mouse enters,
184+ // but if `WM_MOUSEMOVE` happens, the mouse must have entered.
185+ TrackMouseEvent ( & mut track_mouse) ;
186+ * mouse_was_outside_window = false ;
187+
188+ let enter_event = Event :: Mouse ( MouseEvent :: CursorEntered ) ;
189+ window_state. handler . borrow_mut ( ) . as_mut ( ) . unwrap ( ) . on_event ( & mut window, enter_event) ;
190+ }
191+
173192 let x = ( lparam & 0xFFFF ) as i16 as i32 ;
174193 let y = ( ( lparam >> 16 ) & 0xFFFF ) as i16 as i32 ;
175194
176195 let physical_pos = PhyPoint { x, y } ;
177196 let logical_pos = physical_pos. to_logical ( & window_state. window_info . borrow ( ) ) ;
178- let event = Event :: Mouse ( MouseEvent :: CursorMoved {
197+ let move_event = Event :: Mouse ( MouseEvent :: CursorMoved {
179198 position : logical_pos,
180199 modifiers : window_state
181200 . keyboard_state
182201 . borrow ( )
183202 . get_modifiers_from_mouse_wparam ( wparam) ,
184203 } ) ;
204+ window_state. handler . borrow_mut ( ) . as_mut ( ) . unwrap ( ) . on_event ( & mut window, move_event) ;
205+ Some ( 0 )
206+ }
185207
208+ WM_MOUSELEAVE => {
209+ let mut window = crate :: Window :: new ( window_state. create_window ( ) ) ;
210+ let event = Event :: Mouse ( MouseEvent :: CursorLeft ) ;
186211 window_state. handler . borrow_mut ( ) . as_mut ( ) . unwrap ( ) . on_event ( & mut window, event) ;
187212
213+ * window_state. mouse_was_outside_window . borrow_mut ( ) = true ;
188214 Some ( 0 )
189215 }
190216 WM_MOUSEWHEEL | WM_MOUSEHWHEEL => {
@@ -448,6 +474,7 @@ pub(super) struct WindowState {
448474 _parent_handle : Option < ParentHandle > ,
449475 keyboard_state : RefCell < KeyboardState > ,
450476 mouse_button_counter : Cell < usize > ,
477+ mouse_was_outside_window : RefCell < bool > ,
451478 // Initialized late so the `Window` can hold a reference to this `WindowState`
452479 handler : RefCell < Option < Box < dyn WindowHandler > > > ,
453480 _drop_target : RefCell < Option < Rc < DropTarget > > > ,
@@ -655,6 +682,7 @@ impl Window<'_> {
655682 _parent_handle : parent_handle,
656683 keyboard_state : RefCell :: new ( KeyboardState :: new ( ) ) ,
657684 mouse_button_counter : Cell :: new ( 0 ) ,
685+ mouse_was_outside_window : RefCell :: new ( true ) ,
658686 // The Window refers to this `WindowState`, so this `handler` needs to be
659687 // initialized later
660688 handler : RefCell :: new ( None ) ,
0 commit comments