input/event/
tablet_pad.rs

1//! Tablet pad event types
2
3pub use super::{keyboard::KeyState, pointer::ButtonState, EventTrait};
4use crate::{ffi, AsRaw, Context, FromRaw, Libinput};
5
6mod mode_group;
7pub use self::mode_group::*;
8
9/// Common functions all TabletPad-Events implement.
10pub trait TabletPadEventTrait: AsRaw<ffi::libinput_event_tablet_pad> + Context {
11    ffi_func!(
12    /// The event time for this event
13    fn time, ffi::libinput_event_tablet_pad_get_time, u32);
14    ffi_func!(
15    /// The event time for this event in microseconds
16    fn time_usec, ffi::libinput_event_tablet_pad_get_time_usec, u64);
17    ffi_func!(
18    /// Returns the mode the button, ring, or strip that triggered this event is in, at the time of the event.
19    ///
20    /// The mode is a virtual grouping of functionality, usually based on some
21    /// visual feedback like LEDs on the pad. See [Tablet pad modes](https://wayland.freedesktop.org/libinput/doc/latest/tablet-support.html#tablet-pad-modes)
22    /// for details. Mode indices start at 0, a device that does not support modes
23    /// always returns 0.
24    ///
25    /// Mode switching is controlled by libinput and more than one mode may exist
26    /// on the tablet. This function returns the mode that this event's button,
27    /// ring or strip is logically in. If the button is a mode toggle button and
28    /// the button event caused a new mode to be toggled, the mode returned is the
29    /// new mode the button is in.
30    ///
31    /// Note that the returned mode is the mode valid as of the time of the event.
32    /// The returned mode may thus be different to the mode returned by
33    /// `TabletPadModeGroup::mode`. See `TabletPadModeGroup::mode` for details.
34    fn mode, ffi::libinput_event_tablet_pad_get_mode, u32);
35
36    /// Returns the mode group that the button, ring, or strip that triggered this
37    /// event is considered in.
38    ///
39    /// The mode is a virtual grouping of functionality, usually based on some
40    /// visual feedback like LEDs on the pad. See [Tablet pad modes](https://wayland.freedesktop.org/libinput/doc/latest/tablet-support.html#tablet-pad-modes) for details.
41    fn mode_group(&self) -> TabletPadModeGroup {
42        unsafe {
43            TabletPadModeGroup::from_raw(
44                ffi::libinput_event_tablet_pad_get_mode_group(self.as_raw_mut()),
45                self.context(),
46            )
47        }
48    }
49
50    /// Convert into a general `TabletPadEvent` again
51    fn into_tablet_pad_event(self) -> TabletPadEvent
52    where
53        Self: Sized,
54    {
55        unsafe { TabletPadEvent::from_raw(self.as_raw_mut(), self.context()) }
56    }
57}
58
59impl<T: AsRaw<ffi::libinput_event_tablet_pad> + Context> TabletPadEventTrait for T {}
60
61/// A tablet-pad related `Event`
62#[derive(Debug, PartialEq, Eq, Hash)]
63#[non_exhaustive]
64pub enum TabletPadEvent {
65    /// A button pressed on a device with the `DeviceCapability::TabletPad`
66    /// capability.
67    ///
68    /// A Button-Event differs from a `Key`-Event (available with `feature="libinput_1_15"`)
69    /// in that buttons are sequentially indexed from 0 and do not carry any other information.
70    /// Keys have a specific functionality assigned to them. The key code thus carries a
71    /// semantic meaning, a button number does not.
72    ///
73    /// This event is not to be confused with the button events emitted by tools
74    /// on a tablet. See `TabletToolButtonEvent`.
75    Button(TabletPadButtonEvent),
76    /// A status change on a tablet ring with the `DeviceCapability::TabletPad`
77    /// capability.
78    Ring(TabletPadRingEvent),
79    /// A status change on a dial on a device with the
80    /// `DeviceCapability::TabletPad` capability.
81    #[cfg(feature = "libinput_1_26")]
82    Dial(TabletPadDialEvent),
83    /// A status change on a strip on a device with the
84    /// `DeviceCapability::TabletPad` capability.
85    Strip(TabletPadStripEvent),
86    /// A key pressed on a device with the `DeviceCapability::TabletPad` capability.
87    ///
88    /// A `Key`-Event differs from a `Button`-Event in that keys have a specific
89    /// functionality assigned to them (buttons are sequencially ordered). A key code
90    /// thus carries a semantic meaning, a button number does not.
91    #[cfg(feature = "libinput_1_15")]
92    Key(TabletPadKeyEvent),
93}
94
95impl EventTrait for TabletPadEvent {
96    #[doc(hidden)]
97    fn as_raw_event(&self) -> *mut ffi::libinput_event {
98        match self {
99            TabletPadEvent::Button(event) => event.as_raw_event(),
100            TabletPadEvent::Ring(event) => event.as_raw_event(),
101            #[cfg(feature = "libinput_1_26")]
102            TabletPadEvent::Dial(event) => event.as_raw_event(),
103            TabletPadEvent::Strip(event) => event.as_raw_event(),
104            #[cfg(feature = "libinput_1_15")]
105            TabletPadEvent::Key(event) => event.as_raw_event(),
106        }
107    }
108}
109
110impl FromRaw<ffi::libinput_event_tablet_pad> for TabletPadEvent {
111    unsafe fn try_from_raw(
112        event: *mut ffi::libinput_event_tablet_pad,
113        context: &Libinput,
114    ) -> Option<Self> {
115        let base = ffi::libinput_event_tablet_pad_get_base_event(event);
116        match ffi::libinput_event_get_type(base) {
117            ffi::libinput_event_type_LIBINPUT_EVENT_TABLET_PAD_BUTTON => Some(
118                TabletPadEvent::Button(TabletPadButtonEvent::try_from_raw(event, context)?),
119            ),
120            ffi::libinput_event_type_LIBINPUT_EVENT_TABLET_PAD_RING => Some(TabletPadEvent::Ring(
121                TabletPadRingEvent::try_from_raw(event, context)?,
122            )),
123            ffi::libinput_event_type_LIBINPUT_EVENT_TABLET_PAD_STRIP => Some(
124                TabletPadEvent::Strip(TabletPadStripEvent::try_from_raw(event, context)?),
125            ),
126            #[cfg(feature = "libinput_1_15")]
127            ffi::libinput_event_type_LIBINPUT_EVENT_TABLET_PAD_KEY => Some(TabletPadEvent::Key(
128                TabletPadKeyEvent::try_from_raw(event, context)?,
129            )),
130            _ => None,
131        }
132    }
133    unsafe fn from_raw(event: *mut ffi::libinput_event_tablet_pad, context: &Libinput) -> Self {
134        Self::try_from_raw(event, context).expect("Unknown tablet pad event type")
135    }
136}
137
138impl AsRaw<ffi::libinput_event_tablet_pad> for TabletPadEvent {
139    fn as_raw(&self) -> *const ffi::libinput_event_tablet_pad {
140        match self {
141            TabletPadEvent::Button(event) => event.as_raw(),
142            TabletPadEvent::Ring(event) => event.as_raw(),
143            #[cfg(feature = "libinput_1_26")]
144            TabletPadEvent::Dial(event) => event.as_raw(),
145            TabletPadEvent::Strip(event) => event.as_raw(),
146            #[cfg(feature = "libinput_1_15")]
147            TabletPadEvent::Key(event) => event.as_raw(),
148        }
149    }
150}
151
152impl Context for TabletPadEvent {
153    fn context(&self) -> &Libinput {
154        match self {
155            TabletPadEvent::Button(event) => event.context(),
156            TabletPadEvent::Ring(event) => event.context(),
157            #[cfg(feature = "libinput_1_26")]
158            TabletPadEvent::Dial(event) => event.context(),
159            TabletPadEvent::Strip(event) => event.context(),
160            #[cfg(feature = "libinput_1_15")]
161            TabletPadEvent::Key(event) => event.context(),
162        }
163    }
164}
165
166ffi_event_struct!(
167/// A button pressed on a device with the `DeviceCapability::TabletPad`
168/// capability.
169///
170/// This event is not to be confused with the button events emitted by tools
171/// on a tablet. See `TabletToolButtonEvent`.
172struct TabletPadButtonEvent, ffi::libinput_event_tablet_pad, ffi::libinput_event_tablet_pad_get_base_event);
173
174impl TabletPadButtonEvent {
175    ffi_func!(
176    /// Return the button number that triggered this event, starting at 0.
177    ///
178    /// Note that the number returned is a generic sequential button number and
179    /// not a semantic button code as defined in linux/input.h.
180    /// [See Tablet pad button numbers](https://wayland.freedesktop.org/libinput/doc/latest/tablet-support.html#tablet-pad-buttons)
181    /// for more details.
182    pub fn button_number, ffi::libinput_event_tablet_pad_get_button_number, u32);
183
184    /// Return the button state of the event.
185    pub fn button_state(&self) -> ButtonState {
186        match unsafe { ffi::libinput_event_tablet_pad_get_button_state(self.as_raw_mut()) } {
187            ffi::libinput_button_state_LIBINPUT_BUTTON_STATE_PRESSED => ButtonState::Pressed,
188            ffi::libinput_button_state_LIBINPUT_BUTTON_STATE_RELEASED => ButtonState::Released,
189            _ => panic!("libinput returned invalid 'libinput_button_state'"),
190        }
191    }
192}
193
194/// The source for a `TabletPadRingEvent` event.
195#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
196pub enum RingAxisSource {
197    /// An unknown source
198    Unknown,
199    /// Finger source
200    Finger,
201}
202
203ffi_event_struct!(
204/// A status change on a tablet ring with the `DeviceCapability::TabletPad`
205/// capability.
206struct TabletPadRingEvent, ffi::libinput_event_tablet_pad, ffi::libinput_event_tablet_pad_get_base_event);
207
208impl TabletPadRingEvent {
209    ffi_func!(
210    /// Returns the number of the ring that has changed state, with 0 being the
211    /// first ring.
212    ///
213    /// On tablets with only one ring, this function always returns 0.
214    pub fn number, ffi::libinput_event_tablet_pad_get_ring_number, u32);
215    ffi_func!(
216    /// Returns the current position of the ring, in degrees clockwise from
217    /// the northern-most point of the ring in the tablet's current logical
218    /// orientation.
219    ///
220    /// If the source is `RingAxisSource::Finger`, libinput sends a  terminating
221    /// event with a ring value of -1 when the finger is lifted from the ring. A
222    /// caller may use this information to e.g. determine if kinetic scrolling
223    /// should be triggered.
224    pub fn position, ffi::libinput_event_tablet_pad_get_ring_position, f64);
225
226    /// Returns the source of the interaction with the ring.
227    ///
228    /// If the source is `RingAxisSource::Finger`, libinput sends a ring position
229    /// value of -1 to terminate the current interaction.
230    pub fn source(&self) -> RingAxisSource {
231        match unsafe { ffi::libinput_event_tablet_pad_get_ring_source(self.as_raw_mut()) } {
232            ffi::libinput_tablet_pad_ring_axis_source_LIBINPUT_TABLET_PAD_RING_SOURCE_UNKNOWN => {
233                RingAxisSource::Unknown
234            }
235            ffi::libinput_tablet_pad_ring_axis_source_LIBINPUT_TABLET_PAD_RING_SOURCE_FINGER => {
236                RingAxisSource::Finger
237            }
238            _x => {
239                #[cfg(feature = "log")]
240                log::warn!("Unknown `RingAxisSource` returned by libinput: {}", _x);
241                RingAxisSource::Unknown
242            }
243        }
244    }
245}
246
247#[cfg(feature = "libinput_1_26")]
248ffi_event_struct!(
249/// A status change on a dial on a device with the `DeviceCapability::TabletPad`
250/// capability.
251struct TabletPadDialEvent, ffi::libinput_event_tablet_pad, ffi::libinput_event_tablet_pad_get_base_event);
252
253#[cfg(feature = "libinput_1_26")]
254impl TabletPadDialEvent {
255    ffi_func!(
256    /// Returns the delta change of the dial, in multiples or fractions of 120,
257    /// with each multiple of 120 indicating one logical wheel event.
258    ///
259    /// See [`PointerScrollWheelEvent::scroll_value_v120`](crate::event::pointer::PointerScrollWheelEvent::scroll_value_v120)
260    /// for more details.
261    pub fn dial_v120, ffi::libinput_event_tablet_pad_get_dial_delta_v120, f64);
262
263    ffi_func!(
264    /// Returns the number of the dial that has changed state, with 0 being the
265    /// first dial.
266    ///
267    /// On tablets with only one dial, this function always returns 0.
268    pub fn number, ffi::libinput_event_tablet_pad_get_dial_number, u32);
269}
270
271/// The source for a `TabletPadStripEvent` event.
272#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
273pub enum StripAxisSource {
274    /// An unknown source
275    Unknown,
276    /// Finger source
277    Finger,
278}
279
280ffi_event_struct!(
281/// A status change on a strip on a device with the `DeviceCapability::TabletPad`
282/// capability.
283struct TabletPadStripEvent, ffi::libinput_event_tablet_pad, ffi::libinput_event_tablet_pad_get_base_event);
284
285impl TabletPadStripEvent {
286    ffi_func!(
287    /// Returns the number of the strip that has changed state, with 0 being the
288    /// first strip.
289    ///
290    /// On tablets with only one strip, this function always returns 0.
291    pub fn number, ffi::libinput_event_tablet_pad_get_strip_number, u32);
292    ffi_func!(
293    /// Returns the current position of the strip, normalized to the range [0, 1],
294    /// with 0 being the top/left-most point in the tablet's current logical
295    /// orientation.
296    ///
297    /// If the source is `StripAxisSource::Finger`, libinput sends a terminating
298    /// event with a ring value of -1 when the finger is lifted from the ring. A
299    /// caller may use this information to e.g. determine if kinetic scrolling
300    /// should be triggered.
301    pub fn position, ffi::libinput_event_tablet_pad_get_strip_position, f64);
302
303    /// Returns the source of the interaction with the strip.
304    ///
305    /// If the source is `StripAxisSource::Finger`, libinput sends a strip
306    /// position value of -1 to terminate the current interaction
307    pub fn source(&self) -> StripAxisSource {
308        match unsafe { ffi::libinput_event_tablet_pad_get_strip_source(self.as_raw_mut()) } {
309            ffi::libinput_tablet_pad_strip_axis_source_LIBINPUT_TABLET_PAD_STRIP_SOURCE_UNKNOWN => {
310                StripAxisSource::Unknown
311            }
312            ffi::libinput_tablet_pad_strip_axis_source_LIBINPUT_TABLET_PAD_STRIP_SOURCE_FINGER => {
313                StripAxisSource::Finger
314            }
315            _x => {
316                #[cfg(feature = "log")]
317                log::warn!("Unknown `StripAxisSource` returned by libinput: {}", _x);
318                StripAxisSource::Unknown
319            }
320        }
321    }
322}
323
324#[cfg(feature = "libinput_1_15")]
325ffi_event_struct!(
326/// A key pressed on a device with the `DeviceCapability::TabletPad` capability.
327struct TabletPadKeyEvent, ffi::libinput_event_tablet_pad, ffi::libinput_event_tablet_pad_get_base_event);
328
329#[cfg(feature = "libinput_1_15")]
330impl TabletPadKeyEvent {
331    ffi_func!(
332    /// Return the key code that triggered this event, e.g. KEY_CONTROLPANEL.
333    /// The list of key codes is defined in linux/input-event-codes.h
334    pub fn key, ffi::libinput_event_tablet_pad_get_key, u32);
335
336    /// Return the key state of the event
337    pub fn key_state(&self) -> KeyState {
338        match unsafe { ffi::libinput_event_tablet_pad_get_key_state(self.as_raw() as *mut _) } {
339            ffi::libinput_key_state_LIBINPUT_KEY_STATE_PRESSED => KeyState::Pressed,
340            ffi::libinput_key_state_LIBINPUT_KEY_STATE_RELEASED => KeyState::Released,
341            _ => panic!("libinput returned invalid 'libinput_key_state'"),
342        }
343    }
344}