diff --git a/src/ifs/wl_seat.rs b/src/ifs/wl_seat.rs index 031f70e1..167f3904 100644 --- a/src/ifs/wl_seat.rs +++ b/src/ifs/wl_seat.rs @@ -163,6 +163,7 @@ pub struct WlSeatGlobal { constraint: CloneCell>>, idle_notifications: CopyHashMap<(ClientId, ExtIdleNotificationV1Id), Rc>, last_input_usec: Cell, + keymap_version: NumCell, } const CHANGE_CURSOR_MOVED: u32 = 1 << 0; @@ -219,6 +220,7 @@ impl WlSeatGlobal { idle_notifications: Default::default(), last_input_usec: Cell::new(now_usec()), wlr_data_devices: Default::default(), + keymap_version: NumCell::new(1), }); state.add_cursor_size(*DEFAULT_CURSOR_SIZE); let seat = slf.clone(); @@ -513,24 +515,12 @@ impl WlSeatGlobal { return; } }; + self.keyboard_node.get().node_on_unfocus(self); 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() { - let kbs = seat.keyboards.lock(); - for kb in kbs.values() { - let fd = match seat.keymap_fd(keymap) { - Ok(fd) => fd, - Err(e) => { - log::error!("Could not creat a file descriptor to transfer the keymap to client {}: {}", id, ErrorFmt(e)); - continue; - } - }; - kb.send_keymap(wl_keyboard::XKB_V1, fd, keymap.map_len as _); - } - } - } + self.keymap_version.fetch_add(1); + self.pressed_keys.borrow_mut().clear(); + self.keyboard_node.get().node_on_focus(self); } pub fn prepare_for_lock(self: &Rc) { @@ -1180,12 +1170,13 @@ impl WlSeatRequestHandler for WlSeat { track!(self.client, p); self.client.add_client_obj(&p)?; self.keyboards.set(req.id, p.clone()); - let keymap = self.global.kb_map.get(); - p.send_keymap( - wl_keyboard::XKB_V1, - self.keymap_fd(&keymap)?, - keymap.map_len as _, - ); + p.send_keymap(); + if let Some(surface) = self.global.keyboard_node.get().node_into_surface() { + if surface.client.id == self.client.id { + let serial = self.client.next_serial(); + p.send_enter(serial, surface.id, &self.global.pressed_keys.borrow()) + } + } if self.version >= REPEAT_INFO_SINCE { let (rate, delay) = self.global.repeat_rate.get(); p.send_repeat_info(rate, delay); diff --git a/src/ifs/wl_seat/wl_keyboard.rs b/src/ifs/wl_seat/wl_keyboard.rs index f5089eaf..4f3c054c 100644 --- a/src/ifs/wl_seat/wl_keyboard.rs +++ b/src/ifs/wl_seat/wl_keyboard.rs @@ -4,12 +4,11 @@ use { ifs::wl_seat::WlSeat, leaks::Tracker, object::{Object, Version}, - utils::oserror::OsError, + utils::{errorfmt::ErrorFmt, numcell::NumCell, oserror::OsError}, wire::{wl_keyboard::*, WlKeyboardId, WlSurfaceId}, }, std::rc::Rc, thiserror::Error, - uapi::OwnedFd, }; pub const REPEAT_INFO_SINCE: Version = Version(4); @@ -24,6 +23,7 @@ pub(super) const PRESSED: u32 = 1; pub struct WlKeyboard { id: WlKeyboardId, seat: Rc, + pub(super) keymap_version: NumCell, pub tracker: Tracker, } @@ -32,20 +32,38 @@ impl WlKeyboard { Self { id, seat: seat.clone(), + keymap_version: NumCell::new(0), tracker: Default::default(), } } - pub fn send_keymap(self: &Rc, format: u32, fd: Rc, size: u32) { + pub fn send_keymap(&self) { + let map = self.seat.global.kb_map.get(); + let fd = match self.seat.keymap_fd(&map) { + Ok(fd) => fd, + Err(e) => { + log::error!( + "Could not creat a file descriptor to transfer the keymap to client {}: {}", + self.seat.client.id, + ErrorFmt(e) + ); + return; + } + }; self.seat.client.event(Keymap { self_id: self.id, - format, + format: XKB_V1, fd, - size, - }) + size: map.map_len as _, + }); + self.keymap_version + .set(self.seat.global.keymap_version.get()); } pub fn send_enter(self: &Rc, serial: u32, surface: WlSurfaceId, keys: &[u32]) { + if self.keymap_version.get() != self.seat.global.keymap_version.get() { + self.send_keymap(); + } self.seat.client.event(Enter { self_id: self.id, serial, diff --git a/src/ifs/wl_surface.rs b/src/ifs/wl_surface.rs index 74977c19..07a8940f 100644 --- a/src/ifs/wl_surface.rs +++ b/src/ifs/wl_surface.rs @@ -1399,7 +1399,7 @@ impl Node for WlSurface { seat.scroll_surface(&self, event); } - fn node_on_focus(self: Rc, seat: &Rc) { + fn node_on_focus(self: Rc, seat: &WlSeatGlobal) { if let Some(tl) = self.toplevel.get() { tl.tl_data().focus_node.insert(seat.id(), self.clone()); tl.tl_on_activate(); diff --git a/src/tree.rs b/src/tree.rs index a652e1a7..975ff0b0 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -190,7 +190,7 @@ pub trait Node: 'static { let _ = event; } - fn node_on_focus(self: Rc, seat: &Rc) { + fn node_on_focus(self: Rc, seat: &WlSeatGlobal) { let _ = seat; } diff --git a/src/utils/vecset.rs b/src/utils/vecset.rs index 6eec7272..7333ec9b 100644 --- a/src/utils/vecset.rs +++ b/src/utils/vecset.rs @@ -18,6 +18,12 @@ impl Deref for VecSet { } } +impl VecSet { + pub fn clear(&mut self) { + self.vec.clear(); + } +} + impl VecSet { pub fn insert(&mut self, val: T) -> bool { if self.vec.contains(&val) {