1
0
Fork 0
forked from wry/wry

wl_keyboard: don't send key-up events for keys that are not logically down

This commit is contained in:
Julian Orth 2025-01-23 13:48:23 +01:00
parent abaeed4c01
commit 53c38bdd68
9 changed files with 68 additions and 27 deletions

View file

@ -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,
},
});
}
}

View file

@ -111,7 +111,7 @@ impl EiSeat {
self: &Rc<Self>,
time_usec: u64,
key: u32,
state: u32,
state: KeyState,
kb_state: &KeyboardState,
) {
if self.is_sender() {

View file

@ -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();

View file

@ -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,
},
})
}

View file

@ -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<WlSeat>,
kb_state_id: Cell<KeyboardStateId>,
pressed_keys: RefCell<VecSet<u32>>,
pub tracker: Tracker<Self>,
}
@ -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,
},
})
}

View file

@ -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<Self>) -> 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),

View file

@ -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);

View file

@ -189,7 +189,7 @@ pub trait Node: 'static {
seat: &WlSeatGlobal,
time_usec: u64,
key: u32,
state: u32,
state: KeyState,
kb_state: &KeyboardState,
) {
let _ = seat;

View file

@ -19,7 +19,6 @@ impl<T> Deref for VecSet<T> {
}
impl<T> VecSet<T> {
#[expect(dead_code)]
pub fn clear(&mut self) {
self.vec.clear();
}
@ -47,4 +46,13 @@ impl<T: PartialEq> VecSet<T> {
pub fn pop(&mut self) -> Option<T> {
self.vec.pop()
}
pub fn extend(&mut self, vals: &[T])
where
T: Copy,
{
for v in vals.iter().copied() {
self.insert(v);
}
}
}