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: &TouchDownEvent) => event.as_raw_event(),
113 TouchEvent::Up(event: &TouchUpEvent) => event.as_raw_event(),
114 TouchEvent::Motion(event: &TouchMotionEvent) => event.as_raw_event(),
115 TouchEvent::Cancel(event: &TouchCancelEvent) => event.as_raw_event(),
116 TouchEvent::Frame(event: &TouchFrameEvent) => 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: &TouchDownEvent) => event.as_raw(),
155 TouchEvent::Up(event: &TouchUpEvent) => event.as_raw(),
156 TouchEvent::Motion(event: &TouchMotionEvent) => event.as_raw(),
157 TouchEvent::Cancel(event: &TouchCancelEvent) => event.as_raw(),
158 TouchEvent::Frame(event: &TouchFrameEvent) => event.as_raw(),
159 }
160 }
161}
162
163impl Context for TouchEvent {
164 fn context(&self) -> &Libinput {
165 match self {
166 TouchEvent::Down(event: &TouchDownEvent) => event.context(),
167 TouchEvent::Up(event: &TouchUpEvent) => event.context(),
168 TouchEvent::Motion(event: &TouchMotionEvent) => event.context(),
169 TouchEvent::Cancel(event: &TouchCancelEvent) => event.context(),
170 TouchEvent::Frame(event: &TouchFrameEvent) => 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);
206