1
0
Fork 0
forked from wry/wry

seat: implement per-device keymaps

This commit is contained in:
Julian Orth 2024-04-12 17:06:16 +02:00
parent 225995eb2f
commit 826f40adca
21 changed files with 293 additions and 71 deletions

View file

@ -13,10 +13,11 @@ use {
state::{DeviceHandlerData, InputDeviceData},
utils::errorfmt::ErrorFmt,
wire::{jay_input::*, JayInputId},
xkbcommon::XkbCommonError,
xkbcommon::{XkbCommonError, XkbKeymap},
},
std::rc::Rc,
thiserror::Error,
uapi::OwnedFd,
};
pub struct JayInput {
@ -67,8 +68,7 @@ impl JayInput {
});
}
fn send_keymap(&self, data: &WlSeatGlobal) {
let map = data.keymap();
fn send_keymap(&self, map: &XkbKeymap) {
self.client.event(Keymap {
self_id: self.id,
keymap: map.map.clone(),
@ -138,6 +138,20 @@ impl JayInput {
Some(d) => Ok(d.data.clone()),
}
}
fn set_keymap_impl<F>(&self, keymap: &OwnedFd, len: u32, f: F) -> Result<(), JayInputError>
where
F: FnOnce(&Rc<XkbKeymap>) -> Result<(), JayInputError>,
{
let cm = Rc::new(ClientMem::new(keymap.raw(), len as _, true)?).offset(0);
let mut map = vec![];
cm.read(&mut map)?;
self.or_error(|| {
let map = self.client.state.xkb_ctx.keymap_from_str(&map)?;
f(&map)?;
Ok(())
})
}
}
impl JayInputRequestHandler for JayInput {
@ -174,13 +188,9 @@ impl JayInputRequestHandler for JayInput {
}
fn set_keymap(&self, req: SetKeymap, _slf: &Rc<Self>) -> Result<(), Self::Error> {
let cm = Rc::new(ClientMem::new(req.keymap.raw(), req.keymap_len as _, true)?).offset(0);
let mut map = vec![];
cm.read(&mut map)?;
self.or_error(|| {
let map = self.client.state.xkb_ctx.keymap_from_str(&map)?;
self.set_keymap_impl(&req.keymap, req.keymap_len, |map| {
let seat = self.seat(req.seat)?;
seat.set_keymap(&map);
seat.set_seat_keymap(&map);
Ok(())
})
}
@ -200,7 +210,7 @@ impl JayInputRequestHandler for JayInput {
fn get_keymap(&self, req: GetKeymap, _slf: &Rc<Self>) -> Result<(), Self::Error> {
self.or_error(|| {
let seat = self.seat(req.seat)?;
self.send_keymap(&seat);
self.send_keymap(&seat.keymap());
Ok(())
})
}
@ -360,6 +370,24 @@ impl JayInputRequestHandler for JayInput {
}
})
}
fn set_device_keymap(&self, req: SetDeviceKeymap, _slf: &Rc<Self>) -> Result<(), Self::Error> {
self.set_keymap_impl(&req.keymap, req.keymap_len, |map| {
let dev = self.device(req.id)?;
dev.set_keymap(&map);
Ok(())
})
}
fn get_device_keymap(&self, req: GetDeviceKeymap, _slf: &Rc<Self>) -> Result<(), Self::Error> {
self.or_error(|| {
let dev = self.device(req.id)?;
if let Some(map) = dev.keymap.get() {
self.send_keymap(&map);
}
Ok(())
})
}
}
object_base! {

View file

@ -63,7 +63,7 @@ use {
WlSeatId, ZwlrDataControlDeviceV1Id, ZwpPrimarySelectionDeviceV1Id,
ZwpRelativePointerV1Id,
},
xkbcommon::{XkbKeymap, XkbState},
xkbcommon::{KeymapId, XkbKeymap, XkbState},
},
ahash::AHashMap,
jay_config::keyboard::mods::Modifiers,
@ -141,7 +141,10 @@ pub struct WlSeatGlobal {
wlr_data_devices:
CopyHashMap<(ClientId, ZwlrDataControlDeviceV1Id), Rc<ZwlrDataControlDeviceV1>>,
repeat_rate: Cell<(i32, i32)>,
kb_map: CloneCell<Rc<XkbKeymap>>,
seat_kb_map: CloneCell<Rc<XkbKeymap>>,
seat_kb_map_id: Cell<KeymapId>,
effective_kb_map: CloneCell<Rc<XkbKeymap>>,
effective_kb_map_id: Cell<KeymapId>,
kb_state: RefCell<XkbState>,
cursor: CloneCell<Option<Rc<dyn Cursor>>>,
tree_changed: Rc<AsyncEvent>,
@ -197,7 +200,10 @@ impl WlSeatGlobal {
data_devices: RefCell::new(Default::default()),
primary_selection_devices: RefCell::new(Default::default()),
repeat_rate: Cell::new((25, 250)),
kb_map: CloneCell::new(state.default_keymap.clone()),
seat_kb_map: CloneCell::new(state.default_keymap.clone()),
seat_kb_map_id: Cell::new(state.default_keymap.id),
effective_kb_map: CloneCell::new(state.default_keymap.clone()),
effective_kb_map_id: Cell::new(state.default_keymap.id),
kb_state: RefCell::new(state.default_keymap.state().unwrap()),
cursor: Default::default(),
tree_changed: Default::default(),
@ -238,7 +244,7 @@ impl WlSeatGlobal {
}
pub fn keymap(&self) -> Rc<XkbKeymap> {
self.kb_map.get()
self.seat_kb_map.get()
}
pub fn toplevel_drag(&self) -> Option<Rc<XdgToplevelDragV1>> {
@ -507,7 +513,12 @@ impl WlSeatGlobal {
false
}
pub fn set_keymap(&self, keymap: &Rc<XkbKeymap>) {
pub fn set_seat_keymap(&self, keymap: &Rc<XkbKeymap>) {
self.seat_kb_map.set(keymap.clone());
self.seat_kb_map_id.set(keymap.id);
}
fn set_effective_keymap(&self, keymap: &Rc<XkbKeymap>) {
let state = match keymap.state() {
Ok(s) => s,
Err(e) => {
@ -516,7 +527,8 @@ impl WlSeatGlobal {
}
};
self.keyboard_node.get().node_on_unfocus(self);
self.kb_map.set(keymap.clone());
self.effective_kb_map.set(keymap.clone());
self.effective_kb_map_id.set(keymap.id);
*self.kb_state.borrow_mut() = state;
self.keymap_version.fetch_add(1);
self.pressed_keys.borrow_mut().clear();

View file

@ -196,7 +196,20 @@ impl WlSeatGlobal {
time_usec,
key,
state,
} => self.key_event(time_usec, key, state),
} => {
let desired_kb_map_id = match dev.keymap_id.get() {
Some(id) => id,
None => self.seat_kb_map_id.get(),
};
if desired_kb_map_id != self.effective_kb_map_id.get() {
let map = match dev.keymap.get() {
Some(map) => map,
None => self.seat_kb_map.get(),
};
self.set_effective_keymap(&map);
}
self.key_event(time_usec, key, state)
}
InputEvent::ConnectorPosition {
time_usec,
connector,

View file

@ -38,7 +38,7 @@ impl WlKeyboard {
}
pub fn send_keymap(&self) {
let map = self.seat.global.kb_map.get();
let map = self.seat.global.effective_kb_map.get();
let fd = match self.seat.keymap_fd(&map) {
Ok(fd) => fd,
Err(e) => {