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
|
|
|
use std::char;
|
|
|
|
|
use std::os::raw::c_int;
|
|
|
|
|
|
2019-02-05 10:30:33 -05:00
|
|
|
use event::{ScanCode, ModifiersState, VirtualKeyCode};
|
2017-12-24 15:46:47 +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
|
|
|
use winapi::shared::minwindef::{WPARAM, LPARAM, UINT};
|
2017-12-24 15:46:47 +02:00
|
|
|
use winapi::um::winuser;
|
|
|
|
|
|
2017-01-19 19:45:02 -06:00
|
|
|
pub fn get_key_mods() -> ModifiersState {
|
|
|
|
|
let mut mods = ModifiersState::default();
|
|
|
|
|
unsafe {
|
2017-12-24 15:46:47 +02:00
|
|
|
if winuser::GetKeyState(winuser::VK_SHIFT) & (1 << 15) == (1 << 15) {
|
2017-01-19 19:45:02 -06:00
|
|
|
mods.shift = true;
|
|
|
|
|
}
|
2017-12-24 15:46:47 +02:00
|
|
|
if winuser::GetKeyState(winuser::VK_CONTROL) & (1 << 15) == (1 << 15) {
|
2017-01-19 19:45:02 -06:00
|
|
|
mods.ctrl = true;
|
|
|
|
|
}
|
2017-12-24 15:46:47 +02:00
|
|
|
if winuser::GetKeyState(winuser::VK_MENU) & (1 << 15) == (1 << 15) {
|
2017-01-19 19:45:02 -06:00
|
|
|
mods.alt = true;
|
|
|
|
|
}
|
2017-12-24 15:46:47 +02:00
|
|
|
if (winuser::GetKeyState(winuser::VK_LWIN) | winuser::GetKeyState(winuser::VK_RWIN)) & (1 << 15) == (1 << 15) {
|
2017-01-19 19:45:02 -06:00
|
|
|
mods.logo = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
mods
|
|
|
|
|
}
|
|
|
|
|
|
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 vkey_to_winit_vkey(vkey: c_int) -> Option<VirtualKeyCode> {
|
2017-07-24 20:21:04 +10:00
|
|
|
// VK_* codes are documented here https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx
|
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
|
|
|
match vkey {
|
2017-12-24 15:46:47 +02:00
|
|
|
//winuser::VK_LBUTTON => Some(VirtualKeyCode::Lbutton),
|
|
|
|
|
//winuser::VK_RBUTTON => Some(VirtualKeyCode::Rbutton),
|
|
|
|
|
//winuser::VK_CANCEL => Some(VirtualKeyCode::Cancel),
|
|
|
|
|
//winuser::VK_MBUTTON => Some(VirtualKeyCode::Mbutton),
|
|
|
|
|
//winuser::VK_XBUTTON1 => Some(VirtualKeyCode::Xbutton1),
|
|
|
|
|
//winuser::VK_XBUTTON2 => Some(VirtualKeyCode::Xbutton2),
|
|
|
|
|
winuser::VK_BACK => Some(VirtualKeyCode::Back),
|
|
|
|
|
winuser::VK_TAB => Some(VirtualKeyCode::Tab),
|
|
|
|
|
//winuser::VK_CLEAR => Some(VirtualKeyCode::Clear),
|
|
|
|
|
winuser::VK_RETURN => Some(VirtualKeyCode::Return),
|
|
|
|
|
winuser::VK_LSHIFT => Some(VirtualKeyCode::LShift),
|
|
|
|
|
winuser::VK_RSHIFT => Some(VirtualKeyCode::RShift),
|
|
|
|
|
winuser::VK_LCONTROL => Some(VirtualKeyCode::LControl),
|
|
|
|
|
winuser::VK_RCONTROL => Some(VirtualKeyCode::RControl),
|
2018-06-14 03:24:33 +10:00
|
|
|
winuser::VK_LMENU => Some(VirtualKeyCode::LAlt),
|
|
|
|
|
winuser::VK_RMENU => Some(VirtualKeyCode::RAlt),
|
2017-12-24 15:46:47 +02:00
|
|
|
winuser::VK_PAUSE => Some(VirtualKeyCode::Pause),
|
|
|
|
|
winuser::VK_CAPITAL => Some(VirtualKeyCode::Capital),
|
|
|
|
|
winuser::VK_KANA => Some(VirtualKeyCode::Kana),
|
|
|
|
|
//winuser::VK_HANGUEL => Some(VirtualKeyCode::Hanguel),
|
|
|
|
|
//winuser::VK_HANGUL => Some(VirtualKeyCode::Hangul),
|
|
|
|
|
//winuser::VK_JUNJA => Some(VirtualKeyCode::Junja),
|
|
|
|
|
//winuser::VK_FINAL => Some(VirtualKeyCode::Final),
|
|
|
|
|
//winuser::VK_HANJA => Some(VirtualKeyCode::Hanja),
|
|
|
|
|
winuser::VK_KANJI => Some(VirtualKeyCode::Kanji),
|
|
|
|
|
winuser::VK_ESCAPE => Some(VirtualKeyCode::Escape),
|
|
|
|
|
winuser::VK_CONVERT => Some(VirtualKeyCode::Convert),
|
|
|
|
|
winuser::VK_NONCONVERT => Some(VirtualKeyCode::NoConvert),
|
|
|
|
|
//winuser::VK_ACCEPT => Some(VirtualKeyCode::Accept),
|
|
|
|
|
//winuser::VK_MODECHANGE => Some(VirtualKeyCode::Modechange),
|
|
|
|
|
winuser::VK_SPACE => Some(VirtualKeyCode::Space),
|
|
|
|
|
winuser::VK_PRIOR => Some(VirtualKeyCode::PageUp),
|
|
|
|
|
winuser::VK_NEXT => Some(VirtualKeyCode::PageDown),
|
|
|
|
|
winuser::VK_END => Some(VirtualKeyCode::End),
|
|
|
|
|
winuser::VK_HOME => Some(VirtualKeyCode::Home),
|
|
|
|
|
winuser::VK_LEFT => Some(VirtualKeyCode::Left),
|
|
|
|
|
winuser::VK_UP => Some(VirtualKeyCode::Up),
|
|
|
|
|
winuser::VK_RIGHT => Some(VirtualKeyCode::Right),
|
|
|
|
|
winuser::VK_DOWN => Some(VirtualKeyCode::Down),
|
|
|
|
|
//winuser::VK_SELECT => Some(VirtualKeyCode::Select),
|
|
|
|
|
//winuser::VK_PRINT => Some(VirtualKeyCode::Print),
|
|
|
|
|
//winuser::VK_EXECUTE => Some(VirtualKeyCode::Execute),
|
|
|
|
|
winuser::VK_SNAPSHOT => Some(VirtualKeyCode::Snapshot),
|
|
|
|
|
winuser::VK_INSERT => Some(VirtualKeyCode::Insert),
|
|
|
|
|
winuser::VK_DELETE => Some(VirtualKeyCode::Delete),
|
|
|
|
|
//winuser::VK_HELP => Some(VirtualKeyCode::Help),
|
2015-02-16 09:53:01 +01:00
|
|
|
0x30 => Some(VirtualKeyCode::Key0),
|
|
|
|
|
0x31 => Some(VirtualKeyCode::Key1),
|
|
|
|
|
0x32 => Some(VirtualKeyCode::Key2),
|
|
|
|
|
0x33 => Some(VirtualKeyCode::Key3),
|
|
|
|
|
0x34 => Some(VirtualKeyCode::Key4),
|
|
|
|
|
0x35 => Some(VirtualKeyCode::Key5),
|
|
|
|
|
0x36 => Some(VirtualKeyCode::Key6),
|
|
|
|
|
0x37 => Some(VirtualKeyCode::Key7),
|
|
|
|
|
0x38 => Some(VirtualKeyCode::Key8),
|
|
|
|
|
0x39 => Some(VirtualKeyCode::Key9),
|
|
|
|
|
0x41 => Some(VirtualKeyCode::A),
|
|
|
|
|
0x42 => Some(VirtualKeyCode::B),
|
|
|
|
|
0x43 => Some(VirtualKeyCode::C),
|
|
|
|
|
0x44 => Some(VirtualKeyCode::D),
|
|
|
|
|
0x45 => Some(VirtualKeyCode::E),
|
|
|
|
|
0x46 => Some(VirtualKeyCode::F),
|
|
|
|
|
0x47 => Some(VirtualKeyCode::G),
|
|
|
|
|
0x48 => Some(VirtualKeyCode::H),
|
|
|
|
|
0x49 => Some(VirtualKeyCode::I),
|
|
|
|
|
0x4A => Some(VirtualKeyCode::J),
|
|
|
|
|
0x4B => Some(VirtualKeyCode::K),
|
|
|
|
|
0x4C => Some(VirtualKeyCode::L),
|
|
|
|
|
0x4D => Some(VirtualKeyCode::M),
|
|
|
|
|
0x4E => Some(VirtualKeyCode::N),
|
|
|
|
|
0x4F => Some(VirtualKeyCode::O),
|
|
|
|
|
0x50 => Some(VirtualKeyCode::P),
|
|
|
|
|
0x51 => Some(VirtualKeyCode::Q),
|
|
|
|
|
0x52 => Some(VirtualKeyCode::R),
|
|
|
|
|
0x53 => Some(VirtualKeyCode::S),
|
|
|
|
|
0x54 => Some(VirtualKeyCode::T),
|
|
|
|
|
0x55 => Some(VirtualKeyCode::U),
|
|
|
|
|
0x56 => Some(VirtualKeyCode::V),
|
|
|
|
|
0x57 => Some(VirtualKeyCode::W),
|
|
|
|
|
0x58 => Some(VirtualKeyCode::X),
|
|
|
|
|
0x59 => Some(VirtualKeyCode::Y),
|
|
|
|
|
0x5A => Some(VirtualKeyCode::Z),
|
2017-12-24 15:46:47 +02:00
|
|
|
//winuser::VK_LWIN => Some(VirtualKeyCode::Lwin),
|
|
|
|
|
//winuser::VK_RWIN => Some(VirtualKeyCode::Rwin),
|
|
|
|
|
winuser::VK_APPS => Some(VirtualKeyCode::Apps),
|
|
|
|
|
winuser::VK_SLEEP => Some(VirtualKeyCode::Sleep),
|
|
|
|
|
winuser::VK_NUMPAD0 => Some(VirtualKeyCode::Numpad0),
|
|
|
|
|
winuser::VK_NUMPAD1 => Some(VirtualKeyCode::Numpad1),
|
|
|
|
|
winuser::VK_NUMPAD2 => Some(VirtualKeyCode::Numpad2),
|
|
|
|
|
winuser::VK_NUMPAD3 => Some(VirtualKeyCode::Numpad3),
|
|
|
|
|
winuser::VK_NUMPAD4 => Some(VirtualKeyCode::Numpad4),
|
|
|
|
|
winuser::VK_NUMPAD5 => Some(VirtualKeyCode::Numpad5),
|
|
|
|
|
winuser::VK_NUMPAD6 => Some(VirtualKeyCode::Numpad6),
|
|
|
|
|
winuser::VK_NUMPAD7 => Some(VirtualKeyCode::Numpad7),
|
|
|
|
|
winuser::VK_NUMPAD8 => Some(VirtualKeyCode::Numpad8),
|
|
|
|
|
winuser::VK_NUMPAD9 => Some(VirtualKeyCode::Numpad9),
|
|
|
|
|
winuser::VK_MULTIPLY => Some(VirtualKeyCode::Multiply),
|
|
|
|
|
winuser::VK_ADD => Some(VirtualKeyCode::Add),
|
|
|
|
|
//winuser::VK_SEPARATOR => Some(VirtualKeyCode::Separator),
|
|
|
|
|
winuser::VK_SUBTRACT => Some(VirtualKeyCode::Subtract),
|
|
|
|
|
winuser::VK_DECIMAL => Some(VirtualKeyCode::Decimal),
|
|
|
|
|
winuser::VK_DIVIDE => Some(VirtualKeyCode::Divide),
|
|
|
|
|
winuser::VK_F1 => Some(VirtualKeyCode::F1),
|
|
|
|
|
winuser::VK_F2 => Some(VirtualKeyCode::F2),
|
|
|
|
|
winuser::VK_F3 => Some(VirtualKeyCode::F3),
|
|
|
|
|
winuser::VK_F4 => Some(VirtualKeyCode::F4),
|
|
|
|
|
winuser::VK_F5 => Some(VirtualKeyCode::F5),
|
|
|
|
|
winuser::VK_F6 => Some(VirtualKeyCode::F6),
|
|
|
|
|
winuser::VK_F7 => Some(VirtualKeyCode::F7),
|
|
|
|
|
winuser::VK_F8 => Some(VirtualKeyCode::F8),
|
|
|
|
|
winuser::VK_F9 => Some(VirtualKeyCode::F9),
|
|
|
|
|
winuser::VK_F10 => Some(VirtualKeyCode::F10),
|
|
|
|
|
winuser::VK_F11 => Some(VirtualKeyCode::F11),
|
|
|
|
|
winuser::VK_F12 => Some(VirtualKeyCode::F12),
|
|
|
|
|
winuser::VK_F13 => Some(VirtualKeyCode::F13),
|
|
|
|
|
winuser::VK_F14 => Some(VirtualKeyCode::F14),
|
|
|
|
|
winuser::VK_F15 => Some(VirtualKeyCode::F15),
|
2018-09-12 20:04:16 +03:00
|
|
|
winuser::VK_F16 => Some(VirtualKeyCode::F16),
|
2017-12-24 15:46:47 +02:00
|
|
|
winuser::VK_F17 => Some(VirtualKeyCode::F17),
|
|
|
|
|
winuser::VK_F18 => Some(VirtualKeyCode::F18),
|
|
|
|
|
winuser::VK_F19 => Some(VirtualKeyCode::F19),
|
|
|
|
|
winuser::VK_F20 => Some(VirtualKeyCode::F20),
|
|
|
|
|
winuser::VK_F21 => Some(VirtualKeyCode::F21),
|
|
|
|
|
winuser::VK_F22 => Some(VirtualKeyCode::F22),
|
|
|
|
|
winuser::VK_F23 => Some(VirtualKeyCode::F23),
|
2018-09-12 20:04:16 +03:00
|
|
|
winuser::VK_F24 => Some(VirtualKeyCode::F24),
|
2017-12-24 15:46:47 +02:00
|
|
|
winuser::VK_NUMLOCK => Some(VirtualKeyCode::Numlock),
|
|
|
|
|
winuser::VK_SCROLL => Some(VirtualKeyCode::Scroll),
|
|
|
|
|
winuser::VK_BROWSER_BACK => Some(VirtualKeyCode::NavigateBackward),
|
|
|
|
|
winuser::VK_BROWSER_FORWARD => Some(VirtualKeyCode::NavigateForward),
|
|
|
|
|
winuser::VK_BROWSER_REFRESH => Some(VirtualKeyCode::WebRefresh),
|
|
|
|
|
winuser::VK_BROWSER_STOP => Some(VirtualKeyCode::WebStop),
|
|
|
|
|
winuser::VK_BROWSER_SEARCH => Some(VirtualKeyCode::WebSearch),
|
|
|
|
|
winuser::VK_BROWSER_FAVORITES => Some(VirtualKeyCode::WebFavorites),
|
|
|
|
|
winuser::VK_BROWSER_HOME => Some(VirtualKeyCode::WebHome),
|
|
|
|
|
winuser::VK_VOLUME_MUTE => Some(VirtualKeyCode::Mute),
|
|
|
|
|
winuser::VK_VOLUME_DOWN => Some(VirtualKeyCode::VolumeDown),
|
|
|
|
|
winuser::VK_VOLUME_UP => Some(VirtualKeyCode::VolumeUp),
|
|
|
|
|
winuser::VK_MEDIA_NEXT_TRACK => Some(VirtualKeyCode::NextTrack),
|
|
|
|
|
winuser::VK_MEDIA_PREV_TRACK => Some(VirtualKeyCode::PrevTrack),
|
|
|
|
|
winuser::VK_MEDIA_STOP => Some(VirtualKeyCode::MediaStop),
|
|
|
|
|
winuser::VK_MEDIA_PLAY_PAUSE => Some(VirtualKeyCode::PlayPause),
|
|
|
|
|
winuser::VK_LAUNCH_MAIL => Some(VirtualKeyCode::Mail),
|
|
|
|
|
winuser::VK_LAUNCH_MEDIA_SELECT => Some(VirtualKeyCode::MediaSelect),
|
|
|
|
|
/*winuser::VK_LAUNCH_APP1 => Some(VirtualKeyCode::Launch_app1),
|
|
|
|
|
winuser::VK_LAUNCH_APP2 => Some(VirtualKeyCode::Launch_app2),*/
|
|
|
|
|
winuser::VK_OEM_PLUS => Some(VirtualKeyCode::Equals),
|
|
|
|
|
winuser::VK_OEM_COMMA => Some(VirtualKeyCode::Comma),
|
|
|
|
|
winuser::VK_OEM_MINUS => Some(VirtualKeyCode::Minus),
|
|
|
|
|
winuser::VK_OEM_PERIOD => Some(VirtualKeyCode::Period),
|
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
|
|
|
winuser::VK_OEM_1 => map_text_keys(vkey),
|
|
|
|
|
winuser::VK_OEM_2 => map_text_keys(vkey),
|
|
|
|
|
winuser::VK_OEM_3 => map_text_keys(vkey),
|
|
|
|
|
winuser::VK_OEM_4 => map_text_keys(vkey),
|
|
|
|
|
winuser::VK_OEM_5 => map_text_keys(vkey),
|
|
|
|
|
winuser::VK_OEM_6 => map_text_keys(vkey),
|
|
|
|
|
winuser::VK_OEM_7 => map_text_keys(vkey),
|
2017-12-24 15:46:47 +02:00
|
|
|
/*winuser::VK_OEM_8 => Some(VirtualKeyCode::Oem_8), */
|
|
|
|
|
winuser::VK_OEM_102 => Some(VirtualKeyCode::OEM102),
|
|
|
|
|
/*winuser::VK_PROCESSKEY => Some(VirtualKeyCode::Processkey),
|
|
|
|
|
winuser::VK_PACKET => Some(VirtualKeyCode::Packet),
|
|
|
|
|
winuser::VK_ATTN => Some(VirtualKeyCode::Attn),
|
|
|
|
|
winuser::VK_CRSEL => Some(VirtualKeyCode::Crsel),
|
|
|
|
|
winuser::VK_EXSEL => Some(VirtualKeyCode::Exsel),
|
|
|
|
|
winuser::VK_EREOF => Some(VirtualKeyCode::Ereof),
|
|
|
|
|
winuser::VK_PLAY => Some(VirtualKeyCode::Play),
|
|
|
|
|
winuser::VK_ZOOM => Some(VirtualKeyCode::Zoom),
|
|
|
|
|
winuser::VK_NONAME => Some(VirtualKeyCode::Noname),
|
|
|
|
|
winuser::VK_PA1 => Some(VirtualKeyCode::Pa1),
|
|
|
|
|
winuser::VK_OEM_CLEAR => Some(VirtualKeyCode::Oem_clear),*/
|
2015-02-16 09:53:01 +01:00
|
|
|
_ => None
|
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
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-05-18 18:48:19 -04:00
|
|
|
pub fn handle_extended_keys(vkey: c_int, mut scancode: UINT, extended: bool) -> Option<(c_int, UINT)> {
|
|
|
|
|
// Welcome to hell https://blog.molecular-matters.com/2011/09/05/properly-handling-keyboard-input/
|
|
|
|
|
let vkey = match vkey {
|
|
|
|
|
winuser::VK_SHIFT => unsafe { winuser::MapVirtualKeyA(
|
|
|
|
|
scancode,
|
|
|
|
|
winuser::MAPVK_VSC_TO_VK_EX,
|
|
|
|
|
) as _ },
|
|
|
|
|
winuser::VK_CONTROL => if extended {
|
|
|
|
|
winuser::VK_RCONTROL
|
|
|
|
|
} else {
|
|
|
|
|
winuser::VK_LCONTROL
|
|
|
|
|
},
|
|
|
|
|
winuser::VK_MENU => if extended {
|
|
|
|
|
winuser::VK_RMENU
|
|
|
|
|
} else {
|
|
|
|
|
winuser::VK_LMENU
|
|
|
|
|
},
|
|
|
|
|
_ => match scancode {
|
|
|
|
|
// This is only triggered when using raw input. Without this check, we get two events whenever VK_PAUSE is
|
|
|
|
|
// pressed, the first one having scancode 0x1D but vkey VK_PAUSE...
|
|
|
|
|
0x1D if vkey == winuser::VK_PAUSE => return None,
|
|
|
|
|
// ...and the second having scancode 0x45 but an unmatched vkey!
|
|
|
|
|
0x45 => winuser::VK_PAUSE,
|
|
|
|
|
// VK_PAUSE and VK_SCROLL have the same scancode when using modifiers, alongside incorrect vkey values.
|
|
|
|
|
0x46 => {
|
|
|
|
|
if extended {
|
|
|
|
|
scancode = 0x45;
|
|
|
|
|
winuser::VK_PAUSE
|
|
|
|
|
} else {
|
|
|
|
|
winuser::VK_SCROLL
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
_ => vkey,
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
Some((vkey, scancode))
|
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
|
|
|
}
|
|
|
|
|
|
2018-05-18 18:48:19 -04:00
|
|
|
pub fn process_key_params(wparam: WPARAM, lparam: LPARAM) -> Option<(ScanCode, Option<VirtualKeyCode>)> {
|
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 scancode = ((lparam >> 16) & 0xff) as UINT;
|
|
|
|
|
let extended = (lparam & 0x01000000) != 0;
|
2018-05-18 18:48:19 -04:00
|
|
|
handle_extended_keys(wparam as _, scancode, extended)
|
|
|
|
|
.map(|(vkey, scancode)| (scancode, vkey_to_winit_vkey(vkey)))
|
2014-07-27 18:55:14 +02:00
|
|
|
}
|
2017-07-24 20:21:04 +10:00
|
|
|
|
|
|
|
|
// This is needed as windows doesn't properly distinguish
|
|
|
|
|
// some virtual key codes for different keyboard layouts
|
|
|
|
|
fn map_text_keys(win_virtual_key: i32) -> Option<VirtualKeyCode> {
|
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 char_key = unsafe { winuser::MapVirtualKeyA(win_virtual_key as u32, winuser::MAPVK_VK_TO_CHAR) } & 0x7FFF;
|
2017-07-24 20:21:04 +10:00
|
|
|
match char::from_u32(char_key) {
|
|
|
|
|
Some(';') => Some(VirtualKeyCode::Semicolon),
|
|
|
|
|
Some('/') => Some(VirtualKeyCode::Slash),
|
|
|
|
|
Some('`') => Some(VirtualKeyCode::Grave),
|
|
|
|
|
Some('[') => Some(VirtualKeyCode::LBracket),
|
|
|
|
|
Some(']') => Some(VirtualKeyCode::RBracket),
|
|
|
|
|
Some('\'') => Some(VirtualKeyCode::Apostrophe),
|
|
|
|
|
Some('\\') => Some(VirtualKeyCode::Backslash),
|
|
|
|
|
_ => None
|
|
|
|
|
}
|
|
|
|
|
}
|