input/event/
touch.rs

1//! Touch event types
2
3use super::EventTrait;
4use crate::{ffi, AsRaw, Context, FromRaw, Libinput};
5
6/// Common functions all Touch-Events implement.
7pub trait TouchEventTrait: AsRaw<ffi::libinput_event_touch> + Context {
8    ffi_func!(
9    /// The event time for this event
10    fn time, ffi::libinput_event_touch_get_time, u32);
11    ffi_func!(
12    /// The event time for this event in microseconds
13    fn time_usec, ffi::libinput_event_touch_get_time_usec, u64);
14
15    /// Convert into a general `TouchEvent` again
16    fn into_touch_event(self) -> TouchEvent
17    where
18        Self: Sized,
19    {
20        unsafe { TouchEvent::from_raw(self.as_raw_mut(), self.context()) }
21    }
22}
23
24impl<T: AsRaw<ffi::libinput_event_touch> + Context> TouchEventTrait for T {}
25
26/// Touch slot related functions all TouchEvents implement, that can be mapped to slots.
27///
28/// A touch slot is grouping all events related to a single gesture together.
29pub trait TouchEventSlot: AsRaw<ffi::libinput_event_touch> {
30    ffi_func!(
31    /// Get the seat slot of the touch event.
32    ///
33    /// A seat slot is a non-negative seat wide unique identifier of an active
34    /// touch point.
35    ///
36    /// Events from single touch devices will be represented as one individual
37    /// touch point per device.
38    fn seat_slot, ffi::libinput_event_touch_get_seat_slot, u32);
39
40    /// Get the slot of this touch event.
41    ///
42    /// See the kernel's multitouch protocol B documentation for more information.
43    ///
44    /// If the touch event has no assigned slot, for example if it is from a
45    /// single touch device, this function returns `None`.
46    fn slot(&self) -> Option<u32> {
47        match unsafe { ffi::libinput_event_touch_get_slot(self.as_raw_mut()) } {
48            x if x >= 0 => Some(x as u32),
49            -1 => None,
50            _ => panic!("libinput_event_touch_get_slot returned undocumentated value!"),
51        }
52    }
53}
54
55/// Position related functions all TouchEvents implement, that have a screen
56/// position assigned to them.
57pub trait TouchEventPosition: AsRaw<ffi::libinput_event_touch> {
58    ffi_func!(
59    /// Return the current absolute x coordinate of the touch event, in mm from
60    /// the top left corner of the device.
61    ///
62    /// To get the corresponding output screen coordinate, use `x_transformed`.
63    fn x, ffi::libinput_event_touch_get_x, f64);
64    ffi_func!(
65    /// Return the current absolute y coordinate of the touch event, in mm from
66    /// the top left corner of the device.
67    ///
68    /// To get the corresponding output screen coordinate, use `y_transformed`.
69    fn y, ffi::libinput_event_touch_get_y, f64);
70
71    /// Return the current absolute x coordinate of the touch event, transformed
72    /// to screen coordinates.
73    ///
74    /// ## Arguments
75    ///
76    /// - width - The current output screen width
77    fn x_transformed(&self, width: u32) -> f64 {
78        unsafe { ffi::libinput_event_touch_get_x_transformed(self.as_raw_mut(), width) }
79    }
80
81    /// Return the current absolute y coordinate of the touch event, transformed
82    /// to screen coordinates.
83    ///
84    /// ## Arguments
85    ///
86    /// - height - The current output screen height
87    fn y_transformed(&self, height: u32) -> f64 {
88        unsafe { ffi::libinput_event_touch_get_y_transformed(self.as_raw_mut(), height) }
89    }
90}
91
92/// A touch related `Event`
93#[derive(Debug, PartialEq, Eq, Hash)]
94#[non_exhaustive]
95pub enum TouchEvent {
96    /// An event related to resting the finger on the screen
97    Down(TouchDownEvent),
98    /// An event related to lifting the finger on the screen
99    Up(TouchUpEvent),
100    /// An event related to moving a finger on the screen
101    Motion(TouchMotionEvent),
102    /// An event cancelling previous events on this slot
103    Cancel(TouchCancelEvent),
104    /// Signals the end of a set of touchpoints at one device sample time.
105    Frame(TouchFrameEvent),
106}
107
108impl EventTrait for TouchEvent {
109    #[doc(hidden)]
110    fn as_raw_event(&self) -> *mut ffi::libinput_event {
111        match self {
112            TouchEvent::Down(event) => event.as_raw_event(),
113            TouchEvent::Up(event) => event.as_raw_event(),
114            TouchEvent::Motion(event) => event.as_raw_event(),
115            TouchEvent::Cancel(event) => event.as_raw_event(),
116            TouchEvent::Frame(event) => event.as_raw_event(),
117        }
118    }
119}
120
121impl FromRaw<ffi::libinput_event_touch> for TouchEvent {
122    unsafe fn try_from_raw(
123        event: *mut ffi::libinput_event_touch,
124        context: &Libinput,
125    ) -> Option<Self> {
126        let base = ffi::libinput_event_touch_get_base_event(event);
127        match ffi::libinput_event_get_type(base) {
128            ffi::libinput_event_type_LIBINPUT_EVENT_TOUCH_DOWN => Some(TouchEvent::Down(
129                TouchDownEvent::try_from_raw(event, context)?,
130            )),
131            ffi::libinput_event_type_LIBINPUT_EVENT_TOUCH_UP => {
132                Some(TouchEvent::Up(TouchUpEvent::try_from_raw(event, context)?))
133            }
134            ffi::libinput_event_type_LIBINPUT_EVENT_TOUCH_MOTION => Some(TouchEvent::Motion(
135                TouchMotionEvent::try_from_raw(event, context)?,
136            )),
137            ffi::libinput_event_type_LIBINPUT_EVENT_TOUCH_CANCEL => Some(TouchEvent::Cancel(
138                TouchCancelEvent::try_from_raw(event, context)?,
139            )),
140            ffi::libinput_event_type_LIBINPUT_EVENT_TOUCH_FRAME => Some(TouchEvent::Frame(
141                TouchFrameEvent::try_from_raw(event, context)?,
142            )),
143            _ => None,
144        }
145    }
146    unsafe fn from_raw(event: *mut ffi::libinput_event_touch, context: &Libinput) -> Self {
147        Self::try_from_raw(event, context).expect("Unknown touch event type")
148    }
149}
150
151impl AsRaw<ffi::libinput_event_touch> for TouchEvent {
152    fn as_raw(&self) -> *const ffi::libinput_event_touch {
153        match self {
154            TouchEvent::Down(event) => event.as_raw(),
155            TouchEvent::Up(event) => event.as_raw(),
156            TouchEvent::Motion(event) => event.as_raw(),
157            TouchEvent::Cancel(event) => event.as_raw(),
158            TouchEvent::Frame(event) => event.as_raw(),
159        }
160    }
161}
162
163impl Context for TouchEvent {
164    fn context(&self) -> &Libinput {
165        match self {
166            TouchEvent::Down(event) => event.context(),
167            TouchEvent::Up(event) => event.context(),
168            TouchEvent::Motion(event) => event.context(),
169            TouchEvent::Cancel(event) => event.context(),
170            TouchEvent::Frame(event) => event.context(),
171        }
172    }
173}
174
175ffi_event_struct!(
176/// An event related to resting the finger on the screen
177struct TouchDownEvent, ffi::libinput_event_touch, ffi::libinput_event_touch_get_base_event);
178
179impl TouchEventSlot for TouchDownEvent {}
180
181impl TouchEventPosition for TouchDownEvent {}
182
183ffi_event_struct!(
184/// An event related to lifting the finger on the screen
185struct TouchUpEvent, ffi::libinput_event_touch, ffi::libinput_event_touch_get_base_event);
186
187impl TouchEventSlot for TouchUpEvent {}
188
189ffi_event_struct!(
190/// An event related to moving a finger on the screen
191struct TouchMotionEvent, ffi::libinput_event_touch, ffi::libinput_event_touch_get_base_event);
192
193impl TouchEventSlot for TouchMotionEvent {}
194
195impl TouchEventPosition for TouchMotionEvent {}
196
197ffi_event_struct!(
198/// An event cancelling previous events on this slot
199struct TouchCancelEvent, ffi::libinput_event_touch, ffi::libinput_event_touch_get_base_event);
200
201impl TouchEventSlot for TouchCancelEvent {}
202
203ffi_event_struct!(
204/// Signals the end of a set of touchpoints at one device sample time.
205struct TouchFrameEvent, ffi::libinput_event_touch, ffi::libinput_event_touch_get_base_event);