input/event/
gesture.rs

1//! Gesture event types
2
3use super::EventTrait;
4use crate::{ffi, AsRaw, Context, FromRaw, Libinput};
5
6/// Common functions all Gesture-Events implement.
7pub trait GestureEventTrait: AsRaw<ffi::libinput_event_gesture> + Context {
8    ffi_func!(
9    /// The event time for this event
10    fn time, ffi::libinput_event_gesture_get_time, u32);
11    ffi_func!(
12    /// The event time for this event in microseconds
13    fn time_usec, ffi::libinput_event_gesture_get_time_usec, u64);
14    ffi_func!(
15    /// Return the number of fingers used for a gesture.
16    ///
17    /// This can be used e.g. to differentiate between 3 or 4 finger swipes.
18    ///
19    /// This function can be called on all gesture events and the returned finger
20    /// count value will not change during a sequence.
21    fn finger_count, ffi::libinput_event_gesture_get_finger_count, i32);
22
23    /// Convert into a general `GestureEvent` again
24    fn into_gesture_event(self) -> GestureEvent
25    where
26        Self: Sized,
27    {
28        unsafe { GestureEvent::from_raw(self.as_raw_mut(), self.context()) }
29    }
30}
31
32impl<T: AsRaw<ffi::libinput_event_gesture> + Context> GestureEventTrait for T {}
33
34/// A gesture related `Event`
35#[derive(Debug, PartialEq, Eq, Hash)]
36#[non_exhaustive]
37pub enum GestureEvent {
38    /// A swipe gesture `Event`
39    Swipe(GestureSwipeEvent),
40    /// A pinch gesture `Event`
41    Pinch(GesturePinchEvent),
42    #[cfg(feature = "libinput_1_19")]
43    /// A hold gesture `Event`
44    Hold(GestureHoldEvent),
45}
46
47impl EventTrait for GestureEvent {
48    #[doc(hidden)]
49    fn as_raw_event(&self) -> *mut ffi::libinput_event {
50        match self {
51            GestureEvent::Swipe(event) => event.as_raw_event(),
52            GestureEvent::Pinch(event) => event.as_raw_event(),
53            #[cfg(feature = "libinput_1_19")]
54            GestureEvent::Hold(event) => event.as_raw_event(),
55        }
56    }
57}
58
59impl FromRaw<ffi::libinput_event_gesture> for GestureEvent {
60    unsafe fn try_from_raw(
61        event: *mut ffi::libinput_event_gesture,
62        context: &Libinput,
63    ) -> Option<Self> {
64        let base = ffi::libinput_event_gesture_get_base_event(event);
65        match ffi::libinput_event_get_type(base) {
66            ffi::libinput_event_type_LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN
67            | ffi::libinput_event_type_LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE
68            | ffi::libinput_event_type_LIBINPUT_EVENT_GESTURE_SWIPE_END => Some(
69                GestureEvent::Swipe(GestureSwipeEvent::try_from_raw(event, context)?),
70            ),
71            ffi::libinput_event_type_LIBINPUT_EVENT_GESTURE_PINCH_BEGIN
72            | ffi::libinput_event_type_LIBINPUT_EVENT_GESTURE_PINCH_UPDATE
73            | ffi::libinput_event_type_LIBINPUT_EVENT_GESTURE_PINCH_END => Some(
74                GestureEvent::Pinch(GesturePinchEvent::try_from_raw(event, context)?),
75            ),
76            #[cfg(feature = "libinput_1_19")]
77            ffi::libinput_event_type_LIBINPUT_EVENT_GESTURE_HOLD_BEGIN
78            | ffi::libinput_event_type_LIBINPUT_EVENT_GESTURE_HOLD_END => Some(GestureEvent::Hold(
79                GestureHoldEvent::try_from_raw(event, context)?,
80            )),
81            _ => None,
82        }
83    }
84    unsafe fn from_raw(event: *mut ffi::libinput_event_gesture, context: &Libinput) -> Self {
85        Self::try_from_raw(event, context).expect("Unknown gesture event type")
86    }
87}
88
89impl AsRaw<ffi::libinput_event_gesture> for GestureEvent {
90    fn as_raw(&self) -> *const ffi::libinput_event_gesture {
91        match self {
92            GestureEvent::Swipe(event) => event.as_raw(),
93            GestureEvent::Pinch(event) => event.as_raw(),
94            #[cfg(feature = "libinput_1_19")]
95            GestureEvent::Hold(event) => event.as_raw(),
96        }
97    }
98}
99
100impl Context for GestureEvent {
101    fn context(&self) -> &Libinput {
102        match self {
103            GestureEvent::Swipe(event) => event.context(),
104            GestureEvent::Pinch(event) => event.context(),
105            #[cfg(feature = "libinput_1_19")]
106            GestureEvent::Hold(event) => event.context(),
107        }
108    }
109}
110
111/// Common functions for Gesture-Events having coordinates.
112pub trait GestureEventCoordinates: AsRaw<ffi::libinput_event_gesture> {
113    ffi_func!(
114    /// Return the delta between the last event and the current event.
115    ///
116    /// If a device employs pointer acceleration, the delta returned by this
117    /// function is the accelerated delta.
118    ///
119    /// Relative motion deltas are normalized to represent those of a device with
120    /// 1000dpi resolution. See [Normalization of relative motion](https://wayland.freedesktop.org/libinput/doc/latest/motion_normalization.html)
121    /// for more details.
122    fn dx, ffi::libinput_event_gesture_get_dx, f64);
123    ffi_func!(
124    /// Return the relative delta of the unaccelerated motion vector of the
125    /// current event.
126    ///
127    /// Relative unaccelerated motion deltas are normalized to represent those of
128    /// a device with 1000dpi resolution. See [Normalization of relative motion](https://wayland.freedesktop.org/libinput/doc/latest/motion_normalization.html)
129    /// for more details. Note that unaccelerated events are not equivalent to
130    /// 'raw' events as read from the device.
131    ///
132    /// Any rotation applied to the device also applies to gesture motion (see
133    /// `rotation_set_angle`).
134    fn dx_unaccelerated, ffi::libinput_event_gesture_get_dx_unaccelerated, f64);
135    ffi_func!(
136    /// Return the delta between the last event and the current event.
137    ///
138    /// If a device employs pointer acceleration, the delta returned by this
139    /// function is the accelerated delta.
140    ///
141    /// Relative motion deltas are normalized to represent those of a device with
142    /// 1000dpi resolution. See [Normalization of relative motion](https://wayland.freedesktop.org/libinput/doc/latest/motion_normalization.html)
143    /// for more details.
144    fn dy, ffi::libinput_event_gesture_get_dy, f64);
145    ffi_func!(
146    /// Return the relative delta of the unaccelerated motion vector of the
147    /// current event.
148    ///
149    /// Relative unaccelerated motion deltas are normalized to represent those of
150    /// a device with 1000dpi resolution. See [Normalization of relative motion](https://wayland.freedesktop.org/libinput/doc/latest/motion_normalization.html)
151    /// for more details. Note that unaccelerated events are not equivalent to
152    /// 'raw' events as read from the device.
153    ///
154    /// Any rotation applied to the device also applies to gesture motion (see
155    /// `rotation_set_angle`).
156    fn dy_unaccelerated, ffi::libinput_event_gesture_get_dy_unaccelerated, f64);
157}
158
159/// Common functions for events noting the end of a gesture
160pub trait GestureEndEvent: AsRaw<ffi::libinput_event_gesture> {
161    ffi_func!(
162    /// Return if the gesture ended normally, or if it was cancelled.
163    fn cancelled, ffi::libinput_event_gesture_get_cancelled, bool);
164}
165
166/// Events for swipe gestures
167#[derive(Debug, PartialEq, Eq, Hash)]
168#[non_exhaustive]
169pub enum GestureSwipeEvent {
170    /// Swipe gesture began
171    Begin(GestureSwipeBeginEvent),
172    /// In-progress swipe gesture updated
173    Update(GestureSwipeUpdateEvent),
174    /// Swipe gesture ended
175    End(GestureSwipeEndEvent),
176}
177
178/// Common functions for swipe gesture events
179pub trait GestureSwipeEventTrait: AsRaw<ffi::libinput_event_gesture> + Context {
180    /// Convert into a general `GestureSwipeEvent`
181    fn into_gesture_swipe_event(self) -> GestureSwipeEvent
182    where
183        Self: Sized,
184    {
185        unsafe { GestureSwipeEvent::from_raw(self.as_raw_mut(), self.context()) }
186    }
187}
188
189impl GestureSwipeEventTrait for GestureSwipeEvent {}
190
191impl EventTrait for GestureSwipeEvent {
192    #[doc(hidden)]
193    fn as_raw_event(&self) -> *mut ffi::libinput_event {
194        match self {
195            GestureSwipeEvent::Begin(event) => event.as_raw_event(),
196            GestureSwipeEvent::Update(event) => event.as_raw_event(),
197            GestureSwipeEvent::End(event) => event.as_raw_event(),
198        }
199    }
200}
201
202impl FromRaw<ffi::libinput_event_gesture> for GestureSwipeEvent {
203    unsafe fn try_from_raw(
204        event: *mut ffi::libinput_event_gesture,
205        context: &Libinput,
206    ) -> Option<Self> {
207        let base = ffi::libinput_event_gesture_get_base_event(event);
208        match ffi::libinput_event_get_type(base) {
209            ffi::libinput_event_type_LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN => Some(
210                GestureSwipeEvent::Begin(GestureSwipeBeginEvent::try_from_raw(event, context)?),
211            ),
212            ffi::libinput_event_type_LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE => Some(
213                GestureSwipeEvent::Update(GestureSwipeUpdateEvent::try_from_raw(event, context)?),
214            ),
215            ffi::libinput_event_type_LIBINPUT_EVENT_GESTURE_SWIPE_END => Some(
216                GestureSwipeEvent::End(GestureSwipeEndEvent::try_from_raw(event, context)?),
217            ),
218            ffi::libinput_event_type_LIBINPUT_EVENT_GESTURE_PINCH_BEGIN
219            | ffi::libinput_event_type_LIBINPUT_EVENT_GESTURE_PINCH_UPDATE
220            | ffi::libinput_event_type_LIBINPUT_EVENT_GESTURE_PINCH_END => {
221                panic!("Tried to make GestureSwipeEvent from Pinch event")
222            }
223            #[cfg(feature = "libinput_1_19")]
224            ffi::libinput_event_type_LIBINPUT_EVENT_GESTURE_HOLD_BEGIN
225            | ffi::libinput_event_type_LIBINPUT_EVENT_GESTURE_HOLD_END => {
226                panic!("Tried to make GestureSwipeEvent from Hold event")
227            }
228            _ => None,
229        }
230    }
231    unsafe fn from_raw(event: *mut ffi::libinput_event_gesture, context: &Libinput) -> Self {
232        Self::try_from_raw(event, context).expect("Unknown gesture event type")
233    }
234}
235
236impl AsRaw<ffi::libinput_event_gesture> for GestureSwipeEvent {
237    fn as_raw(&self) -> *const ffi::libinput_event_gesture {
238        match self {
239            GestureSwipeEvent::Begin(event) => event.as_raw(),
240            GestureSwipeEvent::Update(event) => event.as_raw(),
241            GestureSwipeEvent::End(event) => event.as_raw(),
242        }
243    }
244}
245
246impl Context for GestureSwipeEvent {
247    fn context(&self) -> &Libinput {
248        match self {
249            GestureSwipeEvent::Begin(event) => event.context(),
250            GestureSwipeEvent::Update(event) => event.context(),
251            GestureSwipeEvent::End(event) => event.context(),
252        }
253    }
254}
255
256/// Events for pinch gestures
257#[derive(Debug, PartialEq, Eq, Hash)]
258#[non_exhaustive]
259pub enum GesturePinchEvent {
260    /// Pinch gesture began
261    Begin(GesturePinchBeginEvent),
262    /// In-progress pinch gesture updated
263    Update(GesturePinchUpdateEvent),
264    /// Pinch gesture ended
265    End(GesturePinchEndEvent),
266}
267
268impl EventTrait for GesturePinchEvent {
269    #[doc(hidden)]
270    fn as_raw_event(&self) -> *mut ffi::libinput_event {
271        match self {
272            GesturePinchEvent::Begin(event) => event.as_raw_event(),
273            GesturePinchEvent::Update(event) => event.as_raw_event(),
274            GesturePinchEvent::End(event) => event.as_raw_event(),
275        }
276    }
277}
278
279/// Common functions for pinch gesture events
280pub trait GesturePinchEventTrait: AsRaw<ffi::libinput_event_gesture> + Context {
281    ffi_func!(
282    /// Return the absolute scale of a pinch gesture, the scale is the division of
283    /// the current distance between the fingers and the distance at the start of
284    /// the gesture.
285    ///
286    /// The scale begins at 1.0, and if e.g. the fingers moved together by 50%
287    /// then the scale will become 0.5, if they move twice as far apart as
288    /// initially the scale becomes 2.0, etc.
289    ///
290    /// For gesture events that are of type `GesturePinchBeginEvent`, this function
291    /// returns 1.0.
292    /// For gesture events that are of type `GesturePinchEndEvent`, this function
293    /// returns the scale value of the most recent `GesturePinchUpdateEvent` event
294    /// (if any) or 1.0 otherwise.
295    fn scale, ffi::libinput_event_gesture_get_scale, f64);
296
297    /// Convert into a general `GesturePinchEvent`
298    fn into_gesture_pinch_event(self) -> GesturePinchEvent
299    where
300        Self: Sized,
301    {
302        unsafe { GesturePinchEvent::from_raw(self.as_raw_mut(), self.context()) }
303    }
304}
305
306impl GesturePinchEventTrait for GesturePinchEvent {}
307
308impl FromRaw<ffi::libinput_event_gesture> for GesturePinchEvent {
309    unsafe fn try_from_raw(
310        event: *mut ffi::libinput_event_gesture,
311        context: &Libinput,
312    ) -> Option<Self> {
313        let base = ffi::libinput_event_gesture_get_base_event(event);
314        match ffi::libinput_event_get_type(base) {
315            ffi::libinput_event_type_LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN
316            | ffi::libinput_event_type_LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE
317            | ffi::libinput_event_type_LIBINPUT_EVENT_GESTURE_SWIPE_END => {
318                panic!("Tried to make GesturePinchEvent from Swipe event")
319            }
320            #[cfg(feature = "libinput_1_19")]
321            ffi::libinput_event_type_LIBINPUT_EVENT_GESTURE_HOLD_BEGIN
322            | ffi::libinput_event_type_LIBINPUT_EVENT_GESTURE_HOLD_END => {
323                panic!("Tried to make GestureSwipeEvent from Hold event")
324            }
325            ffi::libinput_event_type_LIBINPUT_EVENT_GESTURE_PINCH_BEGIN => Some(
326                GesturePinchEvent::Begin(GesturePinchBeginEvent::try_from_raw(event, context)?),
327            ),
328            ffi::libinput_event_type_LIBINPUT_EVENT_GESTURE_PINCH_UPDATE => Some(
329                GesturePinchEvent::Update(GesturePinchUpdateEvent::try_from_raw(event, context)?),
330            ),
331            ffi::libinput_event_type_LIBINPUT_EVENT_GESTURE_PINCH_END => Some(
332                GesturePinchEvent::End(GesturePinchEndEvent::try_from_raw(event, context)?),
333            ),
334            _ => None,
335        }
336    }
337    unsafe fn from_raw(event: *mut ffi::libinput_event_gesture, context: &Libinput) -> Self {
338        Self::try_from_raw(event, context).expect("Unknown gesture event type")
339    }
340}
341
342impl AsRaw<ffi::libinput_event_gesture> for GesturePinchEvent {
343    fn as_raw(&self) -> *const ffi::libinput_event_gesture {
344        match self {
345            GesturePinchEvent::Begin(event) => event.as_raw(),
346            GesturePinchEvent::Update(event) => event.as_raw(),
347            GesturePinchEvent::End(event) => event.as_raw(),
348        }
349    }
350}
351
352impl Context for GesturePinchEvent {
353    fn context(&self) -> &Libinput {
354        match self {
355            GesturePinchEvent::Begin(event) => event.context(),
356            GesturePinchEvent::Update(event) => event.context(),
357            GesturePinchEvent::End(event) => event.context(),
358        }
359    }
360}
361
362#[cfg(feature = "libinput_1_19")]
363#[derive(Debug, PartialEq, Eq, Hash)]
364#[non_exhaustive]
365/// Events for hold gestures
366pub enum GestureHoldEvent {
367    /// Hold gesture began
368    Begin(GestureHoldBeginEvent),
369    /// Hold gesture ended
370    End(GestureHoldEndEvent),
371}
372
373#[cfg(feature = "libinput_1_19")]
374impl EventTrait for GestureHoldEvent {
375    #[doc(hidden)]
376    fn as_raw_event(&self) -> *mut ffi::libinput_event {
377        match self {
378            GestureHoldEvent::Begin(event) => event.as_raw_event(),
379            GestureHoldEvent::End(event) => event.as_raw_event(),
380        }
381    }
382}
383
384#[cfg(feature = "libinput_1_19")]
385/// Common functions for hold gesture events
386pub trait GestureHoldEventTrait: AsRaw<ffi::libinput_event_gesture> + Context {
387    /// Convert into a general `GesturePinchEvent`
388    fn into_gesture_hold_event(self) -> GestureHoldEvent
389    where
390        Self: Sized,
391    {
392        unsafe { GestureHoldEvent::from_raw(self.as_raw_mut(), self.context()) }
393    }
394}
395
396#[cfg(feature = "libinput_1_19")]
397impl GestureHoldEventTrait for GestureHoldEvent {}
398
399#[cfg(feature = "libinput_1_19")]
400impl FromRaw<ffi::libinput_event_gesture> for GestureHoldEvent {
401    unsafe fn try_from_raw(
402        event: *mut ffi::libinput_event_gesture,
403        context: &Libinput,
404    ) -> Option<Self> {
405        let base = ffi::libinput_event_gesture_get_base_event(event);
406        match ffi::libinput_event_get_type(base) {
407            ffi::libinput_event_type_LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN
408            | ffi::libinput_event_type_LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE
409            | ffi::libinput_event_type_LIBINPUT_EVENT_GESTURE_SWIPE_END => {
410                panic!("Tried to make GesturePinchEvent from Swipe event")
411            }
412            ffi::libinput_event_type_LIBINPUT_EVENT_GESTURE_PINCH_BEGIN
413            | ffi::libinput_event_type_LIBINPUT_EVENT_GESTURE_PINCH_UPDATE
414            | ffi::libinput_event_type_LIBINPUT_EVENT_GESTURE_PINCH_END => {
415                panic!("Tried to make GestureSwipeEvent from Pinch event")
416            }
417            ffi::libinput_event_type_LIBINPUT_EVENT_GESTURE_HOLD_BEGIN => Some(
418                GestureHoldEvent::Begin(GestureHoldBeginEvent::try_from_raw(event, context)?),
419            ),
420            ffi::libinput_event_type_LIBINPUT_EVENT_GESTURE_HOLD_END => Some(
421                GestureHoldEvent::End(GestureHoldEndEvent::try_from_raw(event, context)?),
422            ),
423            _ => None,
424        }
425    }
426    unsafe fn from_raw(event: *mut ffi::libinput_event_gesture, context: &Libinput) -> Self {
427        Self::try_from_raw(event, context).expect("Unknown gesture event type")
428    }
429}
430
431#[cfg(feature = "libinput_1_19")]
432impl AsRaw<ffi::libinput_event_gesture> for GestureHoldEvent {
433    fn as_raw(&self) -> *const ffi::libinput_event_gesture {
434        match self {
435            GestureHoldEvent::Begin(event) => event.as_raw(),
436            GestureHoldEvent::End(event) => event.as_raw(),
437        }
438    }
439}
440
441#[cfg(feature = "libinput_1_19")]
442impl Context for GestureHoldEvent {
443    fn context(&self) -> &Libinput {
444        match self {
445            GestureHoldEvent::Begin(event) => event.context(),
446            GestureHoldEvent::End(event) => event.context(),
447        }
448    }
449}
450
451ffi_event_struct!(
452/// Swipe gesture began
453struct GestureSwipeBeginEvent, ffi::libinput_event_gesture, ffi::libinput_event_gesture_get_base_event);
454
455impl GestureSwipeEventTrait for GestureSwipeBeginEvent {}
456
457ffi_event_struct!(
458/// In-progress swipe gesture updated
459struct GestureSwipeUpdateEvent, ffi::libinput_event_gesture, ffi::libinput_event_gesture_get_base_event);
460
461impl GestureSwipeEventTrait for GestureSwipeUpdateEvent {}
462
463impl GestureEventCoordinates for GestureSwipeUpdateEvent {}
464
465ffi_event_struct!(
466/// Swipe gesture ended
467struct GestureSwipeEndEvent, ffi::libinput_event_gesture, ffi::libinput_event_gesture_get_base_event);
468
469impl GestureEndEvent for GestureSwipeEndEvent {}
470
471impl GestureSwipeEventTrait for GestureSwipeEndEvent {}
472
473ffi_event_struct!(
474/// Pinch gesture began
475struct GesturePinchBeginEvent, ffi::libinput_event_gesture, ffi::libinput_event_gesture_get_base_event);
476
477impl GesturePinchEventTrait for GesturePinchBeginEvent {}
478
479ffi_event_struct!(
480/// In-progress pinch gesture updated
481struct GesturePinchUpdateEvent, ffi::libinput_event_gesture, ffi::libinput_event_gesture_get_base_event);
482
483impl GesturePinchEventTrait for GesturePinchUpdateEvent {}
484
485impl GestureEventCoordinates for GesturePinchUpdateEvent {}
486
487impl GesturePinchUpdateEvent {
488    ffi_func!(
489    /// Return the angle delta in degrees between the last and the current
490    /// `GesturePinchUpdateEvent`.
491    ///
492    /// The angle delta is defined as the change in angle of the line formed by
493    /// the 2 fingers of a pinch gesture. Clockwise rotation is represented by a
494    /// positive delta, counter-clockwise by a negative delta. If e.g. the fingers
495    /// are on the 12 and 6 location of a clock face plate and they move to the 1
496    /// resp. 7 location in a single event then the angle delta is 30 degrees.
497    ///
498    /// If more than two fingers are present, the angle represents the rotation
499    /// around the center of gravity. The calculation of the center of gravity is
500    /// implementation-dependent.
501    pub fn angle_delta, ffi::libinput_event_gesture_get_angle_delta, f64);
502}
503
504ffi_event_struct!(
505/// Pinch gesture ended
506struct GesturePinchEndEvent, ffi::libinput_event_gesture, ffi::libinput_event_gesture_get_base_event);
507
508impl GesturePinchEventTrait for GesturePinchEndEvent {}
509
510impl GestureEndEvent for GesturePinchEndEvent {}
511
512#[cfg(feature = "libinput_1_19")]
513ffi_event_struct!(
514/// Hold gesture began
515struct GestureHoldBeginEvent, ffi::libinput_event_gesture, ffi::libinput_event_gesture_get_base_event);
516
517#[cfg(feature = "libinput_1_19")]
518impl GestureHoldEventTrait for GestureHoldBeginEvent {}
519
520#[cfg(feature = "libinput_1_19")]
521ffi_event_struct!(
522/// Hold gesture ended
523struct GestureHoldEndEvent, ffi::libinput_event_gesture, ffi::libinput_event_gesture_get_base_event);
524
525#[cfg(feature = "libinput_1_19")]
526impl GestureEndEvent for GestureHoldEndEvent {}
527
528#[cfg(feature = "libinput_1_19")]
529impl GestureHoldEventTrait for GestureHoldEndEvent {}