1 | //! Tablet pad event types |
2 | |
3 | pub use super::{keyboard::KeyState, pointer::ButtonState, EventTrait}; |
4 | use crate::{ffi, AsRaw, Context, FromRaw, Libinput}; |
5 | |
6 | mod mode_group; |
7 | pub use self::mode_group::*; |
8 | |
9 | /// Common functions all TabletPad-Events implement. |
10 | pub 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 | |
59 | impl<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 ] |
64 | pub 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 | |
91 | impl 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 | |
104 | impl 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 | |
132 | impl 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 | |
144 | impl 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 | |
156 | ffi_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`. |
162 | struct TabletPadButtonEvent, ffi::libinput_event_tablet_pad, ffi::libinput_event_tablet_pad_get_base_event); |
163 | |
164 | impl 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)] |
186 | pub enum RingAxisSource { |
187 | /// An unknown source |
188 | Unknown, |
189 | /// Finger source |
190 | Finger, |
191 | } |
192 | |
193 | ffi_event_struct!( |
194 | /// A status change on a tablet ring with the `DeviceCapability::TabletPad` |
195 | /// capability. |
196 | struct TabletPadRingEvent, ffi::libinput_event_tablet_pad, ffi::libinput_event_tablet_pad_get_base_event); |
197 | |
198 | impl 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)] |
239 | pub enum StripAxisSource { |
240 | /// An unknown source |
241 | Unknown, |
242 | /// Finger source |
243 | Finger, |
244 | } |
245 | |
246 | ffi_event_struct!( |
247 | /// A status change on a strip on a device with the `DeviceCapability::TabletPad` |
248 | /// capability. |
249 | struct TabletPadStripEvent, ffi::libinput_event_tablet_pad, ffi::libinput_event_tablet_pad_get_base_event); |
250 | |
251 | impl 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" )] |
291 | ffi_event_struct!( |
292 | /// A key pressed on a device with the `DeviceCapability::TabletPad` capability. |
293 | struct TabletPadKeyEvent, ffi::libinput_event_tablet_pad, ffi::libinput_event_tablet_pad_get_base_event); |
294 | |
295 | #[cfg (feature = "libinput_1_15" )] |
296 | impl 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 | |