Skip to content

Commit

Permalink
Overhaul the Keyboard API
Browse files Browse the repository at this point in the history
Overhaul the keyboard API in winit to mimic the W3C specification
to achieve better crossplatform parity. The `KeyboardInput` event
is now uses `KeyEvent` which consists of:

  - `physical_key` - a cross platform way to refer to scancodes;
  - `logical_key`  - keysym value, which shows your key respecting the
                     layout;
  - `text`         - the text produced by this keypress;
  - `location`     - the location of the key on the keyboard;
  - `repeat`       - whether the key was produced by the repeat.

And also a `platform_specific` field which encapsulates extra
information on desktop platforms, like key without modifiers
and text with all modifiers.

The `Modifiers` were also slightly reworked as in, the information
whether the left or right modifier is pressed is now also exposed
on platforms where it could be queried reliably. The support was
also added for the web and orbital platforms finishing the API
change.

This change made the `OptionAsAlt` API on macOS redundant thus it
was removed all together.

Co-authored-by: Artúr Kovács <[email protected]>
Co-authored-by: Kirill Chibisov <[email protected]>
Co-authored-by: daxpedda <[email protected]>
Fixes: rust-windowing#2631.
Fixes: rust-windowing#2055.
Fixes: rust-windowing#2032.
Fixes: rust-windowing#1904.
Fixes: rust-windowing#1810.
Fixes: rust-windowing#1700.
Fixes: rust-windowing#1443.
Fixes: rust-windowing#1343.
Fixes: rust-windowing#1208.
Fixes: rust-windowing#1151.
Fixes: rust-windowing#812.
Fixes: rust-windowing#600.
Fixes: rust-windowing#361.
Fixes: rust-windowing#343.
  • Loading branch information
4 people authored May 28, 2023
1 parent f3f46cb commit 9184309
Show file tree
Hide file tree
Showing 81 changed files with 9,570 additions and 3,412 deletions.
6 changes: 1 addition & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@ jobs:
env:
RUST_BACKTRACE: 1
CARGO_INCREMENTAL: 0
PKG_CONFIG_ALLOW_CROSS: 1
RUSTFLAGS: "-C debuginfo=0 --deny warnings"
OPTIONS: ${{ matrix.platform.options }}
FEATURES: ${{ format(',{0}', matrix.platform.features ) }}
Expand All @@ -98,12 +97,9 @@ jobs:
targets: ${{ matrix.platform.target }}
components: clippy

- name: Install Linux dependencies
if: (matrix.platform.os == 'ubuntu-latest')
run: sudo apt-get update && sudo apt-get install pkg-config libxkbcommon-dev
- name: Install GCC Multilib
if: (matrix.platform.os == 'ubuntu-latest') && contains(matrix.platform.target, 'i686')
run: sudo dpkg --add-architecture i386 && sudo apt-get update && sudo apt-get install g++-multilib gcc-multilib libxkbcommon-dev:i386
run: sudo apt-get update && sudo apt-get install gcc-multilib
- name: Install cargo-apk
if: contains(matrix.platform.target, 'android')
run: cargo install cargo-apk
Expand Down
28 changes: 28 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,34 @@ And please only add new entries to the top of this list, right below the `# Unre

# Unreleased

- **Breaking:** Remove all deprecated `modifiers` fields.
- **Breaking:** Overhaul keyboard input handling.
- Replace `KeyboardInput` with `KeyEvent` and `RawKeyEvent`.
- Change `WindowEvent::KeyboardInput` to contain a `KeyEvent`.
- Change `Event::Key` to contain a `RawKeyEvent`.
- Remove `Event::ReceivedCharacter`. In its place, you should use
`KeyEvent.text` in combination with `WindowEvent::Ime`.
- Replace `VirtualKeyCode` with the `Key` enum.
- Replace `ScanCode` with the `KeyCode` enum.
- Rename `ModifiersState::LOGO` to `SUPER` and `ModifiersState::CTRL` to `CONTROL`.
- Add `KeyCode` to refer to keys (roughly) by their physical location.
- Add `NativeKeyCode` to represent raw `KeyCode`s which Winit doesn't
understand.
- Add `Key` to represent the keys after they've been interpreted by the
active (software) keyboard layout.
- Add `NativeKey` to represent raw `Key`s which Winit doesn't understand.
- Add `KeyLocation` to tell apart `Key`s which usually "mean" the same thing,
but can appear simultanesouly in different spots on the same keyboard
layout.
- Add `Window::reset_dead_keys` to enable application-controlled cancellation
of dead key sequences.
- Add `KeyEventExtModifierSupplement` to expose additional (and less
portable) interpretations of a given key-press.
- Add `KeyCodeExtScancode`, which lets you convert between raw keycodes and
`KeyCode`.
- Remove `WindowExtMacOS::option_as_alt` and `WindowExtMacOS::set_option_as_alt`.
- `ModifiersChanged` now uses dedicated `Modifiers` struct.
- On Orbital, fix `ModifiersChanged` not being sent.
- **Breaking:** `CursorIcon` is now used from the `cursor-icon` crate.
- **Breaking:** `CursorIcon::Hand` is now named `CursorIcon::Pointer`.
- **Breaking:** `CursorIcon::Arrow` was removed.
Expand Down
15 changes: 11 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,15 @@ rustdoc-args = ["--cfg", "docsrs"]

[features]
default = ["x11", "wayland", "wayland-dlopen", "wayland-csd-adwaita"]
x11 = ["x11-dl", "mio", "percent-encoding"]
wayland = ["wayland-client", "wayland-backend", "wayland-protocols", "sctk", "fnv"]
x11 = ["x11-dl", "mio", "percent-encoding", "xkbcommon-dl/x11"]
wayland = ["wayland-client", "wayland-backend", "wayland-protocols", "sctk", "fnv", "memmap2"]
wayland-dlopen = ["wayland-backend/dlopen"]
wayland-csd-adwaita = ["sctk-adwaita", "sctk-adwaita/ab_glyph"]
wayland-csd-adwaita-crossfont = ["sctk-adwaita", "sctk-adwaita/crossfont"]
wayland-csd-adwaita-notitle = ["sctk-adwaita"]
android-native-activity = ["android-activity/native-activity"]
android-game-activity = ["android-activity/game-activity"]
serde = ["dep:serde", "cursor-icon/serde"]
serde = ["dep:serde", "cursor-icon/serde", "smol_str/serde"]

[build-dependencies]
cfg_aliases = "0.1.1"
Expand All @@ -58,6 +58,7 @@ mint = { version = "0.5.6", optional = true }
once_cell = "1.12"
raw_window_handle = { package = "raw-window-handle", version = "0.5" }
serde = { version = "1", optional = true, features = ["serde_derive"] }
smol_str = "0.2.0"

[dev-dependencies]
image = { version = "0.24.0", default-features = false, features = ["png"] }
Expand All @@ -67,6 +68,7 @@ simple_logger = { version = "2.1.0", default_features = false }
# Coordinate the next winit release with android-ndk-rs: https://github.com/rust-windowing/winit/issues/1995
android-activity = "0.4.0"
ndk = "0.7.0"
ndk-sys = "0.4.0"

[target.'cfg(any(target_os = "ios", target_os = "macos"))'.dependencies]
core-foundation = "0.9.3"
Expand All @@ -76,6 +78,9 @@ objc2 = ">=0.3.0-beta.3, <0.3.0-beta.4" # Allow `0.3.0-beta.3.patch-leaks`
core-graphics = "0.22.3"
dispatch = "0.2.0"

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

[target.'cfg(target_os = "windows")'.dependencies.windows-sys]
version = "0.45"
features = [
Expand Down Expand Up @@ -110,13 +115,15 @@ libc = "0.2.64"
mio = { version = "0.8", features = ["os-ext"], optional = true }
percent-encoding = { version = "2.0", optional = true }
fnv = { version = "1.0.3", optional = true }
sctk = { package = "smithay-client-toolkit", version = "0.17.0", optional = true }
sctk = { package = "smithay-client-toolkit", version = "0.17.0", default-features = false, features = ["calloop"], optional = true }
sctk-adwaita = { version = "0.6.0", default_features = false, optional = true }
wayland-client = { version = "0.30.0", optional = true }
wayland-backend = { version = "0.1.0", default_features = false, features = ["client_system"], optional = true }
wayland-protocols = { version = "0.30.0", features = [ "staging"], optional = true }
calloop = "0.10.5"
x11-dl = { version = "2.18.5", optional = true }
xkbcommon-dl = { git = "https://github.com/maroider/xkbcommon-dl", rev = "900832888ad6f11011d1369befb344a9aa8a9610" }
memmap2 = { version = "0.5.0", optional = true }

[target.'cfg(target_os = "redox")'.dependencies]
orbclient = { version = "0.3.42", default-features = false }
Expand Down
8 changes: 4 additions & 4 deletions FEATURES.md
Original file line number Diff line number Diff line change
Expand Up @@ -222,9 +222,9 @@ Changes in the API that have been agreed upon but aren't implemented across all

|Feature |Windows|MacOS |Linux x11|Linux Wayland|Android|iOS |WASM |Redox OS|
|------------------------------ | ----- | ---- | ------- | ----------- | ----- | ----- | -------- | ------ |
|New API for HiDPI ([#315] [#319]) |✔️ |✔️ |✔️ |✔️ |✔️ |✔️ |||
|Event Loop 2.0 ([#459]) |✔️ |✔️ |✔️ |✔️ |✔️ |✔️ || |
|Keyboard Input ([#812]) || | | | || | |
|New API for HiDPI ([#315] [#319]) |✔️ |✔️ |✔️ |✔️ |✔️ |✔️ |||
|Event Loop 2.0 ([#459]) |✔️ |✔️ |✔️ |✔️ |✔️ |✔️ ||✔️ |
|Keyboard Input 2.0 ([#753]) |✔️ |✔️ |✔️ |✔️ |✔️ | |✔️ |✔️ |

### Completed API Reworks
|Feature |Windows|MacOS |Linux x11|Linux Wayland|Android|iOS |WASM |Redox OS|
Expand All @@ -243,5 +243,5 @@ Changes in the API that have been agreed upon but aren't implemented across all
[#720]: https://github.com/rust-windowing/winit/issues/720
[#721]: https://github.com/rust-windowing/winit/issues/721
[#750]: https://github.com/rust-windowing/winit/issues/750
[#753]: https://github.com/rust-windowing/winit/issues/753
[#804]: https://github.com/rust-windowing/winit/issues/804
[#812]: https://github.com/rust-windowing/winit/issues/812
11 changes: 11 additions & 0 deletions docs/res/ATTRIBUTION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Image Attribution

These images are used in the documentation of `winit`.

## keyboard_*.svg

These files are a modified version of "[ANSI US QWERTY (Windows)](https://commons.wikimedia.org/wiki/File:ANSI_US_QWERTY_(Windows).svg)"
by [Tomiĉo] (https://commons.wikimedia.org/wiki/User:Tomi%C4%89o). It is
originally released under the [CC-BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/deed.en)
License. Minor modifications have been made by [John Nunley](https://github.com/notgull),
which have been released under the same license as a derivative work.
1 change: 1 addition & 0 deletions docs/res/keyboard_left_shift_key.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions docs/res/keyboard_numpad_1_key.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions docs/res/keyboard_right_shift_key.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions docs/res/keyboard_standard_1_key.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 3 additions & 3 deletions examples/child_window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ fn main() {
use raw_window_handle::HasRawWindowHandle;
use winit::{
dpi::{LogicalPosition, LogicalSize, Position},
event::{ElementState, Event, KeyboardInput, WindowEvent},
event::{ElementState, Event, KeyEvent, WindowEvent},
event_loop::{ControlFlow, EventLoop, EventLoopWindowTarget},
window::{Window, WindowBuilder, WindowId},
};
Expand Down Expand Up @@ -59,8 +59,8 @@ fn main() {
println!("cursor entered in the window {window_id:?}");
}
WindowEvent::KeyboardInput {
input:
KeyboardInput {
event:
KeyEvent {
state: ElementState::Pressed,
..
},
Expand Down
25 changes: 14 additions & 11 deletions examples/control_flow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ use std::{thread, time};

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

Expand Down Expand Up @@ -40,7 +41,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 @@ -54,31 +55,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.as_ref() {
// WARNING: Consider using `key_without_modifers()` if available on your platform.
// See the `key_binding` example
Key::Character("1") => {
mode = Mode::Wait;
println!("\nmode: {mode:?}\n");
}
VirtualKeyCode::Key2 => {
Key::Character("2") => {
mode = Mode::WaitUntil;
println!("\nmode: {mode:?}\n");
}
VirtualKeyCode::Key3 => {
Key::Character("3") => {
mode = Mode::Poll;
println!("\nmode: {mode:?}\n");
}
VirtualKeyCode::R => {
Key::Character("r") => {
request_redraw = !request_redraw;
println!("\nrequest_redraw: {request_redraw}\n");
}
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
Expand Up @@ -2,7 +2,7 @@

use simple_logger::SimpleLogger;
use winit::{
event::{ElementState, Event, KeyboardInput, WindowEvent},
event::{ElementState, Event, KeyEvent, WindowEvent},
event_loop::EventLoop,
window::{CursorIcon, WindowBuilder},
};
Expand All @@ -23,8 +23,8 @@ fn main() {
Event::WindowEvent {
event:
WindowEvent::KeyboardInput {
input:
KeyboardInput {
event:
KeyEvent {
state: ElementState::Pressed,
..
},
Expand Down
31 changes: 17 additions & 14 deletions examples/cursor_grab.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@

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

Expand All @@ -25,35 +26,37 @@ fn main() {
Event::WindowEvent { event, .. } => match event {
WindowEvent::CloseRequested => control_flow.set_exit(),
WindowEvent::KeyboardInput {
input:
KeyboardInput {
event:
KeyEvent {
logical_key: key,
state: ElementState::Released,
virtual_keycode: Some(key),
..
},
..
} => {
use winit::event::VirtualKeyCode::*;
let result = match key {
Escape => {
Key::Escape => {
control_flow.set_exit();
Ok(())
}
G => window.set_cursor_grab(CursorGrabMode::Confined),
L => window.set_cursor_grab(CursorGrabMode::Locked),
A => window.set_cursor_grab(CursorGrabMode::None),
H => {
window.set_cursor_visible(modifiers.shift());
Ok(())
}
Key::Character(ch) => match ch.to_lowercase().as_str() {
"g" => window.set_cursor_grab(CursorGrabMode::Confined),
"l" => window.set_cursor_grab(CursorGrabMode::Locked),
"a" => window.set_cursor_grab(CursorGrabMode::None),
"h" => {
window.set_cursor_visible(modifiers.shift_key());
Ok(())
}
_ => Ok(()),
},
_ => Ok(()),
};

if let Err(err) = result {
println!("error: {err}");
}
}
WindowEvent::ModifiersChanged(m) => modifiers = m,
WindowEvent::ModifiersChanged(new) => modifiers = new.state(),
_ => (),
},
Event::DeviceEvent { event, .. } => match event {
Expand Down
13 changes: 6 additions & 7 deletions examples/drag_window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@

use simple_logger::SimpleLogger;
use winit::{
event::{
ElementState, Event, KeyboardInput, MouseButton, StartCause, VirtualKeyCode, WindowEvent,
},
event::{ElementState, Event, KeyEvent, MouseButton, StartCause, WindowEvent},
event_loop::EventLoop,
keyboard::Key,
window::{Window, WindowBuilder, WindowId},
};

Expand Down Expand Up @@ -45,14 +44,14 @@ 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(c),
..
},
..
} => {
} if c == "x" => {
switched = !switched;
name_windows(entered_id, switched, &window_1, &window_2);
println!("Switched!")
Expand Down
Loading

0 comments on commit 9184309

Please sign in to comment.