smithay_client_toolkit/seat/keyboard/
repeat.rs1use std::sync::atomic::Ordering;
2
3use calloop::{LoopHandle, RegistrationToken};
4use wayland_client::{
5 protocol::{
6 wl_keyboard::{self, WlKeyboard},
7 wl_seat, wl_surface,
8 },
9 Dispatch, QueueHandle,
10};
11
12use super::{
13 Capability, KeyEvent, KeyboardData, KeyboardError, KeyboardHandler, RepeatInfo, SeatError,
14 RMLVO,
15};
16use crate::seat::SeatState;
17
18pub(crate) struct RepeatedKey {
19 pub(crate) key: KeyEvent,
20 pub(crate) is_first: bool,
22 pub(crate) surface: wl_surface::WlSurface,
23}
24
25pub type RepeatCallback<T> = Box<dyn FnMut(&mut T, &WlKeyboard, KeyEvent) + 'static>;
26
27pub(crate) struct RepeatData<T> {
28 pub(crate) current_repeat: Option<RepeatedKey>,
29 pub(crate) repeat_info: RepeatInfo,
30 pub(crate) loop_handle: LoopHandle<'static, T>,
31 pub(crate) callback: RepeatCallback<T>,
32 pub(crate) repeat_token: Option<RegistrationToken>,
33}
34
35impl<T> Drop for RepeatData<T> {
36 fn drop(&mut self) {
37 if let Some(token) = self.repeat_token.take() {
38 self.loop_handle.remove(token);
39 }
40 }
41}
42
43impl SeatState {
44 pub fn get_keyboard_with_repeat<D>(
59 &mut self,
60 qh: &QueueHandle<D>,
61 seat: &wl_seat::WlSeat,
62 rmlvo: Option<RMLVO>,
63 loop_handle: LoopHandle<'static, D>,
64 callback: RepeatCallback<D>,
65 ) -> Result<wl_keyboard::WlKeyboard, KeyboardError>
66 where
67 D: Dispatch<wl_keyboard::WlKeyboard, KeyboardData<D, ()>> + KeyboardHandler + 'static,
68 {
69 let udata = match rmlvo {
70 Some(rmlvo) => KeyboardData::from_rmlvo(seat.clone(), rmlvo, ())?,
71 None => KeyboardData::new(seat.clone(), ()),
72 };
73
74 let inner =
75 self.seats.iter().find(|inner| &inner.seat == seat).ok_or(SeatError::DeadObject)?;
76
77 if !inner.data.has_keyboard.load(Ordering::SeqCst) {
78 return Err(SeatError::UnsupportedCapability(Capability::Keyboard).into());
79 }
80
81 udata.repeat_data.lock().unwrap().replace(RepeatData {
82 current_repeat: None,
83 repeat_info: RepeatInfo::Disable,
84 loop_handle: loop_handle.clone(),
85 callback,
86 repeat_token: None,
87 });
88 udata.init_compose();
89
90 Ok(seat.get_keyboard(qh, udata))
91 }
92
93 pub fn get_keyboard_with_repeat_with_data<D, U>(
108 &mut self,
109 qh: &QueueHandle<D>,
110 seat: &wl_seat::WlSeat,
111 udata: U,
112 loop_handle: LoopHandle<'static, D>,
113 callback: RepeatCallback<D>,
114 ) -> Result<wl_keyboard::WlKeyboard, KeyboardError>
115 where
116 D: Dispatch<wl_keyboard::WlKeyboard, KeyboardData<D, U>> + KeyboardHandler + 'static,
117 U: Send + Sync + 'static,
118 {
119 let inner =
120 self.seats.iter().find(|inner| &inner.seat == seat).ok_or(SeatError::DeadObject)?;
121
122 if !inner.data.has_keyboard.load(Ordering::SeqCst) {
123 return Err(SeatError::UnsupportedCapability(Capability::Keyboard).into());
124 }
125
126 let udata = KeyboardData::new(seat.clone(), udata);
127
128 udata.repeat_data.lock().unwrap().replace(RepeatData {
129 current_repeat: None,
130 repeat_info: RepeatInfo::Disable,
131 loop_handle: loop_handle.clone(),
132 callback,
133 repeat_token: None,
134 });
135 udata.init_compose();
136
137 Ok(seat.get_keyboard(qh, udata))
138 }
139}