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 strip on a device with the
80 /// `DeviceCapability::TabletPad` capability.
81 Strip(TabletPadStripEvent),
82 /// A key pressed on a device with the `DeviceCapability::TabletPad` capability.
83 ///
84 /// A `Key`-Event differs from a `Button`-Event in that keys have a specific
85 /// functionality assigned to them (buttons are sequencially ordered). A key code
86 /// thus carries a semantic meaning, a button number does not.
87 #[cfg(feature = "libinput_1_15")]
88 Key(TabletPadKeyEvent),
89}
90
91impl EventTrait for TabletPadEvent {
92 #[doc(hidden)]
93 fn as_raw_event(&self) -> *mut ffi::libinput_event {
94 match self {
95 TabletPadEvent::Button(event: &TabletPadButtonEvent) => event.as_raw_event(),
96 TabletPadEvent::Ring(event: &TabletPadRingEvent) => event.as_raw_event(),
97 TabletPadEvent::Strip(event: &TabletPadStripEvent) => event.as_raw_event(),
98 #[cfg(feature = "libinput_1_15")]
99 TabletPadEvent::Key(event: &TabletPadKeyEvent) => event.as_raw_event(),
100 }
101 }
102}
103
104impl FromRaw<ffi::libinput_event_tablet_pad> for TabletPadEvent {
105 unsafe fn try_from_raw(
106 event: *mut ffi::libinput_event_tablet_pad,
107 context: &Libinput,
108 ) -> Option<Self> {
109 let base = ffi::libinput_event_tablet_pad_get_base_event(event);
110 match ffi::libinput_event_get_type(base) {
111 ffi::libinput_event_type_LIBINPUT_EVENT_TABLET_PAD_BUTTON => Some(
112 TabletPadEvent::Button(TabletPadButtonEvent::try_from_raw(event, context)?),
113 ),
114 ffi::libinput_event_type_LIBINPUT_EVENT_TABLET_PAD_RING => Some(TabletPadEvent::Ring(
115 TabletPadRingEvent::try_from_raw(event, context)?,
116 )),
117 ffi::libinput_event_type_LIBINPUT_EVENT_TABLET_PAD_STRIP => Some(
118 TabletPadEvent::Strip(TabletPadStripEvent::try_from_raw(event, context)?),
119 ),
120 #[cfg(feature = "libinput_1_15")]
121 ffi::libinput_event_type_LIBINPUT_EVENT_TABLET_PAD_KEY => Some(TabletPadEvent::Key(
122 TabletPadKeyEvent::try_from_raw(event, context)?,
123 )),
124 _ => None,
125 }
126 }
127 unsafe fn from_raw(event: *mut ffi::libinput_event_tablet_pad, context: &Libinput) -> Self {
128 Self::try_from_raw(event, context).expect("Unknown tablet pad event type")
129 }
130}
131
132impl AsRaw<ffi::libinput_event_tablet_pad> for TabletPadEvent {
133 fn as_raw(&self) -> *const ffi::libinput_event_tablet_pad {
134 match self {
135 TabletPadEvent::Button(event: &TabletPadButtonEvent) => event.as_raw(),
136 TabletPadEvent::Ring(event: &TabletPadRingEvent) => event.as_raw(),
137 TabletPadEvent::Strip(event: &TabletPadStripEvent) => event.as_raw(),
138 #[cfg(feature = "libinput_1_15")]
139 TabletPadEvent::Key(event: &TabletPadKeyEvent) => event.as_raw(),
140 }
141 }
142}
143
144impl Context for TabletPadEvent {
145 fn context(&self) -> &Libinput {
146 match self {
147 TabletPadEvent::Button(event: &TabletPadButtonEvent) => event.context(),
148 TabletPadEvent::Ring(event: &TabletPadRingEvent) => event.context(),
149 TabletPadEvent::Strip(event: &TabletPadStripEvent) => event.context(),
150 #[cfg(feature = "libinput_1_15")]
151 TabletPadEvent::Key(event: &TabletPadKeyEvent) => event.context(),
152 }
153 }
154}
155
156ffi_event_struct!(
157/// A button pressed on a device with the `DeviceCapability::TabletPad`
158/// capability.
159///
160/// This event is not to be confused with the button events emitted by tools
161/// on a tablet. See `TabletToolButtonEvent`.
162struct TabletPadButtonEvent, ffi::libinput_event_tablet_pad, ffi::libinput_event_tablet_pad_get_base_event);
163
164impl TabletPadButtonEvent {
165 ffi_func!(
166 /// Return the button number that triggered this event, starting at 0.
167 ///
168 /// Note that the number returned is a generic sequential button number and
169 /// not a semantic button code as defined in linux/input.h.
170 /// [See Tablet pad button numbers](https://wayland.freedesktop.org/libinput/doc/latest/tablet-support.html#tablet-pad-buttons)
171 /// for more details.
172 pub fn button_number, ffi::libinput_event_tablet_pad_get_button_number, u32);
173
174 /// Return the button state of the event.
175 pub fn button_state(&self) -> ButtonState {
176 match unsafe { ffi::libinput_event_tablet_pad_get_button_state(self.as_raw_mut()) } {
177 ffi::libinput_button_state_LIBINPUT_BUTTON_STATE_PRESSED => ButtonState::Pressed,
178 ffi::libinput_button_state_LIBINPUT_BUTTON_STATE_RELEASED => ButtonState::Released,
179 _ => panic!("libinput returned invalid 'libinput_button_state'"),
180 }
181 }
182}
183
184/// The source for a `TabletPadRingEvent` event.
185#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
186pub enum RingAxisSource {
187 /// An unknown source
188 Unknown,
189 /// Finger source
190 Finger,
191}
192
193ffi_event_struct!(
194/// A status change on a tablet ring with the `DeviceCapability::TabletPad`
195/// capability.
196struct TabletPadRingEvent, ffi::libinput_event_tablet_pad, ffi::libinput_event_tablet_pad_get_base_event);
197
198impl TabletPadRingEvent {
199 ffi_func!(
200 /// Returns the number of the ring that has changed state, with 0 being the
201 /// first ring.
202 ///
203 /// On tablets with only one ring, this function always returns 0.
204 pub fn number, ffi::libinput_event_tablet_pad_get_ring_number, u32);
205 ffi_func!(
206 /// Returns the current position of the ring, in degrees counterclockwise from
207 /// the northern-most point of the ring in the tablet's current logical
208 /// orientation.
209 ///
210 /// If the source is `RingAxisSource::Finger`, libinput sends a terminating
211 /// event with a ring value of -1 when the finger is lifted from the ring. A
212 /// caller may use this information to e.g. determine if kinetic scrolling
213 /// should be triggered.
214 pub fn position, ffi::libinput_event_tablet_pad_get_ring_position, f64);
215
216 /// Returns the source of the interaction with the ring.
217 ///
218 /// If the source is `RingAxisSource::Finger`, libinput sends a ring position
219 /// value of -1 to terminate the current interaction.
220 pub fn source(&self) -> RingAxisSource {
221 match unsafe { ffi::libinput_event_tablet_pad_get_ring_source(self.as_raw_mut()) } {
222 ffi::libinput_tablet_pad_ring_axis_source_LIBINPUT_TABLET_PAD_RING_SOURCE_UNKNOWN => {
223 RingAxisSource::Unknown
224 }
225 ffi::libinput_tablet_pad_ring_axis_source_LIBINPUT_TABLET_PAD_RING_SOURCE_FINGER => {
226 RingAxisSource::Finger
227 }
228 _x => {
229 #[cfg(feature = "log")]
230 log::warn!("Unknown `RingAxisSource` returned by libinput: {}", _x);
231 RingAxisSource::Unknown
232 }
233 }
234 }
235}
236
237/// The source for a `TabletPadStripEvent` event.
238#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
239pub enum StripAxisSource {
240 /// An unknown source
241 Unknown,
242 /// Finger source
243 Finger,
244}
245
246ffi_event_struct!(
247/// A status change on a strip on a device with the `DeviceCapability::TabletPad`
248/// capability.
249struct TabletPadStripEvent, ffi::libinput_event_tablet_pad, ffi::libinput_event_tablet_pad_get_base_event);
250
251impl TabletPadStripEvent {
252 ffi_func!(
253 /// Returns the number of the strip that has changed state, with 0 being the
254 /// first strip.
255 ///
256 /// On tablets with only one strip, this function always returns 0.
257 pub fn number, ffi::libinput_event_tablet_pad_get_strip_number, u32);
258 ffi_func!(
259 /// Returns the current position of the strip, normalized to the range [0, 1],
260 /// with 0 being the top/left-most point in the tablet's current logical
261 /// orientation.
262 ///
263 /// If the source is `StripAxisSource::Finger`, libinput sends a terminating
264 /// event with a ring value of -1 when the finger is lifted from the ring. A
265 /// caller may use this information to e.g. determine if kinetic scrolling
266 /// should be triggered.
267 pub fn position, ffi::libinput_event_tablet_pad_get_strip_position, f64);
268
269 /// Returns the source of the interaction with the strip.
270 ///
271 /// If the source is `StripAxisSource::Finger`, libinput sends a strip
272 /// position value of -1 to terminate the current interaction
273 pub fn source(&self) -> StripAxisSource {
274 match unsafe { ffi::libinput_event_tablet_pad_get_strip_source(self.as_raw_mut()) } {
275 ffi::libinput_tablet_pad_strip_axis_source_LIBINPUT_TABLET_PAD_STRIP_SOURCE_UNKNOWN => {
276 StripAxisSource::Unknown
277 }
278 ffi::libinput_tablet_pad_strip_axis_source_LIBINPUT_TABLET_PAD_STRIP_SOURCE_FINGER => {
279 StripAxisSource::Finger
280 }
281 _x => {
282 #[cfg(feature = "log")]
283 log::warn!("Unknown `StripAxisSource` returned by libinput: {}", _x);
284 StripAxisSource::Unknown
285 }
286 }
287 }
288}
289
290#[cfg(feature = "libinput_1_15")]
291ffi_event_struct!(
292/// A key pressed on a device with the `DeviceCapability::TabletPad` capability.
293struct TabletPadKeyEvent, ffi::libinput_event_tablet_pad, ffi::libinput_event_tablet_pad_get_base_event);
294
295#[cfg(feature = "libinput_1_15")]
296impl TabletPadKeyEvent {
297 ffi_func!(
298 /// Return the key code that triggered this event, e.g. KEY_CONTROLPANEL.
299 /// The list of key codes is defined in linux/input-event-codes.h
300 pub fn key, ffi::libinput_event_tablet_pad_get_key, u32);
301
302 /// Return the key state of the event
303 pub fn key_state(&self) -> KeyState {
304 match unsafe { ffi::libinput_event_tablet_pad_get_key_state(self.as_raw() as *mut _) } {
305 ffi::libinput_key_state_LIBINPUT_KEY_STATE_PRESSED => KeyState::Pressed,
306 ffi::libinput_key_state_LIBINPUT_KEY_STATE_RELEASED => KeyState::Released,
307 _ => panic!("libinput returned invalid 'libinput_key_state'"),
308 }
309 }
310}
311