From d9672c5a217dc218ba7aef4de30168f4f8ecaa2e Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Mon, 16 Oct 2023 18:20:46 +0200 Subject: [PATCH] linuxkms: Initialize xkb lazily This has two benefits: - It improves start-up time for device that are touch-only because the xkb parsing is delayed until a keyboard is attached and key is pressed - It fixes #3678 by working around the situation where xkb would crash if the xkbcommon data files (in /usr/share/X11/xkb) aren't there. Sadly, no error is reported in that case (that we could handle), instead just crashes. --- .../linuxkms/calloop_backend/input.rs | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/internal/backends/linuxkms/calloop_backend/input.rs b/internal/backends/linuxkms/calloop_backend/input.rs index 6e0c732694d..0bfe5b0dbf7 100644 --- a/internal/backends/linuxkms/calloop_backend/input.rs +++ b/internal/backends/linuxkms/calloop_backend/input.rs @@ -58,7 +58,7 @@ pub struct LibInputHandler<'a> { mouse_pos: Pin>>>, last_touch_pos: LogicalPosition, window: &'a i_slint_core::api::Window, - keystate: xkb::State, + keystate: Option, } impl<'a> LibInputHandler<'a> { @@ -74,11 +74,6 @@ impl<'a> LibInputHandler<'a> { }); libinput.udev_assign_seat(&seat_name).unwrap(); - let xkb_context = xkb::Context::new(xkb::CONTEXT_NO_FLAGS); - let keymap = xkb::Keymap::new_from_names(&xkb_context, "", "", "", "", None, 0) - .ok_or_else(|| format!("Error compiling keymap"))?; - let keystate = xkb::State::new(&keymap); - let mouse_pos_property = Rc::pin(Property::new(None)); let handler = Self { @@ -87,7 +82,7 @@ impl<'a> LibInputHandler<'a> { mouse_pos: mouse_pos_property.clone(), last_touch_pos: Default::default(), window, - keystate, + keystate: Default::default(), }; event_loop_handle @@ -209,9 +204,17 @@ impl<'a> calloop::EventSource for LibInputHandler<'a> { let key_code = xkb::Keycode::new(key_event.key() + 8); let state = key_event.key_state(); - let sym = self.keystate.key_get_one_sym(key_code); + let xkb_key_state = self.keystate.get_or_insert_with(|| { + let xkb_context = xkb::Context::new(xkb::CONTEXT_NO_FLAGS); + let keymap = + xkb::Keymap::new_from_names(&xkb_context, "", "", "", "", None, 0) + .expect("Error compiling keymap"); + xkb::State::new(&keymap) + }); + + let sym = xkb_key_state.key_get_one_sym(key_code); - self.keystate.update_key( + xkb_key_state.update_key( key_code, match state { input::event::tablet_pad::KeyState::Pressed => xkb::KeyDirection::Down, @@ -219,11 +222,9 @@ impl<'a> calloop::EventSource for LibInputHandler<'a> { }, ); - let control = self - .keystate + let control = xkb_key_state .mod_name_is_active(xkb::MOD_NAME_CTRL, xkb::STATE_MODS_EFFECTIVE); - let alt = self - .keystate + let alt = xkb_key_state .mod_name_is_active(xkb::MOD_NAME_ALT, xkb::STATE_MODS_EFFECTIVE); if state == KeyState::Pressed {