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 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 Orbital, fix `logical_key` and `text` not reported in `KeyEvent`.
- On Orbital, implement `KeyEventExtModifierSupplement`.
# 0.29.10

View file

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

View file

@ -12,6 +12,7 @@ use orbclient::{
ButtonEvent, EventOption, FocusEvent, HoverEvent, KeyEvent, MouseEvent, MoveEvent, QuitEvent,
ResizeEvent, ScrollEvent, TextInputEvent,
};
use smol_str::SmolStr;
use crate::{
error::EventLoopError,
@ -154,6 +155,22 @@ struct 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) {
let code = match key {
PhysicalKey::Code(code) => code,
@ -333,39 +350,61 @@ impl<T: 'static> EventLoop<T> {
{
match event_option {
EventOption::Key(KeyEvent {
character: _,
character,
scancode,
pressed,
}) => {
if scancode != 0 {
let physical_key = convert_scancode(scancode);
let modifiers_before = event_state.keyboard;
event_state.key(physical_key, pressed);
let physical_key = convert_scancode(scancode);
let modifiers_before = event_state.keyboard;
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 {
window_id: RootWindowId(window_id),
event: event::WindowEvent::KeyboardInput {
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()),
})
}
event: event::WindowEvent::ModifiersChanged(event_state.modifiers()),
})
}
}
EventOption::TextInput(TextInputEvent { character }) => {

View file

@ -4,7 +4,12 @@ use std::fmt::{self, Display, Formatter};
use std::str;
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::{
EventLoop, EventLoopProxy, EventLoopWindowTarget, OwnedDisplayHandle,
@ -263,5 +268,8 @@ impl VideoModeHandle {
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct KeyEventExtra {}
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct KeyEventExtra {
pub key_without_modifiers: Key,
pub text_with_all_modifiers: Option<SmolStr>,
}