1
0
Fork 0
forked from wry/wry

keyboard: send keymap without actions/behaviors to xwayland

This commit is contained in:
Julian Orth 2025-01-22 16:49:14 +01:00
parent 541a7b5ebc
commit abaeed4c01
10 changed files with 52 additions and 34 deletions

View file

@ -36,8 +36,8 @@ impl EiKeyboard {
self.client.event(Keymap { self.client.event(Keymap {
self_id: self.id, self_id: self.id,
keymap_type: KEYMAP_TYPE_XKB, keymap_type: KEYMAP_TYPE_XKB,
size: state.map_len as _, size: state.map.len as _,
keymap: state.map.clone(), keymap: state.map.map.clone(),
}); });
} }

View file

@ -75,8 +75,8 @@ impl JayInput {
fn send_keymap(&self, map: &KbvmMap) { fn send_keymap(&self, map: &KbvmMap) {
self.client.event(Keymap { self.client.event(Keymap {
self_id: self.id, self_id: self.id,
keymap: map.map.clone(), keymap: map.map.map.clone(),
keymap_len: (map.map_len - 1) as _, keymap_len: (map.map.len - 1) as _,
}); });
} }

View file

@ -73,7 +73,7 @@ use {
xdg_toplevel_drag_v1::XdgToplevelDragV1, xdg_toplevel_drag_v1::XdgToplevelDragV1,
}, },
kbvm::{KbvmMap, KbvmMapId, KbvmState, PhysicalKeyboardState}, kbvm::{KbvmMap, KbvmMapId, KbvmState, PhysicalKeyboardState},
keyboard::{DynKeyboardState, KeyboardState, KeyboardStateId}, keyboard::{DynKeyboardState, KeyboardState, KeyboardStateId, KeymapFd},
leaks::Tracker, leaks::Tracker,
object::{Object, Version}, object::{Object, Version},
rect::Rect, rect::Rect,
@ -104,7 +104,6 @@ use {
rc::{Rc, Weak}, rc::{Rc, Weak},
}, },
thiserror::Error, thiserror::Error,
uapi::OwnedFd,
}; };
pub use { pub use {
event_handling::NodeSeatState, event_handling::NodeSeatState,
@ -1179,11 +1178,15 @@ impl WlSeat {
}) })
} }
pub fn keymap_fd(&self, state: &KeyboardState) -> Result<Rc<OwnedFd>, WlKeyboardError> { pub fn keymap_fd(&self, state: &KeyboardState) -> Result<KeymapFd, WlKeyboardError> {
let fd = match self.client.is_xwayland {
true => &state.xwayland_map,
_ => &state.map,
};
if self.version >= READ_ONLY_KEYMAP_SINCE { if self.version >= READ_ONLY_KEYMAP_SINCE {
return Ok(state.map.clone()); return Ok(fd.clone());
} }
Ok(state.create_new_keymap_fd()?) Ok(fd.create_unprotected_fd()?)
} }
} }

View file

@ -27,7 +27,7 @@ impl ZwpInputMethodKeyboardGrabV2 {
} }
fn send_keymap(&self, kb_state: &KeyboardState) { fn send_keymap(&self, kb_state: &KeyboardState) {
let map = match kb_state.create_new_keymap_fd() { let map = match kb_state.map.create_unprotected_fd() {
Ok(m) => m, Ok(m) => m,
Err(e) => { Err(e) => {
log::error!("Could not create new keymap fd: {}", ErrorFmt(e)); log::error!("Could not create new keymap fd: {}", ErrorFmt(e));
@ -37,8 +37,8 @@ impl ZwpInputMethodKeyboardGrabV2 {
self.client.event(Keymap { self.client.event(Keymap {
self_id: self.id, self_id: self.id,
format: wl_keyboard::XKB_V1, format: wl_keyboard::XKB_V1,
fd: map, fd: map.map,
size: kb_state.map_len as _, size: map.len as _,
}); });
} }

View file

@ -74,8 +74,8 @@ impl WlKeyboard {
self.seat.client.event(Keymap { self.seat.client.event(Keymap {
self_id: self.id, self_id: self.id,
format: XKB_V1, format: XKB_V1,
fd, fd: fd.map,
size: state.map_len as _, size: fd.len as _,
}); });
} }

View file

@ -87,7 +87,7 @@ impl ZwpVirtualKeyboardManagerV1RequestHandler for ZwpVirtualKeyboardManagerV1 {
kb_state: Rc::new(RefCell::new(KeyboardState { kb_state: Rc::new(RefCell::new(KeyboardState {
id: self.client.state.keyboard_state_ids.next(), id: self.client.state.keyboard_state_ids.next(),
map: seat_keymap.map.clone(), map: seat_keymap.map.clone(),
map_len: seat_keymap.map_len, xwayland_map: seat_keymap.xwayland_map.clone(),
pressed_keys: Default::default(), pressed_keys: Default::default(),
mods: Default::default(), mods: Default::default(),
})), })),

View file

@ -80,7 +80,7 @@ impl ZwpVirtualKeyboardV1RequestHandler for ZwpVirtualKeyboardV1 {
*self.kb_state.borrow_mut() = KeyboardState { *self.kb_state.borrow_mut() = KeyboardState {
id: self.client.state.keyboard_state_ids.next(), id: self.client.state.keyboard_state_ids.next(),
map: map.map.clone(), map: map.map.clone(),
map_len: map.map_len, xwayland_map: map.xwayland_map.clone(),
pressed_keys: Default::default(), pressed_keys: Default::default(),
mods: Default::default(), mods: Default::default(),
}; };

View file

@ -16,7 +16,7 @@ async fn test(run: Rc<TestRun>) -> TestResult {
let virtual_keymap_str = { let virtual_keymap_str = {
let xkb = KbvmContext::default(); let xkb = KbvmContext::default();
let map = xkb.parse_keymap(VIRTUAL_KEYMAP.as_bytes()).unwrap(); let map = xkb.parse_keymap(VIRTUAL_KEYMAP.as_bytes()).unwrap();
read_keymap(&map.map, map.map_len) read_keymap(&map.map.map, map.map.len)
}; };
let ds = run.create_default_setup().await?; let ds = run.create_default_setup().await?;

View file

@ -2,7 +2,7 @@ use {
crate::{ crate::{
backend::KeyState, backend::KeyState,
ifs::wl_seat::WlSeatGlobal, ifs::wl_seat::WlSeatGlobal,
keyboard::{DynKeyboardState, KeyboardState, KeyboardStateId}, keyboard::{DynKeyboardState, KeyboardState, KeyboardStateId, KeymapFd},
utils::{oserror::OsError, syncqueue::SyncQueue, vecset::VecSet}, utils::{oserror::OsError, syncqueue::SyncQueue, vecset::VecSet},
}, },
kbvm::{ kbvm::{
@ -21,7 +21,7 @@ use {
rc::Rc, rc::Rc,
}, },
thiserror::Error, thiserror::Error,
uapi::{c, OwnedFd}, uapi::c,
}; };
#[derive(Debug, Error)] #[derive(Debug, Error)]
@ -54,8 +54,8 @@ pub struct KbvmMap {
pub id: KbvmMapId, pub id: KbvmMapId,
pub state_machine: StateMachine, pub state_machine: StateMachine,
pub lookup_table: LookupTable, pub lookup_table: LookupTable,
pub map: Rc<OwnedFd>, pub map: KeymapFd,
pub map_len: usize, pub xwayland_map: KeymapFd,
} }
pub struct KbvmState { pub struct KbvmState {
@ -89,20 +89,23 @@ impl KbvmContext {
.ctx .ctx
.keymap_from_bytes(WriteToLog, None, keymap) .keymap_from_bytes(WriteToLog, None, keymap)
.map_err(KbvmError::CouldNotParseKeymap)?; .map_err(KbvmError::CouldNotParseKeymap)?;
let (memfd, len) = create_keymap_memfd(&map).map_err(KbvmError::KeymapMemfd)?;
let builder = map.to_builder(); let builder = map.to_builder();
Ok(Rc::new(KbvmMap { Ok(Rc::new(KbvmMap {
id: self.ids.next(), id: self.ids.next(),
state_machine: builder.build_state_machine(), state_machine: builder.build_state_machine(),
map: Rc::new(memfd), map: create_keymap_memfd(&map, false).map_err(KbvmError::KeymapMemfd)?,
map_len: len + 1, xwayland_map: create_keymap_memfd(&map, true).map_err(KbvmError::KeymapMemfd)?,
lookup_table: builder.build_lookup_table(), lookup_table: builder.build_lookup_table(),
})) }))
} }
} }
fn create_keymap_memfd(map: &Keymap) -> Result<(OwnedFd, usize), OsError> { fn create_keymap_memfd(map: &Keymap, xwayland: bool) -> Result<KeymapFd, OsError> {
let str = format!("{}\n", map.format()); let mut format = map.format();
if xwayland {
format = format.lookup_only(true).rename_long_keys(true);
}
let str = format!("{}\n", format);
let mut memfd = uapi::memfd_create("keymap", c::MFD_CLOEXEC | c::MFD_ALLOW_SEALING)?; let mut memfd = uapi::memfd_create("keymap", c::MFD_CLOEXEC | c::MFD_ALLOW_SEALING)?;
memfd.write_all(str.as_bytes())?; memfd.write_all(str.as_bytes())?;
memfd.write_all(&[0])?; memfd.write_all(&[0])?;
@ -111,7 +114,10 @@ fn create_keymap_memfd(map: &Keymap) -> Result<(OwnedFd, usize), OsError> {
memfd.raw(), memfd.raw(),
c::F_SEAL_SEAL | c::F_SEAL_GROW | c::F_SEAL_SHRINK | c::F_SEAL_WRITE, c::F_SEAL_SEAL | c::F_SEAL_GROW | c::F_SEAL_SHRINK | c::F_SEAL_WRITE,
)?; )?;
Ok((memfd, str.len())) Ok(KeymapFd {
map: Rc::new(memfd),
len: str.len() + 1,
})
} }
impl KbvmMap { impl KbvmMap {
@ -122,7 +128,7 @@ impl KbvmMap {
kb_state: KeyboardState { kb_state: KeyboardState {
id, id,
map: self.map.clone(), map: self.map.clone(),
map_len: self.map_len, xwayland_map: self.xwayland_map.clone(),
pressed_keys: Default::default(), pressed_keys: Default::default(),
mods: Default::default(), mods: Default::default(),
}, },

View file

@ -21,8 +21,8 @@ linear_ids!(KeyboardStateIds, KeyboardStateId, u64);
pub struct KeyboardState { pub struct KeyboardState {
pub id: KeyboardStateId, pub id: KeyboardStateId,
pub map: Rc<OwnedFd>, pub map: KeymapFd,
pub map_len: usize, pub xwayland_map: KeymapFd,
pub pressed_keys: VecSet<u32>, pub pressed_keys: VecSet<u32>,
pub mods: Components, pub mods: Components,
} }
@ -37,13 +37,19 @@ impl DynKeyboardState for RefCell<KeyboardState> {
} }
} }
impl KeyboardState { #[derive(Clone)]
pub fn create_new_keymap_fd(&self) -> Result<Rc<OwnedFd>, KeyboardError> { pub struct KeymapFd {
pub map: Rc<OwnedFd>,
pub len: usize,
}
impl KeymapFd {
pub fn create_unprotected_fd(&self) -> Result<Self, KeyboardError> {
let fd = match uapi::memfd_create("shared-keymap", c::MFD_CLOEXEC) { let fd = match uapi::memfd_create("shared-keymap", c::MFD_CLOEXEC) {
Ok(fd) => fd, Ok(fd) => fd,
Err(e) => return Err(KeyboardError::KeymapMemfd(e.into())), Err(e) => return Err(KeyboardError::KeymapMemfd(e.into())),
}; };
let target = self.map_len as c::off_t; let target = self.len as c::off_t;
let mut pos = 0; let mut pos = 0;
while pos < target { while pos < target {
let rem = target - pos; let rem = target - pos;
@ -53,6 +59,9 @@ impl KeyboardState {
Err(e) => return Err(KeyboardError::KeymapCopy(e.into())), Err(e) => return Err(KeyboardError::KeymapCopy(e.into())),
} }
} }
Ok(Rc::new(fd)) Ok(Self {
map: Rc::new(fd),
len: self.len,
})
} }
} }