colpetto/
event.rs

1//! This module contains wrappers for all possible libinput events
2
3use crate::{Device, sys};
4
5pub mod device;
6pub mod gesture;
7pub mod keyboard;
8pub mod pointer;
9pub mod switch;
10pub mod table_pad;
11pub mod tablet_tool;
12pub mod touch;
13
14pub use device::*;
15pub use gesture::*;
16pub use keyboard::*;
17pub use pointer::*;
18pub use switch::*;
19pub use table_pad::*;
20pub use tablet_tool::*;
21pub use touch::*;
22
23macro_rules! define_events {
24    (
25        $(#[$main_meta:meta])*
26        $main:ident,
27        $raw:ident,
28        $get:expr_2021,
29        $set:expr_2021,
30        $(
31            $(#[$event_meta:meta])*
32            $event:ident,
33        )+
34    ) => {
35        paste::paste! {
36            $(#[$main_meta])*
37            #[derive(Debug)]
38            #[non_exhaustive]
39            pub enum [<$main Event>] {
40                $(
41                    $(#[$event_meta])*
42                    $event([<$main $event Event>]),
43                )+
44            }
45
46            impl [<$main Event>] {
47                /// Returns a printable string rappresenting the event type
48                pub const fn event_type(&self) -> &'static str {
49                    match self {
50                        $(
51                            Self::$event(_) => stringify!($main $event),
52                        )+
53                    }
54                }
55            }
56
57            impl crate::event::sealed::EventSealed for [<$main Event>] {}
58
59            impl crate::event::AsRawEvent for [<$main Event>] {
60                fn as_raw_event(&self) -> *mut crate::sys::libinput_event {
61                    match self {
62                        $(
63                            Self::$event(e) => e.as_raw_event(),
64                        )+
65                    }
66                }
67            }
68
69            $(
70                $(#[$event_meta])*
71                pub struct [<$main $event Event>] {
72                    raw: *mut $raw,
73                }
74
75                crate::macros::impl_debug!([<$main $event Event>]);
76
77                impl crate::event::sealed::EventSealed for [<$main $event Event>] {}
78
79                impl crate::event::AsRawEvent for [<$main $event Event>] {
80                    fn as_raw_event(&self) -> *mut crate::sys::libinput_event {
81                        unsafe { $get(self.raw) }
82                    }
83                }
84
85                impl crate::event::FromRawEvent for [<$main $event Event>] {
86                    unsafe fn from_raw_event(event: *mut crate::sys::libinput_event) -> Self { unsafe {
87                        Self {
88                            raw: $set(event),
89                        }
90                    }}
91                }
92
93                impl Drop for [<$main $event Event>] {
94                    fn drop(&mut self) {
95                        unsafe {
96                            crate::sys::libinput_event_destroy(crate::event::AsRawEvent::as_raw_event(self));
97                        }
98                    }
99                }
100
101            )+
102        }
103    };
104}
105
106pub(crate) use define_events;
107
108/// Rappresents a generic libinput event
109///
110/// For more information see each event module
111#[allow(missing_docs)] // FIXME: prob document variants even tho it's annoying
112#[derive(Debug)]
113pub enum Event {
114    Device(DeviceEvent),
115    Gesture(GestureEvent),
116    Keyboard(KeyboardEvent),
117    Pointer(PointerEvent),
118    Switch(SwitchEvent),
119    TabletPad(TabletPadEvent),
120    TabletTool(TabletToolEvent),
121    Touch(TouchEvent),
122    Unknown(Unknown),
123}
124
125impl Event {
126    /// Returns a printable string rappresenting the event type
127    pub const fn event_type(&self) -> &'static str {
128        match self {
129            Event::Device(e) => e.event_type(),
130            Event::Gesture(e) => e.event_type(),
131            Event::Keyboard(e) => e.event_type(),
132            Event::Pointer(e) => e.event_type(),
133            Event::Switch(e) => e.event_type(),
134            Event::TabletPad(e) => e.event_type(),
135            Event::TabletTool(e) => e.event_type(),
136            Event::Touch(e) => e.event_type(),
137            Event::Unknown(e) => e.event_type(),
138        }
139    }
140}
141
142impl sealed::EventSealed for Event {}
143
144impl AsRawEvent for Event {
145    fn as_raw_event(&self) -> *mut sys::libinput_event {
146        match self {
147            Event::Device(e) => e.as_raw_event(),
148            Event::Gesture(e) => e.as_raw_event(),
149            Event::Keyboard(e) => e.as_raw_event(),
150            Event::Pointer(e) => e.as_raw_event(),
151            Event::Switch(e) => e.as_raw_event(),
152            Event::TabletPad(e) => e.as_raw_event(),
153            Event::TabletTool(e) => e.as_raw_event(),
154            Event::Touch(e) => e.as_raw_event(),
155            Event::Unknown(e) => e.as_raw_event(),
156        }
157    }
158}
159
160/// A special event that's not actually part of libinput but allows for graceful handling of newer versions
161#[derive(Debug)]
162pub struct Unknown {
163    #[allow(unused)]
164    raw: *mut sys::libinput_event,
165}
166
167impl Unknown {
168    /// Returns a printable string rappresenting the event type
169    pub const fn event_type(&self) -> &'static str {
170        "unknown"
171    }
172}
173
174impl sealed::EventSealed for Unknown {}
175
176impl AsRawEvent for Unknown {
177    fn as_raw_event(&self) -> *mut sys::libinput_event {
178        self.raw
179    }
180}
181
182impl Drop for Unknown {
183    fn drop(&mut self) {
184        unsafe {
185            sys::libinput_event_destroy(self.raw);
186        }
187    }
188}
189
190macro_rules! map_raw {
191    ($outer:ident($inner:ident), $event:expr_2021) => {
192        paste::paste! {
193            crate::Event::$outer(crate::event::[<$outer Event>]::$inner(unsafe {
194                crate::event::[<$outer $inner Event>]::from_raw_event($event)
195            }))
196        }
197    };
198}
199
200impl Event {
201    /// Builds a new event from raw data
202    ///
203    /// # Safety
204    ///
205    /// The caller must ensure it's passing valid pointers.
206    ///
207    /// The function assumes that the `event_type` has already been checked against [`LIBINPUT_EVENT_NONE`](sys::libinput_event_type::LIBINPUT_EVENT_NONE)
208    pub unsafe fn from_raw(
209        event: *mut sys::libinput_event,
210        event_type: sys::libinput_event_type::Type,
211    ) -> Self {
212        use sys::libinput_event_type::*;
213
214        match event_type {
215            LIBINPUT_EVENT_DEVICE_ADDED => map_raw!(Device(Added), event),
216            LIBINPUT_EVENT_DEVICE_REMOVED => map_raw!(Device(Removed), event),
217
218            LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN => map_raw!(Gesture(SwipeBegin), event),
219            LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE => map_raw!(Gesture(SwipeUpdate), event),
220            LIBINPUT_EVENT_GESTURE_SWIPE_END => map_raw!(Gesture(SwipeEnd), event),
221            LIBINPUT_EVENT_GESTURE_PINCH_BEGIN => map_raw!(Gesture(PinchBegin), event),
222            LIBINPUT_EVENT_GESTURE_PINCH_UPDATE => map_raw!(Gesture(PinchUpdate), event),
223            LIBINPUT_EVENT_GESTURE_PINCH_END => map_raw!(Gesture(PinchEnd), event),
224            LIBINPUT_EVENT_GESTURE_HOLD_BEGIN => map_raw!(Gesture(HoldBegin), event),
225            LIBINPUT_EVENT_GESTURE_HOLD_END => map_raw!(Gesture(HoldEnd), event),
226
227            LIBINPUT_EVENT_KEYBOARD_KEY => map_raw!(Keyboard(Key), event),
228
229            LIBINPUT_EVENT_POINTER_MOTION => map_raw!(Pointer(Motion), event),
230            LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE => map_raw!(Pointer(MotionAbsolute), event),
231            LIBINPUT_EVENT_POINTER_BUTTON => map_raw!(Pointer(Button), event),
232            LIBINPUT_EVENT_POINTER_AXIS => map_raw!(Pointer(Axis), event),
233            LIBINPUT_EVENT_POINTER_SCROLL_WHEEL => map_raw!(Pointer(ScrollWheel), event),
234            LIBINPUT_EVENT_POINTER_SCROLL_FINGER => map_raw!(Pointer(ScrollFinger), event),
235            LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS => map_raw!(Pointer(ScrollContinuous), event),
236
237            LIBINPUT_EVENT_SWITCH_TOGGLE => map_raw!(Switch(Toggle), event),
238
239            LIBINPUT_EVENT_TABLET_PAD_BUTTON => map_raw!(TabletPad(Button), event),
240            LIBINPUT_EVENT_TABLET_PAD_RING => map_raw!(TabletPad(Ring), event),
241            LIBINPUT_EVENT_TABLET_PAD_STRIP => map_raw!(TabletPad(Strip), event),
242            LIBINPUT_EVENT_TABLET_PAD_KEY => map_raw!(TabletPad(Key), event),
243            #[cfg(feature = "1_26")]
244            LIBINPUT_EVENT_TABLET_PAD_DIAL => map_raw!(TabletPad(Dial), event),
245
246            LIBINPUT_EVENT_TABLET_TOOL_AXIS => map_raw!(TabletTool(Axis), event),
247            LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY => map_raw!(TabletTool(Proximity), event),
248            LIBINPUT_EVENT_TABLET_TOOL_TIP => map_raw!(TabletTool(Tip), event),
249            LIBINPUT_EVENT_TABLET_TOOL_BUTTON => map_raw!(TabletTool(Button), event),
250
251            LIBINPUT_EVENT_TOUCH_DOWN => map_raw!(Touch(Down), event),
252            LIBINPUT_EVENT_TOUCH_UP => map_raw!(Touch(Up), event),
253            LIBINPUT_EVENT_TOUCH_MOTION => map_raw!(Touch(Motion), event),
254            LIBINPUT_EVENT_TOUCH_CANCEL => map_raw!(Touch(Cancel), event),
255            LIBINPUT_EVENT_TOUCH_FRAME => map_raw!(Touch(Frame), event),
256
257            _ => Event::Unknown(Unknown { raw: event }),
258        }
259    }
260}
261
262/// Helper trait to get raw libinput events
263pub trait AsRawEvent: sealed::EventSealed {
264    // fn as_raw(&self) -> *mut T;
265
266    /// Returns the raw libinput event. You probably dont wanna use this
267    fn as_raw_event(&self) -> *mut sys::libinput_event;
268
269    /// Gets the device associated with this event
270    fn device(&self) -> Device {
271        unsafe { Device::from_raw(sys::libinput_event_get_device(self.as_raw_event())) }
272    }
273}
274
275/// Helper trait to get an event from a raw one
276pub trait FromRawEvent: sealed::EventSealed {
277    // unsafe fn from_raw(raw: *mut T) -> Self;
278
279    /// Creates an event from a raw libinput one. This should rarely be needed by users of the library
280    ///
281    /// # Safety
282    ///
283    /// The caller must ensure it's passing a valid pointer.
284    ///
285    /// It's the caller responsablity to ensure this function is called for the appropriate event.
286    unsafe fn from_raw_event(event: *mut sys::libinput_event) -> Self;
287}
288
289mod sealed {
290
291    pub trait EventSealed {}
292}