On Orbital, implement KeyEventExtModifiersSupplement

This also fixes `logical_key` and `text` not reported in `KeyEvent`.
This commit is contained in:
Jeremy Soller 2024-02-08 01:55:11 -07:00 committed by GitHub
parent 20687fef1c
commit fedb86ea5a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 81 additions and 31 deletions

View file

@ -50,6 +50,8 @@ Unreleased` header.
- On Wayland, fix `Window::set_{min,max}_inner_size` not always applied. - On Wayland, fix `Window::set_{min,max}_inner_size` not always applied.
- On Windows, fix inconsistent resizing behavior with multi-monitor setups when repositioning outside the event loop. - On Windows, fix inconsistent resizing behavior with multi-monitor setups when repositioning outside the event loop.
- On Wayland, fix `WAYLAND_SOCKET` not used when detecting platform. - On Wayland, fix `WAYLAND_SOCKET` not used when detecting platform.
- On Orbital, fix `logical_key` and `text` not reported in `KeyEvent`.
- On Orbital, implement `KeyEventExtModifierSupplement`.
# 0.29.10 # 0.29.10

View file

@ -46,6 +46,7 @@ pub mod pump_events;
macos_platform, macos_platform,
x11_platform, x11_platform,
wayland_platform, wayland_platform,
orbital_platform,
docsrs docsrs
))] ))]
pub mod modifier_supplement; pub mod modifier_supplement;

View file

@ -12,6 +12,7 @@ use orbclient::{
ButtonEvent, EventOption, FocusEvent, HoverEvent, KeyEvent, MouseEvent, MoveEvent, QuitEvent, ButtonEvent, EventOption, FocusEvent, HoverEvent, KeyEvent, MouseEvent, MoveEvent, QuitEvent,
ResizeEvent, ScrollEvent, TextInputEvent, ResizeEvent, ScrollEvent, TextInputEvent,
}; };
use smol_str::SmolStr;
use crate::{ use crate::{
error::EventLoopError, error::EventLoopError,
@ -154,6 +155,22 @@ struct EventState {
} }
impl EventState { impl EventState {
fn character_all_modifiers(&self, character: char) -> char {
// Modify character if Ctrl is pressed
#[allow(clippy::collapsible_if)]
if self.keyboard.contains(KeyboardModifierState::LCTRL)
|| self.keyboard.contains(KeyboardModifierState::RCTRL)
{
if character.is_ascii_lowercase() {
return ((character as u8 - b'a') + 1) as char;
}
//TODO: more control key variants?
}
// Return character as-is if no special handling required
character
}
fn key(&mut self, key: PhysicalKey, pressed: bool) { fn key(&mut self, key: PhysicalKey, pressed: bool) {
let code = match key { let code = match key {
PhysicalKey::Code(code) => code, PhysicalKey::Code(code) => code,
@ -333,39 +350,61 @@ impl<T: 'static> EventLoop<T> {
{ {
match event_option { match event_option {
EventOption::Key(KeyEvent { EventOption::Key(KeyEvent {
character: _, character,
scancode, scancode,
pressed, pressed,
}) => { }) => {
if scancode != 0 { let physical_key = convert_scancode(scancode);
let physical_key = convert_scancode(scancode); let modifiers_before = event_state.keyboard;
let modifiers_before = event_state.keyboard; event_state.key(physical_key, pressed);
event_state.key(physical_key, pressed); let mut logical_key = Key::Unidentified(NativeKey::Unidentified);
let mut key_without_modifiers = Key::Unidentified(NativeKey::Unidentified);
let mut text = None;
let mut text_with_all_modifiers = None;
if character != '\0' {
let mut tmp = [0u8; 4];
let character_str = character.encode_utf8(&mut tmp);
// The key with Shift and Caps Lock applied (but not Ctrl)
logical_key = Key::Character(character_str.into());
// The key without Shift or Caps Lock applied
key_without_modifiers =
Key::Character(SmolStr::from_iter(character.to_lowercase()));
if pressed {
// The key with Shift and Caps Lock applied (but not Ctrl)
text = Some(character_str.into());
// The key with Shift, Caps Lock, and Ctrl applied
let character_all_modifiers =
event_state.character_all_modifiers(character);
text_with_all_modifiers =
Some(character_all_modifiers.encode_utf8(&mut tmp).into())
}
};
event_handler(event::Event::WindowEvent {
window_id: RootWindowId(window_id),
event: event::WindowEvent::KeyboardInput {
device_id: event::DeviceId(DeviceId),
event: event::KeyEvent {
logical_key,
physical_key,
location: KeyLocation::Standard,
state: element_state(pressed),
repeat: false,
text,
platform_specific: KeyEventExtra {
key_without_modifiers,
text_with_all_modifiers,
},
},
is_synthetic: false,
},
});
// If the state of the modifiers has changed, send the event.
if modifiers_before != event_state.keyboard {
event_handler(event::Event::WindowEvent { event_handler(event::Event::WindowEvent {
window_id: RootWindowId(window_id), window_id: RootWindowId(window_id),
event: event::WindowEvent::KeyboardInput { event: event::WindowEvent::ModifiersChanged(event_state.modifiers()),
device_id: event::DeviceId(DeviceId), })
event: event::KeyEvent {
logical_key: Key::Unidentified(NativeKey::Unidentified),
physical_key,
location: KeyLocation::Standard,
state: element_state(pressed),
repeat: false,
text: None,
platform_specific: KeyEventExtra {},
},
is_synthetic: false,
},
});
// If the state of the modifiers has changed, send the event.
if modifiers_before != event_state.keyboard {
event_handler(event::Event::WindowEvent {
window_id: RootWindowId(window_id),
event: event::WindowEvent::ModifiersChanged(event_state.modifiers()),
})
}
} }
} }
EventOption::TextInput(TextInputEvent { character }) => { EventOption::TextInput(TextInputEvent { character }) => {

View file

@ -4,7 +4,12 @@ use std::fmt::{self, Display, Formatter};
use std::str; use std::str;
use std::sync::Arc; use std::sync::Arc;
use crate::dpi::{PhysicalPosition, PhysicalSize}; use smol_str::SmolStr;
use crate::{
dpi::{PhysicalPosition, PhysicalSize},
keyboard::Key,
};
pub(crate) use self::event_loop::{ pub(crate) use self::event_loop::{
EventLoop, EventLoopProxy, EventLoopWindowTarget, OwnedDisplayHandle, EventLoop, EventLoopProxy, EventLoopWindowTarget, OwnedDisplayHandle,
@ -263,5 +268,8 @@ impl VideoModeHandle {
} }
} }
#[derive(Debug, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct KeyEventExtra {} pub struct KeyEventExtra {
pub key_without_modifiers: Key,
pub text_with_all_modifiers: Option<SmolStr>,
}