Skip to content

Commit

Permalink
New keyboard API for Windows (rust-windowing#1788)
Browse files Browse the repository at this point in the history
* Introducing the new `KeyEvent` and renaming old stuff

* Implemented physical_key on Windows

* Ran cargo fmt

* Progress with the keyboard's windows implementation

* Add proper handling of dead keys

* Add translation for non-printable virtual keys

* Run `cargo fmt`

* Fix for AltGraph not being reported

* Synthesize key events when focus enters or leaves

* Minor improvements

* Remove obsolete API

* Fix numlock and pause not being reported correctly

* Ran `cargo fmt`

* Fix numpad keys being reported incorrectly

* Update examples

* Ran `cargo fmt`

* Add documentation for `ScanCode`

* Add key binding example

* Use consistent modifier key names rust-windowing#1343

* WONT COMPILE transitioning to new keyboard API

* WONT COMPILE Implement new keyboard layout preparation

* WONT COMPILE new keyboard API progress

* Main compile errors fixed for keyboard

* Fix bugs in new keyboard handling

* Remove obsolete code

* Fix examples

* Ran `cargo fmt`

* Fix build error with serde

* Ran `cargo fmt`

* Tweaks in the Windows keyboard implementation

* Add `KeyCodeExtScancode`

* Add `reset_dead_keys`

* Improve the documentation for `Key` and `KeyCode`

* Rename the meta key to super

* Address feedback for the keyboard API

* Fix for rustdoc

Co-authored-by: Markus Røyset <maroider@protonmail.com>

* Improve documentation

Co-authored-by: Markus Røyset <maroider@protonmail.com>

* Fix for arrow keys being reported as unidentified.

And minor improvements

* Fix media keys reporting Unidentified

* Don't report text on key release events

* Fix for NumLock being reported as Pause in raw input

* Fix for strange behaviour around NumLock and Pause

* Fix for NumLock being ineffective

* Fix for location not being reported correctly

* `RawKeyEvent`s now report repeat

* Don't report text for synthetic key releases

* Address feedback

- Add the `Space` variant to the `to_text` function.
- Mark `get_kbd_state` safe.
- Change `[MaybeUninit<u8>; 256]` to `MaybeUninit<[u8; 256]>`

* Filter `Unidentified` from PrtSc key device events

* Don't report incorrect `RawKeyEvent` for shift + numpad

* AltGraph is not reported again

* Document Windows specific behaviour for shift+numpad

* Fix typo

* Dead keys now affect characters from logical_key

* Prevent Pause and NumLock mappings in window events

* Apply suggestions from code review

Co-authored-by: Markus Røyset <maroider@protonmail.com>

* Ran `cargo fmt`

* Add W3C license for `Key` and `KeyCode`

* Extend documentation according to feedback

* Ignore NumLock in `key_without_modifiers`

* Remove unused `key_code_to_non_char_key`

* Remove empty event.rs file

* Use space for resetting dead keys

* Fix reporting multiple graphemes in logical_key

* Avoid incorrect synthetic keypress during setfocus

* Fixed the AltGr keypress not being reported when the AltGr key is pressed and released in a very quick succession

* Filter fake Ctrl events when pressing AltGr

* Improve code quality

* Remove `repeat` from `RawKeyEvent`

* Allow fractional scroll in raw mouse events

* Fix typo

Co-authored-by: Markus Siglreithmaier <m.siglreith@gmail.com>

* Remove unused imports

* Remove unused variable

* Remove unnecessary `unwrap()`

Co-authored-by: Markus Siglreithmaier <m.siglreith@gmail.com>

* Avoid using the deprecated `into_rgba()`

* Fix IME crash

Co-authored-by: Markus Røyset <maroider@protonmail.com>
Co-authored-by: Markus Siglreithmaier <m.siglreith@gmail.com>

Fix the `drag_window` example
  • Loading branch information
ArturKovacs committed Jan 11, 2022
1 parent 8af222c commit 3ee2f02
Show file tree
Hide file tree
Showing 30 changed files with 4,516 additions and 1,264 deletions.
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ serde = { version = "1", optional = true, features = ["serde_derive"] }
raw-window-handle = "0.4.2"
bitflags = "1"
mint = { version = "0.5.6", optional = true }
nameof = "1"

[dev-dependencies]
image = "0.23.12"
Expand All @@ -56,6 +57,7 @@ features = ["display_link"]

[target.'cfg(target_os = "windows")'.dependencies]
parking_lot = "0.11"
unicode-segmentation = "1.7.1"

[target.'cfg(target_os = "windows")'.dependencies.winapi]
version = "0.3.9"
Expand All @@ -79,6 +81,7 @@ features = [
"winerror",
"wingdi",
"winnt",
"winnls",
"winuser",
"mmsystem",
"timeapi"
Expand Down
25 changes: 14 additions & 11 deletions examples/control_flow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ use std::{thread, time};

use simple_logger::SimpleLogger;
use winit::{
event::{Event, KeyboardInput, WindowEvent},
event::{ElementState, Event, KeyEvent, WindowEvent},
event_loop::{ControlFlow, EventLoop},
keyboard::Key,
window::WindowBuilder,
};

Expand Down Expand Up @@ -38,7 +39,7 @@ fn main() {
let mut close_requested = false;

event_loop.run(move |event, _, control_flow| {
use winit::event::{ElementState, StartCause, VirtualKeyCode};
use winit::event::StartCause;
println!("{:?}", event);
match event {
Event::NewEvents(start_cause) => {
Expand All @@ -52,31 +53,33 @@ fn main() {
close_requested = true;
}
WindowEvent::KeyboardInput {
input:
KeyboardInput {
virtual_keycode: Some(virtual_code),
event:
KeyEvent {
logical_key: key,
state: ElementState::Pressed,
..
},
..
} => match virtual_code {
VirtualKeyCode::Key1 => {
} => match key {
// WARNING: Consider using `key_without_modifers()` if available on your platform.
// See the `key_binding` example
Key::Character("1") => {
mode = Mode::Wait;
println!("\nmode: {:?}\n", mode);
}
VirtualKeyCode::Key2 => {
Key::Character("2") => {
mode = Mode::WaitUntil;
println!("\nmode: {:?}\n", mode);
}
VirtualKeyCode::Key3 => {
Key::Character("3") => {
mode = Mode::Poll;
println!("\nmode: {:?}\n", mode);
}
VirtualKeyCode::R => {
Key::Character("r") => {
request_redraw = !request_redraw;
println!("\nrequest_redraw: {}\n", request_redraw);
}
VirtualKeyCode::Escape => {
Key::Escape => {
close_requested = true;
}
_ => (),
Expand Down
6 changes: 3 additions & 3 deletions examples/cursor.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use simple_logger::SimpleLogger;
use winit::{
event::{ElementState, Event, KeyboardInput, WindowEvent},
event::{ElementState, Event, KeyEvent, WindowEvent},
event_loop::{ControlFlow, EventLoop},
window::{CursorIcon, WindowBuilder},
};
Expand All @@ -21,8 +21,8 @@ fn main() {
Event::WindowEvent {
event:
WindowEvent::KeyboardInput {
input:
KeyboardInput {
event:
KeyEvent {
state: ElementState::Pressed,
..
},
Expand Down
21 changes: 13 additions & 8 deletions examples/cursor_grab.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use simple_logger::SimpleLogger;
use winit::{
event::{DeviceEvent, ElementState, Event, KeyboardInput, ModifiersState, WindowEvent},
event::{DeviceEvent, ElementState, Event, KeyEvent, WindowEvent},
event_loop::{ControlFlow, EventLoop},
keyboard::{Key, ModifiersState},
window::WindowBuilder,
};

Expand All @@ -23,19 +24,23 @@ fn main() {
Event::WindowEvent { event, .. } => match event {
WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit,
WindowEvent::KeyboardInput {
input:
KeyboardInput {
event:
KeyEvent {
logical_key: key,
state: ElementState::Released,
virtual_keycode: Some(key),
..
},
..
} => {
use winit::event::VirtualKeyCode::*;
// WARNING: Consider using `key_without_modifers()` if available on your platform.
// See the `key_binding` example
match key {
Escape => *control_flow = ControlFlow::Exit,
G => window.set_cursor_grab(!modifiers.shift()).unwrap(),
H => window.set_cursor_visible(modifiers.shift()),
Key::Escape => *control_flow = ControlFlow::Exit,
Key::Character(ch) => match ch.to_lowercase().as_str() {
"g" => window.set_cursor_grab(!modifiers.shift_key()).unwrap(),
"h" => window.set_cursor_visible(modifiers.shift_key()),
_ => (),
},
_ => (),
}
}
Expand Down
11 changes: 5 additions & 6 deletions examples/drag_window.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
use simple_logger::SimpleLogger;
use winit::{
event::{
ElementState, Event, KeyboardInput, MouseButton, StartCause, VirtualKeyCode, WindowEvent,
},
event::{ElementState, Event, KeyEvent, MouseButton, StartCause, WindowEvent},
event_loop::{ControlFlow, EventLoop},
keyboard::Key,
window::{Window, WindowBuilder, WindowId},
};

Expand Down Expand Up @@ -43,10 +42,10 @@ fn main() {
name_windows(entered_id, switched, &window_1, &window_2)
}
WindowEvent::KeyboardInput {
input:
KeyboardInput {
event:
KeyEvent {
state: ElementState::Released,
virtual_keycode: Some(VirtualKeyCode::X),
logical_key: Key::Character("x"),
..
},
..
Expand Down
26 changes: 15 additions & 11 deletions examples/fullscreen.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use std::io::{stdin, stdout, Write};

use simple_logger::SimpleLogger;
use winit::event::{ElementState, Event, KeyboardInput, VirtualKeyCode, WindowEvent};
use winit::event::{ElementState, Event, KeyEvent, WindowEvent};
use winit::event_loop::{ControlFlow, EventLoop};
use winit::keyboard::Key;
use winit::monitor::{MonitorHandle, VideoMode};
use winit::window::{Fullscreen, WindowBuilder};

Expand Down Expand Up @@ -38,30 +39,33 @@ fn main() {
Event::WindowEvent { event, .. } => match event {
WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit,
WindowEvent::KeyboardInput {
input:
KeyboardInput {
virtual_keycode: Some(virtual_code),
state,
event:
KeyEvent {
logical_key: key,
state: ElementState::Pressed,
..
},
..
} => match (virtual_code, state) {
(VirtualKeyCode::Escape, _) => *control_flow = ControlFlow::Exit,
(VirtualKeyCode::F, ElementState::Pressed) => {
} => match key {
Key::Escape => *control_flow = ControlFlow::Exit,

// WARNING: Consider using `key_without_modifers()` if available on your platform.
// See the `key_binding` example
Key::Character("f") => {
if window.fullscreen().is_some() {
window.set_fullscreen(None);
} else {
window.set_fullscreen(fullscreen.clone());
}
}
(VirtualKeyCode::S, ElementState::Pressed) => {
Key::Character("s") => {
println!("window.fullscreen {:?}", window.fullscreen());
}
(VirtualKeyCode::M, ElementState::Pressed) => {
Key::Character("m") => {
let is_maximized = window.is_maximized();
window.set_maximized(!is_maximized);
}
(VirtualKeyCode::D, ElementState::Pressed) => {
Key::Character("d") => {
decorations = !decorations;
window.set_decorations(decorations);
}
Expand Down
23 changes: 11 additions & 12 deletions examples/handling_close.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use simple_logger::SimpleLogger;
use winit::{
event::{Event, KeyboardInput, WindowEvent},
event::{ElementState, Event, KeyEvent, WindowEvent},
event_loop::{ControlFlow, EventLoop},
keyboard::Key,
window::WindowBuilder,
};

Expand All @@ -17,10 +18,6 @@ fn main() {
let mut close_requested = false;

event_loop.run(move |event, _, control_flow| {
use winit::event::{
ElementState::Released,
VirtualKeyCode::{N, Y},
};
*control_flow = ControlFlow::Wait;

match event {
Expand All @@ -44,16 +41,18 @@ fn main() {
// the Y key.
}
WindowEvent::KeyboardInput {
input:
KeyboardInput {
virtual_keycode: Some(virtual_code),
state: Released,
event:
KeyEvent {
logical_key: key,
state: ElementState::Released,
..
},
..
} => {
match virtual_code {
Y => {
// WARNING: Consider using `key_without_modifers()` if available on your platform.
// See the `key_binding` example
match key {
Key::Character("y") => {
if close_requested {
// This is where you'll want to do any cleanup you need.
println!("Buh-bye!");
Expand All @@ -66,7 +65,7 @@ fn main() {
*control_flow = ControlFlow::Exit;
}
}
N => {
Key::Character("n") => {
if close_requested {
println!("Your window will continue to stay by your side.");
close_requested = false;
Expand Down
58 changes: 58 additions & 0 deletions examples/key_binding.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
use simple_logger::SimpleLogger;
use winit::{
dpi::LogicalSize,
event::{ElementState, Event, KeyEvent, WindowEvent},
event_loop::{ControlFlow, EventLoop},
keyboard::{Key, ModifiersState},
window::WindowBuilder,
};

/////////////////////////////////////////////////////////////////////////////
// WARNING: This is not available on all platforms (for example on the web).
use winit::platform::modifier_supplement::KeyEventExtModifierSupplement;
/////////////////////////////////////////////////////////////////////////////

fn main() {
SimpleLogger::new().init().unwrap();
let event_loop = EventLoop::new();

let _window = WindowBuilder::new()
.with_inner_size(LogicalSize::new(400.0, 200.0))
.build(&event_loop)
.unwrap();

let mut modifiers = ModifiersState::default();

event_loop.run(move |event, _, control_flow| {
*control_flow = ControlFlow::Wait;

match event {
Event::WindowEvent { event, .. } => match event {
WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit,
WindowEvent::ModifiersChanged(new_state) => {
modifiers = new_state;
}
WindowEvent::KeyboardInput { event, .. } => {
handle_key_event(modifiers, event);
}
_ => (),
},
_ => (),
};
});
}

fn handle_key_event(modifiers: ModifiersState, event: KeyEvent) {
if event.state == ElementState::Pressed && !event.repeat {
match event.key_without_modifiers() {
Key::Character("1") => {
if modifiers.shift_key() {
println!("Shift + 1 | logical_key: {:?}", event.logical_key);
} else {
println!("1");
}
}
_ => (),
}
}
}
12 changes: 8 additions & 4 deletions examples/minimize.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
extern crate winit;

use simple_logger::SimpleLogger;
use winit::event::{Event, VirtualKeyCode, WindowEvent};

use winit::event::{Event, WindowEvent};
use winit::event_loop::{ControlFlow, EventLoop};
use winit::keyboard::Key;
use winit::window::WindowBuilder;

fn main() {
Expand All @@ -25,12 +27,14 @@ fn main() {

// Keyboard input event to handle minimize via a hotkey
Event::WindowEvent {
event: WindowEvent::KeyboardInput { input, .. },
event: WindowEvent::KeyboardInput { event, .. },
window_id,
} => {
if window_id == window.id() {
// Pressing the 'M' key will minimize the window
if input.virtual_keycode == Some(VirtualKeyCode::M) {
// Pressing the 'm' key will minimize the window
// WARNING: Consider using `key_without_modifers()` if available on your platform.
// See the `key_binding` example
if let Key::Character("m") = event.logical_key {
window.set_minimized(true);
}
}
Expand Down
Loading

0 comments on commit 3ee2f02

Please sign in to comment.