Skip to content

Commit

Permalink
Don't send key repeat after surface is closed
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
ids1024 authored and wash2 committed Jul 20, 2023
1 parent 4a5c4f5 commit 8027d34
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 1 deletion.
21 changes: 21 additions & 0 deletions src/seat/keyboard/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,7 @@ pub struct KeyboardData<T> {
xkb_compose: Mutex<Option<xkb::compose::State>>,
#[cfg(feature = "calloop")]
repeat_data: Arc<Mutex<Option<RepeatData<T>>>>,
focus: Mutex<Option<wl_surface::WlSurface>>,
_phantom_data: PhantomData<T>,
}

Expand Down Expand Up @@ -369,6 +370,7 @@ impl<T> KeyboardData<T> {
xkb_compose: Mutex::new(None),
#[cfg(feature = "calloop")]
repeat_data: Arc::new(Mutex::new(None)),
focus: Mutex::new(None),
_phantom_data: PhantomData,
};

Expand Down Expand Up @@ -408,6 +410,7 @@ impl<T> KeyboardData<T> {
xkb_compose: Mutex::new(None),
#[cfg(feature = "calloop")]
repeat_data: Arc::new(Mutex::new(None)),
focus: Mutex::new(None),
_phantom_data: PhantomData,
};

Expand Down Expand Up @@ -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 } => {
Expand All @@ -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 {
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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
Expand Down
3 changes: 2 additions & 1 deletion src/seat/keyboard/repeat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use calloop::{LoopHandle, RegistrationToken};
use wayland_client::{
protocol::{
wl_keyboard::{self, WlKeyboard},
wl_seat,
wl_seat, wl_surface,
},
Dispatch, QueueHandle,
};
Expand All @@ -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<T> = Box<dyn FnMut(&mut T, &WlKeyboard, KeyEvent) + 'static>;
Expand Down

0 comments on commit 8027d34

Please sign in to comment.