From 8027d34a91cfb85f856b1f6fc6f54c7ca546de2e Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Wed, 19 Jul 2023 14:46:09 -0700 Subject: [PATCH] Don't send key repeat after surface is closed If a surface is closed when it has keyboard focus, `wl_keyboard::leave` isn't received. But we want to still make sure key repeat events aren't emitted. --- src/seat/keyboard/mod.rs | 21 +++++++++++++++++++++ src/seat/keyboard/repeat.rs | 3 ++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/seat/keyboard/mod.rs b/src/seat/keyboard/mod.rs index aca50a3be..f19e27df5 100644 --- a/src/seat/keyboard/mod.rs +++ b/src/seat/keyboard/mod.rs @@ -323,6 +323,7 @@ pub struct KeyboardData { xkb_compose: Mutex>, #[cfg(feature = "calloop")] repeat_data: Arc>>>, + focus: Mutex>, _phantom_data: PhantomData, } @@ -369,6 +370,7 @@ impl KeyboardData { xkb_compose: Mutex::new(None), #[cfg(feature = "calloop")] repeat_data: Arc::new(Mutex::new(None)), + focus: Mutex::new(None), _phantom_data: PhantomData, }; @@ -408,6 +410,7 @@ impl KeyboardData { xkb_compose: Mutex::new(None), #[cfg(feature = "calloop")] repeat_data: Arc::new(Mutex::new(None)), + focus: Mutex::new(None), _phantom_data: PhantomData, }; @@ -589,6 +592,8 @@ where data.enter(conn, qh, keyboard, &surface, serial, &raw, &keysyms); } + + *udata.focus.lock().unwrap() = Some(surface); } wl_keyboard::Event::Leave { serial, surface } => { @@ -602,6 +607,8 @@ where } data.leave(conn, qh, keyboard, &surface, serial); + + *udata.focus.lock().unwrap() = None; } wl_keyboard::Event::Key { serial, time, key, state } => match state { @@ -677,10 +684,19 @@ where loop_handle.remove(token); } + let surface = udata + .focus + .lock() + .unwrap() + .as_ref() + .cloned() + .expect("wl_keyboard::key with no focused surface"); + // Update the current repeat key. repeat_data.current_repeat.replace(RepeatedKey { key: event.clone(), is_first: true, + surface, }); let (delay, rate) = match repeat_data.repeat_info { @@ -713,6 +729,11 @@ where return TimeoutAction::Drop; } let key = key.as_mut().unwrap(); + // If surface was closed while focused, no `Leave` + // event occurred. + if !key.surface.is_alive() { + return TimeoutAction::Drop; + } key.key.time += if key.is_first { key.is_first = false; delay diff --git a/src/seat/keyboard/repeat.rs b/src/seat/keyboard/repeat.rs index c74e3cc70..0a549c9ce 100644 --- a/src/seat/keyboard/repeat.rs +++ b/src/seat/keyboard/repeat.rs @@ -4,7 +4,7 @@ use calloop::{LoopHandle, RegistrationToken}; use wayland_client::{ protocol::{ wl_keyboard::{self, WlKeyboard}, - wl_seat, + wl_seat, wl_surface, }, Dispatch, QueueHandle, }; @@ -19,6 +19,7 @@ pub(crate) struct RepeatedKey { pub(crate) key: KeyEvent, /// Whether this is the first event of the repeat sequence. pub(crate) is_first: bool, + pub(crate) surface: wl_surface::WlSurface, } pub type RepeatCallback = Box;