Merge KeyEventExtra into KeyEvent (#4029)

To make the fields easier to use, and to allow constructing KeyEvent in
user test code.
This commit is contained in:
Mads Marquart 2025-02-26 17:51:49 +01:00 committed by GitHub
parent 6c0e3c3b15
commit 0c89ea7386
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
19 changed files with 71 additions and 135 deletions

View file

@ -186,6 +186,8 @@ changelog entry.
- To match the corresponding changes in `windows-sys`, the `HWND`, `HMONITOR`, and `HMENU` types
now alias to `*mut c_void` instead of `isize`.
- On macOS, no longer need control of the main `NSApplication` class (which means you can now override it yourself).
- Removed `KeyEventExtModifierSupplement`, and made the fields `text_with_all_modifiers` and
`key_without_modifiers` public on `KeyEvent` instead.
### Removed

View file

@ -49,7 +49,6 @@ use crate::dpi::{PhysicalPosition, PhysicalSize};
use crate::error::RequestError;
use crate::event_loop::AsyncRequestSerial;
use crate::keyboard::{self, ModifiersKeyState, ModifiersKeys, ModifiersState};
use crate::platform_impl;
#[cfg(doc)]
use crate::window::Window;
use crate::window::{ActivationToken, Theme, WindowId};
@ -792,12 +791,6 @@ pub struct KeyEvent {
/// you somehow see this in the wild, we'd like to know :)
pub physical_key: keyboard::PhysicalKey,
// Allowing `broken_intra_doc_links` for `logical_key`, because
// `key_without_modifiers` is not available on all platforms
#[cfg_attr(
not(any(windows_platform, macos_platform, x11_platform, wayland_platform)),
allow(rustdoc::broken_intra_doc_links)
)]
/// This value is affected by all modifiers except <kbd>Ctrl</kbd>.
///
/// This has two use cases:
@ -813,7 +806,7 @@ pub struct KeyEvent {
/// - **Web:** Dead keys might be reported as the real key instead of `Dead` depending on the
/// browser/OS.
///
/// [`key_without_modifiers`]: crate::platform::modifier_supplement::KeyEventExtModifierSupplement::key_without_modifiers
/// [`key_without_modifiers`]: Self::key_without_modifiers
pub logical_key: keyboard::Key,
/// Contains the text produced by this keypress.
@ -834,7 +827,7 @@ pub struct KeyEvent {
/// This is `None` if the current keypress cannot
/// be interpreted as text.
///
/// See also: `text_with_all_modifiers()`
/// See also [`text_with_all_modifiers`][Self::text_with_all_modifiers].
pub text: Option<SmolStr>,
/// Contains the location of this key on the keyboard.
@ -890,13 +883,33 @@ pub struct KeyEvent {
/// ```
pub repeat: bool,
/// Platform-specific key event information.
/// Similar to [`text`][Self::text], except that this is affected by <kbd>Ctrl</kbd>.
///
/// On Windows, Linux and macOS, this type contains the key without modifiers and the text with
/// all modifiers applied.
/// For example, pressing <kbd>Ctrl</kbd>+<kbd>a</kbd> produces `Some("\x01")`.
///
/// On Android, iOS, Redox and Web, this type is a no-op.
pub(crate) platform_specific: platform_impl::KeyEventExtra,
/// ## Platform-specific
///
/// - **Android:** Unimplemented, this field is always the same value as `text`.
/// - **iOS:** Unimplemented, this field is always the same value as `text`.
/// - **Web:** Unsupported, this field is always the same value as `text`.
pub text_with_all_modifiers: Option<SmolStr>,
/// This value ignores all modifiers including, but not limited to <kbd>Shift</kbd>,
/// <kbd>Caps Lock</kbd>, and <kbd>Ctrl</kbd>. In most cases this means that the
/// unicode character in the resulting string is lowercase.
///
/// This is useful for key-bindings / shortcut key combinations.
///
/// In case [`logical_key`][Self::logical_key] reports [`Dead`][keyboard::Key::Dead],
/// this will still report the key as `Character` according to the current keyboard
/// layout. This value cannot be `Dead`.
///
/// ## Platform-specific
///
/// - **Android:** Unimplemented, this field is always the same value as `logical_key`.
/// - **iOS:** Unimplemented, this field is always the same value as `logical_key`.
/// - **Web:** Unsupported, this field is always the same value as `logical_key`.
pub key_without_modifiers: keyboard::Key,
}
/// Describes keyboard modifiers event.

View file

@ -42,15 +42,5 @@ pub mod run_on_demand;
))]
pub mod pump_events;
#[cfg(any(
windows_platform,
macos_platform,
x11_platform,
wayland_platform,
orbital_platform,
docsrs
))]
pub mod modifier_supplement;
#[cfg(any(windows_platform, macos_platform, x11_platform, wayland_platform, docsrs))]
pub mod scancode;

View file

@ -1,35 +0,0 @@
use crate::event::KeyEvent;
use crate::keyboard::Key;
/// Additional methods for the `KeyEvent` which cannot be implemented on all
/// platforms.
pub trait KeyEventExtModifierSupplement {
/// Identical to `KeyEvent::text` but this is affected by <kbd>Ctrl</kbd>.
///
/// For example, pressing <kbd>Ctrl</kbd>+<kbd>a</kbd> produces `Some("\x01")`.
fn text_with_all_modifiers(&self) -> Option<&str>;
/// This value ignores all modifiers including,
/// but not limited to <kbd>Shift</kbd>, <kbd>Caps Lock</kbd>,
/// and <kbd>Ctrl</kbd>. In most cases this means that the
/// unicode character in the resulting string is lowercase.
///
/// This is useful for key-bindings / shortcut key combinations.
///
/// In case `logical_key` reports `Dead`, this will still report the
/// key as `Character` according to the current keyboard layout. This value
/// cannot be `Dead`.
fn key_without_modifiers(&self) -> Key;
}
impl KeyEventExtModifierSupplement for KeyEvent {
#[inline]
fn text_with_all_modifiers(&self) -> Option<&str> {
self.platform_specific.text_with_all_modifiers.as_ref().map(|s| s.as_str())
}
#[inline]
fn key_without_modifiers(&self) -> Key {
self.platform_specific.key_without_modifiers.clone()
}
}

View file

@ -96,9 +96,6 @@ impl RedrawRequester {
}
}
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct KeyEventExtra {}
pub struct EventLoop {
pub(crate) android_app: AndroidApp,
window_target: ActiveEventLoop,
@ -478,7 +475,8 @@ impl EventLoop {
location: keycodes::to_location(keycode),
repeat: key.repeat_count() > 0,
text: None,
platform_specific: KeyEventExtra {},
text_with_all_modifiers: None,
key_without_modifiers: keycodes::to_logical(key_char, keycode),
},
is_synthetic: false,
};

View file

@ -14,12 +14,6 @@ use crate::keyboard::{
PhysicalKey,
};
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct KeyEventExtra {
pub text_with_all_modifiers: Option<SmolStr>,
pub key_without_modifiers: Key,
}
/// Ignores ALL modifiers.
pub fn get_modifierless_char(scancode: u16) -> Key {
let Some(ptr) = NonNull::new(unsafe { ffi::TISCopyCurrentKeyboardLayoutInputSource() }) else {
@ -157,7 +151,8 @@ pub(crate) fn create_key_event(ns_event: &NSEvent, is_press: bool, is_repeat: bo
repeat: is_repeat,
state,
text,
platform_specific: KeyEventExtra { text_with_all_modifiers, key_without_modifiers },
text_with_all_modifiers,
key_without_modifiers,
}
}

View file

@ -15,7 +15,7 @@ mod window;
mod window_delegate;
pub(crate) use self::cursor::CustomCursor as PlatformCustomCursor;
pub(crate) use self::event::{physicalkey_to_scancode, scancode_to_physicalkey, KeyEventExtra};
pub(crate) use self::event::{physicalkey_to_scancode, scancode_to_physicalkey};
pub(crate) use self::event_loop::{
ActiveEventLoop, EventLoop, PlatformSpecificEventLoopAttributes,
};

View file

@ -20,7 +20,7 @@ use super::app_state::AppState;
use super::cursor::{default_cursor, invisible_cursor};
use super::event::{
code_to_key, code_to_location, create_key_event, event_mods, lalt_pressed, ralt_pressed,
scancode_to_physicalkey, KeyEventExtra,
scancode_to_physicalkey,
};
use super::window::window_id;
use crate::dpi::{LogicalPosition, LogicalSize};
@ -940,10 +940,8 @@ impl WinitView {
// We'll correct this later.
state: Pressed,
text: None,
platform_specific: KeyEventExtra {
text_with_all_modifiers: None,
key_without_modifiers: logical_key.clone(),
},
text_with_all_modifiers: None,
key_without_modifiers: logical_key.clone(),
};
let location_mask = ModLocationMask::from_location(event.location);

View file

@ -20,9 +20,6 @@ pub(crate) use crate::cursor::{
pub(crate) use crate::icon::NoIcon as PlatformIcon;
pub(crate) use crate::platform_impl::Fullscreen;
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct KeyEventExtra {}
#[derive(Debug)]
pub enum OsError {}

View file

@ -22,7 +22,6 @@ use crate::event::{
WindowEvent,
};
use crate::keyboard::{Key, KeyCode, KeyLocation, NamedKey, NativeKeyCode, PhysicalKey};
use crate::platform_impl::KeyEventExtra;
use crate::window::WindowAttributes;
pub struct WinitViewState {
@ -644,7 +643,12 @@ impl WinitView {
repeat: false,
logical_key: Key::Character(text.clone()),
physical_key: PhysicalKey::Unidentified(NativeKeyCode::Unidentified),
platform_specific: KeyEventExtra {},
text_with_all_modifiers: if state == ElementState::Pressed {
Some(text.clone())
} else {
None
},
key_without_modifiers: Key::Character(text.clone()),
},
is_synthetic: false,
},
@ -667,10 +671,11 @@ impl WinitView {
state,
logical_key: Key::Named(NamedKey::Backspace),
physical_key: PhysicalKey::Code(KeyCode::Backspace),
platform_specific: KeyEventExtra {},
repeat: false,
location: KeyLocation::Standard,
text: None,
text_with_all_modifiers: None,
key_without_modifiers: Key::Named(NamedKey::Backspace),
},
is_synthetic: false,
},

View file

@ -16,7 +16,6 @@ use {x11_dl::xlib_xcb::xcb_connection_t, xkbcommon_dl::x11::xkbcommon_x11_handle
use crate::event::{ElementState, KeyEvent};
use crate::keyboard::{Key, KeyLocation};
use crate::platform_impl::KeyEventExtra;
use crate::utils::Lazy;
mod compose;
@ -198,9 +197,16 @@ impl KeyContext<'_> {
let (key_without_modifiers, _) = event.key_without_modifiers();
let text_with_all_modifiers = event.text_with_all_modifiers();
let platform_specific = KeyEventExtra { text_with_all_modifiers, key_without_modifiers };
KeyEvent { physical_key, logical_key, text, location, state, repeat, platform_specific }
KeyEvent {
physical_key,
logical_key,
text,
location,
state,
repeat,
text_with_all_modifiers,
key_without_modifiers,
}
}
fn keysym_to_utf8_raw(&mut self, keysym: u32) -> Option<SmolStr> {

View file

@ -9,8 +9,6 @@ use std::time::Duration;
#[cfg(x11_platform)]
use std::{ffi::CStr, mem::MaybeUninit, os::raw::*, sync::Arc, sync::Mutex};
use smol_str::SmolStr;
pub(crate) use self::common::xkb::{physicalkey_to_scancode, scancode_to_physicalkey};
#[cfg(x11_platform)]
use self::x11::{XConnection, XError, XNotSupported};
@ -22,7 +20,6 @@ use crate::dpi::Size;
use crate::error::{EventLoopError, NotSupportedError};
use crate::event_loop::ActiveEventLoop;
pub(crate) use crate::icon::RgbaIcon as PlatformIcon;
use crate::keyboard::Key;
use crate::monitor::VideoMode;
use crate::platform::pump_events::PumpStatus;
#[cfg(x11_platform)]
@ -175,12 +172,6 @@ impl MonitorHandle {
}
}
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct KeyEventExtra {
pub text_with_all_modifiers: Option<SmolStr>,
pub key_without_modifiers: Key,
}
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub(crate) enum PlatformCustomCursor {
#[cfg(wayland_platform)]

View file

@ -12,8 +12,7 @@ use orbclient::{
use smol_str::SmolStr;
use super::{
KeyEventExtra, MonitorHandle, PlatformSpecificEventLoopAttributes, RedoxSocket, TimeSocket,
WindowProperties,
MonitorHandle, PlatformSpecificEventLoopAttributes, RedoxSocket, TimeSocket, WindowProperties,
};
use crate::application::ApplicationHandler;
use crate::error::{EventLoopError, NotSupportedError, RequestError};
@ -372,10 +371,8 @@ impl EventLoop {
state: element_state(pressed),
repeat: false,
text,
platform_specific: KeyEventExtra {
key_without_modifiers,
text_with_all_modifiers,
},
key_without_modifiers,
text_with_all_modifiers,
},
is_synthetic: false,
};

View file

@ -2,12 +2,9 @@
use std::{fmt, str};
use smol_str::SmolStr;
pub(crate) use self::event_loop::{ActiveEventLoop, EventLoop};
pub use self::window::Window;
use crate::dpi::PhysicalPosition;
use crate::keyboard::Key;
use crate::monitor::VideoMode;
mod event_loop;
@ -160,9 +157,3 @@ impl MonitorHandle {
std::iter::empty()
}
}
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct KeyEventExtra {
pub key_without_modifiers: Key,
pub text_with_all_modifiers: Option<SmolStr>,
}

View file

@ -6,8 +6,8 @@ use std::sync::Arc;
use web_sys::Element;
use super::super::lock;
use super::super::monitor::MonitorPermissionFuture;
use super::super::{lock, KeyEventExtra};
use super::runner::Event;
use super::{backend, runner};
use crate::application::ApplicationHandler;
@ -140,12 +140,13 @@ impl ActiveEventLoop {
device_id: None,
event: KeyEvent {
physical_key,
logical_key,
text,
logical_key: logical_key.clone(),
text: text.clone(),
location,
state: ElementState::Pressed,
repeat,
platform_specific: KeyEventExtra,
text_with_all_modifiers: text,
key_without_modifiers: logical_key,
},
is_synthetic: false,
},
@ -174,12 +175,13 @@ impl ActiveEventLoop {
device_id: None,
event: KeyEvent {
physical_key,
logical_key,
text,
logical_key: logical_key.clone(),
text: text.clone(),
location,
state: ElementState::Released,
repeat,
platform_specific: KeyEventExtra,
text_with_all_modifiers: text,
key_without_modifiers: logical_key,
},
is_synthetic: false,
},

View file

@ -2,9 +2,6 @@ use smol_str::SmolStr;
use crate::keyboard::{Key, KeyCode, NamedKey, NativeKey, NativeKeyCode, PhysicalKey};
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub(crate) struct KeyEventExtra;
impl Key {
pub(crate) fn from_key_attribute_value(kav: &str) -> Self {
Key::Named(match kav {

View file

@ -40,7 +40,6 @@ pub(crate) use cursor::{
pub(crate) use self::event_loop::{
ActiveEventLoop, EventLoop, PlatformSpecificEventLoopAttributes,
};
pub(crate) use self::keyboard::KeyEventExtra;
pub(crate) use self::monitor::{
HasMonitorPermissionFuture, MonitorHandle, MonitorPermissionFuture, OrientationLockFuture,
};

View file

@ -31,7 +31,7 @@ use crate::platform_impl::platform::event_loop::ProcResult;
use crate::platform_impl::platform::keyboard_layout::{
Layout, LayoutCache, WindowsModifiers, LAYOUT_CACHE,
};
use crate::platform_impl::platform::{loword, primarylangid, KeyEventExtra};
use crate::platform_impl::platform::{loword, primarylangid};
pub type ExScancode = u16;
@ -451,7 +451,7 @@ impl KeyEventBuilder {
let mut event = event_info.finalize();
event.logical_key = logical_key;
event.platform_specific.text_with_all_modifiers = text;
event.text_with_all_modifiers = text;
Some(MessageAsKeyEvent { event, is_synthetic: true })
}
}
@ -629,10 +629,8 @@ impl PartialKeyEventInfo {
location: self.location,
state: self.key_state,
repeat: self.is_repeat,
platform_specific: KeyEventExtra {
text_with_all_modifiers: char_with_all_modifiers,
key_without_modifiers: self.key_without_modifiers,
},
text_with_all_modifiers: char_with_all_modifiers,
key_without_modifiers: self.key_without_modifiers,
}
}
}

View file

@ -1,4 +1,3 @@
use smol_str::SmolStr;
use windows_sys::Win32::Foundation::HWND;
use windows_sys::Win32::UI::WindowsAndMessaging::{HMENU, WINDOW_LONG_PTR_INDEX};
@ -11,7 +10,6 @@ pub(crate) use self::window::Window;
pub(crate) use crate::cursor::OnlyCursorImageSource as PlatformCustomCursorSource;
use crate::event::DeviceId;
use crate::icon::Icon;
use crate::keyboard::Key;
use crate::platform::windows::{BackdropType, Color, CornerPreference};
use crate::platform_impl::Fullscreen;
@ -61,12 +59,6 @@ fn wrap_device_id(id: u32) -> DeviceId {
DeviceId::from_raw(id as i64)
}
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct KeyEventExtra {
pub text_with_all_modifiers: Option<SmolStr>,
pub key_without_modifiers: Key,
}
#[inline(always)]
const fn get_xbutton_wparam(x: u32) -> u16 {
hiword(x)