chore: refresco desde el monorepo (pin tawasuyu.git v0.2.0)
1//!
2//! Input abstractions
3//!
4//! This module provides some types loosely resembling instances of wayland seats, pointers, touch and keyboards.
5//! It is however not directly tied to wayland and can be used to multiplex various input operations
6//! between different handlers.
7//!
8//! If the `wayland_frontend`-feature is enabled the `smithay::wayland::seat`-module provides additional
9//! functionality for the provided types of this module to map them to advertised wayland globals and objects.
10//!
11//! ## How to use it
12//!
13//! To start using this module you need to create a [`SeatState`] and use that to create [`Seat`]s.
14//! Additionally you need to implement the [`SeatHandler`] trait.
15//!
16//! ### Initialization
17//!
18//! ```
19//! use smithay::input::{Seat, SeatState, SeatHandler, pointer::CursorImageStatus};
20//! # use smithay::backend::input::KeyState;
21//! # use smithay::input::{
22//! # pointer::{PointerTarget, AxisFrame, MotionEvent, ButtonEvent, RelativeMotionEvent,
23//! # GestureSwipeBeginEvent, GestureSwipeUpdateEvent, GestureSwipeEndEvent,
24//! # GesturePinchBeginEvent, GesturePinchUpdateEvent, GesturePinchEndEvent,
25//! # GestureHoldBeginEvent, GestureHoldEndEvent},
26//! # keyboard::{KeyboardTarget, KeysymHandle, ModifiersState},
27//! # touch::{DownEvent, UpEvent, MotionEvent as TouchMotionEvent, ShapeEvent, OrientationEvent, TouchTarget},
28//! # };
29//! # use smithay::utils::{IsAlive, Serial};
30//!
31//! struct State {
32//! seat_state: SeatState<Self>,
33//! // ...
34//! };
35//!
36//! let mut seat_state = SeatState::<State>::new();
37//!
38//! // create the seat
39//! let seat = seat_state.new_seat(
40//! "seat-0", // the name of the seat, will be advertized to clients
41//! );
42//!
43//! # #[derive(Debug, Clone, PartialEq)]
44//! # struct Target;
45//! # impl IsAlive for Target {
46//! # fn alive(&self) -> bool { true }
47//! # }
48//! # impl PointerTarget<State> for Target {
49//! # fn enter(&self, seat: &Seat<State>, data: &mut State, event: &MotionEvent) {}
50//! # fn motion(&self, seat: &Seat<State>, data: &mut State, event: &MotionEvent) {}
51//! # fn relative_motion(&self, seat: &Seat<State>, data: &mut State, event: &RelativeMotionEvent) {}
52//! # fn button(&self, seat: &Seat<State>, data: &mut State, event: &ButtonEvent) {}
53//! # fn axis(&self, seat: &Seat<State>, data: &mut State, frame: AxisFrame) {}
54//! # fn frame(&self, seat: &Seat<State>, data: &mut State) {}
55//! # fn leave(&self, seat: &Seat<State>, data: &mut State, serial: Serial, time: u32) {}
56//! # fn gesture_swipe_begin(&self, seat: &Seat<State>, data: &mut State, event: &GestureSwipeBeginEvent) {}
57//! # fn gesture_swipe_update(&self, seat: &Seat<State>, data: &mut State, event: &GestureSwipeUpdateEvent) {}
58//! # fn gesture_swipe_end(&self, seat: &Seat<State>, data: &mut State, event: &GestureSwipeEndEvent) {}
59//! # fn gesture_pinch_begin(&self, seat: &Seat<State>, data: &mut State, event: &GesturePinchBeginEvent) {}
60//! # fn gesture_pinch_update(&self, seat: &Seat<State>, data: &mut State, event: &GesturePinchUpdateEvent) {}
61//! # fn gesture_pinch_end(&self, seat: &Seat<State>, data: &mut State, event: &GesturePinchEndEvent) {}
62//! # fn gesture_hold_begin(&self, seat: &Seat<State>, data: &mut State, event: &GestureHoldBeginEvent) {}
63//! # fn gesture_hold_end(&self, seat: &Seat<State>, data: &mut State, event: &GestureHoldEndEvent) {}
64//! # }
65//! # impl KeyboardTarget<State> for Target {
66//! # fn enter(&self, seat: &Seat<State>, data: &mut State, keys: Vec<KeysymHandle<'_>>, serial: Serial) {}
67//! # fn leave(&self, seat: &Seat<State>, data: &mut State, serial: Serial) {}
68//! # fn key(
69//! # &self,
70//! # seat: &Seat<State>,
71//! # data: &mut State,
72//! # key: KeysymHandle<'_>,
73//! # state: KeyState,
74//! # serial: Serial,
75//! # time: u32,
76//! # ) {}
77//! # fn modifiers(&self, seat: &Seat<State>, data: &mut State, modifiers: ModifiersState, serial: Serial) {}
78//! # }
79//! # impl TouchTarget<State> for Target {
80//! # fn down(&self, seat: &Seat<State>, data: &mut State, event: &DownEvent, seq: Serial) {}
81//! # fn up(&self, seat: &Seat<State>, data: &mut State, event: &UpEvent, seq: Serial) {}
82//! # fn motion(&self, seat: &Seat<State>, data: &mut State, event: &TouchMotionEvent, seq: Serial) {}
83//! # fn frame(&self, seat: &Seat<State>, data: &mut State, seq: Serial) {}
84//! # fn cancel(&self, seat: &Seat<State>, data: &mut State, seq: Serial) {}
85//! # fn shape(&self, seat: &Seat<State>, data: &mut State, event: &ShapeEvent, seq: Serial) {}
86//! # fn orientation(&self, seat: &Seat<State>, data: &mut State, event: &OrientationEvent, seq: Serial) {}
87//! # }
88//!
89//! // implement the required traits
90//! impl SeatHandler for State {
91//! type KeyboardFocus = Target;
92//! type PointerFocus = Target;
93//! type TouchFocus = Target;
94//!
95//! fn seat_state(&mut self) -> &mut SeatState<Self> {
96//! &mut self.seat_state
97//! }
98//!
99//! fn focus_changed(&mut self, seat: &Seat<Self>, focused: Option<&Target>) {
100//! // handle focus changes, if you need to ...
101//! }
102//! fn cursor_image(&mut self, seat: &Seat<Self>, image: CursorImageStatus) {
103//! // handle new images for the cursor ...
104//! }
105//! }
106//! ```
107//!
108//! ### Run usage
109//!
110//! Once the seat is initialized, you can add capabilities to it.
111//!
112//! Currently, pointer, touch and keyboard capabilities are supported by this module.
113//! [`tablet_manager`](crate::wayland::tablet_manager) also provides client interaction for drawing tablets.
114//!
115//! You can add these capabilities via methods of the [`Seat`] struct:
116//! [`Seat::add_keyboard`], [`Seat::add_pointer`] and [`Seat::add_touch`].
117//! These methods return handles that can be cloned and sent across thread, so you can keep one around
118//! in your event-handling code to forward inputs to your clients.
119//!
120
121use std::{
122 fmt,
123 hash::Hash,
124 sync::{Arc, Mutex, Weak},
125};
126
127use tracing::{info_span, instrument};
128
129use self::touch::TouchTarget;
130use self::{
131 keyboard::{Error as KeyboardError, KeyboardHandle, KeyboardTarget, LedState},
132 touch::TouchHandle,
133};
134use self::{
135 pointer::{CursorImageStatus, PointerHandle, PointerTarget},
136 touch::TouchGrab,
137};
138use crate::utils::{user_data::UserDataMap, Serial};
139
140pub mod keyboard;
141pub mod pointer;
142pub mod touch;
143
144/// Handler trait for Seats
145pub trait SeatHandler: Sized {
146 /// Type used to represent the target currently holding the keyboard focus
147 type KeyboardFocus: KeyboardTarget<Self> + 'static;
148 /// Type used to represent the target currently holding the pointer focus
149 type PointerFocus: PointerTarget<Self> + 'static;
150 /// Type used to represent the target currently holding the touch focus
151 type TouchFocus: TouchTarget<Self> + 'static;
152
153 /// [SeatState] getter
154 fn seat_state(&mut self) -> &mut SeatState<Self>;
155
156 /// Callback that will be notified whenever the focus of the seat changes.
157 fn focus_changed(&mut self, _seat: &Seat<Self>, _focused: Option<&Self::KeyboardFocus>) {}
158
159 /// Callback that will be notified whenever a client requests to set a custom cursor image.
160 fn cursor_image(&mut self, _seat: &Seat<Self>, _image: CursorImageStatus) {}
161
162 /// Callback that will be notified whenever the keyboard led state changes.
163 fn led_state_changed(&mut self, _seat: &Seat<Self>, _led_state: LedState) {}
164}
165/// Delegate type for all [Seat] globals.
166///
167/// Events will be forwarded to an instance of the Seat global.
168pub struct SeatState<D: SeatHandler> {
169 pub(crate) seats: Vec<Seat<D>>,
170}
171
172impl<D: SeatHandler> fmt::Debug for SeatState<D> {
173 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
174 f.debug_struct("SeatState").field("seats", &self.seats).finish()
175 }
176}
177
178/// A Seat handle
179///
180/// This struct gives you access to the control of the
181/// capabilities of the associated seat.
182///
183/// This is an handle to the inner logic, it can be cloned.
184///
185/// See module-level documentation for details of use.
186pub struct Seat<D: SeatHandler> {
187 pub(crate) arc: Arc<SeatRc<D>>,
188}
189
190/// Weak variant of an [`Seat`]
191///
192/// Does not keep associated user data alive,
193/// and can be used to refer to a potentially already destroyed seat.
194#[derive(Debug, Clone)]
195pub struct WeakSeat<D: SeatHandler>(Weak<SeatRc<D>>);
196
197impl<D: SeatHandler> WeakSeat<D> {
198 /// Try to retrieve the original `Seat`, if it still exists
199 pub fn upgrade(&self) -> Option<Seat<D>> {
200 self.0.upgrade().map(|arc| Seat { arc })
201 }
202
203 /// Check if the seat is still alive
204 pub fn is_alive(&self) -> bool {
205 self.0.strong_count() != 0
206 }
207}
208
209impl<D: SeatHandler> Seat<D> {
210 /// Create a weak reference to this seat
211 pub fn downgrade(&self) -> WeakSeat<D> {
212 WeakSeat(Arc::downgrade(&self.arc))
213 }
214}
215
216impl<D: SeatHandler> fmt::Debug for Seat<D> {
217 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
218 f.debug_struct("Seat").field("arc", &self.arc).finish()
219 }
220}
221
222impl<D: SeatHandler> PartialEq for Seat<D> {
223 #[inline]
224 fn eq(&self, other: &Self) -> bool {
225 Arc::ptr_eq(&self.arc, &other.arc)
226 }
227}
228impl<D: SeatHandler> Eq for Seat<D> {}
229
230impl<D: SeatHandler> Hash for Seat<D> {
231 #[inline]
232 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
233 Arc::as_ptr(&self.arc).hash(state)
234 }
235}
236
237pub(crate) struct Inner<D: SeatHandler> {
238 pub(crate) pointer: Option<PointerHandle<D>>,
239 pub(crate) keyboard: Option<KeyboardHandle<D>>,
240 pub(crate) touch: Option<TouchHandle<D>>,
241
242 #[cfg(feature = "wayland_frontend")]
243 pub(crate) global: Option<wayland_server::backend::GlobalId>,
244 #[cfg(feature = "wayland_frontend")]
245 pub(crate) known_seats: Vec<wayland_server::Weak<wayland_server::protocol::wl_seat::WlSeat>>,
246}
247
248#[cfg(not(feature = "wayland_frontend"))]
249impl<D: SeatHandler> fmt::Debug for Inner<D> {
250 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
251 f.debug_struct("Inner")
252 .field("pointer", &self.pointer)
253 .field("keyboard", &self.keyboard)
254 .finish()
255 }
256}
257
258#[cfg(feature = "wayland_frontend")]
259impl<D: SeatHandler> fmt::Debug for Inner<D> {
260 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
261 f.debug_struct("Inner")
262 .field("pointer", &self.pointer)
263 .field("keyboard", &self.keyboard)
264 .field("touch", &self.touch)
265 .field("global", &self.global)
266 .field("known_seats", &self.known_seats)
267 .finish()
268 }
269}
270
271pub(crate) struct SeatRc<D: SeatHandler> {
272 #[allow(dead_code)]
273 pub(crate) name: String,
274 pub(crate) inner: Mutex<Inner<D>>,
275 span: tracing::Span,
276 user_data_map: UserDataMap,
277}
278
279impl<D: SeatHandler> fmt::Debug for SeatRc<D> {
280 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
281 f.debug_struct("SeatRc")
282 .field("name", &self.name)
283 .field("inner", &self.inner)
284 .field("user_data_map", &self.user_data_map)
285 .finish()
286 }
287}
288
289impl<D: SeatHandler> Clone for Seat<D> {
290 #[inline]
291 fn clone(&self) -> Self {
292 Self {
293 arc: self.arc.clone(),
294 }
295 }
296}
297
298impl<D: SeatHandler> Default for SeatState<D> {
299 #[inline]
300 fn default() -> Self {
301 Self::new()
302 }
303}
304
305impl<D: SeatHandler> SeatState<D> {
306 /// Create new delegate SeatState
307 pub fn new() -> Self {
308 Self { seats: Vec::new() }
309 }
310
311 /// Create a new seat
312 pub fn new_seat<N>(&mut self, name: N) -> Seat<D>
313 where
314 N: Into<String>,
315 {
316 let name = name.into();
317 let span = info_span!("input_seat", name);
318
319 let arc = Arc::new(SeatRc {
320 name,
321 inner: Mutex::new(Inner {
322 pointer: None,
323 keyboard: None,
324 touch: None,
325
326 #[cfg(feature = "wayland_frontend")]
327 global: None,
328 #[cfg(feature = "wayland_frontend")]
329 known_seats: Vec::new(),
330 }),
331 span,
332 user_data_map: UserDataMap::new(),
333 });
334 self.seats.push(Seat { arc: arc.clone() });
335
336 Seat { arc }
337 }
338}
339
340impl<D: SeatHandler + 'static> Seat<D> {
341 /// Access the `UserDataMap` associated with this `Seat`
342 pub fn user_data(&self) -> &UserDataMap {
343 &self.arc.user_data_map
344 }
345
346 /// Adds the pointer capability to this seat
347 ///
348 /// You are provided a [`PointerHandle`], which allows you to send input events
349 /// to this pointer. This handle can be cloned.
350 ///
351 /// Calling this method on a seat that already has a pointer capability
352 /// will overwrite it, and will be seen by the clients as if the
353 /// mouse was unplugged and a new one was plugged.
354 ///
355 /// # Examples
356 ///
357 /// ```no_run
358 /// # use smithay::input::{Seat, SeatState, SeatHandler, pointer::CursorImageStatus};
359 /// # use smithay::backend::input::KeyState;
360 /// # use smithay::input::{
361 /// # pointer::{PointerTarget, AxisFrame, MotionEvent, ButtonEvent, RelativeMotionEvent,
362 /// # GestureSwipeBeginEvent, GestureSwipeUpdateEvent, GestureSwipeEndEvent,
363 /// # GesturePinchBeginEvent, GesturePinchUpdateEvent, GesturePinchEndEvent,
364 /// # GestureHoldBeginEvent, GestureHoldEndEvent},
365 /// # keyboard::{KeyboardTarget, KeysymHandle, ModifiersState},
366 /// # touch::{DownEvent, UpEvent, MotionEvent as TouchMotionEvent, ShapeEvent, OrientationEvent, TouchTarget},
367 /// # };
368 /// # use smithay::utils::{IsAlive, Serial};
369 /// #
370 /// # #[derive(Debug, Clone, PartialEq)]
371 /// # struct Target;
372 /// # impl IsAlive for Target {
373 /// # fn alive(&self) -> bool { true }
374 /// # }
375 /// # impl PointerTarget<State> for Target {
376 /// # fn enter(&self, seat: &Seat<State>, data: &mut State, event: &MotionEvent) {}
377 /// # fn motion(&self, seat: &Seat<State>, data: &mut State, event: &MotionEvent) {}
378 /// # fn relative_motion(&self, seat: &Seat<State>, data: &mut State, event: &RelativeMotionEvent) {}
379 /// # fn button(&self, seat: &Seat<State>, data: &mut State, event: &ButtonEvent) {}
380 /// # fn axis(&self, seat: &Seat<State>, data: &mut State, frame: AxisFrame) {}
381 /// # fn frame(&self, seat: &Seat<State>, data: &mut State) {}
382 /// # fn leave(&self, seat: &Seat<State>, data: &mut State, serial: Serial, time: u32) {}
383 /// # fn gesture_swipe_begin(&self, seat: &Seat<State>, data: &mut State, event: &GestureSwipeBeginEvent) {}
384 /// # fn gesture_swipe_update(&self, seat: &Seat<State>, data: &mut State, event: &GestureSwipeUpdateEvent) {}
385 /// # fn gesture_swipe_end(&self, seat: &Seat<State>, data: &mut State, event: &GestureSwipeEndEvent) {}
386 /// # fn gesture_pinch_begin(&self, seat: &Seat<State>, data: &mut State, event: &GesturePinchBeginEvent) {}
387 /// # fn gesture_pinch_update(&self, seat: &Seat<State>, data: &mut State, event: &GesturePinchUpdateEvent) {}
388 /// # fn gesture_pinch_end(&self, seat: &Seat<State>, data: &mut State, event: &GesturePinchEndEvent) {}
389 /// # fn gesture_hold_begin(&self, seat: &Seat<State>, data: &mut State, event: &GestureHoldBeginEvent) {}
390 /// # fn gesture_hold_end(&self, seat: &Seat<State>, data: &mut State, event: &GestureHoldEndEvent) {}
391 /// # }
392 /// # impl KeyboardTarget<State> for Target {
393 /// # fn enter(&self, seat: &Seat<State>, data: &mut State, keys: Vec<KeysymHandle<'_>>, serial: Serial) {}
394 /// # fn leave(&self, seat: &Seat<State>, data: &mut State, serial: Serial) {}
395 /// # fn key(
396 /// # &self,
397 /// # seat: &Seat<State>,
398 /// # data: &mut State,
399 /// # key: KeysymHandle<'_>,
400 /// # state: KeyState,
401 /// # serial: Serial,
402 /// # time: u32,
403 /// # ) {}
404 /// # fn modifiers(&self, seat: &Seat<State>, data: &mut State, modifiers: ModifiersState, serial: Serial) {}
405 /// # }
406 /// # impl TouchTarget<State> for Target {
407 /// # fn down(&self, seat: &Seat<State>, data: &mut State, event: &DownEvent, seq: Serial) {}
408 /// # fn up(&self, seat: &Seat<State>, data: &mut State, event: &UpEvent, seq: Serial) {}
409 /// # fn motion(&self, seat: &Seat<State>, data: &mut State, event: &TouchMotionEvent, seq: Serial) {}
410 /// # fn frame(&self, seat: &Seat<State>, data: &mut State, seq: Serial) {}
411 /// # fn cancel(&self, seat: &Seat<State>, data: &mut State, seq: Serial) {}
412 /// # fn shape(&self, seat: &Seat<State>, data: &mut State, event: &ShapeEvent, seq: Serial) {}
413 /// # fn orientation(&self, seat: &Seat<State>, data: &mut State, event: &OrientationEvent, seq: Serial) {}
414 /// # }
415 /// # struct State;
416 /// # impl SeatHandler for State {
417 /// # type KeyboardFocus = Target;
418 /// # type PointerFocus = Target;
419 /// # type TouchFocus = Target;
420 /// #
421 /// # fn seat_state(&mut self) -> &mut SeatState<Self> { unimplemented!() }
422 /// # fn focus_changed(&mut self, seat: &Seat<Self>, focused: Option<&Target>) { unimplemented!() }
423 /// # fn cursor_image(&mut self, seat: &Seat<Self>, image: CursorImageStatus) { unimplemented!() }
424 /// # }
425 /// # let mut seat: Seat<State> = unimplemented!();
426 /// let pointer_handle = seat.add_pointer();
427 /// ```
428 #[instrument(parent = &self.arc.span, skip(self))]
429 pub fn add_pointer(&mut self) -> PointerHandle<D> {
430 let mut inner = self.arc.inner.lock().unwrap();
431 let pointer = PointerHandle::new();
432 if inner.pointer.is_some() {
433 // there is already a pointer, remove it and notify the clients
434 // of the change
435 inner.pointer = None;
436 #[cfg(feature = "wayland_frontend")]
437 inner.send_all_caps();
438 }
439 inner.pointer = Some(pointer.clone());
440 #[cfg(feature = "wayland_frontend")]
441 inner.send_all_caps();
442 pointer
443 }
444
445 /// Access the pointer of this seat if any
446 pub fn get_pointer(&self) -> Option<PointerHandle<D>> {
447 self.arc.inner.lock().unwrap().pointer.clone()
448 }
449
450 /// Remove the pointer capability from this seat
451 ///
452 /// Clients will be appropriately notified.
453 #[instrument(parent = &self.arc.span, skip(self))]
454 pub fn remove_pointer(&mut self) {
455 let mut inner = self.arc.inner.lock().unwrap();
456 if inner.pointer.is_some() {
457 inner.pointer = None;
458 #[cfg(feature = "wayland_frontend")]
459 inner.send_all_caps();
460 }
461 }
462
463 /// Adds the keyboard capability to this seat
464 ///
465 /// You are provided a [`KeyboardHandle`], which allows you to send input events
466 /// to this keyboard. This handle can be cloned.
467 ///
468 /// You also provide a Model/Layout/Variant/Options specification of the
469 /// keymap to be used for this keyboard, as well as any repeat-info that
470 /// will be forwarded to the clients.
471 ///
472 /// Calling this method on a seat that already has a keyboard capability
473 /// will overwrite it, and will be seen by the clients as if the
474 /// keyboard was unplugged and a new one was plugged.
475 ///
476 /// # Examples
477 ///
478 /// ```no_run
479 /// # use smithay::input::{Seat, SeatState, SeatHandler, keyboard::XkbConfig, pointer::CursorImageStatus};
480 /// # use smithay::backend::input::KeyState;
481 /// # use smithay::input::{
482 /// # pointer::{PointerTarget, AxisFrame, MotionEvent, ButtonEvent, RelativeMotionEvent,
483 /// # GestureSwipeBeginEvent, GestureSwipeUpdateEvent, GestureSwipeEndEvent,
484 /// # GesturePinchBeginEvent, GesturePinchUpdateEvent, GesturePinchEndEvent,
485 /// # GestureHoldBeginEvent, GestureHoldEndEvent},
486 /// # keyboard::{KeyboardTarget, KeysymHandle, ModifiersState},
487 /// # touch::{DownEvent, UpEvent, MotionEvent as TouchMotionEvent, ShapeEvent, OrientationEvent, TouchTarget},
488 /// # };
489 /// # use smithay::utils::{IsAlive, Serial};
490 /// #
491 /// # #[derive(Debug, Clone, PartialEq)]
492 /// # struct Target;
493 /// # impl IsAlive for Target {
494 /// # fn alive(&self) -> bool { true }
495 /// # }
496 /// # impl PointerTarget<State> for Target {
497 /// # fn enter(&self, seat: &Seat<State>, data: &mut State, event: &MotionEvent) {}
498 /// # fn motion(&self, seat: &Seat<State>, data: &mut State, event: &MotionEvent) {}
499 /// # fn relative_motion(&self, seat: &Seat<State>, data: &mut State, event: &RelativeMotionEvent) {}
500 /// # fn button(&self, seat: &Seat<State>, data: &mut State, event: &ButtonEvent) {}
501 /// # fn axis(&self, seat: &Seat<State>, data: &mut State, frame: AxisFrame) {}
502 /// # fn frame(&self, seat: &Seat<State>, data: &mut State) {}
503 /// # fn leave(&self, seat: &Seat<State>, data: &mut State, serial: Serial, time: u32) {}
504 /// # fn gesture_swipe_begin(&self, seat: &Seat<State>, data: &mut State, event: &GestureSwipeBeginEvent) {}
505 /// # fn gesture_swipe_update(&self, seat: &Seat<State>, data: &mut State, event: &GestureSwipeUpdateEvent) {}
506 /// # fn gesture_swipe_end(&self, seat: &Seat<State>, data: &mut State, event: &GestureSwipeEndEvent) {}
507 /// # fn gesture_pinch_begin(&self, seat: &Seat<State>, data: &mut State, event: &GesturePinchBeginEvent) {}
508 /// # fn gesture_pinch_update(&self, seat: &Seat<State>, data: &mut State, event: &GesturePinchUpdateEvent) {}
509 /// # fn gesture_pinch_end(&self, seat: &Seat<State>, data: &mut State, event: &GesturePinchEndEvent) {}
510 /// # fn gesture_hold_begin(&self, seat: &Seat<State>, data: &mut State, event: &GestureHoldBeginEvent) {}
511 /// # fn gesture_hold_end(&self, seat: &Seat<State>, data: &mut State, event: &GestureHoldEndEvent) {}
512 /// # }
513 /// # impl KeyboardTarget<State> for Target {
514 /// # fn enter(&self, seat: &Seat<State>, data: &mut State, keys: Vec<KeysymHandle<'_>>, serial: Serial) {}
515 /// # fn leave(&self, seat: &Seat<State>, data: &mut State, serial: Serial) {}
516 /// # fn key(
517 /// # &self,
518 /// # seat: &Seat<State>,
519 /// # data: &mut State,
520 /// # key: KeysymHandle<'_>,
521 /// # state: KeyState,
522 /// # serial: Serial,
523 /// # time: u32,
524 /// # ) {}
525 /// # fn modifiers(&self, seat: &Seat<State>, data: &mut State, modifiers: ModifiersState, serial: Serial) {}
526 /// # }
527 /// # impl TouchTarget<State> for Target {
528 /// # fn down(&self, seat: &Seat<State>, data: &mut State, event: &DownEvent, seq: Serial) {}
529 /// # fn up(&self, seat: &Seat<State>, data: &mut State, event: &UpEvent, seq: Serial) {}
530 /// # fn motion(&self, seat: &Seat<State>, data: &mut State, event: &TouchMotionEvent, seq: Serial) {}
531 /// # fn frame(&self, seat: &Seat<State>, data: &mut State, seq: Serial) {}
532 /// # fn cancel(&self, seat: &Seat<State>, data: &mut State, seq: Serial) {}
533 /// # fn shape(&self, seat: &Seat<State>, data: &mut State, event: &ShapeEvent, seq: Serial) {}
534 /// # fn orientation(&self, seat: &Seat<State>, data: &mut State, event: &OrientationEvent, seq: Serial) {}
535 /// # }
536 /// #
537 /// # struct State;
538 /// # impl SeatHandler for State {
539 /// # type KeyboardFocus = Target;
540 /// # type PointerFocus = Target;
541 /// # type TouchFocus = Target;
542 /// #
543 /// # fn seat_state(&mut self) -> &mut SeatState<Self> { unimplemented!() }
544 /// # fn focus_changed(&mut self, seat: &Seat<Self>, focused: Option<&Target>) { unimplemented!() }
545 /// # fn cursor_image(&mut self, seat: &Seat<Self>, image: CursorImageStatus) { unimplemented!() }
546 /// # }
547 /// # let mut seat: Seat<State> = unimplemented!();
548 /// let keyboard = seat
549 /// .add_keyboard(
550 /// XkbConfig {
551 /// layout: "de",
552 /// variant: "nodeadkeys",
553 /// ..XkbConfig::default()
554 /// },
555 /// 200,
556 /// 25,
557 /// )
558 /// .expect("Failed to initialize the keyboard");
559 /// ```
560 #[instrument(parent = &self.arc.span, skip(self))]
561 pub fn add_keyboard(
562 &mut self,
563 xkb_config: keyboard::XkbConfig<'_>,
564 repeat_delay: i32,
565 repeat_rate: i32,
566 ) -> Result<KeyboardHandle<D>, KeyboardError> {
567 let mut inner = self.arc.inner.lock().unwrap();
568 let keyboard = self::keyboard::KeyboardHandle::new(xkb_config, repeat_delay, repeat_rate)?;
569 if inner.keyboard.is_some() {
570 // there is already a keyboard, remove it and notify the clients
571 // of the change
572 inner.keyboard = None;
573 #[cfg(feature = "wayland_frontend")]
574 inner.send_all_caps();
575 }
576 inner.keyboard = Some(keyboard.clone());
577 #[cfg(feature = "wayland_frontend")]
578 inner.send_all_caps();
579 Ok(keyboard)
580 }
581
582 /// Access the keyboard of this seat if any
583 pub fn get_keyboard(&self) -> Option<KeyboardHandle<D>> {
584 self.arc.inner.lock().unwrap().keyboard.clone()
585 }
586
587 /// Remove the keyboard capability from this seat
588 ///
589 /// Clients will be appropriately notified.
590 #[instrument(parent = &self.arc.span, skip(self))]
591 pub fn remove_keyboard(&mut self) {
592 let mut inner = self.arc.inner.lock().unwrap();
593 if inner.keyboard.is_some() {
594 inner.keyboard = None;
595 #[cfg(feature = "wayland_frontend")]
596 inner.send_all_caps();
597 }
598 }
599
600 /// Adds the touch capability to this seat
601 ///
602 /// You are provided a [`TouchHandle`], which allows you to send input events
603 /// to this pointer. This handle can be cloned.
604 ///
605 /// Calling this method on a seat that already has a touch capability
606 /// will overwrite it, and will be seen by the clients as if the
607 /// touchscreen was unplugged and a new one was plugged in.
608 ///
609 /// # Examples
610 ///
611 /// ```no_run
612 /// # use smithay::input::{Seat, SeatState, SeatHandler, pointer::CursorImageStatus};
613 /// # use smithay::reexports::wayland_server::protocol::wl_surface::WlSurface;
614 /// #
615 /// # struct State;
616 /// # impl SeatHandler for State {
617 /// # type KeyboardFocus = WlSurface;
618 /// # type PointerFocus = WlSurface;
619 /// # type TouchFocus = WlSurface;
620 /// # fn seat_state(&mut self) -> &mut SeatState<Self> { unimplemented!() }
621 /// # fn focus_changed(&mut self, seat: &Seat<Self>, focused: Option<&WlSurface>) { unimplemented!() }
622 /// # fn cursor_image(&mut self, seat: &Seat<Self>, image: CursorImageStatus) { unimplemented!() }
623 /// # }
624 /// # let mut seat: Seat<State> = unimplemented!();
625 /// let touch_handle = seat.add_touch();
626 /// ```
627 pub fn add_touch(&mut self) -> TouchHandle<D> {
628 Self::add_touch_with_default_grab(self, || Box::new(touch::DefaultGrab))
629 }
630
631 /// Adds the touch capability to this seat and allows the use of a custom default [`TouchGrab`]
632 ///
633 /// The default grab is used in case no other grab is currently active. When using [`Seat::add_touch`]
634 /// it will use [`touch::DefaultGrab`] which will install [`touch::TouchDownGrab`] on the first touch point.
635 /// [`touch::TouchDownGrab`] makes sure all further touch points will use the same target until all touch
636 /// points are released again.
637 ///
638 /// See [`Seat::add_touch`] for more information
639 pub fn add_touch_with_default_grab<F>(&mut self, defaut_grab: F) -> TouchHandle<D>
640 where
641 F: Fn() -> Box<dyn TouchGrab<D>> + Send + 'static,
642 {
643 let mut inner = self.arc.inner.lock().unwrap();
644 let touch = TouchHandle::new(defaut_grab);
645 if inner.touch.is_some() {
646 // If there's already a tocuh device, remove it notify the clients about the change.
647 inner.touch = None;
648 #[cfg(feature = "wayland_frontend")]
649 inner.send_all_caps();
650 }
651 inner.touch = Some(touch.clone());
652 #[cfg(feature = "wayland_frontend")]
653 inner.send_all_caps();
654 touch
655 }
656
657 /// Access the touch device of this seat, if any.
658 pub fn get_touch(&self) -> Option<TouchHandle<D>> {
659 self.arc.inner.lock().unwrap().touch.clone()
660 }
661
662 /// Remove the touch capability from this seat
663 ///
664 /// Clients will be appropriately notified.
665 pub fn remove_touch(&mut self) {
666 let mut inner = self.arc.inner.lock().unwrap();
667 if inner.touch.is_some() {
668 inner.touch = None;
669 #[cfg(feature = "wayland_frontend")]
670 inner.send_all_caps();
671 }
672 }
673
674 /// Gets this seat's name
675 pub fn name(&self) -> &str {
676 &self.arc.name
677 }
678}
679
680pub(super) enum GrabStatus<G: ?Sized> {
681 None,
682 Active(Serial, Box<G>),
683 Borrowed,
684}
685
686// `G` is not `Debug`, so we have to impl Debug manually
687impl<G: ?Sized> fmt::Debug for GrabStatus<G> {
688 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
689 match self {
690 GrabStatus::None => f.debug_tuple("GrabStatus::None").finish(),
691 GrabStatus::Active(serial, _) => f.debug_tuple("GrabStatus::Active").field(&serial).finish(),
692 GrabStatus::Borrowed => f.debug_tuple("GrabStatus::Borrowed").finish(),
693 }
694 }
695}