diff --git a/CHANGELOG.md b/CHANGELOG.md index cf486c07..edd90848 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ And please only add new entries to the top of this list, right below the `# Unre - On macOS, fixed touch phase reporting when scrolling. - On X11, fix min, max and resize increment hints not persisting for resizable windows (e.g. on DPI change). - On Windows, respect min/max inner sizes when creating the window. +- **Breaking:** On Windows, device events are now ignored for unfocused windows by default, use `EventLoopWindowTarget::set_device_event_filter` to set the filter level. # 0.27.1 (2022-07-30) diff --git a/src/event_loop.rs b/src/event_loop.rs index b96c80c9..f376ceab 100644 --- a/src/event_loop.rs +++ b/src/event_loop.rs @@ -323,7 +323,7 @@ impl EventLoopWindowTarget { /// /// ## Platform-specific /// - /// - **Wayland / Windows / macOS / iOS / Android / Web:** Unsupported. + /// - **Wayland / macOS / iOS / Android / Web:** Unsupported. /// /// [`DeviceEvent`]: crate::event::DeviceEvent pub fn set_device_event_filter(&self, _filter: DeviceEventFilter) { @@ -332,7 +332,8 @@ impl EventLoopWindowTarget { target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", - target_os = "openbsd" + target_os = "openbsd", + target_os = "windows" ))] self.p.set_device_event_filter(_filter); } diff --git a/src/platform_impl/windows/event_loop.rs b/src/platform_impl/windows/event_loop.rs index 632fc854..8c6fdfbd 100644 --- a/src/platform_impl/windows/event_loop.rs +++ b/src/platform_impl/windows/event_loop.rs @@ -77,7 +77,9 @@ use windows_sys::Win32::{ use crate::{ dpi::{PhysicalPosition, PhysicalSize}, event::{DeviceEvent, Event, Force, Ime, KeyboardInput, Touch, TouchPhase, WindowEvent}, - event_loop::{ControlFlow, EventLoopClosed, EventLoopWindowTarget as RootELW}, + event_loop::{ + ControlFlow, DeviceEventFilter, EventLoopClosed, EventLoopWindowTarget as RootELW, + }, monitor::MonitorHandle as RootMonitorHandle, platform_impl::platform::{ dark_mode::try_theme, @@ -207,7 +209,10 @@ impl EventLoop { let thread_msg_sender = insert_event_target_window_data::(thread_msg_target, runner_shared.clone()); - raw_input::register_all_mice_and_keyboards_for_raw_input(thread_msg_target); + raw_input::register_all_mice_and_keyboards_for_raw_input( + thread_msg_target, + Default::default(), + ); EventLoop { thread_msg_sender, @@ -322,6 +327,10 @@ impl EventLoopWindowTarget { pub fn raw_display_handle(&self) -> RawDisplayHandle { RawDisplayHandle::Windows(WindowsDisplayHandle::empty()) } + + pub fn set_device_event_filter(&self, filter: DeviceEventFilter) { + raw_input::register_all_mice_and_keyboards_for_raw_input(self.thread_msg_target, filter); + } } /// Returns the id of the main thread. diff --git a/src/platform_impl/windows/raw_input.rs b/src/platform_impl/windows/raw_input.rs index 143293d3..c8d9a8b2 100644 --- a/src/platform_impl/windows/raw_input.rs +++ b/src/platform_impl/windows/raw_input.rs @@ -12,9 +12,9 @@ use windows_sys::Win32::{ Input::{ GetRawInputData, GetRawInputDeviceInfoW, GetRawInputDeviceList, RegisterRawInputDevices, HRAWINPUT, RAWINPUT, RAWINPUTDEVICE, RAWINPUTDEVICELIST, - RAWINPUTHEADER, RIDEV_DEVNOTIFY, RIDEV_INPUTSINK, RIDI_DEVICEINFO, RIDI_DEVICENAME, - RID_DEVICE_INFO, RID_DEVICE_INFO_HID, RID_DEVICE_INFO_KEYBOARD, RID_DEVICE_INFO_MOUSE, - RID_INPUT, RIM_TYPEHID, RIM_TYPEKEYBOARD, RIM_TYPEMOUSE, + RAWINPUTHEADER, RIDEV_DEVNOTIFY, RIDEV_INPUTSINK, RIDEV_REMOVE, RIDI_DEVICEINFO, + RIDI_DEVICENAME, RID_DEVICE_INFO, RID_DEVICE_INFO_HID, RID_DEVICE_INFO_KEYBOARD, + RID_DEVICE_INFO_MOUSE, RID_INPUT, RIM_TYPEHID, RIM_TYPEKEYBOARD, RIM_TYPEMOUSE, }, WindowsAndMessaging::{ RI_MOUSE_LEFT_BUTTON_DOWN, RI_MOUSE_LEFT_BUTTON_UP, RI_MOUSE_MIDDLE_BUTTON_DOWN, @@ -23,7 +23,7 @@ use windows_sys::Win32::{ }, }; -use crate::{event::ElementState, platform_impl::platform::util}; +use crate::{event::ElementState, event_loop::DeviceEventFilter, platform_impl::platform::util}; #[allow(dead_code)] pub fn get_raw_input_device_list() -> Option> { @@ -138,10 +138,21 @@ pub fn register_raw_input_devices(devices: &[RAWINPUTDEVICE]) -> bool { } } -pub fn register_all_mice_and_keyboards_for_raw_input(window_handle: HWND) -> bool { +pub fn register_all_mice_and_keyboards_for_raw_input( + mut window_handle: HWND, + filter: DeviceEventFilter, +) -> bool { // RIDEV_DEVNOTIFY: receive hotplug events // RIDEV_INPUTSINK: receive events even if we're not in the foreground - let flags = RIDEV_DEVNOTIFY | RIDEV_INPUTSINK; + // RIDEV_REMOVE: don't receive device events (requires NULL hwndTarget) + let flags = match filter { + DeviceEventFilter::Always => { + window_handle = 0; + RIDEV_REMOVE + } + DeviceEventFilter::Unfocused => RIDEV_DEVNOTIFY, + DeviceEventFilter::Never => RIDEV_DEVNOTIFY | RIDEV_INPUTSINK, + }; let devices: [RAWINPUTDEVICE; 2] = [ RAWINPUTDEVICE {