diff --git a/src/ei/ei_ifs/ei_keyboard.rs b/src/ei/ei_ifs/ei_keyboard.rs index a510d87e..b17a9c55 100644 --- a/src/ei/ei_ifs/ei_keyboard.rs +++ b/src/ei/ei_ifs/ei_keyboard.rs @@ -52,11 +52,14 @@ impl EiKeyboard { }); } - pub fn send_key(&self, key: u32, state: u32) { + pub fn send_key(&self, key: u32, state: KeyState) { self.client.event(ServerKey { self_id: self.id, key, - state, + state: match state { + KeyState::Released => 0, + KeyState::Pressed => 1, + }, }); } } diff --git a/src/ei/ei_ifs/ei_seat.rs b/src/ei/ei_ifs/ei_seat.rs index e7c016a7..1177e1ea 100644 --- a/src/ei/ei_ifs/ei_seat.rs +++ b/src/ei/ei_ifs/ei_seat.rs @@ -111,7 +111,7 @@ impl EiSeat { self: &Rc, time_usec: u64, key: u32, - state: u32, + state: KeyState, kb_state: &KeyboardState, ) { if self.is_sender() { diff --git a/src/ifs/wl_seat/event_handling.rs b/src/ifs/wl_seat/event_handling.rs index ed720292..d5f24ab5 100644 --- a/src/ifs/wl_seat/event_handling.rs +++ b/src/ifs/wl_seat/event_handling.rs @@ -19,7 +19,7 @@ use { wl_seat::{ tablet::{TabletPad, TabletPadId, TabletTool, TabletToolId}, text_input::TextDisconnectReason, - wl_keyboard::{self, WlKeyboard}, + wl_keyboard::WlKeyboard, wl_pointer::{ self, PendingScroll, WlPointer, AXIS_DISCRETE_SINCE_VERSION, AXIS_RELATIVE_DIRECTION_SINCE_VERSION, AXIS_SOURCE_SINCE_VERSION, @@ -873,22 +873,18 @@ impl WlSeatGlobal { } } self.send_components(&mut components_changed, &kbvm_state); - let state = match key_state { - KeyState::Released => wl_keyboard::RELEASED, - KeyState::Pressed => wl_keyboard::PRESSED, - }; match self.input_method_grab.get() { - Some(g) => g.on_key(time_usec, kc.to_evdev(), state, &kbvm_state.kb_state), + Some(g) => g.on_key(time_usec, kc.to_evdev(), key_state, &kbvm_state.kb_state), _ => self.keyboard_node.get().node_on_key( self, time_usec, kc.to_evdev(), - state, + key_state, &kbvm_state.kb_state, ), } self.for_each_ei_seat(|ei_seat| { - ei_seat.handle_key(time_usec, kc.to_evdev(), state, &kbvm_state.kb_state); + ei_seat.handle_key(time_usec, kc.to_evdev(), key_state, &kbvm_state.kb_state); }); update_pressed_keys(&mut kbvm_state); } @@ -1339,7 +1335,7 @@ impl WlSeatGlobal { surface: &WlSurface, time_usec: u64, key: u32, - state: u32, + state: KeyState, kb_state: &KeyboardState, ) { let serial = surface.client.next_serial(); diff --git a/src/ifs/wl_seat/text_input/zwp_input_method_keyboard_grab_v2.rs b/src/ifs/wl_seat/text_input/zwp_input_method_keyboard_grab_v2.rs index 927e9de7..f8e826fa 100644 --- a/src/ifs/wl_seat/text_input/zwp_input_method_keyboard_grab_v2.rs +++ b/src/ifs/wl_seat/text_input/zwp_input_method_keyboard_grab_v2.rs @@ -1,5 +1,6 @@ use { crate::{ + backend::KeyState, client::{Client, ClientError}, ifs::wl_seat::{text_input::zwp_input_method_v2::ZwpInputMethodV2, wl_keyboard}, keyboard::{KeyboardState, KeyboardStateId}, @@ -48,7 +49,7 @@ impl ZwpInputMethodKeyboardGrabV2 { self.kb_state_id.set(kb_state.id); } - pub fn on_key(&self, time_usec: u64, key: u32, state: u32, kb_state: &KeyboardState) { + pub fn on_key(&self, time_usec: u64, key: u32, state: KeyState, kb_state: &KeyboardState) { let serial = self.client.next_serial(); if self.kb_state_id.get() != kb_state.id { self.update_state(serial, kb_state); @@ -56,13 +57,16 @@ impl ZwpInputMethodKeyboardGrabV2 { self.send_key(serial, time_usec, key, state); } - fn send_key(&self, serial: u64, time_usec: u64, key: u32, state: u32) { + fn send_key(&self, serial: u64, time_usec: u64, key: u32, state: KeyState) { self.client.event(Key { self_id: self.id, serial: serial as _, time: (time_usec / 1000) as _, key, - state, + state: match state { + KeyState::Released => wl_keyboard::RELEASED, + KeyState::Pressed => wl_keyboard::PRESSED, + }, }) } diff --git a/src/ifs/wl_seat/wl_keyboard.rs b/src/ifs/wl_seat/wl_keyboard.rs index aaea9c07..94aadd30 100644 --- a/src/ifs/wl_seat/wl_keyboard.rs +++ b/src/ifs/wl_seat/wl_keyboard.rs @@ -1,15 +1,19 @@ use { crate::{ + backend::KeyState, client::ClientError, ifs::wl_seat::WlSeat, keyboard::{KeyboardError, KeyboardState, KeyboardStateId}, leaks::Tracker, object::{Object, Version}, - utils::errorfmt::ErrorFmt, + utils::{errorfmt::ErrorFmt, vecset::VecSet}, wire::{wl_keyboard::*, WlKeyboardId, WlSurfaceId}, }, kbvm::Components, - std::{cell::Cell, rc::Rc}, + std::{ + cell::{Cell, RefCell}, + rc::Rc, + }, thiserror::Error, }; @@ -26,6 +30,7 @@ pub struct WlKeyboard { id: WlKeyboardId, seat: Rc, kb_state_id: Cell, + pressed_keys: RefCell>, pub tracker: Tracker, } @@ -35,6 +40,7 @@ impl WlKeyboard { id, seat: seat.clone(), kb_state_id: Cell::new(KeyboardStateId::from_raw(0)), + pressed_keys: Default::default(), tracker: Default::default(), } } @@ -89,6 +95,11 @@ impl WlKeyboard { } fn send_enter(&self, serial: u64, surface: WlSurfaceId, keys: &[u32]) { + { + let pk = &mut self.pressed_keys.borrow_mut(); + pk.clear(); + pk.extend(keys); + } self.seat.client.event(Enter { self_id: self.id, serial: serial as _, @@ -110,7 +121,7 @@ impl WlKeyboard { serial: u64, time: u32, key: u32, - state: u32, + state: KeyState, surface: WlSurfaceId, kb_state: &KeyboardState, ) { @@ -120,13 +131,31 @@ impl WlKeyboard { self.send_key(serial, time, key, state); } - fn send_key(&self, serial: u64, time: u32, key: u32, state: u32) { + fn send_key(&self, serial: u64, time: u32, key: u32, state: KeyState) { + { + let pk = &mut self.pressed_keys.borrow_mut(); + match state { + KeyState::Released => { + if !pk.remove(&key) { + return; + } + } + KeyState::Pressed => { + if !pk.insert(key) { + return; + } + } + } + } self.seat.client.event(Key { self_id: self.id, serial: serial as _, time, key, - state, + state: match state { + KeyState::Released => RELEASED, + KeyState::Pressed => PRESSED, + }, }) } diff --git a/src/ifs/wl_seat/zwp_virtual_keyboard_v1.rs b/src/ifs/wl_seat/zwp_virtual_keyboard_v1.rs index 2f748dcf..4ef07028 100644 --- a/src/ifs/wl_seat/zwp_virtual_keyboard_v1.rs +++ b/src/ifs/wl_seat/zwp_virtual_keyboard_v1.rs @@ -1,5 +1,6 @@ use { crate::{ + backend::KeyState, client::{Client, ClientError}, clientmem::{ClientMem, ClientMemError}, ifs::{ @@ -90,14 +91,14 @@ impl ZwpVirtualKeyboardV1RequestHandler for ZwpVirtualKeyboardV1 { fn key(&self, req: Key, _slf: &Rc) -> Result<(), Self::Error> { let kb_state = &mut *self.kb_state.borrow_mut(); let contains = kb_state.pressed_keys.contains(&req.key); - let valid = match req.state { - wl_keyboard::RELEASED => contains, - wl_keyboard::PRESSED => !contains, + let (state, valid) = match req.state { + wl_keyboard::RELEASED => (KeyState::Released, contains), + wl_keyboard::PRESSED => (KeyState::Pressed, !contains), _ => return Err(ZwpVirtualKeyboardV1Error::UnknownState(req.state)), }; if valid { self.for_each_kb(|serial, surface, kb| { - kb.on_key(serial, req.time, req.key, req.state, surface.id, kb_state); + kb.on_key(serial, req.time, req.key, state, surface.id, kb_state); }); match req.state { wl_keyboard::RELEASED => kb_state.pressed_keys.remove(&req.key), diff --git a/src/ifs/wl_surface.rs b/src/ifs/wl_surface.rs index db826948..8559a0bb 100644 --- a/src/ifs/wl_surface.rs +++ b/src/ifs/wl_surface.rs @@ -1741,7 +1741,7 @@ impl Node for WlSurface { seat: &WlSeatGlobal, time_usec: u64, key: u32, - state: u32, + state: KeyState, kb_state: &KeyboardState, ) { seat.key_surface(self, time_usec, key, state, kb_state); diff --git a/src/tree.rs b/src/tree.rs index bff62ef1..53352391 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -189,7 +189,7 @@ pub trait Node: 'static { seat: &WlSeatGlobal, time_usec: u64, key: u32, - state: u32, + state: KeyState, kb_state: &KeyboardState, ) { let _ = seat; diff --git a/src/utils/vecset.rs b/src/utils/vecset.rs index d058fe0a..49c3356d 100644 --- a/src/utils/vecset.rs +++ b/src/utils/vecset.rs @@ -19,7 +19,6 @@ impl Deref for VecSet { } impl VecSet { - #[expect(dead_code)] pub fn clear(&mut self) { self.vec.clear(); } @@ -47,4 +46,13 @@ impl VecSet { pub fn pop(&mut self) -> Option { self.vec.pop() } + + pub fn extend(&mut self, vals: &[T]) + where + T: Copy, + { + for v in vals.iter().copied() { + self.insert(v); + } + } }