diff --git a/CHANGELOG.md b/CHANGELOG.md index decfd7ae..523f2a97 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/src/platform/mod.rs b/src/platform/mod.rs index 187489da..da6c7aa8 100644 --- a/src/platform/mod.rs +++ b/src/platform/mod.rs @@ -46,6 +46,7 @@ pub mod pump_events; macos_platform, x11_platform, wayland_platform, + orbital_platform, docsrs ))] pub mod modifier_supplement; diff --git a/src/platform_impl/orbital/event_loop.rs b/src/platform_impl/orbital/event_loop.rs index aa7acb2a..6ff4aeb3 100644 --- a/src/platform_impl/orbital/event_loop.rs +++ b/src/platform_impl/orbital/event_loop.rs @@ -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 EventLoop { { 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 }) => { diff --git a/src/platform_impl/orbital/mod.rs b/src/platform_impl/orbital/mod.rs index 4d544998..945da77e 100644 --- a/src/platform_impl/orbital/mod.rs +++ b/src/platform_impl/orbital/mod.rs @@ -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, +}