From 932cbe40bff9f034d7aaad590470d44880fa14c9 Mon Sep 17 00:00:00 2001 From: Samuel Date: Tue, 15 Dec 2020 03:31:13 -0300 Subject: [PATCH] On Windows, fix bug causing mouse capture to not be released. (#1797) --- CHANGELOG.md | 1 + src/platform_impl/windows/event_loop.rs | 24 +++++++++++++++-------- src/platform_impl/windows/window_state.rs | 4 ++-- 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 15880942..602c209d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ # Unreleased +- On Windows, fix bug causing mouse capture to not be released. - On Windows, fix fullscreen not preserving minimized/maximized state. # 0.24.0 (2020-12-09) diff --git a/src/platform_impl/windows/event_loop.rs b/src/platform_impl/windows/event_loop.rs index 3ccd55c1..2a249585 100644 --- a/src/platform_impl/windows/event_loop.rs +++ b/src/platform_impl/windows/event_loop.rs @@ -619,15 +619,17 @@ fn subclass_event_target_window( /// Capture mouse input, allowing `window` to receive mouse events when the cursor is outside of /// the window. unsafe fn capture_mouse(window: HWND, window_state: &mut WindowState) { - window_state.mouse.buttons_down += 1; + window_state.mouse.capture_count += 1; winuser::SetCapture(window); } /// Release mouse input, stopping windows on this thread from receiving mouse input when the cursor /// is outside the window. -unsafe fn release_mouse(window_state: &mut WindowState) { - window_state.mouse.buttons_down = window_state.mouse.buttons_down.saturating_sub(1); - if window_state.mouse.buttons_down == 0 { +unsafe fn release_mouse(mut window_state: parking_lot::MutexGuard<'_, WindowState>) { + window_state.mouse.capture_count = window_state.mouse.capture_count.saturating_sub(1); + if window_state.mouse.capture_count == 0 { + // ReleaseCapture() causes a WM_CAPTURECHANGED where we lock the window_state. + drop(window_state); winuser::ReleaseCapture(); } } @@ -1192,7 +1194,7 @@ unsafe extern "system" fn public_window_callback( ElementState::Released, MouseButton::Left, WindowEvent::MouseInput, }; - release_mouse(&mut *subclass_input.window_state.lock()); + release_mouse(subclass_input.window_state.lock()); update_modifiers(window, subclass_input); @@ -1234,7 +1236,7 @@ unsafe extern "system" fn public_window_callback( ElementState::Released, MouseButton::Right, WindowEvent::MouseInput, }; - release_mouse(&mut *subclass_input.window_state.lock()); + release_mouse(subclass_input.window_state.lock()); update_modifiers(window, subclass_input); @@ -1276,7 +1278,7 @@ unsafe extern "system" fn public_window_callback( ElementState::Released, MouseButton::Middle, WindowEvent::MouseInput, }; - release_mouse(&mut *subclass_input.window_state.lock()); + release_mouse(subclass_input.window_state.lock()); update_modifiers(window, subclass_input); @@ -1320,7 +1322,7 @@ unsafe extern "system" fn public_window_callback( }; let xbutton = winuser::GET_XBUTTON_WPARAM(wparam); - release_mouse(&mut *subclass_input.window_state.lock()); + release_mouse(subclass_input.window_state.lock()); update_modifiers(window, subclass_input); @@ -1336,6 +1338,12 @@ unsafe extern "system" fn public_window_callback( 0 } + winuser::WM_CAPTURECHANGED => { + // window lost mouse capture + subclass_input.window_state.lock().mouse.capture_count = 0; + 0 + } + winuser::WM_TOUCH => { let pcount = LOWORD(wparam as DWORD) as usize; let mut inputs = Vec::with_capacity(pcount); diff --git a/src/platform_impl/windows/window_state.rs b/src/platform_impl/windows/window_state.rs index d9b43f06..70c5330a 100644 --- a/src/platform_impl/windows/window_state.rs +++ b/src/platform_impl/windows/window_state.rs @@ -45,7 +45,7 @@ pub struct SavedWindow { #[derive(Clone)] pub struct MouseProperties { pub cursor: CursorIcon, - pub buttons_down: u32, + pub capture_count: u32, cursor_flags: CursorFlags, pub last_position: Option>, } @@ -102,7 +102,7 @@ impl WindowState { WindowState { mouse: MouseProperties { cursor: CursorIcon::default(), - buttons_down: 0, + capture_count: 0, cursor_flags: CursorFlags::empty(), last_position: None, },