linuxkms: Implement keyboard input and clamp mouse

Unfortunately, this is currently not mapped to the right keyboard layout

Also keep the mouse clamped in the visible area.
And make it start in the middle of the screen.
This commit is contained in:
Olivier Goffart 2023-07-31 16:43:33 +02:00 committed by Olivier Goffart
parent 23ca0cb36c
commit ad389aa4eb
10 changed files with 139 additions and 85 deletions

View file

@ -67,7 +67,7 @@ namespace slint::platform::key_codes {{
"#
)?;
macro_rules! print_key_codes {
($($char:literal # $name:ident # $($qt:ident)|* # $($winit:ident)|* ;)*) => {
($($char:literal # $name:ident # $($qt:ident)|* # $($winit:ident)|* # $($_xkb:ident)|*;)*) => {
$(
writeln!(enums_pub, "/// A constant that represents the key code to be used in slint::Window::dispatch_key_press_event()")?;
writeln!(enums_pub, r#"constexpr std::u8string_view {} = u8"\u{:04x}";"#, stringify!($name), $char as u32)?;

View file

@ -25,6 +25,7 @@ renderer-femtovg = ["i-slint-renderer-femtovg", "drm", "gbm", "glutin", "raw-win
[dependencies]
i-slint-core = { version = "=1.2.0", path = "../../../internal/core", features = ["image-decoders", "svg"] }
i-slint-common = { version = "=1.2.0", path = "../../../internal/common" }
i-slint-renderer-skia = { version = "=1.2.0", path = "../../renderers/skia", optional = true }
i-slint-renderer-femtovg = { version = "=1.2.0", path = "../../renderers/femtovg", optional = true }

View file

@ -73,6 +73,8 @@ pub struct Backend {
Box<dyn crate::fullscreenwindowadapter::FullscreenRenderer>,
i_slint_core::platform::PlatformError,
>,
sel_clipboard: RefCell<Option<String>>,
clipboard: RefCell<Option<String>>,
}
impl Backend {
@ -133,6 +135,8 @@ impl Backend {
user_event_receiver: RefCell::new(Some(user_event_receiver)),
proxy: Proxy::new(user_event_sender),
renderer_factory,
sel_clipboard: Default::default(),
clipboard: Default::default(),
})
}
}
@ -229,6 +233,27 @@ impl i_slint_core::platform::Platform for Backend {
fn new_event_loop_proxy(&self) -> Option<Box<dyn i_slint_core::platform::EventLoopProxy>> {
Some(Box::new(self.proxy.clone()))
}
fn clipboard_text(&self, clipboard: i_slint_core::platform::Clipboard) -> Option<String> {
match clipboard {
i_slint_core::platform::Clipboard::DefaultClipboard => self.clipboard.borrow().clone(),
i_slint_core::platform::Clipboard::SelectionClipboard => {
self.sel_clipboard.borrow().clone()
}
_ => None,
}
}
fn set_clipboard_text(&self, text: &str, clipboard: i_slint_core::platform::Clipboard) {
match clipboard {
i_slint_core::platform::Clipboard::DefaultClipboard => {
*self.clipboard.borrow_mut() = Some(text.into())
}
i_slint_core::platform::Clipboard::SelectionClipboard => {
*self.sel_clipboard.borrow_mut() = Some(text.into())
}
_ => (),
}
}
}
#[derive(Default)]

View file

@ -13,10 +13,10 @@ use std::rc::Rc;
use i_slint_core::api::LogicalPosition;
use i_slint_core::platform::{PlatformError, PointerEventButton, WindowEvent};
use i_slint_core::Property;
use i_slint_core::{Property, SharedString};
use input::LibinputInterface;
use input::event::keyboard::KeyboardEventTrait;
use input::event::keyboard::{KeyState, KeyboardEventTrait};
use input::event::touch::TouchEventPosition;
use xkbcommon::*;
@ -124,9 +124,17 @@ impl<'a> calloop::EventSource for LibInputHandler<'a> {
input::Event::Pointer(pointer_event) => {
match pointer_event {
input::event::PointerEvent::Motion(motion_event) => {
let mut mouse_pos = self.mouse_pos.as_ref().get().unwrap_or_default();
mouse_pos.x += motion_event.dx() as f32;
mouse_pos.y += motion_event.dy() as f32;
let screen_size =
self.window.size().to_logical(self.window.scale_factor());
let mut mouse_pos =
self.mouse_pos.as_ref().get().unwrap_or(LogicalPosition {
x: screen_size.width / 2.,
y: screen_size.height / 2.,
});
mouse_pos.x = (mouse_pos.x + motion_event.dx() as f32)
.clamp(0., screen_size.width);
mouse_pos.y = (mouse_pos.y + motion_event.dy() as f32)
.clamp(0., screen_size.height);
self.mouse_pos.set(Some(mouse_pos));
let event = WindowEvent::PointerMoved { position: mouse_pos };
self.window.dispatch_event(event);
@ -207,7 +215,7 @@ impl<'a> calloop::EventSource for LibInputHandler<'a> {
.keystate
.mod_name_is_active(xkb::MOD_NAME_ALT, xkb::STATE_MODS_EFFECTIVE);
if state == input::event::keyboard::KeyState::Pressed {
if state == KeyState::Pressed {
//eprintln!(
//"key {} state {:#?} sym {:x} control {control} alt {alt}",
//key_code, state, sym
@ -218,14 +226,21 @@ impl<'a> calloop::EventSource for LibInputHandler<'a> {
{
i_slint_core::api::quit_event_loop()
.expect("Unable to quit event loop multiple times");
} else {
if (xkb::KEY_XF86Switch_VT_1..=xkb::KEY_XF86Switch_VT_12).contains(&sym)
{
// let target_vt = (sym - xkb::KEY_XF86Switch_VT_1 + 1) as i32;
// TODO: eprintln!("switch vt {target_vt}");
}
} else if (xkb::KEY_XF86Switch_VT_1..=xkb::KEY_XF86Switch_VT_12)
.contains(&sym)
{
// let target_vt = (sym - xkb::KEY_XF86Switch_VT_1 + 1) as i32;
// TODO: eprintln!("switch vt {target_vt}");
}
}
if let Some(text) = map_key_sym(sym) {
let event = match state {
KeyState::Pressed => WindowEvent::KeyPressed { text },
KeyState::Released => WindowEvent::KeyReleased { text },
};
self.window.dispatch_event(event);
}
}
_ => {}
}
@ -268,3 +283,16 @@ impl<'a> calloop::EventSource for LibInputHandler<'a> {
poll.unregister(self.libinput.as_raw_fd())
}
}
fn map_key_sym(sym: u32) -> Option<SharedString> {
macro_rules! keysym_to_string {
($($char:literal # $name:ident # $($_qt:ident)|* # $($_winit:ident)|* # $($xkb:ident)|*;)*) => {
match(sym) {
$($(xkb::$xkb => $char,)*)*
_ => std::char::from_u32(xkbcommon::xkb::keysym_to_utf32(sym))?,
}
};
}
let char = i_slint_common::for_each_special_keys!(keysym_to_string);
Some(char.into())
}

View file

@ -2120,7 +2120,7 @@ pub(crate) fn timer_event() {
mod key_codes {
macro_rules! define_qt_key_to_string_fn {
($($char:literal # $name:ident # $($qt:ident)|* # $($winit:ident)|* ;)*) => {
($($char:literal # $name:ident # $($qt:ident)|* # $($winit:ident)|* # $($_xkb:ident)|*;)*) => {
use crate::key_generated;
pub fn qt_key_to_string(key: key_generated::Qt_Key) -> Option<i_slint_core::SharedString> {

View file

@ -246,7 +246,7 @@ impl std::fmt::Debug for CustomEvent {
mod key_codes {
macro_rules! winit_key_to_char_fn {
($($char:literal # $name:ident # $($_qt:ident)|* # $($winit:ident)|* ;)*) => {
($($char:literal # $name:ident # $($_qt:ident)|* # $($winit:ident)|* # $($_xkb:ident)|*;)*) => {
pub fn winit_key_to_char(virtual_keycode: winit::event::VirtualKeyCode) -> Option<char> {
let char = match(virtual_keycode) {
$($(winit::event::VirtualKeyCode::$winit => $char,)*)*

View file

@ -289,7 +289,7 @@ fn event_text(e: &web_sys::KeyboardEvent) -> Option<SharedString> {
use i_slint_core::platform::Key;
macro_rules! check_non_printable_code {
($($char:literal # $name:ident # $($_qt:ident)|* # $($_winit:ident)|* ;)*) => {
($($char:literal # $name:ident # $($_qt:ident)|* # $($_winit:ident)|* # $($_xkb:ident)|* ;)*) => {
match key.as_str() {
"Tab" if e.shift_key() => return Some(Key::Backtab.into()),
$(stringify!($name) => {

View file

@ -7,13 +7,13 @@
//! the names comes should match with <https://www.w3.org/TR/uievents-key/#named-key-attribute-values>,
//!
//! The format is a semicolon separated list of keys
//! `<char code> # Slint name # Qt code # Winit code`
//! `<char code> # Slint name # Qt code # Winit code # xkb code`
//!
//! ## Example
//!
//! ```
//! macro_rules! do_something_with_keys {
//! ($($char:literal # $name:ident # $($qt:ident)|* # $($winit:ident)|* ;)*) => {
//! ($($char:literal # $name:ident # $($qt:ident)|* # $($winit:ident)|* # $($xkb:ident)|* ;)*) => {
//! //...
//! };
//! }
@ -25,82 +25,82 @@
macro_rules! for_each_special_keys {
($macro:ident) => {
$macro![
'\u{0008}' # Backspace # Qt_Key_Key_Backspace # Back ;
'\u{0009}' # Tab # Qt_Key_Key_Tab # Tab ;
'\u{000a}' # Return # Qt_Key_Key_Enter|Qt_Key_Key_Return # NumpadEnter|Return ;
'\u{001b}' # Escape # Qt_Key_Key_Escape # Escape ;
'\u{0019}' # Backtab # Qt_Key_Key_Backtab # ;
'\u{007f}' # Delete # Qt_Key_Key_Delete # Delete ;
'\u{0008}' # Backspace # Qt_Key_Key_Backspace # Back # KEY_BackSpace ;
'\u{0009}' # Tab # Qt_Key_Key_Tab # Tab # KEY_Tab ;
'\u{000a}' # Return # Qt_Key_Key_Enter|Qt_Key_Key_Return # NumpadEnter|Return # KEY_Return;
'\u{001b}' # Escape # Qt_Key_Key_Escape # Escape # KEY_Escape ;
'\u{0019}' # Backtab # Qt_Key_Key_Backtab # # KEY_BackTab ;
'\u{007f}' # Delete # Qt_Key_Key_Delete # Delete # KEY_Delete ;
// The modifier key codes comes from https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode.
'\u{0010}' # Shift # Qt_Key_Key_Shift # LShift ;
'\u{0011}' # Control # Qt_Key_Key_Control # LControl ;
'\u{0012}' # Alt # Qt_Key_Key_Alt # LAlt ;
'\u{0013}' # AltGr # Qt_Key_Key_AltGr # RAlt ;
'\u{0014}' # CapsLock # Qt_Key_Key_CapsLock # ;
'\u{0010}' # Shift # Qt_Key_Key_Shift # LShift # KEY_Shift_L ;
'\u{0011}' # Control # Qt_Key_Key_Control # LControl # KEY_Control_L ;
'\u{0012}' # Alt # Qt_Key_Key_Alt # LAlt # KEY_Alt_L ;
'\u{0013}' # AltGr # Qt_Key_Key_AltGr # RAlt # KEY_Mode_switch;
'\u{0014}' # CapsLock # Qt_Key_Key_CapsLock # # KEY_Caps_Lock ;
'\u{0015}' # ShiftR # # RShift ;
'\u{0016}' # ControlR # # RControl ;
'\u{0015}' # ShiftR # # RShift # KEY_Shift_R ;
'\u{0016}' # ControlR # # RControl # KEY_Control_R ;
// Use custom codes instead of DOM_VK_META for meta, because the Mozilla defined code is a regular character (E0; LATIN SMALL LETTER A WITH GRAVE)
// which makes those keys appear as text.
'\u{0017}' # Meta # Qt_Key_Key_Meta # LWin ;
'\u{0018}' # MetaR # # RWin ;
'\u{0017}' # Meta # Qt_Key_Key_Meta # LWin # KEY_Meta_L ;
'\u{0018}' # MetaR # # RWin # KEY_Meta_R ;
'\u{F700}' # UpArrow # Qt_Key_Key_Up # Up ;
'\u{F701}' # DownArrow # Qt_Key_Key_Down # Down ;
'\u{F702}' # LeftArrow # Qt_Key_Key_Left # Left ;
'\u{F703}' # RightArrow # Qt_Key_Key_Right # Right ;
'\u{F704}' # F1 # Qt_Key_Key_F1 # F1 ;
'\u{F705}' # F2 # Qt_Key_Key_F2 # F2 ;
'\u{F706}' # F3 # Qt_Key_Key_F3 # F3 ;
'\u{F707}' # F4 # Qt_Key_Key_F4 # F4 ;
'\u{F708}' # F5 # Qt_Key_Key_F5 # F5 ;
'\u{F709}' # F6 # Qt_Key_Key_F6 # F6 ;
'\u{F70A}' # F7 # Qt_Key_Key_F7 # F7 ;
'\u{F70B}' # F8 # Qt_Key_Key_F8 # F8 ;
'\u{F70C}' # F9 # Qt_Key_Key_F9 # F9 ;
'\u{F70D}' # F10 # Qt_Key_Key_F10 # F10 ;
'\u{F70E}' # F11 # Qt_Key_Key_F11 # F11 ;
'\u{F70F}' # F12 # Qt_Key_Key_F12 # F12 ;
'\u{F710}' # F13 # Qt_Key_Key_F13 # F13 ;
'\u{F711}' # F14 # Qt_Key_Key_F14 # F14 ;
'\u{F712}' # F15 # Qt_Key_Key_F15 # F15 ;
'\u{F713}' # F16 # Qt_Key_Key_F16 # F16 ;
'\u{F714}' # F17 # Qt_Key_Key_F17 # F17 ;
'\u{F715}' # F18 # Qt_Key_Key_F18 # F18 ;
'\u{F716}' # F19 # Qt_Key_Key_F19 # F19 ;
'\u{F717}' # F20 # Qt_Key_Key_F20 # F20 ;
'\u{F718}' # F21 # Qt_Key_Key_F21 # F21 ;
'\u{F719}' # F22 # Qt_Key_Key_F22 # F22 ;
'\u{F71A}' # F23 # Qt_Key_Key_F23 # F23 ;
'\u{F71B}' # F24 # Qt_Key_Key_F24 # F24 ;
//'\u{F71C}' # F25 # Qt_Key_Key_F25 # ;
//'\u{F71D}' # F26 # Qt_Key_Key_F26 # ;
//'\u{F71E}' # F27 # Qt_Key_Key_F27 # ;
//'\u{F71F}' # F28 # Qt_Key_Key_F28 # ;
//'\u{F720}' # F29 # Qt_Key_Key_F29 # ;
//'\u{F721}' # F30 # Qt_Key_Key_F30 # ;
//'\u{F722}' # F31 # Qt_Key_Key_F31 # ;
//'\u{F723}' # F32 # Qt_Key_Key_F32 # ;
//'\u{F724}' # F33 # Qt_Key_Key_F33 # ;
//'\u{F725}' # F34 # Qt_Key_Key_F34 # ;
//'\u{F726}' # F35 # Qt_Key_Key_F35 # ;
'\u{F727}' # Insert # Qt_Key_Key_Insert # Insert ;
//'\u{F728}' # Delete # Qt_Key_Key_Delete # Delete ; // already as a control code
'\u{F729}' # Home # Qt_Key_Key_Home # Home ;
'\u{F700}' # UpArrow # Qt_Key_Key_Up # Up # KEY_Up ;
'\u{F701}' # DownArrow # Qt_Key_Key_Down # Down # KEY_Down ;
'\u{F702}' # LeftArrow # Qt_Key_Key_Left # Left # KEY_Left ;
'\u{F703}' # RightArrow # Qt_Key_Key_Right # Right # KEY_Right ;
'\u{F704}' # F1 # Qt_Key_Key_F1 # F1 # KEY_F1 ;
'\u{F705}' # F2 # Qt_Key_Key_F2 # F2 # KEY_F2 ;
'\u{F706}' # F3 # Qt_Key_Key_F3 # F3 # KEY_F3 ;
'\u{F707}' # F4 # Qt_Key_Key_F4 # F4 # KEY_F4 ;
'\u{F708}' # F5 # Qt_Key_Key_F5 # F5 # KEY_F5 ;
'\u{F709}' # F6 # Qt_Key_Key_F6 # F6 # KEY_F6 ;
'\u{F70A}' # F7 # Qt_Key_Key_F7 # F7 # KEY_F7 ;
'\u{F70B}' # F8 # Qt_Key_Key_F8 # F8 # KEY_F8 ;
'\u{F70C}' # F9 # Qt_Key_Key_F9 # F9 # KEY_F9 ;
'\u{F70D}' # F10 # Qt_Key_Key_F10 # F10 # KEY_F10 ;
'\u{F70E}' # F11 # Qt_Key_Key_F11 # F11 # KEY_F11 ;
'\u{F70F}' # F12 # Qt_Key_Key_F12 # F12 # KEY_F12 ;
'\u{F710}' # F13 # Qt_Key_Key_F13 # F13 # KEY_F13 ;
'\u{F711}' # F14 # Qt_Key_Key_F14 # F14 # KEY_F14 ;
'\u{F712}' # F15 # Qt_Key_Key_F15 # F15 # KEY_F15 ;
'\u{F713}' # F16 # Qt_Key_Key_F16 # F16 # KEY_F16 ;
'\u{F714}' # F17 # Qt_Key_Key_F17 # F17 # KEY_F17 ;
'\u{F715}' # F18 # Qt_Key_Key_F18 # F18 # KEY_F18 ;
'\u{F716}' # F19 # Qt_Key_Key_F19 # F19 # KEY_F19 ;
'\u{F717}' # F20 # Qt_Key_Key_F20 # F20 # KEY_F20 ;
'\u{F718}' # F21 # Qt_Key_Key_F21 # F21 # KEY_F21 ;
'\u{F719}' # F22 # Qt_Key_Key_F22 # F22 # KEY_F22 ;
'\u{F71A}' # F23 # Qt_Key_Key_F23 # F23 # KEY_F23 ;
'\u{F71B}' # F24 # Qt_Key_Key_F24 # F24 # KEY_F24 ;
//'\u{F71C}'# F25 # Qt_Key_Key_F25 # # KEY_F25 ;
//'\u{F71D}'# F26 # Qt_Key_Key_F26 # # KEY_F26 ;
//'\u{F71E}'# F27 # Qt_Key_Key_F27 # # KEY_F27 ;
//'\u{F71F}'# F28 # Qt_Key_Key_F28 # # KEY_F28 ;
//'\u{F720}'# F29 # Qt_Key_Key_F29 # # KEY_F29 ;
//'\u{F721}'# F30 # Qt_Key_Key_F30 # # KEY_F30 ;
//'\u{F722}'# F31 # Qt_Key_Key_F31 # # KEY_F31 ;
//'\u{F723}'# F32 # Qt_Key_Key_F32 # # KEY_F32 ;
//'\u{F724}'# F33 # Qt_Key_Key_F33 # # KEY_F33 ;
//'\u{F725}'# F34 # Qt_Key_Key_F34 # # KEY_F34 ;
//'\u{F726}'# F35 # Qt_Key_Key_F35 # # KEY_F35 ;
'\u{F727}' # Insert # Qt_Key_Key_Insert # Insert # KEY_Insert ;
//'\u{F728}' # Delete ; // already as a control code
'\u{F729}' # Home # Qt_Key_Key_Home # Home # KEY_Home ;
//'\u{F72A}' # Begin # # ;
'\u{F72B}' # End # Qt_Key_Key_End # End ;
'\u{F72C}' # PageUp # Qt_Key_Key_PageUp # PageUp ;
'\u{F72D}' # PageDown # Qt_Key_Key_PageDown # PageDown ;
'\u{F72B}' # End # Qt_Key_Key_End # End # KEY_End ;
'\u{F72C}' # PageUp # Qt_Key_Key_PageUp # PageUp # KEY_Page_Up ;
'\u{F72D}' # PageDown # Qt_Key_Key_PageDown # PageDown # KEY_Page_Down ;
//'\u{F72E}' # PrintScreen # # Snapshot ;
'\u{F72F}' # ScrollLock # Qt_Key_Key_ScrollLock # Scroll ;
'\u{F730}' # Pause # Qt_Key_Key_Pause # Pause ;
'\u{F731}' # SysReq # Qt_Key_Key_SysReq # Sysrq ;
'\u{F72F}' # ScrollLock # Qt_Key_Key_ScrollLock # Scroll # KEY_Scroll_Lock;
'\u{F730}' # Pause # Qt_Key_Key_Pause # Pause # KEY_Pause ;
'\u{F731}' # SysReq # Qt_Key_Key_SysReq # Sysrq # KEY_Sys_Req ;
//'\u{F732}' # Break # # ;
//'\u{F733}' # Reset # # ;
'\u{F734}' # Stop # Qt_Key_Key_Stop # Stop ;
'\u{F735}' # Menu # Qt_Key_Key_Menu # ;
'\u{F734}' # Stop # Qt_Key_Key_Stop # Stop # KEY_XF86Stop ;
'\u{F735}' # Menu # Qt_Key_Key_Menu # # KEY_Menu ;
//'\u{F736}' # User # # ;
//'\u{F737}' # System # # ;
//'\u{F738}' # Print # Qt_Key_Key_Print # ;

View file

@ -556,7 +556,7 @@ impl ColorSpecific {
struct KeysLookup;
macro_rules! special_keys_lookup {
($($char:literal # $name:ident # $($qt:ident)|* # $($winit:ident)|* ;)*) => {
($($char:literal # $name:ident # $($qt:ident)|* # $($winit:ident)|* # $($_xkb:ident)|*;)*) => {
impl LookupObject for KeysLookup {
fn for_each_entry<R>(
&self,

View file

@ -126,7 +126,7 @@ pub enum InputEventFilterResult {
#[allow(missing_docs, non_upper_case_globals)]
pub mod key_codes {
macro_rules! declare_consts_for_special_keys {
($($char:literal # $name:ident # $($_qt:ident)|* # $($_winit:ident)|* ;)*) => {
($($char:literal # $name:ident # $($_qt:ident)|* # $($_winit:ident)|* # $($_xkb:ident)|*;)*) => {
$(pub const $name : char = $char;)*
#[allow(missing_docs)]