input/event/
device.rs

1//! Device event types
2
3use super::EventTrait;
4use crate::{ffi, AsRaw, Context, FromRaw, Libinput};
5
6/// Common functions all Device-Events implement.
7pub trait DeviceEventTrait: AsRaw<ffi::libinput_event_device_notify> + Context {
8    /// Convert into a general `DeviceEvent` again
9    fn into_device_event(self) -> DeviceEvent
10    where
11        Self: Sized,
12    {
13        unsafe { DeviceEvent::from_raw(self.as_raw_mut(), self.context()) }
14    }
15}
16
17impl<T: AsRaw<ffi::libinput_event_device_notify> + Context> DeviceEventTrait for T {}
18
19/// A device related `Event`
20#[derive(Debug, PartialEq, Eq, Hash)]
21#[non_exhaustive]
22pub enum DeviceEvent {
23    /// Signals that a device has been added to the context.
24    Added(DeviceAddedEvent),
25    /// Signals that a device has been removed.
26    Removed(DeviceRemovedEvent),
27}
28
29impl EventTrait for DeviceEvent {
30    #[doc(hidden)]
31    fn as_raw_event(&self) -> *mut ffi::libinput_event {
32        match self {
33            DeviceEvent::Added(event) => event.as_raw_event(),
34            DeviceEvent::Removed(event) => event.as_raw_event(),
35        }
36    }
37}
38
39impl FromRaw<ffi::libinput_event_device_notify> for DeviceEvent {
40    unsafe fn try_from_raw(
41        event: *mut ffi::libinput_event_device_notify,
42        context: &Libinput,
43    ) -> Option<Self> {
44        let base = ffi::libinput_event_device_notify_get_base_event(event);
45        match ffi::libinput_event_get_type(base) {
46            ffi::libinput_event_type_LIBINPUT_EVENT_DEVICE_ADDED => Some(DeviceEvent::Added(
47                DeviceAddedEvent::try_from_raw(event, context)?,
48            )),
49            ffi::libinput_event_type_LIBINPUT_EVENT_DEVICE_REMOVED => Some(DeviceEvent::Removed(
50                DeviceRemovedEvent::try_from_raw(event, context)?,
51            )),
52            _ => None,
53        }
54    }
55    unsafe fn from_raw(event: *mut ffi::libinput_event_device_notify, context: &Libinput) -> Self {
56        Self::try_from_raw(event, context).expect("Unknown libinput_event_device type")
57    }
58}
59
60impl AsRaw<ffi::libinput_event_device_notify> for DeviceEvent {
61    fn as_raw(&self) -> *const ffi::libinput_event_device_notify {
62        match self {
63            DeviceEvent::Added(event) => event.as_raw(),
64            DeviceEvent::Removed(event) => event.as_raw(),
65        }
66    }
67}
68
69impl Context for DeviceEvent {
70    fn context(&self) -> &Libinput {
71        match self {
72            DeviceEvent::Added(event) => event.context(),
73            DeviceEvent::Removed(event) => event.context(),
74        }
75    }
76}
77
78ffi_event_struct! {
79    /// Signals that a device has been added to the context.
80    ///
81    /// The device will not be read until the next time the user calls
82    /// `Libinput::dispatch` and data is available.
83    ///
84    /// This allows setting up initial device configuration before any events are created.
85    struct DeviceAddedEvent, ffi::libinput_event_device_notify, ffi::libinput_event_device_notify_get_base_event
86}
87
88ffi_event_struct! {
89    /// Signals that a device has been removed.
90    ///
91    /// No more events from the associated device will be in the queue or be queued after this event.
92    struct DeviceRemovedEvent, ffi::libinput_event_device_notify, ffi::libinput_event_device_notify_get_base_event
93}