input/event/
switch.rs

1//! Switch event types
2
3use super::EventTrait;
4use crate::{ffi, AsRaw, Context, FromRaw, Libinput};
5
6/// Common functions all Switch-Events implement.
7pub trait SwitchEventTrait: AsRaw<ffi::libinput_event_switch> + Context {
8    ffi_func!(
9    /// The event time for this event
10    fn time, ffi::libinput_event_switch_get_time, u32);
11    ffi_func!(
12    /// The event time for this event in microseconds
13    fn time_usec, ffi::libinput_event_switch_get_time_usec, u64);
14
15    /// Convert into a general `SwitchEvent` again
16    fn into_switch_event(self) -> SwitchEvent
17    where
18        Self: Sized,
19    {
20        unsafe { SwitchEvent::from_raw(self.as_raw_mut(), self.context()) }
21    }
22}
23
24impl<T: AsRaw<ffi::libinput_event_switch> + Context> SwitchEventTrait for T {}
25
26/// A switch related `Event`
27#[derive(Debug, PartialEq, Eq, Hash)]
28#[non_exhaustive]
29pub enum SwitchEvent {
30    /// An event related a switch, that was toggled
31    Toggle(SwitchToggleEvent),
32}
33
34impl EventTrait for SwitchEvent {
35    #[doc(hidden)]
36    fn as_raw_event(&self) -> *mut ffi::libinput_event {
37        match self {
38            SwitchEvent::Toggle(event) => event.as_raw_event(),
39        }
40    }
41}
42
43impl FromRaw<ffi::libinput_event_switch> for SwitchEvent {
44    unsafe fn try_from_raw(
45        event: *mut ffi::libinput_event_switch,
46        context: &Libinput,
47    ) -> Option<Self> {
48        let base = ffi::libinput_event_switch_get_base_event(event);
49        match ffi::libinput_event_get_type(base) {
50            ffi::libinput_event_type_LIBINPUT_EVENT_SWITCH_TOGGLE => Some(SwitchEvent::Toggle(
51                SwitchToggleEvent::try_from_raw(event, context)?,
52            )),
53            _ => None,
54        }
55    }
56    unsafe fn from_raw(event: *mut ffi::libinput_event_switch, context: &Libinput) -> Self {
57        Self::try_from_raw(event, context).expect("Unknown switch event type")
58    }
59}
60
61impl AsRaw<ffi::libinput_event_switch> for SwitchEvent {
62    fn as_raw(&self) -> *const ffi::libinput_event_switch {
63        match self {
64            SwitchEvent::Toggle(event) => event.as_raw(),
65        }
66    }
67}
68
69impl Context for SwitchEvent {
70    fn context(&self) -> &Libinput {
71        match self {
72            SwitchEvent::Toggle(event) => event.context(),
73        }
74    }
75}
76
77/// Types of Switches
78#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
79#[repr(u32)]
80#[non_exhaustive]
81pub enum Switch {
82    /// The laptop lid was closed when the `SwitchState` is
83    /// `On`, or was opened when it is `Off`
84    Lid = ffi::libinput_switch_LIBINPUT_SWITCH_LID,
85    /// This switch indicates whether the device is in normal laptop mode
86    /// or behaves like a tablet-like device where the primary
87    /// interaction is usually a touch screen. When in tablet mode, the
88    /// keyboard and touchpad are usually inaccessible.
89    ///
90    /// If the switch is in state `SwitchState::Off`, the
91    /// device is in laptop mode. If the switch is in state
92    /// `SwitchState::On`, the device is in tablet mode and the
93    /// keyboard or touchpad may not be  accessible.
94    ///
95    /// It is up to the caller to identify which devices are inaccessible
96    /// `in tablet mode.
97    TabletMode = ffi::libinput_switch_LIBINPUT_SWITCH_TABLET_MODE,
98}
99
100/// State of a Switch
101#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
102pub enum SwitchState {
103    /// Switch is off
104    Off,
105    /// Switch is on
106    On,
107}
108
109ffi_event_struct!(
110/// An event related a switch, that was toggled
111struct SwitchToggleEvent, ffi::libinput_event_switch, ffi::libinput_event_switch_get_base_event);
112
113impl SwitchToggleEvent {
114    /// Return the switch that triggered this event.
115    ///
116    /// A return value of `None` means, the switch type is not known
117    pub fn switch(&self) -> Option<Switch> {
118        match unsafe { ffi::libinput_event_switch_get_switch(self.as_raw_mut()) } {
119            ffi::libinput_switch_LIBINPUT_SWITCH_LID => Some(Switch::Lid),
120            ffi::libinput_switch_LIBINPUT_SWITCH_TABLET_MODE => Some(Switch::TabletMode),
121            _x => {
122                #[cfg(feature = "log")]
123                log::warn!("Unknown Switch type returned by libinput: {}", _x);
124                None
125            }
126        }
127    }
128
129    /// Return the switch state that triggered this event.
130    pub fn switch_state(&self) -> SwitchState {
131        match unsafe { ffi::libinput_event_switch_get_switch_state(self.as_raw_mut()) } {
132            ffi::libinput_switch_state_LIBINPUT_SWITCH_STATE_OFF => SwitchState::Off,
133            ffi::libinput_switch_state_LIBINPUT_SWITCH_STATE_ON => SwitchState::On,
134            _ => panic!("libinput returned invalid 'libinput_switch_state'"),
135        }
136    }
137}