2019-06-21 11:33:15 -04:00
|
|
|
use std::mem::{self, size_of};
|
|
|
|
|
use std::ptr;
|
|
|
|
|
|
2022-03-07 22:58:12 +01:00
|
|
|
use windows_sys::Win32::Devices::HumanInterfaceDevice::{
|
|
|
|
|
HID_USAGE_GENERIC_KEYBOARD, HID_USAGE_GENERIC_MOUSE, HID_USAGE_PAGE_GENERIC,
|
2019-06-21 11:33:15 -04:00
|
|
|
};
|
2022-03-07 22:58:12 +01:00
|
|
|
use windows_sys::Win32::Foundation::{HANDLE, HWND};
|
2023-12-22 18:42:17 +01:00
|
|
|
use windows_sys::Win32::UI::Input::KeyboardAndMouse::{
|
|
|
|
|
MapVirtualKeyW, MAPVK_VK_TO_VSC_EX, VK_NUMLOCK, VK_SHIFT,
|
2024-04-26 19:11:44 +04:00
|
|
|
};
|
2022-03-07 22:58:12 +01:00
|
|
|
use windows_sys::Win32::UI::Input::{
|
|
|
|
|
GetRawInputData, GetRawInputDeviceInfoW, GetRawInputDeviceList, RegisterRawInputDevices,
|
2023-12-22 18:42:17 +01:00
|
|
|
HRAWINPUT, RAWINPUT, RAWINPUTDEVICE, RAWINPUTDEVICELIST, RAWINPUTHEADER, RAWKEYBOARD,
|
|
|
|
|
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,
|
2022-03-07 22:58:12 +01:00
|
|
|
};
|
|
|
|
|
use windows_sys::Win32::UI::WindowsAndMessaging::{
|
2023-12-22 18:42:17 +01:00
|
|
|
RI_KEY_E0, RI_KEY_E1, RI_MOUSE_BUTTON_1_DOWN, RI_MOUSE_BUTTON_1_UP, RI_MOUSE_BUTTON_2_DOWN,
|
|
|
|
|
RI_MOUSE_BUTTON_2_UP, RI_MOUSE_BUTTON_3_DOWN, RI_MOUSE_BUTTON_3_UP, RI_MOUSE_BUTTON_4_DOWN,
|
|
|
|
|
RI_MOUSE_BUTTON_4_UP, RI_MOUSE_BUTTON_5_DOWN, RI_MOUSE_BUTTON_5_UP,
|
Windows: Implement DeviceEvents (#482)
Fixes #467
All variants other than Text have been implemented. While Text can
be implemented using ToUnicode, that doesn't play nice with dead
keys, IME, etc.
Most of the mouse DeviceEvents were already implemented, but due
to the flags that were used when registering for raw input events,
they only worked when the window was in the foreground.
This is also a step forward for #338, as DeviceIds are no longer
useless on Windows. On DeviceEvents, the DeviceId contains that
device's handle. While that handle could ostensibly be used by
developers to query device information, my actual reason for
choosing it is because it's simply a very easy way to handle this.
As a fun bonus, this enabled me to create this method:
DevideIdExt::get_persistent_identifier() -> Option<String>
Using this gives you a unique identifier for the device that
persists across replugs/reboots/etc., so it's ideal for something
like device-specific configuration.
There's a notable caveat to the new DeviceIds, which is that the
value will always be 0 for a WindowEvent. There doesn't seem to be
any straightforward way around this limitation.
I was concerned that multi-window applications would receive n
copies of every DeviceEvent, but Windows only sends them to one
window per application.
Lastly, there's a chance that these additions will cause
antivirus/etc. software to detect winit applications as keyloggers.
I don't know how likely that is to actually happen to people, but
if it does become an issue, the raw input code is neatly
sequestered and would be easy to make optional during compilation.
2018-04-28 12:42:33 -04:00
|
|
|
};
|
|
|
|
|
|
2024-01-04 12:54:35 +01:00
|
|
|
use super::scancode_to_physicalkey;
|
2023-12-22 18:42:17 +01:00
|
|
|
use crate::event::ElementState;
|
|
|
|
|
use crate::event_loop::DeviceEvents;
|
|
|
|
|
use crate::keyboard::{KeyCode, PhysicalKey};
|
|
|
|
|
use crate::platform_impl::platform::util;
|
Windows: Implement DeviceEvents (#482)
Fixes #467
All variants other than Text have been implemented. While Text can
be implemented using ToUnicode, that doesn't play nice with dead
keys, IME, etc.
Most of the mouse DeviceEvents were already implemented, but due
to the flags that were used when registering for raw input events,
they only worked when the window was in the foreground.
This is also a step forward for #338, as DeviceIds are no longer
useless on Windows. On DeviceEvents, the DeviceId contains that
device's handle. While that handle could ostensibly be used by
developers to query device information, my actual reason for
choosing it is because it's simply a very easy way to handle this.
As a fun bonus, this enabled me to create this method:
DevideIdExt::get_persistent_identifier() -> Option<String>
Using this gives you a unique identifier for the device that
persists across replugs/reboots/etc., so it's ideal for something
like device-specific configuration.
There's a notable caveat to the new DeviceIds, which is that the
value will always be 0 for a WindowEvent. There doesn't seem to be
any straightforward way around this limitation.
I was concerned that multi-window applications would receive n
copies of every DeviceEvent, but Windows only sends them to one
window per application.
Lastly, there's a chance that these additions will cause
antivirus/etc. software to detect winit applications as keyloggers.
I don't know how likely that is to actually happen to people, but
if it does become an issue, the raw input code is neatly
sequestered and would be easy to make optional during compilation.
2018-04-28 12:42:33 -04:00
|
|
|
|
|
|
|
|
#[allow(dead_code)]
|
|
|
|
|
pub fn get_raw_input_device_list() -> Option<Vec<RAWINPUTDEVICELIST>> {
|
2022-03-07 22:58:12 +01:00
|
|
|
let list_size = size_of::<RAWINPUTDEVICELIST>() as u32;
|
Windows: Implement DeviceEvents (#482)
Fixes #467
All variants other than Text have been implemented. While Text can
be implemented using ToUnicode, that doesn't play nice with dead
keys, IME, etc.
Most of the mouse DeviceEvents were already implemented, but due
to the flags that were used when registering for raw input events,
they only worked when the window was in the foreground.
This is also a step forward for #338, as DeviceIds are no longer
useless on Windows. On DeviceEvents, the DeviceId contains that
device's handle. While that handle could ostensibly be used by
developers to query device information, my actual reason for
choosing it is because it's simply a very easy way to handle this.
As a fun bonus, this enabled me to create this method:
DevideIdExt::get_persistent_identifier() -> Option<String>
Using this gives you a unique identifier for the device that
persists across replugs/reboots/etc., so it's ideal for something
like device-specific configuration.
There's a notable caveat to the new DeviceIds, which is that the
value will always be 0 for a WindowEvent. There doesn't seem to be
any straightforward way around this limitation.
I was concerned that multi-window applications would receive n
copies of every DeviceEvent, but Windows only sends them to one
window per application.
Lastly, there's a chance that these additions will cause
antivirus/etc. software to detect winit applications as keyloggers.
I don't know how likely that is to actually happen to people, but
if it does become an issue, the raw input code is neatly
sequestered and would be easy to make optional during compilation.
2018-04-28 12:42:33 -04:00
|
|
|
|
|
|
|
|
let mut num_devices = 0;
|
2022-03-07 22:58:12 +01:00
|
|
|
let status = unsafe { GetRawInputDeviceList(ptr::null_mut(), &mut num_devices, list_size) };
|
Windows: Implement DeviceEvents (#482)
Fixes #467
All variants other than Text have been implemented. While Text can
be implemented using ToUnicode, that doesn't play nice with dead
keys, IME, etc.
Most of the mouse DeviceEvents were already implemented, but due
to the flags that were used when registering for raw input events,
they only worked when the window was in the foreground.
This is also a step forward for #338, as DeviceIds are no longer
useless on Windows. On DeviceEvents, the DeviceId contains that
device's handle. While that handle could ostensibly be used by
developers to query device information, my actual reason for
choosing it is because it's simply a very easy way to handle this.
As a fun bonus, this enabled me to create this method:
DevideIdExt::get_persistent_identifier() -> Option<String>
Using this gives you a unique identifier for the device that
persists across replugs/reboots/etc., so it's ideal for something
like device-specific configuration.
There's a notable caveat to the new DeviceIds, which is that the
value will always be 0 for a WindowEvent. There doesn't seem to be
any straightforward way around this limitation.
I was concerned that multi-window applications would receive n
copies of every DeviceEvent, but Windows only sends them to one
window per application.
Lastly, there's a chance that these additions will cause
antivirus/etc. software to detect winit applications as keyloggers.
I don't know how likely that is to actually happen to people, but
if it does become an issue, the raw input code is neatly
sequestered and would be easy to make optional during compilation.
2018-04-28 12:42:33 -04:00
|
|
|
|
2022-03-07 22:58:12 +01:00
|
|
|
if status == u32::MAX {
|
Windows: Implement DeviceEvents (#482)
Fixes #467
All variants other than Text have been implemented. While Text can
be implemented using ToUnicode, that doesn't play nice with dead
keys, IME, etc.
Most of the mouse DeviceEvents were already implemented, but due
to the flags that were used when registering for raw input events,
they only worked when the window was in the foreground.
This is also a step forward for #338, as DeviceIds are no longer
useless on Windows. On DeviceEvents, the DeviceId contains that
device's handle. While that handle could ostensibly be used by
developers to query device information, my actual reason for
choosing it is because it's simply a very easy way to handle this.
As a fun bonus, this enabled me to create this method:
DevideIdExt::get_persistent_identifier() -> Option<String>
Using this gives you a unique identifier for the device that
persists across replugs/reboots/etc., so it's ideal for something
like device-specific configuration.
There's a notable caveat to the new DeviceIds, which is that the
value will always be 0 for a WindowEvent. There doesn't seem to be
any straightforward way around this limitation.
I was concerned that multi-window applications would receive n
copies of every DeviceEvent, but Windows only sends them to one
window per application.
Lastly, there's a chance that these additions will cause
antivirus/etc. software to detect winit applications as keyloggers.
I don't know how likely that is to actually happen to people, but
if it does become an issue, the raw input code is neatly
sequestered and would be easy to make optional during compilation.
2018-04-28 12:42:33 -04:00
|
|
|
return None;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let mut buffer = Vec::with_capacity(num_devices as _);
|
|
|
|
|
|
2022-03-07 22:58:12 +01:00
|
|
|
let num_stored =
|
|
|
|
|
unsafe { GetRawInputDeviceList(buffer.as_mut_ptr(), &mut num_devices, list_size) };
|
Windows: Implement DeviceEvents (#482)
Fixes #467
All variants other than Text have been implemented. While Text can
be implemented using ToUnicode, that doesn't play nice with dead
keys, IME, etc.
Most of the mouse DeviceEvents were already implemented, but due
to the flags that were used when registering for raw input events,
they only worked when the window was in the foreground.
This is also a step forward for #338, as DeviceIds are no longer
useless on Windows. On DeviceEvents, the DeviceId contains that
device's handle. While that handle could ostensibly be used by
developers to query device information, my actual reason for
choosing it is because it's simply a very easy way to handle this.
As a fun bonus, this enabled me to create this method:
DevideIdExt::get_persistent_identifier() -> Option<String>
Using this gives you a unique identifier for the device that
persists across replugs/reboots/etc., so it's ideal for something
like device-specific configuration.
There's a notable caveat to the new DeviceIds, which is that the
value will always be 0 for a WindowEvent. There doesn't seem to be
any straightforward way around this limitation.
I was concerned that multi-window applications would receive n
copies of every DeviceEvent, but Windows only sends them to one
window per application.
Lastly, there's a chance that these additions will cause
antivirus/etc. software to detect winit applications as keyloggers.
I don't know how likely that is to actually happen to people, but
if it does become an issue, the raw input code is neatly
sequestered and would be easy to make optional during compilation.
2018-04-28 12:42:33 -04:00
|
|
|
|
2022-03-07 22:58:12 +01:00
|
|
|
if num_stored == u32::MAX {
|
Windows: Implement DeviceEvents (#482)
Fixes #467
All variants other than Text have been implemented. While Text can
be implemented using ToUnicode, that doesn't play nice with dead
keys, IME, etc.
Most of the mouse DeviceEvents were already implemented, but due
to the flags that were used when registering for raw input events,
they only worked when the window was in the foreground.
This is also a step forward for #338, as DeviceIds are no longer
useless on Windows. On DeviceEvents, the DeviceId contains that
device's handle. While that handle could ostensibly be used by
developers to query device information, my actual reason for
choosing it is because it's simply a very easy way to handle this.
As a fun bonus, this enabled me to create this method:
DevideIdExt::get_persistent_identifier() -> Option<String>
Using this gives you a unique identifier for the device that
persists across replugs/reboots/etc., so it's ideal for something
like device-specific configuration.
There's a notable caveat to the new DeviceIds, which is that the
value will always be 0 for a WindowEvent. There doesn't seem to be
any straightforward way around this limitation.
I was concerned that multi-window applications would receive n
copies of every DeviceEvent, but Windows only sends them to one
window per application.
Lastly, there's a chance that these additions will cause
antivirus/etc. software to detect winit applications as keyloggers.
I don't know how likely that is to actually happen to people, but
if it does become an issue, the raw input code is neatly
sequestered and would be easy to make optional during compilation.
2018-04-28 12:42:33 -04:00
|
|
|
return None;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
debug_assert_eq!(num_devices, num_stored);
|
|
|
|
|
|
|
|
|
|
unsafe { buffer.set_len(num_devices as _) };
|
|
|
|
|
|
|
|
|
|
Some(buffer)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[allow(dead_code)]
|
|
|
|
|
pub enum RawDeviceInfo {
|
|
|
|
|
Mouse(RID_DEVICE_INFO_MOUSE),
|
|
|
|
|
Keyboard(RID_DEVICE_INFO_KEYBOARD),
|
|
|
|
|
Hid(RID_DEVICE_INFO_HID),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl From<RID_DEVICE_INFO> for RawDeviceInfo {
|
|
|
|
|
fn from(info: RID_DEVICE_INFO) -> Self {
|
|
|
|
|
unsafe {
|
|
|
|
|
match info.dwType {
|
2022-03-07 22:58:12 +01:00
|
|
|
RIM_TYPEMOUSE => RawDeviceInfo::Mouse(info.Anonymous.mouse),
|
|
|
|
|
RIM_TYPEKEYBOARD => RawDeviceInfo::Keyboard(info.Anonymous.keyboard),
|
|
|
|
|
RIM_TYPEHID => RawDeviceInfo::Hid(info.Anonymous.hid),
|
Windows: Implement DeviceEvents (#482)
Fixes #467
All variants other than Text have been implemented. While Text can
be implemented using ToUnicode, that doesn't play nice with dead
keys, IME, etc.
Most of the mouse DeviceEvents were already implemented, but due
to the flags that were used when registering for raw input events,
they only worked when the window was in the foreground.
This is also a step forward for #338, as DeviceIds are no longer
useless on Windows. On DeviceEvents, the DeviceId contains that
device's handle. While that handle could ostensibly be used by
developers to query device information, my actual reason for
choosing it is because it's simply a very easy way to handle this.
As a fun bonus, this enabled me to create this method:
DevideIdExt::get_persistent_identifier() -> Option<String>
Using this gives you a unique identifier for the device that
persists across replugs/reboots/etc., so it's ideal for something
like device-specific configuration.
There's a notable caveat to the new DeviceIds, which is that the
value will always be 0 for a WindowEvent. There doesn't seem to be
any straightforward way around this limitation.
I was concerned that multi-window applications would receive n
copies of every DeviceEvent, but Windows only sends them to one
window per application.
Lastly, there's a chance that these additions will cause
antivirus/etc. software to detect winit applications as keyloggers.
I don't know how likely that is to actually happen to people, but
if it does become an issue, the raw input code is neatly
sequestered and would be easy to make optional during compilation.
2018-04-28 12:42:33 -04:00
|
|
|
_ => unreachable!(),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[allow(dead_code)]
|
|
|
|
|
pub fn get_raw_input_device_info(handle: HANDLE) -> Option<RawDeviceInfo> {
|
2019-06-29 00:07:36 +02:00
|
|
|
let mut info: RID_DEVICE_INFO = unsafe { mem::zeroed() };
|
2022-03-07 22:58:12 +01:00
|
|
|
let info_size = size_of::<RID_DEVICE_INFO>() as u32;
|
Windows: Implement DeviceEvents (#482)
Fixes #467
All variants other than Text have been implemented. While Text can
be implemented using ToUnicode, that doesn't play nice with dead
keys, IME, etc.
Most of the mouse DeviceEvents were already implemented, but due
to the flags that were used when registering for raw input events,
they only worked when the window was in the foreground.
This is also a step forward for #338, as DeviceIds are no longer
useless on Windows. On DeviceEvents, the DeviceId contains that
device's handle. While that handle could ostensibly be used by
developers to query device information, my actual reason for
choosing it is because it's simply a very easy way to handle this.
As a fun bonus, this enabled me to create this method:
DevideIdExt::get_persistent_identifier() -> Option<String>
Using this gives you a unique identifier for the device that
persists across replugs/reboots/etc., so it's ideal for something
like device-specific configuration.
There's a notable caveat to the new DeviceIds, which is that the
value will always be 0 for a WindowEvent. There doesn't seem to be
any straightforward way around this limitation.
I was concerned that multi-window applications would receive n
copies of every DeviceEvent, but Windows only sends them to one
window per application.
Lastly, there's a chance that these additions will cause
antivirus/etc. software to detect winit applications as keyloggers.
I don't know how likely that is to actually happen to people, but
if it does become an issue, the raw input code is neatly
sequestered and would be easy to make optional during compilation.
2018-04-28 12:42:33 -04:00
|
|
|
|
|
|
|
|
info.cbSize = info_size;
|
|
|
|
|
|
|
|
|
|
let mut minimum_size = 0;
|
2019-06-21 11:33:15 -04:00
|
|
|
let status = unsafe {
|
|
|
|
|
GetRawInputDeviceInfoW(handle, RIDI_DEVICEINFO, &mut info as *mut _ as _, &mut minimum_size)
|
|
|
|
|
};
|
Windows: Implement DeviceEvents (#482)
Fixes #467
All variants other than Text have been implemented. While Text can
be implemented using ToUnicode, that doesn't play nice with dead
keys, IME, etc.
Most of the mouse DeviceEvents were already implemented, but due
to the flags that were used when registering for raw input events,
they only worked when the window was in the foreground.
This is also a step forward for #338, as DeviceIds are no longer
useless on Windows. On DeviceEvents, the DeviceId contains that
device's handle. While that handle could ostensibly be used by
developers to query device information, my actual reason for
choosing it is because it's simply a very easy way to handle this.
As a fun bonus, this enabled me to create this method:
DevideIdExt::get_persistent_identifier() -> Option<String>
Using this gives you a unique identifier for the device that
persists across replugs/reboots/etc., so it's ideal for something
like device-specific configuration.
There's a notable caveat to the new DeviceIds, which is that the
value will always be 0 for a WindowEvent. There doesn't seem to be
any straightforward way around this limitation.
I was concerned that multi-window applications would receive n
copies of every DeviceEvent, but Windows only sends them to one
window per application.
Lastly, there's a chance that these additions will cause
antivirus/etc. software to detect winit applications as keyloggers.
I don't know how likely that is to actually happen to people, but
if it does become an issue, the raw input code is neatly
sequestered and would be easy to make optional during compilation.
2018-04-28 12:42:33 -04:00
|
|
|
|
2022-03-07 22:58:12 +01:00
|
|
|
if status == u32::MAX || status == 0 {
|
Windows: Implement DeviceEvents (#482)
Fixes #467
All variants other than Text have been implemented. While Text can
be implemented using ToUnicode, that doesn't play nice with dead
keys, IME, etc.
Most of the mouse DeviceEvents were already implemented, but due
to the flags that were used when registering for raw input events,
they only worked when the window was in the foreground.
This is also a step forward for #338, as DeviceIds are no longer
useless on Windows. On DeviceEvents, the DeviceId contains that
device's handle. While that handle could ostensibly be used by
developers to query device information, my actual reason for
choosing it is because it's simply a very easy way to handle this.
As a fun bonus, this enabled me to create this method:
DevideIdExt::get_persistent_identifier() -> Option<String>
Using this gives you a unique identifier for the device that
persists across replugs/reboots/etc., so it's ideal for something
like device-specific configuration.
There's a notable caveat to the new DeviceIds, which is that the
value will always be 0 for a WindowEvent. There doesn't seem to be
any straightforward way around this limitation.
I was concerned that multi-window applications would receive n
copies of every DeviceEvent, but Windows only sends them to one
window per application.
Lastly, there's a chance that these additions will cause
antivirus/etc. software to detect winit applications as keyloggers.
I don't know how likely that is to actually happen to people, but
if it does become an issue, the raw input code is neatly
sequestered and would be easy to make optional during compilation.
2018-04-28 12:42:33 -04:00
|
|
|
return None;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
debug_assert_eq!(info_size, status);
|
|
|
|
|
|
|
|
|
|
Some(info.into())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn get_raw_input_device_name(handle: HANDLE) -> Option<String> {
|
|
|
|
|
let mut minimum_size = 0;
|
2019-06-21 11:33:15 -04:00
|
|
|
let status = unsafe {
|
2022-03-07 22:58:12 +01:00
|
|
|
GetRawInputDeviceInfoW(handle, RIDI_DEVICENAME, ptr::null_mut(), &mut minimum_size)
|
2019-06-21 11:33:15 -04:00
|
|
|
};
|
Windows: Implement DeviceEvents (#482)
Fixes #467
All variants other than Text have been implemented. While Text can
be implemented using ToUnicode, that doesn't play nice with dead
keys, IME, etc.
Most of the mouse DeviceEvents were already implemented, but due
to the flags that were used when registering for raw input events,
they only worked when the window was in the foreground.
This is also a step forward for #338, as DeviceIds are no longer
useless on Windows. On DeviceEvents, the DeviceId contains that
device's handle. While that handle could ostensibly be used by
developers to query device information, my actual reason for
choosing it is because it's simply a very easy way to handle this.
As a fun bonus, this enabled me to create this method:
DevideIdExt::get_persistent_identifier() -> Option<String>
Using this gives you a unique identifier for the device that
persists across replugs/reboots/etc., so it's ideal for something
like device-specific configuration.
There's a notable caveat to the new DeviceIds, which is that the
value will always be 0 for a WindowEvent. There doesn't seem to be
any straightforward way around this limitation.
I was concerned that multi-window applications would receive n
copies of every DeviceEvent, but Windows only sends them to one
window per application.
Lastly, there's a chance that these additions will cause
antivirus/etc. software to detect winit applications as keyloggers.
I don't know how likely that is to actually happen to people, but
if it does become an issue, the raw input code is neatly
sequestered and would be easy to make optional during compilation.
2018-04-28 12:42:33 -04:00
|
|
|
|
|
|
|
|
if status != 0 {
|
|
|
|
|
return None;
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-07 22:58:12 +01:00
|
|
|
let mut name: Vec<u16> = Vec::with_capacity(minimum_size as _);
|
Windows: Implement DeviceEvents (#482)
Fixes #467
All variants other than Text have been implemented. While Text can
be implemented using ToUnicode, that doesn't play nice with dead
keys, IME, etc.
Most of the mouse DeviceEvents were already implemented, but due
to the flags that were used when registering for raw input events,
they only worked when the window was in the foreground.
This is also a step forward for #338, as DeviceIds are no longer
useless on Windows. On DeviceEvents, the DeviceId contains that
device's handle. While that handle could ostensibly be used by
developers to query device information, my actual reason for
choosing it is because it's simply a very easy way to handle this.
As a fun bonus, this enabled me to create this method:
DevideIdExt::get_persistent_identifier() -> Option<String>
Using this gives you a unique identifier for the device that
persists across replugs/reboots/etc., so it's ideal for something
like device-specific configuration.
There's a notable caveat to the new DeviceIds, which is that the
value will always be 0 for a WindowEvent. There doesn't seem to be
any straightforward way around this limitation.
I was concerned that multi-window applications would receive n
copies of every DeviceEvent, but Windows only sends them to one
window per application.
Lastly, there's a chance that these additions will cause
antivirus/etc. software to detect winit applications as keyloggers.
I don't know how likely that is to actually happen to people, but
if it does become an issue, the raw input code is neatly
sequestered and would be easy to make optional during compilation.
2018-04-28 12:42:33 -04:00
|
|
|
|
2019-06-21 11:33:15 -04:00
|
|
|
let status = unsafe {
|
2022-03-07 22:58:12 +01:00
|
|
|
GetRawInputDeviceInfoW(handle, RIDI_DEVICENAME, name.as_ptr() as _, &mut minimum_size)
|
2019-06-21 11:33:15 -04:00
|
|
|
};
|
Windows: Implement DeviceEvents (#482)
Fixes #467
All variants other than Text have been implemented. While Text can
be implemented using ToUnicode, that doesn't play nice with dead
keys, IME, etc.
Most of the mouse DeviceEvents were already implemented, but due
to the flags that were used when registering for raw input events,
they only worked when the window was in the foreground.
This is also a step forward for #338, as DeviceIds are no longer
useless on Windows. On DeviceEvents, the DeviceId contains that
device's handle. While that handle could ostensibly be used by
developers to query device information, my actual reason for
choosing it is because it's simply a very easy way to handle this.
As a fun bonus, this enabled me to create this method:
DevideIdExt::get_persistent_identifier() -> Option<String>
Using this gives you a unique identifier for the device that
persists across replugs/reboots/etc., so it's ideal for something
like device-specific configuration.
There's a notable caveat to the new DeviceIds, which is that the
value will always be 0 for a WindowEvent. There doesn't seem to be
any straightforward way around this limitation.
I was concerned that multi-window applications would receive n
copies of every DeviceEvent, but Windows only sends them to one
window per application.
Lastly, there's a chance that these additions will cause
antivirus/etc. software to detect winit applications as keyloggers.
I don't know how likely that is to actually happen to people, but
if it does become an issue, the raw input code is neatly
sequestered and would be easy to make optional during compilation.
2018-04-28 12:42:33 -04:00
|
|
|
|
2022-03-07 22:58:12 +01:00
|
|
|
if status == u32::MAX || status == 0 {
|
Windows: Implement DeviceEvents (#482)
Fixes #467
All variants other than Text have been implemented. While Text can
be implemented using ToUnicode, that doesn't play nice with dead
keys, IME, etc.
Most of the mouse DeviceEvents were already implemented, but due
to the flags that were used when registering for raw input events,
they only worked when the window was in the foreground.
This is also a step forward for #338, as DeviceIds are no longer
useless on Windows. On DeviceEvents, the DeviceId contains that
device's handle. While that handle could ostensibly be used by
developers to query device information, my actual reason for
choosing it is because it's simply a very easy way to handle this.
As a fun bonus, this enabled me to create this method:
DevideIdExt::get_persistent_identifier() -> Option<String>
Using this gives you a unique identifier for the device that
persists across replugs/reboots/etc., so it's ideal for something
like device-specific configuration.
There's a notable caveat to the new DeviceIds, which is that the
value will always be 0 for a WindowEvent. There doesn't seem to be
any straightforward way around this limitation.
I was concerned that multi-window applications would receive n
copies of every DeviceEvent, but Windows only sends them to one
window per application.
Lastly, there's a chance that these additions will cause
antivirus/etc. software to detect winit applications as keyloggers.
I don't know how likely that is to actually happen to people, but
if it does become an issue, the raw input code is neatly
sequestered and would be easy to make optional during compilation.
2018-04-28 12:42:33 -04:00
|
|
|
return None;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
debug_assert_eq!(minimum_size, status);
|
|
|
|
|
|
|
|
|
|
unsafe { name.set_len(minimum_size as _) };
|
|
|
|
|
|
2022-04-30 13:58:51 +02:00
|
|
|
util::decode_wide(&name).into_string().ok()
|
Windows: Implement DeviceEvents (#482)
Fixes #467
All variants other than Text have been implemented. While Text can
be implemented using ToUnicode, that doesn't play nice with dead
keys, IME, etc.
Most of the mouse DeviceEvents were already implemented, but due
to the flags that were used when registering for raw input events,
they only worked when the window was in the foreground.
This is also a step forward for #338, as DeviceIds are no longer
useless on Windows. On DeviceEvents, the DeviceId contains that
device's handle. While that handle could ostensibly be used by
developers to query device information, my actual reason for
choosing it is because it's simply a very easy way to handle this.
As a fun bonus, this enabled me to create this method:
DevideIdExt::get_persistent_identifier() -> Option<String>
Using this gives you a unique identifier for the device that
persists across replugs/reboots/etc., so it's ideal for something
like device-specific configuration.
There's a notable caveat to the new DeviceIds, which is that the
value will always be 0 for a WindowEvent. There doesn't seem to be
any straightforward way around this limitation.
I was concerned that multi-window applications would receive n
copies of every DeviceEvent, but Windows only sends them to one
window per application.
Lastly, there's a chance that these additions will cause
antivirus/etc. software to detect winit applications as keyloggers.
I don't know how likely that is to actually happen to people, but
if it does become an issue, the raw input code is neatly
sequestered and would be easy to make optional during compilation.
2018-04-28 12:42:33 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn register_raw_input_devices(devices: &[RAWINPUTDEVICE]) -> bool {
|
2022-03-07 22:58:12 +01:00
|
|
|
let device_size = size_of::<RAWINPUTDEVICE>() as u32;
|
Windows: Implement DeviceEvents (#482)
Fixes #467
All variants other than Text have been implemented. While Text can
be implemented using ToUnicode, that doesn't play nice with dead
keys, IME, etc.
Most of the mouse DeviceEvents were already implemented, but due
to the flags that were used when registering for raw input events,
they only worked when the window was in the foreground.
This is also a step forward for #338, as DeviceIds are no longer
useless on Windows. On DeviceEvents, the DeviceId contains that
device's handle. While that handle could ostensibly be used by
developers to query device information, my actual reason for
choosing it is because it's simply a very easy way to handle this.
As a fun bonus, this enabled me to create this method:
DevideIdExt::get_persistent_identifier() -> Option<String>
Using this gives you a unique identifier for the device that
persists across replugs/reboots/etc., so it's ideal for something
like device-specific configuration.
There's a notable caveat to the new DeviceIds, which is that the
value will always be 0 for a WindowEvent. There doesn't seem to be
any straightforward way around this limitation.
I was concerned that multi-window applications would receive n
copies of every DeviceEvent, but Windows only sends them to one
window per application.
Lastly, there's a chance that these additions will cause
antivirus/etc. software to detect winit applications as keyloggers.
I don't know how likely that is to actually happen to people, but
if it does become an issue, the raw input code is neatly
sequestered and would be easy to make optional during compilation.
2018-04-28 12:42:33 -04:00
|
|
|
|
2022-03-07 22:58:12 +01:00
|
|
|
unsafe {
|
|
|
|
|
RegisterRawInputDevices(devices.as_ptr(), devices.len() as u32, device_size) == true.into()
|
|
|
|
|
}
|
Windows: Implement DeviceEvents (#482)
Fixes #467
All variants other than Text have been implemented. While Text can
be implemented using ToUnicode, that doesn't play nice with dead
keys, IME, etc.
Most of the mouse DeviceEvents were already implemented, but due
to the flags that were used when registering for raw input events,
they only worked when the window was in the foreground.
This is also a step forward for #338, as DeviceIds are no longer
useless on Windows. On DeviceEvents, the DeviceId contains that
device's handle. While that handle could ostensibly be used by
developers to query device information, my actual reason for
choosing it is because it's simply a very easy way to handle this.
As a fun bonus, this enabled me to create this method:
DevideIdExt::get_persistent_identifier() -> Option<String>
Using this gives you a unique identifier for the device that
persists across replugs/reboots/etc., so it's ideal for something
like device-specific configuration.
There's a notable caveat to the new DeviceIds, which is that the
value will always be 0 for a WindowEvent. There doesn't seem to be
any straightforward way around this limitation.
I was concerned that multi-window applications would receive n
copies of every DeviceEvent, but Windows only sends them to one
window per application.
Lastly, there's a chance that these additions will cause
antivirus/etc. software to detect winit applications as keyloggers.
I don't know how likely that is to actually happen to people, but
if it does become an issue, the raw input code is neatly
sequestered and would be easy to make optional during compilation.
2018-04-28 12:42:33 -04:00
|
|
|
}
|
|
|
|
|
|
2022-08-11 15:17:46 +02:00
|
|
|
pub fn register_all_mice_and_keyboards_for_raw_input(
|
|
|
|
|
mut window_handle: HWND,
|
2023-05-30 21:32:31 +02:00
|
|
|
filter: DeviceEvents,
|
2022-08-11 15:17:46 +02:00
|
|
|
) -> bool {
|
Windows: Implement DeviceEvents (#482)
Fixes #467
All variants other than Text have been implemented. While Text can
be implemented using ToUnicode, that doesn't play nice with dead
keys, IME, etc.
Most of the mouse DeviceEvents were already implemented, but due
to the flags that were used when registering for raw input events,
they only worked when the window was in the foreground.
This is also a step forward for #338, as DeviceIds are no longer
useless on Windows. On DeviceEvents, the DeviceId contains that
device's handle. While that handle could ostensibly be used by
developers to query device information, my actual reason for
choosing it is because it's simply a very easy way to handle this.
As a fun bonus, this enabled me to create this method:
DevideIdExt::get_persistent_identifier() -> Option<String>
Using this gives you a unique identifier for the device that
persists across replugs/reboots/etc., so it's ideal for something
like device-specific configuration.
There's a notable caveat to the new DeviceIds, which is that the
value will always be 0 for a WindowEvent. There doesn't seem to be
any straightforward way around this limitation.
I was concerned that multi-window applications would receive n
copies of every DeviceEvent, but Windows only sends them to one
window per application.
Lastly, there's a chance that these additions will cause
antivirus/etc. software to detect winit applications as keyloggers.
I don't know how likely that is to actually happen to people, but
if it does become an issue, the raw input code is neatly
sequestered and would be easy to make optional during compilation.
2018-04-28 12:42:33 -04:00
|
|
|
// RIDEV_DEVNOTIFY: receive hotplug events
|
|
|
|
|
// RIDEV_INPUTSINK: receive events even if we're not in the foreground
|
2022-08-11 15:17:46 +02:00
|
|
|
// RIDEV_REMOVE: don't receive device events (requires NULL hwndTarget)
|
|
|
|
|
let flags = match filter {
|
2023-05-30 21:32:31 +02:00
|
|
|
DeviceEvents::Never => {
|
2022-08-11 15:17:46 +02:00
|
|
|
window_handle = 0;
|
|
|
|
|
RIDEV_REMOVE
|
|
|
|
|
},
|
2023-05-30 21:32:31 +02:00
|
|
|
DeviceEvents::WhenFocused => RIDEV_DEVNOTIFY,
|
|
|
|
|
DeviceEvents::Always => RIDEV_DEVNOTIFY | RIDEV_INPUTSINK,
|
2022-08-11 15:17:46 +02:00
|
|
|
};
|
Windows: Implement DeviceEvents (#482)
Fixes #467
All variants other than Text have been implemented. While Text can
be implemented using ToUnicode, that doesn't play nice with dead
keys, IME, etc.
Most of the mouse DeviceEvents were already implemented, but due
to the flags that were used when registering for raw input events,
they only worked when the window was in the foreground.
This is also a step forward for #338, as DeviceIds are no longer
useless on Windows. On DeviceEvents, the DeviceId contains that
device's handle. While that handle could ostensibly be used by
developers to query device information, my actual reason for
choosing it is because it's simply a very easy way to handle this.
As a fun bonus, this enabled me to create this method:
DevideIdExt::get_persistent_identifier() -> Option<String>
Using this gives you a unique identifier for the device that
persists across replugs/reboots/etc., so it's ideal for something
like device-specific configuration.
There's a notable caveat to the new DeviceIds, which is that the
value will always be 0 for a WindowEvent. There doesn't seem to be
any straightforward way around this limitation.
I was concerned that multi-window applications would receive n
copies of every DeviceEvent, but Windows only sends them to one
window per application.
Lastly, there's a chance that these additions will cause
antivirus/etc. software to detect winit applications as keyloggers.
I don't know how likely that is to actually happen to people, but
if it does become an issue, the raw input code is neatly
sequestered and would be easy to make optional during compilation.
2018-04-28 12:42:33 -04:00
|
|
|
|
|
|
|
|
let devices: [RAWINPUTDEVICE; 2] = [
|
|
|
|
|
RAWINPUTDEVICE {
|
|
|
|
|
usUsagePage: HID_USAGE_PAGE_GENERIC,
|
|
|
|
|
usUsage: HID_USAGE_GENERIC_MOUSE,
|
|
|
|
|
dwFlags: flags,
|
|
|
|
|
hwndTarget: window_handle,
|
|
|
|
|
},
|
|
|
|
|
RAWINPUTDEVICE {
|
|
|
|
|
usUsagePage: HID_USAGE_PAGE_GENERIC,
|
|
|
|
|
usUsage: HID_USAGE_GENERIC_KEYBOARD,
|
|
|
|
|
dwFlags: flags,
|
|
|
|
|
hwndTarget: window_handle,
|
|
|
|
|
},
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
register_raw_input_devices(&devices)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn get_raw_input_data(handle: HRAWINPUT) -> Option<RAWINPUT> {
|
2019-06-29 00:07:36 +02:00
|
|
|
let mut data: RAWINPUT = unsafe { mem::zeroed() };
|
2022-03-07 22:58:12 +01:00
|
|
|
let mut data_size = size_of::<RAWINPUT>() as u32;
|
|
|
|
|
let header_size = size_of::<RAWINPUTHEADER>() as u32;
|
Windows: Implement DeviceEvents (#482)
Fixes #467
All variants other than Text have been implemented. While Text can
be implemented using ToUnicode, that doesn't play nice with dead
keys, IME, etc.
Most of the mouse DeviceEvents were already implemented, but due
to the flags that were used when registering for raw input events,
they only worked when the window was in the foreground.
This is also a step forward for #338, as DeviceIds are no longer
useless on Windows. On DeviceEvents, the DeviceId contains that
device's handle. While that handle could ostensibly be used by
developers to query device information, my actual reason for
choosing it is because it's simply a very easy way to handle this.
As a fun bonus, this enabled me to create this method:
DevideIdExt::get_persistent_identifier() -> Option<String>
Using this gives you a unique identifier for the device that
persists across replugs/reboots/etc., so it's ideal for something
like device-specific configuration.
There's a notable caveat to the new DeviceIds, which is that the
value will always be 0 for a WindowEvent. There doesn't seem to be
any straightforward way around this limitation.
I was concerned that multi-window applications would receive n
copies of every DeviceEvent, but Windows only sends them to one
window per application.
Lastly, there's a chance that these additions will cause
antivirus/etc. software to detect winit applications as keyloggers.
I don't know how likely that is to actually happen to people, but
if it does become an issue, the raw input code is neatly
sequestered and would be easy to make optional during compilation.
2018-04-28 12:42:33 -04:00
|
|
|
|
2019-06-21 11:33:15 -04:00
|
|
|
let status = unsafe {
|
|
|
|
|
GetRawInputData(handle, RID_INPUT, &mut data as *mut _ as _, &mut data_size, header_size)
|
|
|
|
|
};
|
Windows: Implement DeviceEvents (#482)
Fixes #467
All variants other than Text have been implemented. While Text can
be implemented using ToUnicode, that doesn't play nice with dead
keys, IME, etc.
Most of the mouse DeviceEvents were already implemented, but due
to the flags that were used when registering for raw input events,
they only worked when the window was in the foreground.
This is also a step forward for #338, as DeviceIds are no longer
useless on Windows. On DeviceEvents, the DeviceId contains that
device's handle. While that handle could ostensibly be used by
developers to query device information, my actual reason for
choosing it is because it's simply a very easy way to handle this.
As a fun bonus, this enabled me to create this method:
DevideIdExt::get_persistent_identifier() -> Option<String>
Using this gives you a unique identifier for the device that
persists across replugs/reboots/etc., so it's ideal for something
like device-specific configuration.
There's a notable caveat to the new DeviceIds, which is that the
value will always be 0 for a WindowEvent. There doesn't seem to be
any straightforward way around this limitation.
I was concerned that multi-window applications would receive n
copies of every DeviceEvent, but Windows only sends them to one
window per application.
Lastly, there's a chance that these additions will cause
antivirus/etc. software to detect winit applications as keyloggers.
I don't know how likely that is to actually happen to people, but
if it does become an issue, the raw input code is neatly
sequestered and would be easy to make optional during compilation.
2018-04-28 12:42:33 -04:00
|
|
|
|
2022-03-07 22:58:12 +01:00
|
|
|
if status == u32::MAX || status == 0 {
|
Windows: Implement DeviceEvents (#482)
Fixes #467
All variants other than Text have been implemented. While Text can
be implemented using ToUnicode, that doesn't play nice with dead
keys, IME, etc.
Most of the mouse DeviceEvents were already implemented, but due
to the flags that were used when registering for raw input events,
they only worked when the window was in the foreground.
This is also a step forward for #338, as DeviceIds are no longer
useless on Windows. On DeviceEvents, the DeviceId contains that
device's handle. While that handle could ostensibly be used by
developers to query device information, my actual reason for
choosing it is because it's simply a very easy way to handle this.
As a fun bonus, this enabled me to create this method:
DevideIdExt::get_persistent_identifier() -> Option<String>
Using this gives you a unique identifier for the device that
persists across replugs/reboots/etc., so it's ideal for something
like device-specific configuration.
There's a notable caveat to the new DeviceIds, which is that the
value will always be 0 for a WindowEvent. There doesn't seem to be
any straightforward way around this limitation.
I was concerned that multi-window applications would receive n
copies of every DeviceEvent, but Windows only sends them to one
window per application.
Lastly, there's a chance that these additions will cause
antivirus/etc. software to detect winit applications as keyloggers.
I don't know how likely that is to actually happen to people, but
if it does become an issue, the raw input code is neatly
sequestered and would be easy to make optional during compilation.
2018-04-28 12:42:33 -04:00
|
|
|
return None;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Some(data)
|
|
|
|
|
}
|
|
|
|
|
|
2019-06-21 11:33:15 -04:00
|
|
|
fn button_flags_to_element_state(
|
2022-03-07 22:58:12 +01:00
|
|
|
button_flags: u32,
|
|
|
|
|
down_flag: u32,
|
|
|
|
|
up_flag: u32,
|
2019-06-21 11:33:15 -04:00
|
|
|
) -> Option<ElementState> {
|
Windows: Implement DeviceEvents (#482)
Fixes #467
All variants other than Text have been implemented. While Text can
be implemented using ToUnicode, that doesn't play nice with dead
keys, IME, etc.
Most of the mouse DeviceEvents were already implemented, but due
to the flags that were used when registering for raw input events,
they only worked when the window was in the foreground.
This is also a step forward for #338, as DeviceIds are no longer
useless on Windows. On DeviceEvents, the DeviceId contains that
device's handle. While that handle could ostensibly be used by
developers to query device information, my actual reason for
choosing it is because it's simply a very easy way to handle this.
As a fun bonus, this enabled me to create this method:
DevideIdExt::get_persistent_identifier() -> Option<String>
Using this gives you a unique identifier for the device that
persists across replugs/reboots/etc., so it's ideal for something
like device-specific configuration.
There's a notable caveat to the new DeviceIds, which is that the
value will always be 0 for a WindowEvent. There doesn't seem to be
any straightforward way around this limitation.
I was concerned that multi-window applications would receive n
copies of every DeviceEvent, but Windows only sends them to one
window per application.
Lastly, there's a chance that these additions will cause
antivirus/etc. software to detect winit applications as keyloggers.
I don't know how likely that is to actually happen to people, but
if it does become an issue, the raw input code is neatly
sequestered and would be easy to make optional during compilation.
2018-04-28 12:42:33 -04:00
|
|
|
// We assume the same button won't be simultaneously pressed and released.
|
|
|
|
|
if util::has_flag(button_flags, down_flag) {
|
|
|
|
|
Some(ElementState::Pressed)
|
|
|
|
|
} else if util::has_flag(button_flags, up_flag) {
|
|
|
|
|
Some(ElementState::Released)
|
|
|
|
|
} else {
|
|
|
|
|
None
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-20 19:03:05 +02:00
|
|
|
pub fn get_raw_mouse_button_state(button_flags: u32) -> [Option<ElementState>; 5] {
|
Windows: Implement DeviceEvents (#482)
Fixes #467
All variants other than Text have been implemented. While Text can
be implemented using ToUnicode, that doesn't play nice with dead
keys, IME, etc.
Most of the mouse DeviceEvents were already implemented, but due
to the flags that were used when registering for raw input events,
they only worked when the window was in the foreground.
This is also a step forward for #338, as DeviceIds are no longer
useless on Windows. On DeviceEvents, the DeviceId contains that
device's handle. While that handle could ostensibly be used by
developers to query device information, my actual reason for
choosing it is because it's simply a very easy way to handle this.
As a fun bonus, this enabled me to create this method:
DevideIdExt::get_persistent_identifier() -> Option<String>
Using this gives you a unique identifier for the device that
persists across replugs/reboots/etc., so it's ideal for something
like device-specific configuration.
There's a notable caveat to the new DeviceIds, which is that the
value will always be 0 for a WindowEvent. There doesn't seem to be
any straightforward way around this limitation.
I was concerned that multi-window applications would receive n
copies of every DeviceEvent, but Windows only sends them to one
window per application.
Lastly, there's a chance that these additions will cause
antivirus/etc. software to detect winit applications as keyloggers.
I don't know how likely that is to actually happen to people, but
if it does become an issue, the raw input code is neatly
sequestered and would be easy to make optional during compilation.
2018-04-28 12:42:33 -04:00
|
|
|
[
|
2023-10-20 19:03:05 +02:00
|
|
|
button_flags_to_element_state(button_flags, RI_MOUSE_BUTTON_1_DOWN, RI_MOUSE_BUTTON_1_UP),
|
|
|
|
|
button_flags_to_element_state(button_flags, RI_MOUSE_BUTTON_2_DOWN, RI_MOUSE_BUTTON_2_UP),
|
|
|
|
|
button_flags_to_element_state(button_flags, RI_MOUSE_BUTTON_3_DOWN, RI_MOUSE_BUTTON_3_UP),
|
|
|
|
|
button_flags_to_element_state(button_flags, RI_MOUSE_BUTTON_4_DOWN, RI_MOUSE_BUTTON_4_UP),
|
|
|
|
|
button_flags_to_element_state(button_flags, RI_MOUSE_BUTTON_5_DOWN, RI_MOUSE_BUTTON_5_UP),
|
Windows: Implement DeviceEvents (#482)
Fixes #467
All variants other than Text have been implemented. While Text can
be implemented using ToUnicode, that doesn't play nice with dead
keys, IME, etc.
Most of the mouse DeviceEvents were already implemented, but due
to the flags that were used when registering for raw input events,
they only worked when the window was in the foreground.
This is also a step forward for #338, as DeviceIds are no longer
useless on Windows. On DeviceEvents, the DeviceId contains that
device's handle. While that handle could ostensibly be used by
developers to query device information, my actual reason for
choosing it is because it's simply a very easy way to handle this.
As a fun bonus, this enabled me to create this method:
DevideIdExt::get_persistent_identifier() -> Option<String>
Using this gives you a unique identifier for the device that
persists across replugs/reboots/etc., so it's ideal for something
like device-specific configuration.
There's a notable caveat to the new DeviceIds, which is that the
value will always be 0 for a WindowEvent. There doesn't seem to be
any straightforward way around this limitation.
I was concerned that multi-window applications would receive n
copies of every DeviceEvent, but Windows only sends them to one
window per application.
Lastly, there's a chance that these additions will cause
antivirus/etc. software to detect winit applications as keyloggers.
I don't know how likely that is to actually happen to people, but
if it does become an issue, the raw input code is neatly
sequestered and would be easy to make optional during compilation.
2018-04-28 12:42:33 -04:00
|
|
|
]
|
|
|
|
|
}
|
2023-12-22 18:42:17 +01:00
|
|
|
|
|
|
|
|
pub fn get_keyboard_physical_key(keyboard: RAWKEYBOARD) -> Option<PhysicalKey> {
|
|
|
|
|
let extension = {
|
|
|
|
|
if util::has_flag(keyboard.Flags, RI_KEY_E0 as _) {
|
|
|
|
|
0xe000
|
|
|
|
|
} else if util::has_flag(keyboard.Flags, RI_KEY_E1 as _) {
|
|
|
|
|
0xe100
|
|
|
|
|
} else {
|
|
|
|
|
0x0000
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
let scancode = if keyboard.MakeCode == 0 {
|
|
|
|
|
// In some cases (often with media keys) the device reports a scancode of 0 but a
|
|
|
|
|
// valid virtual key. In these cases we obtain the scancode from the virtual key.
|
|
|
|
|
unsafe { MapVirtualKeyW(keyboard.VKey as u32, MAPVK_VK_TO_VSC_EX) as u16 }
|
|
|
|
|
} else {
|
|
|
|
|
keyboard.MakeCode | extension
|
|
|
|
|
};
|
|
|
|
|
if scancode == 0xe11d || scancode == 0xe02a {
|
|
|
|
|
// At the hardware (or driver?) level, pressing the Pause key is equivalent to pressing
|
|
|
|
|
// Ctrl+NumLock.
|
|
|
|
|
// This equvalence means that if the user presses Pause, the keyboard will emit two
|
|
|
|
|
// subsequent keypresses:
|
|
|
|
|
// 1, 0xE11D - Which is a left Ctrl (0x1D) with an extension flag (0xE100)
|
|
|
|
|
// 2, 0x0045 - Which on its own can be interpreted as Pause
|
|
|
|
|
//
|
|
|
|
|
// There's another combination which isn't quite an equivalence:
|
|
|
|
|
// PrtSc used to be Shift+Asterisk. This means that on some keyboards, presssing
|
|
|
|
|
// PrtSc (print screen) produces the following sequence:
|
|
|
|
|
// 1, 0xE02A - Which is a left shift (0x2A) with an extension flag (0xE000)
|
|
|
|
|
// 2, 0xE037 - Which is a numpad multiply (0x37) with an exteion flag (0xE000). This on
|
|
|
|
|
// its own it can be interpreted as PrtSc
|
|
|
|
|
//
|
|
|
|
|
// For this reason, if we encounter the first keypress, we simply ignore it, trusting
|
|
|
|
|
// that there's going to be another event coming, from which we can extract the
|
|
|
|
|
// appropriate key.
|
|
|
|
|
// For more on this, read the article by Raymond Chen, titled:
|
|
|
|
|
// "Why does Ctrl+ScrollLock cancel dialogs?"
|
|
|
|
|
// https://devblogs.microsoft.com/oldnewthing/20080211-00/?p=23503
|
|
|
|
|
return None;
|
|
|
|
|
}
|
|
|
|
|
let physical_key = if keyboard.VKey == VK_NUMLOCK {
|
|
|
|
|
// Historically, the NumLock and the Pause key were one and the same physical key.
|
|
|
|
|
// The user could trigger Pause by pressing Ctrl+NumLock.
|
|
|
|
|
// Now these are often physically separate and the two keys can be differentiated by
|
|
|
|
|
// checking the extension flag of the scancode. NumLock is 0xE045, Pause is 0x0045.
|
|
|
|
|
//
|
|
|
|
|
// However in this event, both keys are reported as 0x0045 even on modern hardware.
|
|
|
|
|
// Therefore we use the virtual key instead to determine whether it's a NumLock and
|
|
|
|
|
// set the KeyCode accordingly.
|
|
|
|
|
//
|
|
|
|
|
// For more on this, read the article by Raymond Chen, titled:
|
|
|
|
|
// "Why does Ctrl+ScrollLock cancel dialogs?"
|
|
|
|
|
// https://devblogs.microsoft.com/oldnewthing/20080211-00/?p=23503
|
|
|
|
|
PhysicalKey::Code(KeyCode::NumLock)
|
|
|
|
|
} else {
|
2024-01-04 12:54:35 +01:00
|
|
|
scancode_to_physicalkey(scancode as u32)
|
2023-12-22 18:42:17 +01:00
|
|
|
};
|
|
|
|
|
if keyboard.VKey == VK_SHIFT {
|
2024-07-25 15:15:21 +02:00
|
|
|
if let PhysicalKey::Code(
|
|
|
|
|
KeyCode::NumpadDecimal
|
|
|
|
|
| KeyCode::Numpad0
|
|
|
|
|
| KeyCode::Numpad1
|
|
|
|
|
| KeyCode::Numpad2
|
|
|
|
|
| KeyCode::Numpad3
|
|
|
|
|
| KeyCode::Numpad4
|
|
|
|
|
| KeyCode::Numpad5
|
|
|
|
|
| KeyCode::Numpad6
|
|
|
|
|
| KeyCode::Numpad7
|
|
|
|
|
| KeyCode::Numpad8
|
|
|
|
|
| KeyCode::Numpad9,
|
|
|
|
|
) = physical_key
|
|
|
|
|
{
|
|
|
|
|
// On Windows, holding the Shift key makes numpad keys behave as if NumLock
|
|
|
|
|
// wasn't active. The way this is exposed to applications by the system is that
|
|
|
|
|
// the application receives a fake key release event for the shift key at the
|
|
|
|
|
// moment when the numpad key is pressed, just before receiving the numpad key
|
|
|
|
|
// as well.
|
|
|
|
|
//
|
|
|
|
|
// The issue is that in the raw device event (here), the fake shift release
|
|
|
|
|
// event reports the numpad key as the scancode. Unfortunately, the event
|
|
|
|
|
// doesn't have any information to tell whether it's the
|
|
|
|
|
// left shift or the right shift that needs to get the fake
|
|
|
|
|
// release (or press) event so we don't forward this
|
|
|
|
|
// event to the application at all.
|
|
|
|
|
//
|
|
|
|
|
// For more on this, read the article by Raymond Chen, titled:
|
|
|
|
|
// "The shift key overrides NumLock"
|
|
|
|
|
// https://devblogs.microsoft.com/oldnewthing/20040906-00/?p=37953
|
|
|
|
|
return None;
|
2023-12-22 18:42:17 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Some(physical_key)
|
|
|
|
|
}
|