From 76c47c24d0242450b213423e3e3466c0447ef2e5 Mon Sep 17 00:00:00 2001 From: Julian Orth Date: Wed, 4 May 2022 22:10:38 +0200 Subject: [PATCH] seat: update xkb_state when keymap changes --- jay-config/src/keyboard/mod.rs | 2 +- src/ifs/wl_seat.rs | 8 ++++++ src/it/test_backend.rs | 25 ++++++++++++++++- src/it/test_config.rs | 39 +++++++++++++++++++++++++-- src/it/testrun.rs | 4 +++ src/it/tests.rs | 4 ++- src/it/tests/t0011_set_keymap.rs | 46 ++++++++++++++++++++++++++++++++ 7 files changed, 123 insertions(+), 5 deletions(-) create mode 100644 src/it/tests/t0011_set_keymap.rs diff --git a/jay-config/src/keyboard/mod.rs b/jay-config/src/keyboard/mod.rs index f90a9208..7bbac76e 100644 --- a/jay-config/src/keyboard/mod.rs +++ b/jay-config/src/keyboard/mod.rs @@ -8,7 +8,7 @@ pub mod keymap; pub mod mods; pub mod syms; -#[derive(Encode, Decode, Copy, Clone, Eq, PartialEq, Hash)] +#[derive(Encode, Decode, Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct ModifiedKeySym { pub mods: Modifiers, pub sym: KeySym, diff --git a/src/ifs/wl_seat.rs b/src/ifs/wl_seat.rs index fab5e87c..dc4043ee 100644 --- a/src/ifs/wl_seat.rs +++ b/src/ifs/wl_seat.rs @@ -265,7 +265,15 @@ impl WlSeatGlobal { } pub fn set_keymap(&self, keymap: &Rc) { + let state = match keymap.state() { + Ok(s) => s, + Err(e) => { + log::error!("Could not create keymap state: {}", ErrorFmt(e)); + return; + } + }; self.kb_map.set(keymap.clone()); + *self.kb_state.borrow_mut() = state; let bindings = self.bindings.borrow_mut(); for (id, client) in bindings.iter() { for seat in client.values() { diff --git a/src/it/test_backend.rs b/src/it/test_backend.rs index e10868b9..b6e56cd0 100644 --- a/src/it/test_backend.rs +++ b/src/it/test_backend.rs @@ -4,7 +4,7 @@ use { backend::{ Backend, BackendEvent, Connector, ConnectorEvent, ConnectorId, ConnectorKernelId, InputDevice, InputDeviceAccelProfile, InputDeviceCapability, InputDeviceId, InputEvent, - Mode, MonitorInfo, TransformMatrix, + KeyState, Mode, MonitorInfo, TransformMatrix, }, compositor::TestFuture, fixed::Fixed, @@ -258,6 +258,29 @@ pub struct TestBackendKb { pub common: TestInputDeviceCommon, } +pub struct PressedKey { + pub kb: Rc, + pub key: u32, +} + +impl Drop for PressedKey { + fn drop(&mut self) { + self.kb + .common + .event(InputEvent::Key(self.key, KeyState::Released)); + } +} + +impl TestBackendKb { + pub fn press(self: &Rc, key: u32) -> PressedKey { + self.common.event(InputEvent::Key(key, KeyState::Pressed)); + PressedKey { + kb: self.clone(), + key, + } + } +} + impl TestInputDevice for TestBackendKb { fn common(&self) -> &TestInputDeviceCommon { &self.common diff --git a/src/it/test_config.rs b/src/it/test_config.rs index 89301be4..6ffc744b 100644 --- a/src/it/test_config.rs +++ b/src/it/test_config.rs @@ -3,7 +3,7 @@ use { backend::InputDeviceId, ifs::wl_seat::SeatId, it::test_error::{TestError, TestResult}, - utils::stack::Stack, + utils::{copyhashmap::CopyHashMap, stack::Stack}, }, isnt::std_1::primitive::IsntConstPtrExt, jay_config::{ @@ -13,6 +13,7 @@ use { ConfigEntry, VERSION, }, input::{InputDevice, Seat}, + keyboard::{keymap::Keymap, ModifiedKeySym}, Direction, }, std::{cell::Cell, ops::Deref, ptr, rc::Rc}, @@ -36,6 +37,7 @@ where let tc = Rc::new(TestConfig { srv: Cell::new(None), responses: Default::default(), + invoked_shortcuts: Default::default(), }); let old = CONFIG; CONFIG = tc.deref(); @@ -86,7 +88,10 @@ unsafe extern "C" fn handle_msg(data: *const u8, msg: *const u8, size: usize) { ServerMessage::Response { response } => { tc.responses.push(response); } - ServerMessage::InvokeShortcut { .. } => {} + ServerMessage::InvokeShortcut { seat, mods, sym } => { + tc.invoked_shortcuts + .set((SeatId::from_raw(seat.0 as _), mods | sym), ()); + } ServerMessage::NewInputDevice { .. } => {} ServerMessage::DelInputDevice { .. } => {} ServerMessage::ConnectorConnect { .. } => {} @@ -109,6 +114,7 @@ struct ServerData { pub struct TestConfig { srv: Cell>, responses: Stack, + pub invoked_shortcuts: CopyHashMap<(SeatId, ModifiedKeySym), ()>, } macro_rules! get_response { @@ -167,6 +173,35 @@ impl TestConfig { }) } + pub fn parse_keymap(&self, keymap: &str) -> Result { + let reply = self.send_with_reply(ClientMessage::ParseKeymap { keymap })?; + get_response!(reply, ParseKeymap { keymap }); + if keymap.is_invalid() { + bail!("Could not parse the keymap"); + } + Ok(keymap) + } + + pub fn set_keymap(&self, seat: SeatId, keymap: Keymap) -> TestResult { + self.send(ClientMessage::SeatSetKeymap { + seat: Seat(seat.raw() as _), + keymap, + }) + } + + pub fn add_shortcut>( + &self, + seat: SeatId, + key: T, + ) -> Result<(), TestError> { + let key = key.into(); + self.send(ClientMessage::AddShortcut { + seat: Seat(seat.raw() as _), + mods: key.mods, + sym: key.sym, + }) + } + pub fn set_input_device_seat(&self, id: InputDeviceId, seat: SeatId) -> Result<(), TestError> { self.send(ClientMessage::SetSeat { device: InputDevice(id.raw() as _), diff --git a/src/it/testrun.rs b/src/it/testrun.rs index 2fa875c9..fd44eff3 100644 --- a/src/it/testrun.rs +++ b/src/it/testrun.rs @@ -125,6 +125,10 @@ impl TestRun { seat, }) } + + pub async fn sync(&self) { + self.state.eng.yield_now().await; + } } pub trait ParseFull<'a>: Sized { diff --git a/src/it/tests.rs b/src/it/tests.rs index 0eac4cb2..b80ca514 100644 --- a/src/it/tests.rs +++ b/src/it/tests.rs @@ -19,7 +19,7 @@ macro_rules! testcase { fn run( &self, testrun: std::rc::Rc, - ) -> Box>> { + ) -> Box> { Box::new(test(testrun)) } } @@ -36,6 +36,7 @@ mod t0007_subsurface; mod t0008_map_focus; mod t0009_tab_focus; mod t0010_fullscreen_focus; +mod t0011_set_keymap; pub trait TestCase: Sync { fn name(&self) -> &'static str; @@ -64,5 +65,6 @@ pub fn tests() -> Vec<&'static dyn TestCase> { t0008_map_focus, t0009_tab_focus, t0010_fullscreen_focus, + t0011_set_keymap, } } diff --git a/src/it/tests/t0011_set_keymap.rs b/src/it/tests/t0011_set_keymap.rs new file mode 100644 index 00000000..a79fc7d3 --- /dev/null +++ b/src/it/tests/t0011_set_keymap.rs @@ -0,0 +1,46 @@ +use { + crate::it::{test_error::TestResult, testrun::TestRun}, + jay_config::keyboard::syms::SYM_F13, + std::rc::Rc, +}; + +testcase!(); + +async fn test(run: Rc) -> TestResult { + let ds = run.create_default_setup().await?; + + run.cfg.add_shortcut(ds.seat.id(), SYM_F13)?; + run.sync().await; + + ds.kb.press(1); + run.sync().await; + tassert!(run.cfg.invoked_shortcuts.is_empty()); + + let keymap = r#" +xkb_keymap { + xkb_keycodes { + <1> = 9; # ESC + }; + xkb_types { + }; + xkb_compatibility { + }; + xkb_symbols { + key <1> { [ F13 ] }; + }; +}; + "#; + + let keymap = run.cfg.parse_keymap(keymap)?; + run.cfg.set_keymap(ds.seat.id(), keymap)?; + run.sync().await; + + ds.kb.press(1); + run.sync().await; + tassert!(run + .cfg + .invoked_shortcuts + .contains(&(ds.seat.id(), SYM_F13.into()))); + + Ok(()) +}