winit/platform_impl/windows/
raw_input.rs1use std::mem::{self, size_of};
2use std::ptr;
3
4use windows_sys::Win32::Devices::HumanInterfaceDevice::{
5 HID_USAGE_GENERIC_KEYBOARD, HID_USAGE_GENERIC_MOUSE, HID_USAGE_PAGE_GENERIC,
6};
7use windows_sys::Win32::Foundation::{HANDLE, HWND};
8use windows_sys::Win32::UI::Input::KeyboardAndMouse::{
9 MapVirtualKeyW, MAPVK_VK_TO_VSC_EX, VK_NUMLOCK, VK_SHIFT,
10};
11use windows_sys::Win32::UI::Input::{
12 GetRawInputData, GetRawInputDeviceInfoW, GetRawInputDeviceList, RegisterRawInputDevices,
13 HRAWINPUT, RAWINPUT, RAWINPUTDEVICE, RAWINPUTDEVICELIST, RAWINPUTHEADER, RAWKEYBOARD,
14 RIDEV_DEVNOTIFY, RIDEV_INPUTSINK, RIDEV_REMOVE, RIDI_DEVICEINFO, RIDI_DEVICENAME,
15 RID_DEVICE_INFO, RID_DEVICE_INFO_HID, RID_DEVICE_INFO_KEYBOARD, RID_DEVICE_INFO_MOUSE,
16 RID_INPUT, RIM_TYPEHID, RIM_TYPEKEYBOARD, RIM_TYPEMOUSE,
17};
18use windows_sys::Win32::UI::WindowsAndMessaging::{
19 RI_KEY_E0, RI_KEY_E1, RI_MOUSE_BUTTON_1_DOWN, RI_MOUSE_BUTTON_1_UP, RI_MOUSE_BUTTON_2_DOWN,
20 RI_MOUSE_BUTTON_2_UP, RI_MOUSE_BUTTON_3_DOWN, RI_MOUSE_BUTTON_3_UP, RI_MOUSE_BUTTON_4_DOWN,
21 RI_MOUSE_BUTTON_4_UP, RI_MOUSE_BUTTON_5_DOWN, RI_MOUSE_BUTTON_5_UP,
22};
23
24use super::scancode_to_physicalkey;
25use crate::event::ElementState;
26use crate::event_loop::DeviceEvents;
27use crate::keyboard::{KeyCode, PhysicalKey};
28use crate::platform_impl::platform::util;
29
30#[allow(dead_code)]
31pub fn get_raw_input_device_list() -> Option<Vec<RAWINPUTDEVICELIST>> {
32 let list_size = size_of::<RAWINPUTDEVICELIST>() as u32;
33
34 let mut num_devices = 0;
35 let status = unsafe { GetRawInputDeviceList(ptr::null_mut(), &mut num_devices, list_size) };
36
37 if status == u32::MAX {
38 return None;
39 }
40
41 let mut buffer = Vec::with_capacity(num_devices as _);
42
43 let num_stored =
44 unsafe { GetRawInputDeviceList(buffer.as_mut_ptr(), &mut num_devices, list_size) };
45
46 if num_stored == u32::MAX {
47 return None;
48 }
49
50 debug_assert_eq!(num_devices, num_stored);
51
52 unsafe { buffer.set_len(num_devices as _) };
53
54 Some(buffer)
55}
56
57#[allow(dead_code)]
58pub enum RawDeviceInfo {
59 Mouse(RID_DEVICE_INFO_MOUSE),
60 Keyboard(RID_DEVICE_INFO_KEYBOARD),
61 Hid(RID_DEVICE_INFO_HID),
62}
63
64impl From<RID_DEVICE_INFO> for RawDeviceInfo {
65 fn from(info: RID_DEVICE_INFO) -> Self {
66 unsafe {
67 match info.dwType {
68 RIM_TYPEMOUSE => RawDeviceInfo::Mouse(info.Anonymous.mouse),
69 RIM_TYPEKEYBOARD => RawDeviceInfo::Keyboard(info.Anonymous.keyboard),
70 RIM_TYPEHID => RawDeviceInfo::Hid(info.Anonymous.hid),
71 _ => unreachable!(),
72 }
73 }
74 }
75}
76
77#[allow(dead_code)]
78pub fn get_raw_input_device_info(handle: HANDLE) -> Option<RawDeviceInfo> {
79 let mut info: RID_DEVICE_INFO = unsafe { mem::zeroed() };
80 let info_size = size_of::<RID_DEVICE_INFO>() as u32;
81
82 info.cbSize = info_size;
83
84 let mut minimum_size = 0;
85 let status = unsafe {
86 GetRawInputDeviceInfoW(handle, RIDI_DEVICEINFO, &mut info as *mut _ as _, &mut minimum_size)
87 };
88
89 if status == u32::MAX || status == 0 {
90 return None;
91 }
92
93 debug_assert_eq!(info_size, status);
94
95 Some(info.into())
96}
97
98pub fn get_raw_input_device_name(handle: HANDLE) -> Option<String> {
99 let mut minimum_size = 0;
100 let status = unsafe {
101 GetRawInputDeviceInfoW(handle, RIDI_DEVICENAME, ptr::null_mut(), &mut minimum_size)
102 };
103
104 if status != 0 {
105 return None;
106 }
107
108 let mut name: Vec<u16> = Vec::with_capacity(minimum_size as _);
109
110 let status = unsafe {
111 GetRawInputDeviceInfoW(handle, RIDI_DEVICENAME, name.as_ptr() as _, &mut minimum_size)
112 };
113
114 if status == u32::MAX || status == 0 {
115 return None;
116 }
117
118 debug_assert_eq!(minimum_size, status);
119
120 unsafe { name.set_len(minimum_size as _) };
121
122 util::decode_wide(&name).into_string().ok()
123}
124
125pub fn register_raw_input_devices(devices: &[RAWINPUTDEVICE]) -> bool {
126 let device_size = size_of::<RAWINPUTDEVICE>() as u32;
127
128 unsafe {
129 RegisterRawInputDevices(devices.as_ptr(), devices.len() as u32, device_size) == true.into()
130 }
131}
132
133pub fn register_all_mice_and_keyboards_for_raw_input(
134 mut window_handle: HWND,
135 filter: DeviceEvents,
136) -> bool {
137 let flags = match filter {
141 DeviceEvents::Never => {
142 window_handle = 0;
143 RIDEV_REMOVE
144 },
145 DeviceEvents::WhenFocused => RIDEV_DEVNOTIFY,
146 DeviceEvents::Always => RIDEV_DEVNOTIFY | RIDEV_INPUTSINK,
147 };
148
149 let devices: [RAWINPUTDEVICE; 2] = [
150 RAWINPUTDEVICE {
151 usUsagePage: HID_USAGE_PAGE_GENERIC,
152 usUsage: HID_USAGE_GENERIC_MOUSE,
153 dwFlags: flags,
154 hwndTarget: window_handle,
155 },
156 RAWINPUTDEVICE {
157 usUsagePage: HID_USAGE_PAGE_GENERIC,
158 usUsage: HID_USAGE_GENERIC_KEYBOARD,
159 dwFlags: flags,
160 hwndTarget: window_handle,
161 },
162 ];
163
164 register_raw_input_devices(&devices)
165}
166
167pub fn get_raw_input_data(handle: HRAWINPUT) -> Option<RAWINPUT> {
168 let mut data: RAWINPUT = unsafe { mem::zeroed() };
169 let mut data_size = size_of::<RAWINPUT>() as u32;
170 let header_size = size_of::<RAWINPUTHEADER>() as u32;
171
172 let status = unsafe {
173 GetRawInputData(handle, RID_INPUT, &mut data as *mut _ as _, &mut data_size, header_size)
174 };
175
176 if status == u32::MAX || status == 0 {
177 return None;
178 }
179
180 Some(data)
181}
182
183fn button_flags_to_element_state(
184 button_flags: u32,
185 down_flag: u32,
186 up_flag: u32,
187) -> Option<ElementState> {
188 if util::has_flag(button_flags, down_flag) {
190 Some(ElementState::Pressed)
191 } else if util::has_flag(button_flags, up_flag) {
192 Some(ElementState::Released)
193 } else {
194 None
195 }
196}
197
198pub fn get_raw_mouse_button_state(button_flags: u32) -> [Option<ElementState>; 5] {
199 [
200 button_flags_to_element_state(button_flags, RI_MOUSE_BUTTON_1_DOWN, RI_MOUSE_BUTTON_1_UP),
201 button_flags_to_element_state(button_flags, RI_MOUSE_BUTTON_2_DOWN, RI_MOUSE_BUTTON_2_UP),
202 button_flags_to_element_state(button_flags, RI_MOUSE_BUTTON_3_DOWN, RI_MOUSE_BUTTON_3_UP),
203 button_flags_to_element_state(button_flags, RI_MOUSE_BUTTON_4_DOWN, RI_MOUSE_BUTTON_4_UP),
204 button_flags_to_element_state(button_flags, RI_MOUSE_BUTTON_5_DOWN, RI_MOUSE_BUTTON_5_UP),
205 ]
206}
207
208pub fn get_keyboard_physical_key(keyboard: RAWKEYBOARD) -> Option<PhysicalKey> {
209 let extension = {
210 if util::has_flag(keyboard.Flags, RI_KEY_E0 as _) {
211 0xe000
212 } else if util::has_flag(keyboard.Flags, RI_KEY_E1 as _) {
213 0xe100
214 } else {
215 0x0000
216 }
217 };
218 let scancode = if keyboard.MakeCode == 0 {
219 unsafe { MapVirtualKeyW(keyboard.VKey as u32, MAPVK_VK_TO_VSC_EX) as u16 }
222 } else {
223 keyboard.MakeCode | extension
224 };
225 if scancode == 0xe11d || scancode == 0xe02a {
226 return None;
247 }
248 let physical_key = if keyboard.VKey == VK_NUMLOCK {
249 PhysicalKey::Code(KeyCode::NumLock)
262 } else {
263 scancode_to_physicalkey(scancode as u32)
264 };
265 if keyboard.VKey == VK_SHIFT {
266 if let PhysicalKey::Code(
267 KeyCode::NumpadDecimal
268 | KeyCode::Numpad0
269 | KeyCode::Numpad1
270 | KeyCode::Numpad2
271 | KeyCode::Numpad3
272 | KeyCode::Numpad4
273 | KeyCode::Numpad5
274 | KeyCode::Numpad6
275 | KeyCode::Numpad7
276 | KeyCode::Numpad8
277 | KeyCode::Numpad9,
278 ) = physical_key
279 {
280 return None;
297 }
298 }
299
300 Some(physical_key)
301}