seat: update xkb_state when keymap changes
This commit is contained in:
parent
a80c5690c8
commit
76c47c24d0
7 changed files with 123 additions and 5 deletions
|
|
@ -8,7 +8,7 @@ pub mod keymap;
|
||||||
pub mod mods;
|
pub mod mods;
|
||||||
pub mod syms;
|
pub mod syms;
|
||||||
|
|
||||||
#[derive(Encode, Decode, Copy, Clone, Eq, PartialEq, Hash)]
|
#[derive(Encode, Decode, Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||||
pub struct ModifiedKeySym {
|
pub struct ModifiedKeySym {
|
||||||
pub mods: Modifiers,
|
pub mods: Modifiers,
|
||||||
pub sym: KeySym,
|
pub sym: KeySym,
|
||||||
|
|
|
||||||
|
|
@ -265,7 +265,15 @@ impl WlSeatGlobal {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_keymap(&self, keymap: &Rc<XkbKeymap>) {
|
pub fn set_keymap(&self, keymap: &Rc<XkbKeymap>) {
|
||||||
|
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_map.set(keymap.clone());
|
||||||
|
*self.kb_state.borrow_mut() = state;
|
||||||
let bindings = self.bindings.borrow_mut();
|
let bindings = self.bindings.borrow_mut();
|
||||||
for (id, client) in bindings.iter() {
|
for (id, client) in bindings.iter() {
|
||||||
for seat in client.values() {
|
for seat in client.values() {
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ use {
|
||||||
backend::{
|
backend::{
|
||||||
Backend, BackendEvent, Connector, ConnectorEvent, ConnectorId, ConnectorKernelId,
|
Backend, BackendEvent, Connector, ConnectorEvent, ConnectorId, ConnectorKernelId,
|
||||||
InputDevice, InputDeviceAccelProfile, InputDeviceCapability, InputDeviceId, InputEvent,
|
InputDevice, InputDeviceAccelProfile, InputDeviceCapability, InputDeviceId, InputEvent,
|
||||||
Mode, MonitorInfo, TransformMatrix,
|
KeyState, Mode, MonitorInfo, TransformMatrix,
|
||||||
},
|
},
|
||||||
compositor::TestFuture,
|
compositor::TestFuture,
|
||||||
fixed::Fixed,
|
fixed::Fixed,
|
||||||
|
|
@ -258,6 +258,29 @@ pub struct TestBackendKb {
|
||||||
pub common: TestInputDeviceCommon,
|
pub common: TestInputDeviceCommon,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct PressedKey {
|
||||||
|
pub kb: Rc<TestBackendKb>,
|
||||||
|
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<Self>, key: u32) -> PressedKey {
|
||||||
|
self.common.event(InputEvent::Key(key, KeyState::Pressed));
|
||||||
|
PressedKey {
|
||||||
|
kb: self.clone(),
|
||||||
|
key,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl TestInputDevice for TestBackendKb {
|
impl TestInputDevice for TestBackendKb {
|
||||||
fn common(&self) -> &TestInputDeviceCommon {
|
fn common(&self) -> &TestInputDeviceCommon {
|
||||||
&self.common
|
&self.common
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ use {
|
||||||
backend::InputDeviceId,
|
backend::InputDeviceId,
|
||||||
ifs::wl_seat::SeatId,
|
ifs::wl_seat::SeatId,
|
||||||
it::test_error::{TestError, TestResult},
|
it::test_error::{TestError, TestResult},
|
||||||
utils::stack::Stack,
|
utils::{copyhashmap::CopyHashMap, stack::Stack},
|
||||||
},
|
},
|
||||||
isnt::std_1::primitive::IsntConstPtrExt,
|
isnt::std_1::primitive::IsntConstPtrExt,
|
||||||
jay_config::{
|
jay_config::{
|
||||||
|
|
@ -13,6 +13,7 @@ use {
|
||||||
ConfigEntry, VERSION,
|
ConfigEntry, VERSION,
|
||||||
},
|
},
|
||||||
input::{InputDevice, Seat},
|
input::{InputDevice, Seat},
|
||||||
|
keyboard::{keymap::Keymap, ModifiedKeySym},
|
||||||
Direction,
|
Direction,
|
||||||
},
|
},
|
||||||
std::{cell::Cell, ops::Deref, ptr, rc::Rc},
|
std::{cell::Cell, ops::Deref, ptr, rc::Rc},
|
||||||
|
|
@ -36,6 +37,7 @@ where
|
||||||
let tc = Rc::new(TestConfig {
|
let tc = Rc::new(TestConfig {
|
||||||
srv: Cell::new(None),
|
srv: Cell::new(None),
|
||||||
responses: Default::default(),
|
responses: Default::default(),
|
||||||
|
invoked_shortcuts: Default::default(),
|
||||||
});
|
});
|
||||||
let old = CONFIG;
|
let old = CONFIG;
|
||||||
CONFIG = tc.deref();
|
CONFIG = tc.deref();
|
||||||
|
|
@ -86,7 +88,10 @@ unsafe extern "C" fn handle_msg(data: *const u8, msg: *const u8, size: usize) {
|
||||||
ServerMessage::Response { response } => {
|
ServerMessage::Response { response } => {
|
||||||
tc.responses.push(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::NewInputDevice { .. } => {}
|
||||||
ServerMessage::DelInputDevice { .. } => {}
|
ServerMessage::DelInputDevice { .. } => {}
|
||||||
ServerMessage::ConnectorConnect { .. } => {}
|
ServerMessage::ConnectorConnect { .. } => {}
|
||||||
|
|
@ -109,6 +114,7 @@ struct ServerData {
|
||||||
pub struct TestConfig {
|
pub struct TestConfig {
|
||||||
srv: Cell<Option<ServerData>>,
|
srv: Cell<Option<ServerData>>,
|
||||||
responses: Stack<Response>,
|
responses: Stack<Response>,
|
||||||
|
pub invoked_shortcuts: CopyHashMap<(SeatId, ModifiedKeySym), ()>,
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! get_response {
|
macro_rules! get_response {
|
||||||
|
|
@ -167,6 +173,35 @@ impl TestConfig {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn parse_keymap(&self, keymap: &str) -> Result<Keymap, TestError> {
|
||||||
|
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<T: Into<ModifiedKeySym>>(
|
||||||
|
&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> {
|
pub fn set_input_device_seat(&self, id: InputDeviceId, seat: SeatId) -> Result<(), TestError> {
|
||||||
self.send(ClientMessage::SetSeat {
|
self.send(ClientMessage::SetSeat {
|
||||||
device: InputDevice(id.raw() as _),
|
device: InputDevice(id.raw() as _),
|
||||||
|
|
|
||||||
|
|
@ -125,6 +125,10 @@ impl TestRun {
|
||||||
seat,
|
seat,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn sync(&self) {
|
||||||
|
self.state.eng.yield_now().await;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ParseFull<'a>: Sized {
|
pub trait ParseFull<'a>: Sized {
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ macro_rules! testcase {
|
||||||
fn run(
|
fn run(
|
||||||
&self,
|
&self,
|
||||||
testrun: std::rc::Rc<crate::it::testrun::TestRun>,
|
testrun: std::rc::Rc<crate::it::testrun::TestRun>,
|
||||||
) -> Box<dyn std::future::Future<Output = Result<(), TestError>>> {
|
) -> Box<dyn std::future::Future<Output = crate::it::test_error::TestResult>> {
|
||||||
Box::new(test(testrun))
|
Box::new(test(testrun))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -36,6 +36,7 @@ mod t0007_subsurface;
|
||||||
mod t0008_map_focus;
|
mod t0008_map_focus;
|
||||||
mod t0009_tab_focus;
|
mod t0009_tab_focus;
|
||||||
mod t0010_fullscreen_focus;
|
mod t0010_fullscreen_focus;
|
||||||
|
mod t0011_set_keymap;
|
||||||
|
|
||||||
pub trait TestCase: Sync {
|
pub trait TestCase: Sync {
|
||||||
fn name(&self) -> &'static str;
|
fn name(&self) -> &'static str;
|
||||||
|
|
@ -64,5 +65,6 @@ pub fn tests() -> Vec<&'static dyn TestCase> {
|
||||||
t0008_map_focus,
|
t0008_map_focus,
|
||||||
t0009_tab_focus,
|
t0009_tab_focus,
|
||||||
t0010_fullscreen_focus,
|
t0010_fullscreen_focus,
|
||||||
|
t0011_set_keymap,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
46
src/it/tests/t0011_set_keymap.rs
Normal file
46
src/it/tests/t0011_set_keymap.rs
Normal file
|
|
@ -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<TestRun>) -> 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(())
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue