diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ad58ed1..fa740e80 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Unreleased +- Implement `MonitorId::get_dimensions` for Android. +- Fixed windows not receiving mouse events when click-dragging the mouse outside the client area of a window, on Windows platforms. + +======= # Version 0.11.0 (2018-02-09) - Implement `MonitorId::get_dimensions` for Android. diff --git a/src/platform/windows/events_loop.rs b/src/platform/windows/events_loop.rs index 4eb9290d..1a62c6ab 100644 --- a/src/platform/windows/events_loop.rs +++ b/src/platform/windows/events_loop.rs @@ -102,7 +102,8 @@ impl EventsLoop { *context_stash.borrow_mut() = Some(ThreadLocalData { sender: tx, windows: HashMap::with_capacity(4), - win32_block_loop: win32_block_loop_child + win32_block_loop: win32_block_loop_child, + mouse_buttons_down: 0 }); }); @@ -296,7 +297,8 @@ thread_local!(static CONTEXT_STASH: RefCell> = RefCell:: struct ThreadLocalData { sender: mpsc::Sender, windows: HashMap>>, - win32_block_loop: Arc<(Mutex, Condvar)> + win32_block_loop: Arc<(Mutex, Condvar)>, + mouse_buttons_down: u32 } // Utility function that dispatches an event on the current thread. @@ -308,6 +310,32 @@ fn send_event(event: Event) { }); } +/// Capture mouse input, allowing `window` to receive mouse events when the cursor is outside of +/// the window. +unsafe fn capture_mouse(window: HWND) { + CONTEXT_STASH.with(|context_stash| { + let mut context_stash = context_stash.borrow_mut(); + if let Some(context_stash) = context_stash.as_mut() { + context_stash.mouse_buttons_down += 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() { + CONTEXT_STASH.with(|context_stash| { + let mut context_stash = context_stash.borrow_mut(); + if let Some(context_stash) = context_stash.as_mut() { + context_stash.mouse_buttons_down = context_stash.mouse_buttons_down.saturating_sub(1); + if context_stash.mouse_buttons_down == 0 { + winuser::ReleaseCapture(); + } + } + }); +} + /// Any window whose callback is configured to this function will have its events propagated /// through the events loop of the thread the window was created in. // @@ -550,6 +578,9 @@ pub unsafe extern "system" fn callback(window: HWND, msg: UINT, use events::WindowEvent::MouseInput; use events::MouseButton::Left; use events::ElementState::Pressed; + + capture_mouse(window); + send_event(Event::WindowEvent { window_id: SuperWindowId(WindowId(window)), event: MouseInput { device_id: DEVICE_ID, state: Pressed, button: Left, modifiers: event::get_key_mods() } @@ -561,6 +592,9 @@ pub unsafe extern "system" fn callback(window: HWND, msg: UINT, use events::WindowEvent::MouseInput; use events::MouseButton::Left; use events::ElementState::Released; + + release_mouse(); + send_event(Event::WindowEvent { window_id: SuperWindowId(WindowId(window)), event: MouseInput { device_id: DEVICE_ID, state: Released, button: Left, modifiers: event::get_key_mods() } @@ -572,6 +606,9 @@ pub unsafe extern "system" fn callback(window: HWND, msg: UINT, use events::WindowEvent::MouseInput; use events::MouseButton::Right; use events::ElementState::Pressed; + + capture_mouse(window); + send_event(Event::WindowEvent { window_id: SuperWindowId(WindowId(window)), event: MouseInput { device_id: DEVICE_ID, state: Pressed, button: Right, modifiers: event::get_key_mods() } @@ -583,6 +620,9 @@ pub unsafe extern "system" fn callback(window: HWND, msg: UINT, use events::WindowEvent::MouseInput; use events::MouseButton::Right; use events::ElementState::Released; + + release_mouse(); + send_event(Event::WindowEvent { window_id: SuperWindowId(WindowId(window)), event: MouseInput { device_id: DEVICE_ID, state: Released, button: Right, modifiers: event::get_key_mods() } @@ -594,6 +634,9 @@ pub unsafe extern "system" fn callback(window: HWND, msg: UINT, use events::WindowEvent::MouseInput; use events::MouseButton::Middle; use events::ElementState::Pressed; + + capture_mouse(window); + send_event(Event::WindowEvent { window_id: SuperWindowId(WindowId(window)), event: MouseInput { device_id: DEVICE_ID, state: Pressed, button: Middle, modifiers: event::get_key_mods() } @@ -605,6 +648,9 @@ pub unsafe extern "system" fn callback(window: HWND, msg: UINT, use events::WindowEvent::MouseInput; use events::MouseButton::Middle; use events::ElementState::Released; + + release_mouse(); + send_event(Event::WindowEvent { window_id: SuperWindowId(WindowId(window)), event: MouseInput { device_id: DEVICE_ID, state: Released, button: Middle, modifiers: event::get_key_mods() } @@ -617,6 +663,9 @@ pub unsafe extern "system" fn callback(window: HWND, msg: UINT, use events::MouseButton::Other; use events::ElementState::Pressed; let xbutton = winuser::GET_XBUTTON_WPARAM(wparam); + + capture_mouse(window); + send_event(Event::WindowEvent { window_id: SuperWindowId(WindowId(window)), event: MouseInput { device_id: DEVICE_ID, state: Pressed, button: Other(xbutton as u8), modifiers: event::get_key_mods() } @@ -629,6 +678,9 @@ pub unsafe extern "system" fn callback(window: HWND, msg: UINT, use events::MouseButton::Other; use events::ElementState::Released; let xbutton = winuser::GET_XBUTTON_WPARAM(wparam); + + release_mouse(); + send_event(Event::WindowEvent { window_id: SuperWindowId(WindowId(window)), event: MouseInput { device_id: DEVICE_ID, state: Released, button: Other(xbutton as u8), modifiers: event::get_key_mods() }