input/device.rs
1// Allow unnecessary casts since ffi types may differ by C ABI
2// TODO Error type instead of `Result<_, ()>`
3// TODO Better way to handle `SendEventsMode::ENABLED` being 0?
4#![allow(
5 clippy::bad_bit_mask,
6 clippy::result_unit_err,
7 clippy::unnecessary_cast
8)]
9
10#[cfg(feature = "libinput_1_23")]
11use crate::accel_config::AccelConfig;
12use crate::{
13 event::{switch::Switch, tablet_pad::TabletPadModeGroup},
14 ffi, AsRaw, FromRaw, Libinput, Seat,
15};
16use bitflags::bitflags;
17use std::{
18 borrow::Cow,
19 ffi::{CStr, CString},
20};
21#[cfg(feature = "udev")]
22use udev::{
23 ffi::{udev as udev_context, udev_device, udev_device_get_udev, udev_ref},
24 Device as UdevDevice, FromRawWithContext as UdevFromRawWithContext,
25};
26
27/// Capabilities on a device.
28///
29/// A device may have one or more capabilities at a time, capabilities
30/// remain static for the lifetime of the device.
31#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
32#[non_exhaustive]
33pub enum DeviceCapability {
34 /// Keyboard capability
35 Keyboard,
36 /// Pointer capability
37 Pointer,
38 /// Touch capability
39 Touch,
40 /// TabletTool capability
41 TabletTool,
42 /// TabletPad capability
43 TabletPad,
44 /// Gesture capability
45 Gesture,
46 /// Switch capability
47 Switch,
48}
49
50/// Pointer Acceleration Profile
51#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
52#[non_exhaustive]
53pub enum AccelProfile {
54 /// A flat acceleration profile.
55 ///
56 /// Pointer motion is accelerated by a constant (device-specific)
57 /// factor, depending on the current speed.
58 Flat,
59 /// An adaptive acceleration profile.
60 ///
61 /// Pointer acceleration depends on the input speed. This is the
62 /// default profile for most devices.
63 Adaptive,
64 /// A custom acceleration profile.
65 ///
66 /// Device movement acceleration depends on user defined custom
67 /// acceleration functions for each movement type.
68 #[cfg(feature = "libinput_1_23")]
69 Custom,
70}
71
72/// Acceleration types are categories of movement by a device that may have
73/// specific acceleration functions applied. A device always supports the
74/// [`AccelType::Motion`] type (for regular pointer motion).
75/// Other types (e.g. scrolling) may be added in the future.
76///
77/// The special type [`AccelType::Fallback`] specifies the acceleration function
78/// to be moved for any movement produced by the device that does not have a
79/// specific acceleration type defined.
80///
81/// Use to specify the acceleration function type in [`AccelConfig::set_points`].
82///
83/// Each device implements a subset of those types, see a list of supported
84/// devices for each movement type definition.
85#[cfg(feature = "libinput_1_23")]
86#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
87#[non_exhaustive]
88pub enum AccelType {
89 /// The default acceleration type used as a fallback when other acceleration
90 /// types are not provided.
91 Fallback,
92 /// Acceleration type for regular pointer movement.
93 ///
94 /// This type is always supported.
95 Motion,
96 /// Acceleration type for scroll movement.
97 ///
98 /// This type is supported by mouse and touchpad.
99 Scroll,
100}
101
102/// The click method defines when to generate software-emulated
103/// buttons, usually on a device that does not have a specific
104/// physical button available.
105#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
106#[non_exhaustive]
107pub enum ClickMethod {
108 /// Use software-button areas (see [Clickfinger behavior](https://wayland.freedesktop.org/libinput/doc/latest/clickpad_softbuttons.html#clickfinger))
109 /// to generate button events.
110 ButtonAreas,
111 /// The number of fingers decides which button press to generate.
112 Clickfinger,
113}
114
115/// The scroll method of a device selects when to generate scroll axis
116/// events instead of pointer motion events.
117#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
118#[non_exhaustive]
119pub enum ScrollMethod {
120 /// Never send scroll events instead of pointer motion events.
121 ///
122 /// This has no effect on events generated by scroll wheels.
123 NoScroll,
124 /// Send scroll events when two fingers are logically down on the
125 /// device.
126 TwoFinger,
127 /// Send scroll events when a finger moves along the bottom or
128 /// right edge of a device.
129 Edge,
130 /// Send scroll events when a button is down and the device moves
131 /// along a scroll-capable axis.
132 OnButtonDown,
133}
134
135/// Errors returned when applying configuration settings.
136#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
137pub enum DeviceConfigError {
138 /// Configuration not available on this device.
139 Unsupported,
140 /// Invalid parameter range.
141 Invalid,
142}
143
144impl DeviceConfigError {
145 #[cfg(feature = "libinput_1_29")]
146 pub(crate) fn from_ffi(v: ffi::libinput_config_status) -> DeviceConfigResult {
147 match v {
148 ffi::libinput_config_status_LIBINPUT_CONFIG_STATUS_SUCCESS => Ok(()),
149 ffi::libinput_config_status_LIBINPUT_CONFIG_STATUS_UNSUPPORTED => {
150 Err(DeviceConfigError::Unsupported)
151 }
152 ffi::libinput_config_status_LIBINPUT_CONFIG_STATUS_INVALID => {
153 Err(DeviceConfigError::Invalid)
154 }
155 _ => unreachable!("libinput returned invalid 'libinput_config_status'"),
156 }
157 }
158}
159
160bitflags! {
161 /// The send-event mode of a device defines when a device may generate
162 /// events and pass those events to the caller.
163 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
164 pub struct SendEventsMode: u32 {
165 /// Send events from this device normally.
166 ///
167 /// This is a placeholder mode only, any device detected by
168 /// libinput can be enabled. Do not test for this value as bitmask.
169 const ENABLED = ffi::libinput_config_send_events_mode_LIBINPUT_CONFIG_SEND_EVENTS_ENABLED;
170 /// Do not send events through this device.
171 ///
172 /// Depending on the device, this may close all file descriptors
173 /// on the device or it may leave the file descriptors open and
174 /// route events through a different device.
175 ///
176 /// If this mode is set, other disable modes may be ignored.
177 /// For example, if both `Disabled` and `DisabledOnExternalMouse`
178 /// are set, the device remains disabled when all external pointer
179 /// devices are unplugged.
180 const DISABLED = ffi::libinput_config_send_events_mode_LIBINPUT_CONFIG_SEND_EVENTS_DISABLED;
181 /// If an external pointer device is plugged in, do not send
182 /// events from this device.
183 ///
184 /// This option may be available on built-in touchpads.
185 const DISABLED_ON_EXTERNAL_MOUSE = ffi::libinput_config_send_events_mode_LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE;
186 }
187}
188
189/// Map 1/2/3 finger tips to buttons
190#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
191#[non_exhaustive]
192pub enum TapButtonMap {
193 /// 1/2/3 finger tap maps to left/right/middle
194 LeftRightMiddle,
195 /// 1/2/3 finger tap maps to left/middle/right
196 LeftMiddleRight,
197}
198
199/// Map 1/2/3 finger clicks to buttons
200#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
201#[non_exhaustive]
202#[cfg(feature = "libinput_1_26")]
203pub enum ClickfingerButtonMap {
204 /// 1/2/3 finger click maps to left/right/middle
205 LeftRightMiddle,
206 /// 1/2/3 finger click maps to left/middle/right
207 LeftMiddleRight,
208}
209
210/// Drag lock state
211#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
212#[non_exhaustive]
213pub enum DragLockState {
214 /// Drag lock is to be disabled, or is currently disabled
215 Disabled,
216 /// Drag lock is to be enabled in timeout mode,
217 /// or is currently enabled in timeout mode
218 EnabledTimeout,
219 /// Drag lock is to be enabled in sticky mode,
220 /// or is currently enabled in sticky mode
221 #[cfg(feature = "libinput_1_27")]
222 EnabledSticky,
223}
224
225/// A config status to distinguish or set 3-finger dragging on a device.
226#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
227#[non_exhaustive]
228#[cfg(feature = "libinput_1_28")]
229pub enum ThreeFingerDragState {
230 /// Drag is to be disabled, or is currently disabled
231 Disabled,
232 /// Drag is to be enabled for 3 fingers, or is currently enabled
233 EnabledThreeFinger,
234 /// Drag is to be enabled for 4 fingers, or is currently enabled
235 EnabledFourFinger,
236}
237
238/// Whenever scroll button lock is enabled or not
239#[cfg(feature = "libinput_1_15")]
240#[allow(missing_docs)]
241#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
242pub enum ScrollButtonLockState {
243 Disabled,
244 Enabled,
245}
246
247/// Result returned when applying configuration settings.
248pub type DeviceConfigResult = Result<(), DeviceConfigError>;
249
250bitflags! {
251 /// Mask reflecting LEDs on a device.
252 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
253 pub struct Led: u32 {
254 /// Num Lock Led
255 const NUMLOCK = ffi::libinput_led_LIBINPUT_LED_NUM_LOCK;
256 /// Caps Lock Led
257 const CAPSLOCK = ffi::libinput_led_LIBINPUT_LED_CAPS_LOCK;
258 /// Scroll Lock Led
259 const SCROLLLOCK = ffi::libinput_led_LIBINPUT_LED_SCROLL_LOCK;
260 /// Compose Key Led
261 #[cfg(feature = "libinput_1_26")]
262 const COMPOSE = ffi::libinput_led_LIBINPUT_LED_COMPOSE;
263 /// Kana Key Led
264 #[cfg(feature = "libinput_1_26")]
265 const KANA = ffi::libinput_led_LIBINPUT_LED_KANA;
266 }
267}
268
269/// Describes a rectangle to configure a device’s area, see [`Device::config_area_set_rectangle`].
270///
271/// This struct describes a rectangle via the upper left points (x1, y1) and the lower right point (x2, y2).
272///
273/// All arguments are normalized to the range [0.0, 1.0] to represent the corresponding proportion of the device’s width and height, respectively. A rectangle covering the whole device thus comprises of the points (0.0, 0.0) and (1.0, 1.0).
274///
275/// The conditions x1 < x2 and y1 < y2 must be true.
276#[derive(Debug, Copy, Clone, PartialEq)]
277#[cfg(feature = "libinput_1_27")]
278pub struct AreaRectangle {
279 /// x1 coordinate
280 pub x1: f64,
281 /// y1 coordinate
282 pub y1: f64,
283 /// x2 coordinate
284 pub x2: f64,
285 /// y2 coordinate
286 pub y2: f64,
287}
288
289#[cfg(feature = "libinput_1_27")]
290impl From<AreaRectangle> for ffi::libinput_config_area_rectangle {
291 fn from(rect: AreaRectangle) -> Self {
292 input_sys::libinput_config_area_rectangle {
293 x1: rect.x1,
294 y1: rect.y1,
295 x2: rect.x2,
296 y2: rect.y2,
297 }
298 }
299}
300
301#[cfg(feature = "libinput_1_27")]
302impl From<ffi::libinput_config_area_rectangle> for AreaRectangle {
303 fn from(rect: ffi::libinput_config_area_rectangle) -> Self {
304 AreaRectangle {
305 x1: rect.x1,
306 y1: rect.y1,
307 x2: rect.x2,
308 y2: rect.y2,
309 }
310 }
311}
312
313ffi_ref_struct!(
314/// Device group
315///
316/// Some physical devices like graphics tablets are represented by
317/// multiple kernel devices and thus by multiple `Device`s.
318///
319/// libinput assigns these devices to the same `DeviceGroup` allowing
320/// the caller to identify such devices and adjust configuration
321/// settings accordingly. For example, setting a tablet to left-handed
322/// often means turning it upside down. A touch device on the same
323/// tablet would need to be turned upside down too to work correctly.
324///
325/// All devices are part of a device group though for most devices the
326/// group will be a singleton. A device is assigned to a device group
327/// on `DeviceAddedEvent` and removed from that group on
328/// `DeviceRemovedEvent`. It is up to the caller to track how many
329/// devices are in each device group.
330///
331/// Device groups do not get re-used once the last device in the group
332/// was removed, i.e. unplugging and re-plugging a physical device
333/// with grouped devices will return a different device group after
334/// every unplug.
335///
336/// Device groups are assigned based on the LIBINPUT_DEVICE_GROUP udev
337/// property, see [Static device configuration](https://wayland.freedesktop.org/libinput/doc/latest/udev_config.html) via udev.
338struct DeviceGroup, ffi::libinput_device_group, ffi::libinput_device_group_ref, ffi::libinput_device_group_unref);
339
340ffi_ref_struct!(
341/// Representation of a single input device as seen by the kernel.
342///
343/// A single physical device might consist out of multiple input
344/// devices like a keyboard-touchpad combination. See `DeviceGroup`
345/// if you want to track such combined physical devices.
346struct Device, ffi::libinput_device, ffi::libinput_device_ref, ffi::libinput_device_unref);
347
348impl Device {
349 /// Get the libinput context from the device.
350 pub fn context(&self) -> Libinput {
351 self.context.clone()
352 }
353
354 /// Get the device group this device is assigned to.
355 ///
356 /// Some physical devices like graphics tablets are represented by
357 /// multiple kernel devices and thus by multiple `Device`s.
358 ///
359 /// libinput assigns these devices to the same `DeviceGroup`
360 /// allowing the caller to identify such devices and adjust
361 /// configuration settings accordingly. For example, setting a
362 /// tablet to left-handed often means turning it upside down. A
363 /// touch device on the same tablet would need to be turned upside
364 /// down too to work correctly.
365 ///
366 /// All devices are part of a device group though for most devices
367 /// the group will be a singleton. A device is assigned to a
368 /// device group on `DeviceAddedEvent` and removed from that group
369 /// on `DeviceRemovedEvent`. It is up to the caller to track how
370 /// many devices are in each device group.
371 ///
372 /// Device groups do not get re-used once the last device in the
373 /// group was removed, i.e. unplugging and re-plugging a physical
374 /// device with grouped devices will return a different device
375 /// group after every unplug.
376 ///
377 /// Device groups are assigned based on the `LIBINPUT_DEVICE_GROUP`
378 /// udev property, see [Static device configuration](https://wayland.freedesktop.org/libinput/doc/latest/udev_config.html) via udev.
379 pub fn device_group(&self) -> DeviceGroup {
380 unsafe {
381 DeviceGroup::from_raw(
382 ffi::libinput_device_get_device_group(self.as_raw_mut()),
383 &self.context,
384 )
385 }
386 }
387
388 /// Get the system name of the device.
389 ///
390 /// To get the descriptive device name, use `name`.
391 pub fn sysname(&self) -> &str {
392 unsafe {
393 CStr::from_ptr(ffi::libinput_device_get_sysname(self.as_raw_mut()))
394 .to_str()
395 .expect("Device sysname is no valid utf8")
396 }
397 }
398
399 /// The descriptive device name as advertised by the kernel and/or
400 /// the hardware itself.
401 ///
402 /// To get the sysname for this device, use `sysname`.
403 pub fn name(&self) -> Cow<'_, str> {
404 unsafe {
405 CStr::from_ptr(ffi::libinput_device_get_name(self.as_raw_mut())).to_string_lossy()
406 }
407 }
408
409 /// A device may be mapped to a single output, or all available
410 /// outputs.
411 ///
412 /// If a device is mapped to a single output only, a relative
413 /// device may not move beyond the boundaries of this output. An
414 /// absolute device has its input coordinates mapped to the
415 /// extents of this output.
416 pub fn output_name(&self) -> Option<Cow<'_, str>> {
417 unsafe {
418 let ptr = ffi::libinput_device_get_output_name(self.as_raw_mut());
419 if !ptr.is_null() {
420 Some(CStr::from_ptr(ptr).to_string_lossy())
421 } else {
422 None
423 }
424 }
425 }
426
427 ffi_func!(
428 /// Get the product ID for this device.
429 pub fn id_product, ffi::libinput_device_get_id_product, u32);
430
431 #[cfg(feature = "libinput_1_26")]
432 ffi_func!(
433 /// Get the bus type ID for this device.
434 pub fn id_bustype, ffi::libinput_device_get_id_bustype, u32);
435
436 ffi_func!(
437 /// Get the vendor ID for this device.
438 pub fn id_vendor, ffi::libinput_device_get_id_vendor, u32);
439
440 /// Get the seat associated with this input device, see
441 /// [Seats](https://wayland.freedesktop.org/libinput/doc/latest/seats.html)
442 /// for details.
443 ///
444 /// A seat can be uniquely identified by the physical and logical
445 /// seat name. There will ever be only one seat instance with a
446 /// given physical and logical seat name pair at any given time,
447 /// but if no external reference is kept, it may be destroyed if
448 /// no device belonging to it is left.
449 pub fn seat(&self) -> Seat {
450 unsafe {
451 Seat::from_raw(
452 ffi::libinput_device_get_seat(self.as_raw_mut()),
453 &self.context,
454 )
455 }
456 }
457
458 /// Change the logical seat associated with this device by removing the device and adding it to the new seat.
459 ///
460 /// This command is identical to physically unplugging the device,
461 /// then re-plugging it as a member of the new seat. libinput will
462 /// generate a `DeviceRemovedEvent` event and this `Device` is
463 /// considered removed from the context; it will not generate
464 /// further events and will be freed when it goes out of scope.
465 /// A `DeviceAddedEvent` event is generated with a new `Device`
466 /// handle. It is the caller's responsibility to update references
467 /// to the new device accordingly.
468 ///
469 /// If the logical seat name already exists in the device's
470 /// physical seat, the device is added to this seat. Otherwise, a
471 /// new seat is created.
472 ///
473 /// ## Note
474 /// This change applies to this device until removal or `suspend`,
475 /// whichever happens earlier.
476 pub fn set_seat_logical_name(&mut self, name: &str) -> Result<(), ()> {
477 let name = CString::new(name).expect("New logical_seat name contained a null-byte");
478 unsafe {
479 if ffi::libinput_device_set_seat_logical_name(self.as_raw_mut(), name.as_ptr()) == 0 {
480 Ok(())
481 } else {
482 Err(())
483 }
484 }
485 }
486
487 /// Return a udev handle to the device that is this libinput
488 /// device, if any.
489 ///
490 /// Some devices may not have a udev device, or the udev device
491 /// may be unobtainable. This function returns `None` if no udev
492 /// device was available.
493 ///
494 /// Calling this function multiple times for the same device may
495 /// not return the same udev handle each time.
496 ///
497 /// # Safety
498 ///
499 /// The result of this function is not definied if the passed udev `Context`
500 /// is not the same as the one the libinput `Context` was created from.
501 #[cfg(feature = "udev")]
502 pub unsafe fn udev_device(&self) -> Option<UdevDevice> {
503 let dev: *mut udev_device = ffi::libinput_device_get_udev_device(self.ffi) as *mut _;
504 if dev.is_null() {
505 None
506 } else {
507 // We have to ref the returned udev context as udev_device_get_udev does not
508 // increase the ref_count but dropping a UdevDevice will unref it
509 let ctx: *mut udev_context = udev_ref(udev_device_get_udev(dev));
510 Some(UdevDevice::from_raw_with_context(ctx, dev))
511 }
512 }
513
514 /// Update the LEDs on the device, if any.
515 ///
516 /// If the device does not have LEDs, or does not have one or more
517 /// of the LEDs given in the mask, this function does nothing.
518 ///
519 /// ## Arguments
520 ///
521 /// leds: Leds to turn on
522 ///
523 /// Missing `Led`s will be turned off.
524 /// The slice is interpreted as a bitmap.
525 pub fn led_update(&mut self, leds: Led) {
526 unsafe { ffi::libinput_device_led_update(self.as_raw_mut(), leds.bits()) }
527 }
528
529 /// Check if the given device has the specified capability.
530 pub fn has_capability(&self, cap: DeviceCapability) -> bool {
531 unsafe {
532 ffi::libinput_device_has_capability(
533 self.as_raw_mut(),
534 match cap {
535 DeviceCapability::Keyboard => {
536 ffi::libinput_device_capability_LIBINPUT_DEVICE_CAP_KEYBOARD
537 }
538 DeviceCapability::Pointer => {
539 ffi::libinput_device_capability_LIBINPUT_DEVICE_CAP_POINTER
540 }
541 DeviceCapability::Touch => {
542 ffi::libinput_device_capability_LIBINPUT_DEVICE_CAP_TOUCH
543 }
544 DeviceCapability::TabletTool => {
545 ffi::libinput_device_capability_LIBINPUT_DEVICE_CAP_TABLET_TOOL
546 }
547 DeviceCapability::TabletPad => {
548 ffi::libinput_device_capability_LIBINPUT_DEVICE_CAP_TABLET_PAD
549 }
550 DeviceCapability::Gesture => {
551 ffi::libinput_device_capability_LIBINPUT_DEVICE_CAP_GESTURE
552 }
553 DeviceCapability::Switch => {
554 ffi::libinput_device_capability_LIBINPUT_DEVICE_CAP_SWITCH
555 }
556 },
557 ) != 0
558 }
559 }
560
561 /// Get the physical size of a device in mm, where meaningful.
562 ///
563 /// This function only succeeds on devices with the required data,
564 /// i.e. tablets, touchpads and touchscreens.
565 pub fn size(&self) -> Option<(f64, f64)> {
566 let mut width = 0.0;
567 let mut height = 0.0;
568
569 match unsafe {
570 ffi::libinput_device_get_size(
571 self.as_raw_mut(),
572 &mut width as *mut _,
573 &mut height as *mut _,
574 )
575 } {
576 0 => Some((width, height)),
577 _ => None,
578 }
579 }
580
581 /// Check if a `DeviceCapability::Pointer` device has a button
582 /// with the given code (see linux/input.h).
583 pub fn pointer_has_button(&self, button: u32) -> Result<bool, ()> {
584 match unsafe { ffi::libinput_device_pointer_has_button(self.as_raw_mut(), button) } {
585 1 => Ok(true),
586 0 => Ok(false),
587 -1 => Err(()),
588 _ => unreachable!(),
589 }
590 }
591
592 /// Check if a `DeviceCapability::Keyboard` device has a key with
593 /// the given code (see linux/input.h).
594 pub fn keyboard_has_key(&self, key: u32) -> Result<bool, ()> {
595 match unsafe { ffi::libinput_device_keyboard_has_key(self.as_raw_mut(), key) } {
596 1 => Ok(true),
597 0 => Ok(false),
598 -1 => Err(()),
599 _ => unreachable!(),
600 }
601 }
602
603 /// Check if a `DeviceCapability::Switch` device has a switch of the
604 /// given type.
605 pub fn switch_has_switch(&self, switch: Switch) -> Result<bool, ()> {
606 match unsafe { ffi::libinput_device_switch_has_switch(self.as_raw_mut(), switch as u32) } {
607 1 => Ok(true),
608 0 => Ok(false),
609 -1 => Err(()),
610 _ => unreachable!(),
611 }
612 }
613
614 ffi_func!(
615 /// Return the number of buttons on a device with the
616 /// `DeviceCapability::TabletPad` capability.
617 ///
618 /// Buttons on a pad device are numbered sequentially, see Tablet
619 /// pad button numbers for details.
620 pub fn tablet_pad_number_of_buttons, ffi::libinput_device_tablet_pad_get_num_buttons, i32);
621 ffi_func!(
622 /// Return the number of rings a device with the
623 /// `DeviceCapability::TabletPad` capability provides.
624 pub fn tablet_pad_number_of_rings, ffi::libinput_device_tablet_pad_get_num_rings, i32);
625 ffi_func!(
626 /// Return the number of strips a device with the
627 /// `DeviceCapability::TabletPad` capability provides.
628 pub fn tablet_pad_number_of_strips, ffi::libinput_device_tablet_pad_get_num_strips, i32);
629 ffi_func!(
630 /// Most devices only provide a single mode group, however devices
631 /// such as the Wacom Cintiq 22HD provide two mode groups.
632 ///
633 /// If multiple mode groups are available, a caller should use
634 /// `TabletPadModeGroup::has_button`,
635 /// `TabletPadModeGroup::has_ring`,
636 /// `TabletPadModeGroup::has_dial` (since libinput 1.26.0) and
637 /// `TabletPadModeGroup::has_strip()` to associate each button,
638 /// ring and strip with the correct mode group.
639 pub fn tablet_pad_number_of_mode_groups, ffi::libinput_device_tablet_pad_get_num_mode_groups, i32);
640
641 /// Return the current mode this mode group is in.
642 ///
643 /// Note that the returned mode is the mode valid as of completing
644 /// the last `dispatch`. The returned mode may thus be
645 /// different than the mode returned by
646 /// `TabletPadEventTrait::mode`.
647 ///
648 /// For example, if the mode was toggled three times between the
649 /// call to `dispatch`, this function returns the third mode but
650 /// the events in the event queue will return the modes 1, 2 and
651 /// 3, respectively.
652 pub fn tablet_pad_mode_group(&self, index: u32) -> Option<TabletPadModeGroup> {
653 let ptr =
654 unsafe { ffi::libinput_device_tablet_pad_get_mode_group(self.as_raw_mut(), index) };
655 if ptr.is_null() {
656 None
657 } else {
658 Some(unsafe { TabletPadModeGroup::from_raw(ptr, &self.context) })
659 }
660 }
661
662 /// Check if a `DeviceCapability::TabletPad`-device has a key with the given code (see linux/input-event-codes.h).
663 ///
664 /// ## Returns
665 /// - `Some(true)` if it has the requested key
666 /// - `Some(false)` if it has not
667 /// - `None` on error (no TabletPad device)
668 #[cfg(feature = "libinput_1_15")]
669 pub fn tablet_pad_has_key(&self, code: u32) -> Option<bool> {
670 match unsafe { ffi::libinput_device_tablet_pad_has_key(self.as_raw_mut(), code) } {
671 -1 => None,
672 0 => Some(false),
673 1 => Some(true),
674 _ => panic!(
675 "libinput returned invalid return code for libinput_device_tablet_pad_has_key"
676 ),
677 }
678 }
679
680 /// Check how many touches a `DeviceCapability::Touch`-exposing Device supports simultaneously.
681 ///
682 /// ## Returns
683 /// - `Some(n)` amount of touches
684 /// - `Some(0)` if unknown
685 /// - `None` on error (no touch device)
686 #[cfg(feature = "libinput_1_11")]
687 pub fn touch_count(&mut self) -> Option<u32> {
688 match unsafe { ffi::libinput_device_touch_get_touch_count(self.as_raw_mut()) } {
689 -1 => None,
690 n => Some(n as u32),
691 }
692 }
693
694 /// Apply this pointer acceleration configuration to the device.
695 ///
696 /// This changes the device’s pointer acceleration method to the method
697 /// given in [`AccelConfig::new`] and applies all other configuration
698 /// settings.
699 #[cfg(feature = "libinput_1_23")]
700 pub fn config_accel_apply(&self, accel_config: AccelConfig) -> DeviceConfigResult {
701 match unsafe {
702 ffi::libinput_device_config_accel_apply(self.as_raw_mut(), accel_config.as_raw_mut())
703 } {
704 ffi::libinput_config_status_LIBINPUT_CONFIG_STATUS_SUCCESS => Ok(()),
705 ffi::libinput_config_status_LIBINPUT_CONFIG_STATUS_UNSUPPORTED => {
706 Err(DeviceConfigError::Unsupported)
707 }
708 ffi::libinput_config_status_LIBINPUT_CONFIG_STATUS_INVALID => {
709 Err(DeviceConfigError::Invalid)
710 }
711 _ => panic!("libinput returned invalid 'libinput_config_status'"),
712 }
713 }
714
715 /// Return the default pointer acceleration profile for this
716 /// pointer device.
717 pub fn config_accel_default_profile(&self) -> Option<AccelProfile> {
718 match unsafe { ffi::libinput_device_config_accel_get_default_profile(self.as_raw_mut()) } {
719 ffi::libinput_config_accel_profile_LIBINPUT_CONFIG_ACCEL_PROFILE_NONE => None,
720 ffi::libinput_config_accel_profile_LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT => {
721 Some(AccelProfile::Flat)
722 }
723 ffi::libinput_config_accel_profile_LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE => {
724 Some(AccelProfile::Adaptive)
725 }
726 #[cfg(feature = "libinput_1_23")]
727 ffi::libinput_config_accel_profile_LIBINPUT_CONFIG_ACCEL_PROFILE_CUSTOM => {
728 Some(AccelProfile::Custom)
729 }
730 _x => {
731 #[cfg(feature = "log")]
732 log::warn!(
733 "Unknown AccelProfile ({}). Unsupported libinput version?",
734 _x
735 );
736 None
737 }
738 }
739 }
740
741 /// Get the current pointer acceleration profile for this pointer
742 /// device.
743 pub fn config_accel_profile(&self) -> Option<AccelProfile> {
744 match unsafe { ffi::libinput_device_config_accel_get_profile(self.as_raw_mut()) } {
745 ffi::libinput_config_accel_profile_LIBINPUT_CONFIG_ACCEL_PROFILE_NONE => None,
746 ffi::libinput_config_accel_profile_LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT => {
747 Some(AccelProfile::Flat)
748 }
749 ffi::libinput_config_accel_profile_LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE => {
750 Some(AccelProfile::Adaptive)
751 }
752 #[cfg(feature = "libinput_1_23")]
753 ffi::libinput_config_accel_profile_LIBINPUT_CONFIG_ACCEL_PROFILE_CUSTOM => {
754 Some(AccelProfile::Custom)
755 }
756 _x => {
757 #[cfg(feature = "log")]
758 log::warn!(
759 "Unknown AccelProfile ({}). Unsupported libinput version?",
760 _x
761 );
762 None
763 }
764 }
765 }
766
767 /// Returns a bitmask of the configurable acceleration modes
768 /// available on this device.
769 pub fn config_accel_profiles(&self) -> Vec<AccelProfile> {
770 let mut profiles = Vec::new();
771 let bitmask = unsafe { ffi::libinput_device_config_accel_get_profiles(self.as_raw_mut()) };
772 if bitmask & ffi::libinput_config_accel_profile_LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT as u32
773 != 0
774 {
775 profiles.push(AccelProfile::Flat);
776 }
777 if bitmask
778 & ffi::libinput_config_accel_profile_LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE as u32
779 != 0
780 {
781 profiles.push(AccelProfile::Adaptive);
782 }
783 #[cfg(feature = "libinput_1_23")]
784 if bitmask & ffi::libinput_config_accel_profile_LIBINPUT_CONFIG_ACCEL_PROFILE_CUSTOM as u32
785 != 0
786 {
787 profiles.push(AccelProfile::Custom);
788 }
789 profiles
790 }
791
792 /// Set the pointer acceleration profile of this pointer device to
793 /// the given mode.
794 pub fn config_accel_set_profile(&mut self, profile: AccelProfile) -> DeviceConfigResult {
795 match unsafe {
796 ffi::libinput_device_config_accel_set_profile(
797 self.as_raw_mut(),
798 match profile {
799 AccelProfile::Flat => {
800 ffi::libinput_config_accel_profile_LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT
801 }
802 AccelProfile::Adaptive => {
803 ffi::libinput_config_accel_profile_LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE
804 }
805 #[cfg(feature = "libinput_1_23")]
806 AccelProfile::Custom => {
807 ffi::libinput_config_accel_profile_LIBINPUT_CONFIG_ACCEL_PROFILE_CUSTOM
808 }
809 },
810 )
811 } {
812 ffi::libinput_config_status_LIBINPUT_CONFIG_STATUS_SUCCESS => Ok(()),
813 ffi::libinput_config_status_LIBINPUT_CONFIG_STATUS_UNSUPPORTED => {
814 Err(DeviceConfigError::Unsupported)
815 }
816 ffi::libinput_config_status_LIBINPUT_CONFIG_STATUS_INVALID => {
817 Err(DeviceConfigError::Invalid)
818 }
819 _ => panic!("libinput returned invalid 'libinput_config_status'"),
820 }
821 }
822
823 ffi_func!(
824 /// Return the default speed setting for this device, normalized
825 /// to a range of [-1, 1].
826 pub fn config_accel_default_speed, ffi::libinput_device_config_accel_get_default_speed, f64);
827 ffi_func!(
828 /// Get the current pointer acceleration setting for this pointer
829 /// device.
830 ///
831 /// The returned value is normalized to a range of [-1, 1]. See
832 /// `config_accel_set_speed` for details.
833 pub fn config_accel_speed, ffi::libinput_device_config_accel_get_speed, f64);
834
835 /// Set the pointer acceleration speed of this pointer device
836 /// within a range of [-1, 1], where 0 is the default acceleration
837 /// for this device, -1 is the slowest acceleration and 1 is the
838 /// maximum acceleration available on this device.
839 ///
840 /// The actual pointer acceleration mechanism is
841 /// implementation-dependent, as is the number of steps available
842 /// within the range. libinput picks the semantically closest
843 /// acceleration step if the requested value does not match a
844 /// discrete setting.
845 pub fn config_accel_set_speed(&mut self, speed: f64) -> DeviceConfigResult {
846 match unsafe { ffi::libinput_device_config_accel_set_speed(self.as_raw_mut(), speed) } {
847 ffi::libinput_config_status_LIBINPUT_CONFIG_STATUS_SUCCESS => Ok(()),
848 ffi::libinput_config_status_LIBINPUT_CONFIG_STATUS_UNSUPPORTED => {
849 Err(DeviceConfigError::Unsupported)
850 }
851 ffi::libinput_config_status_LIBINPUT_CONFIG_STATUS_INVALID => {
852 Err(DeviceConfigError::Invalid)
853 }
854 _ => panic!("libinput returned invalid 'libinput_config_status'"),
855 }
856 }
857
858 ffi_func!(
859 /// Check if a device uses libinput-internal pointer-acceleration.
860 pub fn config_accel_is_available, ffi::libinput_device_config_accel_is_available, bool);
861
862 /// Return the default calibration matrix for this device.
863 ///
864 /// On most devices, this is the identity matrix. If the udev
865 /// property `LIBINPUT_CALIBRATION_MATRIX` is set on the respective u
866 /// dev device, that property's value becomes the default matrix,
867 /// see [Static device configuration via udev](https://wayland.freedesktop.org/libinput/doc/latest/udev_config.html).
868 pub fn config_calibration_default_matrix(&self) -> Option<[f32; 6]> {
869 let mut matrix = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0];
870 if unsafe {
871 ffi::libinput_device_config_calibration_get_default_matrix(
872 self.as_raw_mut(),
873 matrix.as_mut_ptr(),
874 ) != 0
875 } {
876 Some(matrix)
877 } else {
878 None
879 }
880 }
881
882 /// Return the current calibration matrix for this device.
883 pub fn config_calibration_matrix(&self) -> Option<[f32; 6]> {
884 let mut matrix = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0];
885 if unsafe {
886 ffi::libinput_device_config_calibration_get_matrix(
887 self.as_raw_mut(),
888 matrix.as_mut_ptr(),
889 ) != 0
890 } {
891 Some(matrix)
892 } else {
893 None
894 }
895 }
896
897 ffi_func!(
898 /// Check if the device can be calibrated via a calibration matrix.
899 pub fn config_calibration_has_matrix, ffi::libinput_device_config_calibration_has_matrix, bool);
900
901 #[cfg(feature = "libinput_1_27")]
902 ffi_func!(
903 /// Check if the device can change its logical input area via a rectangle.
904 pub fn config_area_has_rectangle, ffi::libinput_device_config_area_has_rectangle, bool);
905
906 /// Set the given rectangle as the logical input area of this device.
907 ///
908 /// Future interactions by a tablet tool on this devices are scaled to only
909 /// consider events within this logical input area - as if the logical input
910 /// area were the available physical area.
911 ///
912 /// The coordinates of the rectangle represent the proportion of the
913 /// available maximum physical area, normalized to the range [0.0, 1.0].
914 /// For example, a rectangle with the two points 0.25, 0.5, 0.75, 1.0 adds
915 /// a 25% dead zone to the left and right and a 50% dead zone on the top:
916 ///
917 /// ```text
918 /// +----------------------------------+
919 /// | |
920 /// | 50% |
921 /// | |
922 /// | +-----------------+ |
923 /// | | | |
924 /// | 25% | | 25% |
925 /// | | | |
926 /// +--------+-----------------+-------+
927 /// ```
928 /// The area applies in the tablet’s current logical rotation, i.e. the
929 /// above example is always at the bottom of the tablet.
930 ///
931 /// Once applied, the logical area’s top-left coordinate (in the current
932 /// logical rotation) becomes the new offset (0/0) and the return values
933 /// of [`TabletToolEventTrait::x`](crate::event::tablet_tool::TabletToolEventTrait::x) and
934 /// [`TabletToolEventTrait::y`](crate::event::tablet_tool::TabletToolEventTrait::y)
935 /// are in relation to this new offset.
936 ///
937 /// Likewise, [`TabletToolEventTrait::x_transformed`](crate::event::tablet_tool::TabletToolEventTrait::x_transformed)
938 /// and [`TabletToolEventTrait::y_transformed`](crate::event::tablet_tool::TabletToolEventTrait::y_transformed)
939 /// represent the value scaled into the configured logical area.
940 ///
941 /// The return value of libinput_device_get_size() is not affected by the configured area.
942 ///
943 /// Changing the area may not take effect immediately, the device may wait until it is in a
944 /// neutral state before applying any changes.
945 #[cfg(feature = "libinput_1_27")]
946 pub fn config_area_set_rectangle(&self, area: AreaRectangle) -> DeviceConfigResult {
947 let area = area.into();
948 match unsafe {
949 ffi::libinput_device_config_area_set_rectangle(self.as_raw_mut(), &raw const area)
950 } {
951 ffi::libinput_config_status_LIBINPUT_CONFIG_STATUS_SUCCESS => Ok(()),
952 ffi::libinput_config_status_LIBINPUT_CONFIG_STATUS_UNSUPPORTED => {
953 Err(DeviceConfigError::Unsupported)
954 }
955 ffi::libinput_config_status_LIBINPUT_CONFIG_STATUS_INVALID => {
956 Err(DeviceConfigError::Invalid)
957 }
958 _ => panic!("libinput returned invalid 'libinput_config_status'"),
959 }
960 }
961
962 /// Return the current area rectangle for this device.
963 ///
964 /// The return value for a device that does not support area rectangles is
965 /// a rectangle with the points 0/0 and 1/1.
966 #[cfg(feature = "libinput_1_27")]
967 pub fn config_area_get_rectangle(&self) -> AreaRectangle {
968 unsafe { ffi::libinput_device_config_area_get_rectangle(self.as_raw_mut()) }.into()
969 }
970
971 /// Return the default area rectangle for this device.
972 ///
973 /// The return value for a device that does not support area rectangles is
974 /// a rectangle with the points 0/0 and 1/1.
975 #[cfg(feature = "libinput_1_27")]
976 pub fn config_area_get_default_rectangle(&self) -> AreaRectangle {
977 unsafe { ffi::libinput_device_config_area_get_default_rectangle(self.as_raw_mut()) }.into()
978 }
979
980 /// Apply the 3x3 transformation matrix to absolute device
981 /// coordinates.
982 ///
983 /// This matrix has no effect on relative events.
984 ///
985 /// Given a 6-element array [a, b, c, d, e, f], the matrix is
986 /// applied as
987 /// ```text
988 /// [ a b c ] [ x ]
989 /// [ d e f ] * [ y ]
990 /// [ 0 0 1 ] [ 1 ]
991 /// # *
992 /// ```
993 /// The translation component (c, f) is expected to be normalized
994 /// to the device coordinate range. For example, the matrix
995 /// ```text
996 /// [ 1 0 1 ]
997 /// [ 0 1 -1 ]
998 /// [ 0 0 1 ]
999 /// ```
1000 /// moves all coordinates by 1 device-width to the right and 1
1001 /// device-height up.
1002 ///
1003 /// The rotation matrix for rotation around the origin is defined
1004 /// as
1005 /// ```text
1006 /// [ cos(a) -sin(a) 0 ]
1007 /// [ sin(a) cos(a) 0 ]
1008 /// [ 0 0 1 ]
1009 /// ```
1010 /// Note that any rotation requires an additional translation
1011 /// component to translate the rotated coordinates back into the
1012 /// original device space. The rotation matrixes for 90, 180 and
1013 /// 270 degrees clockwise are:
1014 /// ```text
1015 /// 90 deg cw: 180 deg cw: 270 deg cw:
1016 /// [ 0 -1 1] [ -1 0 1] [ 0 1 0 ]
1017 /// [ 1 0 0] [ 0 -1 1] [ -1 0 1 ]
1018 /// [ 0 0 1] [ 0 0 1] [ 0 0 1 ]
1019 /// ```
1020 pub fn config_calibration_set_matrix(&mut self, matrix: [f32; 6]) -> DeviceConfigResult {
1021 match unsafe {
1022 ffi::libinput_device_config_calibration_set_matrix(self.as_raw_mut(), matrix.as_ptr())
1023 } {
1024 ffi::libinput_config_status_LIBINPUT_CONFIG_STATUS_SUCCESS => Ok(()),
1025 ffi::libinput_config_status_LIBINPUT_CONFIG_STATUS_UNSUPPORTED => {
1026 Err(DeviceConfigError::Unsupported)
1027 }
1028 ffi::libinput_config_status_LIBINPUT_CONFIG_STATUS_INVALID => {
1029 Err(DeviceConfigError::Invalid)
1030 }
1031 _ => panic!("libinput returned invalid 'libinput_config_status'"),
1032 }
1033 }
1034
1035 /// Get the default button click method for this device.
1036 ///
1037 /// The button click method defines when to generate
1038 /// software-emulated buttons, usually on a device that does not
1039 /// have a specific physical button available.
1040 pub fn config_click_default_method(&self) -> Option<ClickMethod> {
1041 match unsafe { ffi::libinput_device_config_click_get_default_method(self.as_raw_mut()) } {
1042 ffi::libinput_config_click_method_LIBINPUT_CONFIG_CLICK_METHOD_NONE => None,
1043 ffi::libinput_config_click_method_LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS => {
1044 Some(ClickMethod::ButtonAreas)
1045 }
1046 ffi::libinput_config_click_method_LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER => {
1047 Some(ClickMethod::Clickfinger)
1048 }
1049 _x => {
1050 #[cfg(feature = "log")]
1051 log::warn!(
1052 "Unknown ClickMethod ({}). Unsupported libinput version?",
1053 _x
1054 );
1055 None
1056 }
1057 }
1058 }
1059
1060 /// Get the button click method for this device.
1061 ///
1062 /// The button click method defines when to generate
1063 /// software-emulated buttons, usually on a device that does not
1064 /// have a specific physical button available.
1065 pub fn config_click_method(&self) -> Option<ClickMethod> {
1066 match unsafe { ffi::libinput_device_config_click_get_method(self.as_raw_mut()) } {
1067 ffi::libinput_config_click_method_LIBINPUT_CONFIG_CLICK_METHOD_NONE => None,
1068 ffi::libinput_config_click_method_LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS => {
1069 Some(ClickMethod::ButtonAreas)
1070 }
1071 ffi::libinput_config_click_method_LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER => {
1072 Some(ClickMethod::Clickfinger)
1073 }
1074 _x => {
1075 #[cfg(feature = "log")]
1076 log::warn!(
1077 "Unknown ClickMethod ({}). Unsupported libinput version?",
1078 _x
1079 );
1080 None
1081 }
1082 }
1083 }
1084
1085 /// Check which button click methods a device supports.
1086 ///
1087 /// The button click method defines when to generate
1088 /// software-emulated buttons, usually on a device that does not
1089 /// have a specific physical button available.
1090 pub fn config_click_methods(&self) -> Vec<ClickMethod> {
1091 let mut methods = Vec::new();
1092 let bitmask = unsafe { ffi::libinput_device_config_click_get_methods(self.as_raw_mut()) };
1093 if bitmask
1094 & ffi::libinput_config_click_method_LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER as u32
1095 != 0
1096 {
1097 methods.push(ClickMethod::Clickfinger);
1098 }
1099 if bitmask
1100 & ffi::libinput_config_click_method_LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS as u32
1101 != 0
1102 {
1103 methods.push(ClickMethod::ButtonAreas);
1104 }
1105 methods
1106 }
1107
1108 /// Set the button click method for this device.
1109 ///
1110 /// The button click method defines when to generate
1111 /// software-emulated buttons, usually on a device that does not
1112 /// have a specific physical button available.
1113 ///
1114 /// ## Note
1115 ///
1116 /// The selected click method may not take effect immediately. The
1117 /// device may require changing to a neutral state first before
1118 /// activating the new method.
1119 pub fn config_click_set_method(&mut self, method: ClickMethod) -> DeviceConfigResult {
1120 match unsafe {
1121 ffi::libinput_device_config_click_set_method(
1122 self.as_raw_mut(),
1123 match method {
1124 ClickMethod::ButtonAreas => {
1125 ffi::libinput_config_click_method_LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS
1126 }
1127 ClickMethod::Clickfinger => {
1128 ffi::libinput_config_click_method_LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER
1129 }
1130 },
1131 )
1132 } {
1133 ffi::libinput_config_status_LIBINPUT_CONFIG_STATUS_SUCCESS => Ok(()),
1134 ffi::libinput_config_status_LIBINPUT_CONFIG_STATUS_UNSUPPORTED => {
1135 Err(DeviceConfigError::Unsupported)
1136 }
1137 ffi::libinput_config_status_LIBINPUT_CONFIG_STATUS_INVALID => {
1138 Err(DeviceConfigError::Invalid)
1139 }
1140 _ => panic!("libinput returned invalid 'libinput_config_status'"),
1141 }
1142 }
1143
1144 /// Get the finger number to button number mapping for clickfinger.
1145 ///
1146 /// The return value for a device that does not support clickfinger is
1147 /// always [`ClickfingerButtonMap::LeftRightMiddle`].
1148 #[cfg(feature = "libinput_1_26")]
1149 pub fn config_click_clickfinger_default_button_map(&self) -> ClickfingerButtonMap {
1150 match unsafe {
1151 ffi::libinput_device_config_click_get_default_clickfinger_button_map(self.as_raw_mut())
1152 } {
1153 ffi::libinput_config_clickfinger_button_map_LIBINPUT_CONFIG_CLICKFINGER_MAP_LRM => {
1154 ClickfingerButtonMap::LeftRightMiddle
1155 }
1156 ffi::libinput_config_clickfinger_button_map_LIBINPUT_CONFIG_CLICKFINGER_MAP_LMR => {
1157 ClickfingerButtonMap::LeftMiddleRight
1158 }
1159 _ => panic!("libinput returned invalid 'libinput_config_tap_button_map'"),
1160 }
1161 }
1162
1163 /// Get the default finger number to button number mapping for clickfinger.
1164 ///
1165 /// The return value for a device that does not support clickfinger is
1166 /// always [`ClickfingerButtonMap::LeftRightMiddle`].
1167 #[cfg(feature = "libinput_1_26")]
1168 pub fn config_click_clickfinger_button_map(&self) -> ClickfingerButtonMap {
1169 match unsafe {
1170 ffi::libinput_device_config_click_get_clickfinger_button_map(self.as_raw_mut())
1171 } {
1172 ffi::libinput_config_clickfinger_button_map_LIBINPUT_CONFIG_CLICKFINGER_MAP_LRM => {
1173 ClickfingerButtonMap::LeftRightMiddle
1174 }
1175 ffi::libinput_config_clickfinger_button_map_LIBINPUT_CONFIG_CLICKFINGER_MAP_LMR => {
1176 ClickfingerButtonMap::LeftMiddleRight
1177 }
1178 _ => panic!("libinput returned invalid 'libinput_config_tap_button_map'"),
1179 }
1180 }
1181
1182 /// Set the finger number to button number mapping for clickfinger.
1183 ///
1184 /// The default mapping on most devices is to have a 1, 2 and 3 finger tap
1185 /// to map to the left, right and middle button, respectively. A device may
1186 /// permit changing the button mapping but disallow specific maps. In this
1187 /// case [`DeviceConfigError::Unsupported`] is returned, the caller is expected
1188 /// to handle this case correctly.
1189 ///
1190 /// Changing the button mapping may not take effect immediately, the device may
1191 /// wait until it is in a neutral state before applying any changes.
1192 #[cfg(feature = "libinput_1_26")]
1193 pub fn config_click_clickfinger_set_button_map(
1194 &self,
1195 map: ClickfingerButtonMap,
1196 ) -> DeviceConfigResult {
1197 match unsafe {
1198 ffi::libinput_device_config_click_set_clickfinger_button_map(self.as_raw_mut(), match map {
1199 ClickfingerButtonMap::LeftRightMiddle => ffi::libinput_config_clickfinger_button_map_LIBINPUT_CONFIG_CLICKFINGER_MAP_LRM,
1200 ClickfingerButtonMap::LeftMiddleRight => ffi::libinput_config_clickfinger_button_map_LIBINPUT_CONFIG_CLICKFINGER_MAP_LMR,
1201 })
1202 } {
1203 ffi::libinput_config_status_LIBINPUT_CONFIG_STATUS_SUCCESS => Ok(()),
1204 ffi::libinput_config_status_LIBINPUT_CONFIG_STATUS_UNSUPPORTED => {
1205 Err(DeviceConfigError::Unsupported)
1206 }
1207 ffi::libinput_config_status_LIBINPUT_CONFIG_STATUS_INVALID => {
1208 Err(DeviceConfigError::Invalid)
1209 }
1210 _ => panic!("libinput returned invalid 'libinput_config_status'"),
1211 }
1212 }
1213
1214 /// Check if the disable-while typing feature is enabled on this
1215 /// device by default.
1216 ///
1217 /// If the device does not support disable-while-typing, this
1218 /// function returns `false`.
1219 pub fn config_dwt_default_enabled(&self) -> bool {
1220 match unsafe { ffi::libinput_device_config_dwt_get_default_enabled(self.as_raw_mut()) } {
1221 ffi::libinput_config_dwt_state_LIBINPUT_CONFIG_DWT_ENABLED => true,
1222 ffi::libinput_config_dwt_state_LIBINPUT_CONFIG_DWT_DISABLED => false,
1223 _ => panic!("libinput returned invalid 'libinput_config_dwt_state'"),
1224 }
1225 }
1226
1227 /// Check if the disable-while typing feature is currently enabled
1228 /// on this device.
1229 ///
1230 /// If the device does not support disable-while-typing, this
1231 /// function returns `false`.
1232 pub fn config_dwt_enabled(&self) -> bool {
1233 match unsafe { ffi::libinput_device_config_dwt_get_enabled(self.as_raw_mut()) } {
1234 ffi::libinput_config_dwt_state_LIBINPUT_CONFIG_DWT_ENABLED => true,
1235 ffi::libinput_config_dwt_state_LIBINPUT_CONFIG_DWT_DISABLED => false,
1236 _ => panic!("libinput returned invalid 'libinput_config_dwt_state'"),
1237 }
1238 }
1239
1240 ffi_func!(
1241 /// Check if this device supports configurable
1242 /// disable-while-typing feature.
1243 ///
1244 /// This feature is usually available on built-in touchpads and
1245 /// disables the touchpad while typing. See [Disable-while-typing](https://wayland.freedesktop.org/libinput/doc/latest/palm_detection.html#disable-while-typing)
1246 /// for details.
1247 pub fn config_dwt_is_available, ffi::libinput_device_config_dwt_is_available, bool);
1248
1249 /// Enable or disable the disable-while-typing feature.
1250 ///
1251 /// When enabled, the device will be disabled while typing and
1252 /// for a short period after. See Disable-while-typing for
1253 /// details.
1254 ///
1255 /// ## Note
1256 ///
1257 /// Enabling or disabling disable-while-typing may not take
1258 /// effect immediately.
1259 pub fn config_dwt_set_enabled(&self, enabled: bool) -> DeviceConfigResult {
1260 match unsafe {
1261 ffi::libinput_device_config_dwt_set_enabled(
1262 self.as_raw_mut(),
1263 if enabled {
1264 ffi::libinput_config_dwt_state_LIBINPUT_CONFIG_DWT_ENABLED
1265 } else {
1266 ffi::libinput_config_dwt_state_LIBINPUT_CONFIG_DWT_DISABLED
1267 },
1268 )
1269 } {
1270 ffi::libinput_config_status_LIBINPUT_CONFIG_STATUS_SUCCESS => Ok(()),
1271 ffi::libinput_config_status_LIBINPUT_CONFIG_STATUS_UNSUPPORTED => {
1272 Err(DeviceConfigError::Unsupported)
1273 }
1274 ffi::libinput_config_status_LIBINPUT_CONFIG_STATUS_INVALID => {
1275 Err(DeviceConfigError::Invalid)
1276 }
1277 _ => panic!("libinput returned invalid 'libinput_config_status'"),
1278 }
1279 }
1280
1281 /// Check if the disable-while trackpointing feature is enabled on this
1282 /// device by default.
1283 ///
1284 /// If the device does not support disable-while-trackpointing, this
1285 /// function returns `false`.
1286 #[cfg(feature = "libinput_1_21")]
1287 pub fn config_dwtp_default_enabled(&self) -> bool {
1288 match unsafe { ffi::libinput_device_config_dwtp_get_default_enabled(self.as_raw_mut()) } {
1289 ffi::libinput_config_dwtp_state_LIBINPUT_CONFIG_DWTP_ENABLED => true,
1290 ffi::libinput_config_dwtp_state_LIBINPUT_CONFIG_DWTP_DISABLED => false,
1291 _ => panic!("libinput returned invalid 'libinput_config_dwtp_state'"),
1292 }
1293 }
1294
1295 /// Check if the disable-while trackpointing feature is currently enabled
1296 /// on this device.
1297 ///
1298 /// If the device does not support disable-while-trackpointing, this
1299 /// function returns `false`.
1300 #[cfg(feature = "libinput_1_21")]
1301 pub fn config_dwtp_enabled(&self) -> bool {
1302 match unsafe { ffi::libinput_device_config_dwtp_get_enabled(self.as_raw_mut()) } {
1303 ffi::libinput_config_dwtp_state_LIBINPUT_CONFIG_DWTP_ENABLED => true,
1304 ffi::libinput_config_dwtp_state_LIBINPUT_CONFIG_DWTP_DISABLED => false,
1305 _ => panic!("libinput returned invalid 'libinput_config_dwtp_state'"),
1306 }
1307 }
1308
1309 ffi_func!(
1310 /// Check if this device supports configurable
1311 /// disable-while-trackpointing feature.
1312 ///
1313 /// This feature is usually available on Thinkpads and
1314 /// disables the touchpad while using the trackpoint.
1315 #[cfg(feature = "libinput_1_21")]
1316 pub fn config_dwtp_is_available, ffi::libinput_device_config_dwtp_is_available, bool);
1317
1318 /// Enable or disable the disable-while-trackpointing feature.
1319 ///
1320 /// When enabled, the device will be disabled while using the trackpoint and
1321 /// for a short period after.
1322 ///
1323 /// ## Note
1324 ///
1325 /// Enabling or disabling disable-while-trackpointing may not take
1326 /// effect immediately.
1327 #[cfg(feature = "libinput_1_21")]
1328 pub fn config_dwtp_set_enabled(&self, enabled: bool) -> DeviceConfigResult {
1329 match unsafe {
1330 ffi::libinput_device_config_dwtp_set_enabled(
1331 self.as_raw_mut(),
1332 if enabled {
1333 ffi::libinput_config_dwtp_state_LIBINPUT_CONFIG_DWTP_ENABLED
1334 } else {
1335 ffi::libinput_config_dwtp_state_LIBINPUT_CONFIG_DWTP_DISABLED
1336 },
1337 )
1338 } {
1339 ffi::libinput_config_status_LIBINPUT_CONFIG_STATUS_SUCCESS => Ok(()),
1340 ffi::libinput_config_status_LIBINPUT_CONFIG_STATUS_UNSUPPORTED => {
1341 Err(DeviceConfigError::Unsupported)
1342 }
1343 ffi::libinput_config_status_LIBINPUT_CONFIG_STATUS_INVALID => {
1344 Err(DeviceConfigError::Invalid)
1345 }
1346 _ => panic!("libinput returned invalid 'libinput_config_status'"),
1347 }
1348 }
1349
1350 ffi_func!(
1351 /// Get the current left-handed configuration of the device.
1352 pub fn config_left_handed, ffi::libinput_device_config_left_handed_get, bool);
1353 ffi_func!(
1354 /// Get the default left-handed configuration of the device.
1355 pub fn config_left_handed_default, ffi::libinput_device_config_left_handed_get_default, bool);
1356 ffi_func!(
1357 /// Check if a device has a configuration that supports
1358 /// left-handed usage.
1359 pub fn config_left_handed_is_available, ffi::libinput_device_config_left_handed_is_available, bool);
1360
1361 /// Set the left-handed configuration of the device.
1362 ///
1363 /// The exact behavior is device-dependent. On a mouse and most
1364 /// pointing devices, left and right buttons are swapped but the
1365 /// middle button is unmodified. On a touchpad, physical buttons
1366 /// (if present) are swapped. On a clickpad, the top and bottom
1367 /// software-emulated buttons are swapped where present, the main
1368 /// area of the touchpad remains a left button. Tapping and
1369 /// clickfinger behavior is not affected by this setting.
1370 ///
1371 /// Changing the left-handed configuration of a device may not
1372 /// take effect until all buttons have been logically released.
1373 pub fn config_left_handed_set(&self, enabled: bool) -> DeviceConfigResult {
1374 match unsafe {
1375 ffi::libinput_device_config_left_handed_set(self.as_raw_mut(), enabled as i32)
1376 } {
1377 ffi::libinput_config_status_LIBINPUT_CONFIG_STATUS_SUCCESS => Ok(()),
1378 ffi::libinput_config_status_LIBINPUT_CONFIG_STATUS_UNSUPPORTED => {
1379 Err(DeviceConfigError::Unsupported)
1380 }
1381 ffi::libinput_config_status_LIBINPUT_CONFIG_STATUS_INVALID => {
1382 Err(DeviceConfigError::Invalid)
1383 }
1384 _ => panic!("libinput returned invalid 'libinput_config_status'"),
1385 }
1386 }
1387
1388 /// Check if configurable middle button emulation is enabled by
1389 /// default on this device.
1390 ///
1391 /// See [Middle button emulation](https://wayland.freedesktop.org/libinput/doc/latest/middle-button-emulation.html) for details.
1392 ///
1393 /// If the device does not have configurable middle button
1394 /// emulation, this function returns `false`.
1395 ///
1396 /// ## Note
1397 ///
1398 /// Some devices provide middle mouse button emulation but do not
1399 /// allow enabling/disabling that emulation. These devices always
1400 /// return `false`.
1401 pub fn config_middle_emulation_default_enabled(&self) -> bool {
1402 match unsafe {
1403 ffi::libinput_device_config_middle_emulation_get_default_enabled(self.as_raw_mut())
1404 } {
1405 ffi::libinput_config_middle_emulation_state_LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED => true,
1406 ffi::libinput_config_middle_emulation_state_LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED => false,
1407 _ => panic!("libinput returned invalid 'libinput_config_middle_emulation_state'"),
1408 }
1409 }
1410
1411 /// Check if configurable middle button emulation is enabled on
1412 /// this device.
1413 ///
1414 /// See [Middle button emulation](https://wayland.freedesktop.org/libinput/doc/latest/middle-button-emulation.html)
1415 /// for details.
1416 ///
1417 /// If the device does not have configurable middle button
1418 /// emulation, this function returns `false`.
1419 ///
1420 /// ## Note
1421 ///
1422 /// Some devices provide middle mouse button emulation but do not
1423 /// allow enabling/disabling that emulation. These devices always
1424 /// return `false`.
1425 pub fn config_middle_emulation_enabled(&self) -> bool {
1426 match unsafe { ffi::libinput_device_config_middle_emulation_get_enabled(self.as_raw_mut()) } {
1427 ffi::libinput_config_middle_emulation_state_LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED => true,
1428 ffi::libinput_config_middle_emulation_state_LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED => false,
1429 _ => panic!("libinput returned invalid 'libinput_config_middle_emulation_state'"),
1430 }
1431 }
1432
1433 ffi_func!(
1434 /// Check if middle mouse button emulation configuration is
1435 /// available on this device.
1436 ///
1437 /// See [Middle button emulation](https://wayland.freedesktop.org/libinput/doc/latest/middle-button-emulation.html)
1438 /// for details.
1439 ///
1440 /// ## Note
1441 ///
1442 /// Some devices provide middle mouse button emulation but do not
1443 /// allow enabling/disabling that emulation. These devices return
1444 /// `false` in `config_middle_emulation_is_available`.
1445 pub fn config_middle_emulation_is_available, ffi::libinput_device_config_middle_emulation_is_available, bool);
1446
1447 /// Enable or disable middle button emulation on this device.
1448 ///
1449 /// When enabled, a simultaneous press of the left and right
1450 /// button generates a middle mouse button event. Releasing the
1451 /// buttons generates a middle mouse button release, the left and
1452 /// right button events are discarded otherwise.
1453 ///
1454 /// See [Middle button emulation](https://wayland.freedesktop.org/libinput/doc/latest/middle-button-emulation.html)
1455 /// for details.
1456 pub fn config_middle_emulation_set_enabled(&self, enabled: bool) -> DeviceConfigResult {
1457 match unsafe {
1458 ffi::libinput_device_config_middle_emulation_set_enabled(
1459 self.as_raw_mut(),
1460 if enabled {
1461 ffi::libinput_config_middle_emulation_state_LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED
1462 } else {
1463 ffi::libinput_config_middle_emulation_state_LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED
1464 },
1465 )
1466 } {
1467 ffi::libinput_config_status_LIBINPUT_CONFIG_STATUS_SUCCESS => Ok(()),
1468 ffi::libinput_config_status_LIBINPUT_CONFIG_STATUS_UNSUPPORTED => {
1469 Err(DeviceConfigError::Unsupported)
1470 }
1471 ffi::libinput_config_status_LIBINPUT_CONFIG_STATUS_INVALID => {
1472 Err(DeviceConfigError::Invalid)
1473 }
1474 _ => panic!("libinput returned invalid 'libinput_config_status'"),
1475 }
1476 }
1477
1478 ffi_func!(
1479 /// Get the current rotation of a device in degrees clockwise off
1480 /// the logical neutral position.
1481 ///
1482 /// If this device does not support rotation, the return value is
1483 /// always 0.
1484 pub fn config_rotation_angle, ffi::libinput_device_config_rotation_get_angle, u32);
1485 ffi_func!(
1486 /// Get the default rotation of a device in degrees clockwise off
1487 /// the logical neutral position.
1488 ///
1489 /// If this device does not support rotation, the return value is
1490 /// always 0.
1491 pub fn config_rotation_default_angle, ffi::libinput_device_config_rotation_get_default_angle, u32);
1492 ffi_func!(
1493 /// Check whether a device can have a custom rotation applied.
1494 pub fn config_rotation_is_available, ffi::libinput_device_config_rotation_is_available, bool);
1495
1496 /// Set the rotation of a device in degrees clockwise off the
1497 /// logical neutral position.
1498 ///
1499 /// Any subsequent motion events are adjusted according to the
1500 /// given angle.
1501 ///
1502 /// The angle has to be in the range of [0, 360] degrees,
1503 /// otherwise this function returns `DeviceConfigError::Invalid`.
1504 /// If the angle is a multiple of 360 or negative, the caller
1505 /// must ensure the correct ranging before calling this function.
1506 ///
1507 /// The rotation angle is applied to all motion events emitted by
1508 /// the device. Thus, rotating the device also changes the angle
1509 /// required or presented by scrolling, gestures, etc.
1510 ///
1511 /// Setting a rotation of 0 degrees on a device that does not
1512 /// support rotation always succeeds.
1513 pub fn config_rotation_set_angle(&self, angle: u32) -> DeviceConfigResult {
1514 match unsafe { ffi::libinput_device_config_rotation_set_angle(self.as_raw_mut(), angle) } {
1515 ffi::libinput_config_status_LIBINPUT_CONFIG_STATUS_SUCCESS => Ok(()),
1516 ffi::libinput_config_status_LIBINPUT_CONFIG_STATUS_UNSUPPORTED => {
1517 Err(DeviceConfigError::Unsupported)
1518 }
1519 ffi::libinput_config_status_LIBINPUT_CONFIG_STATUS_INVALID => {
1520 Err(DeviceConfigError::Invalid)
1521 }
1522 _ => panic!("libinput returned invalid 'libinput_config_status'"),
1523 }
1524 }
1525
1526 ffi_func!(
1527 /// Get the button for the `ScrollMethod::OnButtonDown` method
1528 /// for this device.
1529 ///
1530 /// If `ScrollMethod::OnButtonDown` scroll method is not
1531 /// supported, or no button is set, this function returns 0.
1532 ///
1533 /// ## Note
1534 ///
1535 /// The return value is independent of the currently selected
1536 /// scroll-method. For button scrolling to activate, a device
1537 /// must have the `ScrollMethod::OnButtonDown` method enabled,
1538 /// and a non-zero button set as scroll button.
1539 pub fn config_scroll_button, ffi::libinput_device_config_scroll_get_button, u32);
1540 ffi_func!(
1541 /// Get the default button for the `ScrollMethod::OnButtonDown`
1542 /// method for this device.
1543 ///
1544 /// If `ScrollMethod::OnButtonDown` scroll method is not
1545 /// supported, or no default button is set,
1546 /// this function returns 0.
1547 pub fn config_scroll_default_button, ffi::libinput_device_config_scroll_get_default_button, u32);
1548
1549 /// Get the default scroll method for this device.
1550 ///
1551 /// The method defines when to generate scroll axis events
1552 /// instead of pointer motion events.
1553 ///
1554 /// A return value of `None` means the scroll method is not known
1555 pub fn config_scroll_default_method(&self) -> Option<ScrollMethod> {
1556 match unsafe { ffi::libinput_device_config_scroll_get_default_method(self.as_raw_mut()) } {
1557 ffi::libinput_config_scroll_method_LIBINPUT_CONFIG_SCROLL_NO_SCROLL => {
1558 Some(ScrollMethod::NoScroll)
1559 }
1560 ffi::libinput_config_scroll_method_LIBINPUT_CONFIG_SCROLL_2FG => {
1561 Some(ScrollMethod::TwoFinger)
1562 }
1563 ffi::libinput_config_scroll_method_LIBINPUT_CONFIG_SCROLL_EDGE => {
1564 Some(ScrollMethod::Edge)
1565 }
1566 ffi::libinput_config_scroll_method_LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN => {
1567 Some(ScrollMethod::OnButtonDown)
1568 }
1569 _x => {
1570 #[cfg(feature = "log")]
1571 log::warn!(
1572 "Unknown ScrollMethod ({}). Unsupported libinput version?",
1573 _x
1574 );
1575 None
1576 }
1577 }
1578 }
1579
1580 /// Get the scroll method for this device.
1581 ///
1582 /// The method defines when to generate scroll axis events
1583 /// instead of pointer motion events.
1584 ///
1585 /// A return value of `None` means the scroll method is not known
1586 pub fn config_scroll_method(&self) -> Option<ScrollMethod> {
1587 match unsafe { ffi::libinput_device_config_scroll_get_method(self.as_raw_mut()) } {
1588 ffi::libinput_config_scroll_method_LIBINPUT_CONFIG_SCROLL_NO_SCROLL => {
1589 Some(ScrollMethod::NoScroll)
1590 }
1591 ffi::libinput_config_scroll_method_LIBINPUT_CONFIG_SCROLL_2FG => {
1592 Some(ScrollMethod::TwoFinger)
1593 }
1594 ffi::libinput_config_scroll_method_LIBINPUT_CONFIG_SCROLL_EDGE => {
1595 Some(ScrollMethod::Edge)
1596 }
1597 ffi::libinput_config_scroll_method_LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN => {
1598 Some(ScrollMethod::OnButtonDown)
1599 }
1600 _ => panic!("libinput returned invalid 'libinput_config_scroll_method'"),
1601 }
1602 }
1603
1604 /// Check which scroll methods a device supports.
1605 ///
1606 /// The method defines when to generate scroll axis events
1607 /// instead of pointer motion events.
1608 pub fn config_scroll_methods(&self) -> Vec<ScrollMethod> {
1609 let mut methods = Vec::new();
1610 let bitmask = unsafe { ffi::libinput_device_config_scroll_get_methods(self.as_raw_mut()) };
1611 if bitmask & ffi::libinput_config_scroll_method_LIBINPUT_CONFIG_SCROLL_NO_SCROLL as u32 != 0
1612 {
1613 methods.push(ScrollMethod::NoScroll);
1614 }
1615 if bitmask & ffi::libinput_config_scroll_method_LIBINPUT_CONFIG_SCROLL_2FG as u32 != 0 {
1616 methods.push(ScrollMethod::TwoFinger);
1617 }
1618 if bitmask & ffi::libinput_config_scroll_method_LIBINPUT_CONFIG_SCROLL_EDGE as u32 != 0 {
1619 methods.push(ScrollMethod::Edge);
1620 }
1621 if bitmask & ffi::libinput_config_scroll_method_LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN as u32
1622 != 0
1623 {
1624 methods.push(ScrollMethod::OnButtonDown);
1625 }
1626 methods
1627 }
1628
1629 /// Set the scroll method for this device.
1630 ///
1631 /// The method defines when to generate scroll axis events
1632 /// instead of pointer motion events.
1633 ///
1634 /// ## Note
1635 ///
1636 /// Setting `ScrollMethod::OnButtonDown` enables the scroll
1637 /// method, but scrolling is only activated when the configured
1638 /// button is held down. If no button is set, i.e.
1639 /// `config_scroll_button` returns 0, scrolling cannot activate.
1640 pub fn config_scroll_set_method(&mut self, method: ScrollMethod) -> DeviceConfigResult {
1641 match unsafe {
1642 ffi::libinput_device_config_scroll_set_method(
1643 self.as_raw_mut(),
1644 match method {
1645 ScrollMethod::NoScroll => {
1646 ffi::libinput_config_scroll_method_LIBINPUT_CONFIG_SCROLL_NO_SCROLL
1647 }
1648 ScrollMethod::TwoFinger => {
1649 ffi::libinput_config_scroll_method_LIBINPUT_CONFIG_SCROLL_2FG
1650 }
1651 ScrollMethod::Edge => {
1652 ffi::libinput_config_scroll_method_LIBINPUT_CONFIG_SCROLL_EDGE
1653 }
1654 ScrollMethod::OnButtonDown => {
1655 ffi::libinput_config_scroll_method_LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN
1656 }
1657 },
1658 )
1659 } {
1660 ffi::libinput_config_status_LIBINPUT_CONFIG_STATUS_SUCCESS => Ok(()),
1661 ffi::libinput_config_status_LIBINPUT_CONFIG_STATUS_UNSUPPORTED => {
1662 Err(DeviceConfigError::Unsupported)
1663 }
1664 ffi::libinput_config_status_LIBINPUT_CONFIG_STATUS_INVALID => {
1665 Err(DeviceConfigError::Invalid)
1666 }
1667 _ => panic!("libinput returned invalid 'libinput_config_status'"),
1668 }
1669 }
1670
1671 ffi_func!(
1672 /// Get the default mode for scrolling on this device.
1673 pub fn config_scroll_default_natural_scroll_enabled, ffi::libinput_device_config_scroll_get_default_natural_scroll_enabled, bool);
1674 ffi_func!(
1675 /// Get the current mode for scrolling on this device.
1676 pub fn config_scroll_natural_scroll_enabled, ffi::libinput_device_config_scroll_get_natural_scroll_enabled, bool);
1677 ffi_func!(
1678 /// Return non-zero if the device supports "natural scrolling".
1679 ///
1680 /// In traditional scroll mode, the movement of fingers on a
1681 /// touchpad when scrolling matches the movement of the scroll
1682 /// bars. When the fingers move down, the scroll bar moves down,
1683 /// a line of text on the screen moves towards the upper end of
1684 /// the screen. This also matches scroll wheels on mice (wheel
1685 /// down, content moves up).
1686 ///
1687 /// Natural scrolling is the term coined by Apple for inverted
1688 /// scrolling. In this mode, the effect of scrolling movement of
1689 /// fingers on a touchpad resemble physical manipulation of
1690 /// paper. When the fingers move down, a line of text on the
1691 /// screen moves down (scrollbars move up). This is the opposite
1692 /// of scroll wheels on mice.
1693 ///
1694 /// A device supporting natural scrolling can be switched between
1695 /// traditional scroll mode and natural scroll mode.
1696 pub fn config_scroll_has_natural_scroll, ffi::libinput_device_config_scroll_has_natural_scroll, bool);
1697
1698 /// Enable or disable natural scrolling on the device.
1699 pub fn config_scroll_set_natural_scroll_enabled(
1700 &mut self,
1701 enabled: bool,
1702 ) -> DeviceConfigResult {
1703 match unsafe {
1704 ffi::libinput_device_config_scroll_set_natural_scroll_enabled(
1705 self.as_raw_mut(),
1706 enabled as i32,
1707 )
1708 } {
1709 ffi::libinput_config_status_LIBINPUT_CONFIG_STATUS_SUCCESS => Ok(()),
1710 ffi::libinput_config_status_LIBINPUT_CONFIG_STATUS_UNSUPPORTED => {
1711 Err(DeviceConfigError::Unsupported)
1712 }
1713 ffi::libinput_config_status_LIBINPUT_CONFIG_STATUS_INVALID => {
1714 Err(DeviceConfigError::Invalid)
1715 }
1716 _ => panic!("libinput returned invalid 'libinput_config_status'"),
1717 }
1718 }
1719
1720 /// Set the button for the `ScrollMethod::OnButtonDown` method
1721 /// for this device.
1722 ///
1723 /// When the current scroll method is set to
1724 /// `ScrollMethod::OnButtonDown`, no button press/release events
1725 /// will be send for the configured button.
1726 ///
1727 /// When the configured button is pressed, any motion events
1728 /// along a scroll-capable axis are turned into scroll axis
1729 /// events.
1730 ///
1731 /// ## Note
1732 ///
1733 /// Setting the button does not change the scroll method. To
1734 /// change the scroll method call `config_scroll_set_method`.
1735 /// If the button is 0, button scrolling is effectively disabled.
1736 pub fn config_scroll_set_button(&mut self, button: u32) -> DeviceConfigResult {
1737 match unsafe { ffi::libinput_device_config_scroll_set_button(self.as_raw_mut(), button) } {
1738 ffi::libinput_config_status_LIBINPUT_CONFIG_STATUS_SUCCESS => Ok(()),
1739 ffi::libinput_config_status_LIBINPUT_CONFIG_STATUS_UNSUPPORTED => {
1740 Err(DeviceConfigError::Unsupported)
1741 }
1742 ffi::libinput_config_status_LIBINPUT_CONFIG_STATUS_INVALID => {
1743 Err(DeviceConfigError::Invalid)
1744 }
1745 _ => panic!("libinput returned invalid 'libinput_config_status'"),
1746 }
1747 }
1748
1749 /// Get the current scroll button lock state
1750 ///
1751 /// If `ScrollMethod::OnButtonDown` is not supported, or no button is set,
1752 /// this functions returns `Disabled`.
1753 ///
1754 /// ## Note
1755 ///
1756 /// The return value is independent of the currently selected scroll-method.
1757 /// For the scroll button lock to activate, a device must have the
1758 /// `ScrollMethod::OnButtonDown` enabled, and a non-zero button set as scroll button.
1759 #[cfg(feature = "libinput_1_15")]
1760 pub fn config_scroll_button_lock(&self) -> ScrollButtonLockState {
1761 match unsafe { ffi::libinput_device_config_scroll_get_button_lock(self.as_raw() as *mut _) } {
1762 ffi::libinput_config_scroll_button_lock_state_LIBINPUT_CONFIG_SCROLL_BUTTON_LOCK_DISABLED => ScrollButtonLockState::Disabled,
1763 ffi::libinput_config_scroll_button_lock_state_LIBINPUT_CONFIG_SCROLL_BUTTON_LOCK_ENABLED => ScrollButtonLockState::Enabled,
1764 _ => panic!("libinput returned invalid libinput_config_scroll_button_lock_state"),
1765 }
1766 }
1767
1768 /// Get the default scroll button lock state
1769 ///
1770 /// If `ScrollMethod::OnButtonDown` is not supported, or no button is set,
1771 /// this functions returns `Disabled`.
1772 #[cfg(feature = "libinput_1_15")]
1773 pub fn config_scroll_default_button_lock(&self) -> ScrollButtonLockState {
1774 match unsafe { ffi::libinput_device_config_scroll_get_default_button_lock(self.as_raw() as *mut _) } {
1775 ffi::libinput_config_scroll_button_lock_state_LIBINPUT_CONFIG_SCROLL_BUTTON_LOCK_DISABLED => ScrollButtonLockState::Disabled,
1776 ffi::libinput_config_scroll_button_lock_state_LIBINPUT_CONFIG_SCROLL_BUTTON_LOCK_ENABLED => ScrollButtonLockState::Enabled,
1777 _ => panic!("libinput returned invalid libinput_config_scroll_button_lock_state"),
1778 }
1779 }
1780
1781 /// Set the scroll button lock.
1782 ///
1783 /// If the state is `Disabled` the button must physically be held down for
1784 /// button scrolling to work. If the state is `Enabled`, the button is considered
1785 /// logically down after the first press and release sequence, and logically
1786 /// up after the second press and release sequence.
1787 #[cfg(feature = "libinput_1_15")]
1788 pub fn config_scroll_set_button_lock(
1789 &mut self,
1790 state: ScrollButtonLockState,
1791 ) -> DeviceConfigResult {
1792 match unsafe {
1793 ffi::libinput_device_config_scroll_set_button_lock(self.as_raw_mut(),
1794 match state {
1795 ScrollButtonLockState::Enabled => ffi::libinput_config_scroll_button_lock_state_LIBINPUT_CONFIG_SCROLL_BUTTON_LOCK_ENABLED,
1796 ScrollButtonLockState::Disabled => ffi::libinput_config_scroll_button_lock_state_LIBINPUT_CONFIG_SCROLL_BUTTON_LOCK_DISABLED,
1797 }
1798 )
1799 } {
1800 ffi::libinput_config_status_LIBINPUT_CONFIG_STATUS_SUCCESS => Ok(()),
1801 ffi::libinput_config_status_LIBINPUT_CONFIG_STATUS_UNSUPPORTED => {
1802 Err(DeviceConfigError::Unsupported)
1803 }
1804 ffi::libinput_config_status_LIBINPUT_CONFIG_STATUS_INVALID => {
1805 Err(DeviceConfigError::Invalid)
1806 }
1807 _ => panic!("libinput returned invalid 'libinput_config_status'"),
1808 }
1809 }
1810
1811 /// Get the send-event mode for this device.
1812 ///
1813 /// The mode defines when the device processes and sends events
1814 /// to the caller.
1815 ///
1816 /// If a caller enables the bits for multiple modes, some of
1817 /// which are subsets of another mode libinput may drop the bits
1818 /// that are subsets. In other words, don't expect
1819 /// `config_send_events_mode` to always return exactly the same
1820 /// as passed into `config_send_events_set_mode`.
1821 pub fn config_send_events_mode(&self) -> SendEventsMode {
1822 SendEventsMode::from_bits_truncate(unsafe {
1823 ffi::libinput_device_config_send_events_get_mode(self.as_raw_mut())
1824 })
1825 }
1826
1827 /// Return the possible send-event modes for this device.
1828 ///
1829 /// These modes define when a device may process and send events.
1830 pub fn config_send_events_modes(&self) -> SendEventsMode {
1831 SendEventsMode::from_bits_truncate(unsafe {
1832 ffi::libinput_device_config_send_events_get_modes(self.as_raw_mut())
1833 })
1834 }
1835
1836 /// Set the send-event mode for this device.
1837 ///
1838 /// The mode defines when the device processes and sends events
1839 /// to the caller.
1840 ///
1841 /// The selected mode may not take effect immediately. Events
1842 /// already received and processed from this device are
1843 /// unaffected and will be passed to the caller on the next call
1844 /// to `<Libinput as Iterator>::next()`.
1845 ///
1846 /// If the mode is a mixture of `SendEventsMode`s, the device may
1847 /// wait for or generate events until it is in a neutral state.
1848 /// For example, this may include waiting for or generating
1849 /// button release events.
1850 ///
1851 /// If the device is already suspended, this function does
1852 /// nothing and returns success. Changing the send-event mode on
1853 /// a device that has been removed is permitted.
1854 pub fn config_send_events_set_mode(&self, mode: SendEventsMode) -> DeviceConfigResult {
1855 match unsafe {
1856 ffi::libinput_device_config_send_events_set_mode(self.as_raw_mut(), mode.bits())
1857 } {
1858 ffi::libinput_config_status_LIBINPUT_CONFIG_STATUS_SUCCESS => Ok(()),
1859 ffi::libinput_config_status_LIBINPUT_CONFIG_STATUS_UNSUPPORTED => {
1860 Err(DeviceConfigError::Unsupported)
1861 }
1862 ffi::libinput_config_status_LIBINPUT_CONFIG_STATUS_INVALID => {
1863 Err(DeviceConfigError::Invalid)
1864 }
1865 _ => panic!("libinput returned invalid 'libinput_config_status'"),
1866 }
1867 }
1868
1869 /// Get the finger number to button number mapping for
1870 /// tap-to-click.
1871 ///
1872 /// The return value for a device that does not support tapping
1873 /// is always `TapButtonMap::LeftRightMiddle`.
1874 ///
1875 /// This will return `None` for devices
1876 /// where `config_tap_finger_count` returns 0.
1877 pub fn config_tap_button_map(&self) -> Option<TapButtonMap> {
1878 if self.config_tap_finger_count() == 0 {
1879 None
1880 } else {
1881 match unsafe { ffi::libinput_device_config_tap_get_button_map(self.as_raw_mut()) } {
1882 ffi::libinput_config_tap_button_map_LIBINPUT_CONFIG_TAP_MAP_LRM => {
1883 Some(TapButtonMap::LeftRightMiddle)
1884 }
1885 ffi::libinput_config_tap_button_map_LIBINPUT_CONFIG_TAP_MAP_LMR => {
1886 Some(TapButtonMap::LeftMiddleRight)
1887 }
1888 _ => panic!("libinput returned invalid 'libinput_config_tap_button_map'"),
1889 }
1890 }
1891 }
1892
1893 /// Get the default finger number to button number mapping for
1894 /// tap-to-click.
1895 ///
1896 /// The return value for a device that does not support tapping
1897 /// is always `TapButtonMap::LeftRightMiddle`.
1898 ///
1899 /// This will return `None` for devices
1900 /// where `config_tap_finger_count` returns 0.
1901 pub fn config_tap_default_button_map(&self) -> Option<TapButtonMap> {
1902 if self.config_tap_finger_count() == 0 {
1903 None
1904 } else {
1905 match unsafe {
1906 ffi::libinput_device_config_tap_get_default_button_map(self.as_raw_mut())
1907 } {
1908 ffi::libinput_config_tap_button_map_LIBINPUT_CONFIG_TAP_MAP_LRM => {
1909 Some(TapButtonMap::LeftRightMiddle)
1910 }
1911 ffi::libinput_config_tap_button_map_LIBINPUT_CONFIG_TAP_MAP_LMR => {
1912 Some(TapButtonMap::LeftMiddleRight)
1913 }
1914 _ => panic!("libinput returned invalid 'libinput_config_tap_button_map'"),
1915 }
1916 }
1917 }
1918
1919 /// Return whether tap-and-drag is enabled or disabled by default
1920 /// on this device.
1921 pub fn config_tap_default_drag_enabled(&self) -> bool {
1922 match unsafe { ffi::libinput_device_config_tap_get_default_drag_enabled(self.as_raw_mut()) }
1923 {
1924 ffi::libinput_config_drag_state_LIBINPUT_CONFIG_DRAG_ENABLED => true,
1925 ffi::libinput_config_drag_state_LIBINPUT_CONFIG_DRAG_DISABLED => false,
1926 _ => panic!("libinput returned invalid 'libinput_config_drag_state'"),
1927 }
1928 }
1929
1930 /// Check if drag-lock during tapping is enabled by default on
1931 /// this device.
1932 ///
1933 /// If the device does not support tapping, this function always
1934 /// returns `false`.
1935 ///
1936 /// Drag lock may be enabled by default even when tapping is
1937 /// disabled by default.
1938 pub fn config_tap_default_drag_lock_enabled(&self) -> DragLockState {
1939 match unsafe {
1940 ffi::libinput_device_config_tap_get_default_drag_lock_enabled(self.as_raw_mut())
1941 } {
1942 ffi::libinput_config_drag_lock_state_LIBINPUT_CONFIG_DRAG_LOCK_DISABLED => {
1943 DragLockState::Disabled
1944 }
1945 // legacy spelling for LIBINPUT_CONFIG_DRAG_LOCK_ENABLED_TIMEOUT
1946 #[cfg(not(feature = "libinput_1_27"))]
1947 ffi::libinput_config_drag_lock_state_LIBINPUT_CONFIG_DRAG_LOCK_ENABLED => {
1948 DragLockState::EnabledTimeout
1949 }
1950 #[cfg(feature = "libinput_1_27")]
1951 ffi::libinput_config_drag_lock_state_LIBINPUT_CONFIG_DRAG_LOCK_ENABLED_TIMEOUT => {
1952 DragLockState::EnabledTimeout
1953 }
1954 #[cfg(feature = "libinput_1_27")]
1955 ffi::libinput_config_drag_lock_state_LIBINPUT_CONFIG_DRAG_LOCK_ENABLED_STICKY => {
1956 DragLockState::EnabledSticky
1957 }
1958 _ => panic!("libinput returned invalid 'libinput_config_drag_lock_state'"),
1959 }
1960 }
1961
1962 /// Return the default setting for whether tap-to-click is
1963 /// enabled on this device.
1964 pub fn config_tap_default_enabled(&self) -> bool {
1965 match unsafe { ffi::libinput_device_config_tap_get_default_enabled(self.as_raw_mut()) } {
1966 ffi::libinput_config_tap_state_LIBINPUT_CONFIG_TAP_ENABLED => true,
1967 ffi::libinput_config_tap_state_LIBINPUT_CONFIG_TAP_DISABLED => false,
1968 _ => panic!("libinput returned invalid 'libinput_config_tap_state'"),
1969 }
1970 }
1971
1972 /// Return whether tap-and-drag is enabled or disabled on this
1973 /// device.
1974 pub fn config_tap_drag_enabled(&self) -> bool {
1975 match unsafe { ffi::libinput_device_config_tap_get_drag_enabled(self.as_raw_mut()) } {
1976 ffi::libinput_config_drag_state_LIBINPUT_CONFIG_DRAG_ENABLED => true,
1977 ffi::libinput_config_drag_state_LIBINPUT_CONFIG_DRAG_DISABLED => false,
1978 _ => panic!("libinput returned invalid 'libinput_config_drag_state'"),
1979 }
1980 }
1981
1982 /// Check if drag-lock during tapping is enabled on this device.
1983 ///
1984 /// If the device does not support tapping, this function always
1985 /// returns `false`.
1986 ///
1987 /// Drag lock may be enabled even when tapping is disabled.
1988 pub fn config_tap_drag_lock_enabled(&self) -> bool {
1989 match unsafe { ffi::libinput_device_config_tap_get_drag_lock_enabled(self.as_raw_mut()) } {
1990 ffi::libinput_config_drag_lock_state_LIBINPUT_CONFIG_DRAG_LOCK_ENABLED => true,
1991 ffi::libinput_config_drag_lock_state_LIBINPUT_CONFIG_DRAG_LOCK_DISABLED => false,
1992 _ => panic!("libinput returned invalid 'libinput_config_drag_lock_state'"),
1993 }
1994 }
1995
1996 /// Check if tap-to-click is enabled on this device.
1997 ///
1998 /// If the device does not support tapping, this function always
1999 /// returns `false`.
2000 pub fn config_tap_enabled(&self) -> bool {
2001 match unsafe { ffi::libinput_device_config_tap_get_enabled(self.as_raw_mut()) } {
2002 ffi::libinput_config_tap_state_LIBINPUT_CONFIG_TAP_ENABLED => true,
2003 ffi::libinput_config_tap_state_LIBINPUT_CONFIG_TAP_DISABLED => false,
2004 _ => panic!("libinput returned invalid 'libinput_config_tap_state'"),
2005 }
2006 }
2007
2008 ffi_func!(
2009 /// Check if the device supports tap-to-click and how many
2010 /// fingers can be used for tapping.
2011 ///
2012 /// See `config_tap_set_enabled` for more information.
2013 pub fn config_tap_finger_count, ffi::libinput_device_config_tap_get_finger_count, u32);
2014
2015 #[cfg(feature = "libinput_1_28")]
2016 ffi_func!(
2017 /// Returns the maximum number of fingers available for 3-finger dragging.
2018 pub fn config_3fg_drag_get_finger_count, ffi::libinput_device_config_3fg_drag_get_finger_count, u32);
2019
2020 /// Enable or disable 3-finger drag on this device.
2021 ///
2022 /// When enabled, three fingers down will result in a button down event,
2023 /// subsequent finger motion triggers a drag. The button is released shortly
2024 /// after all fingers are logically up.
2025 ///
2026 /// See [Three-finger drag](https://wayland.freedesktop.org/libinput/doc/latest/configuration.html#three-finger-drag) for details.
2027 #[cfg(feature = "libinput_1_28")]
2028 pub fn config_3fg_drag_set_enabled(&self, state: ThreeFingerDragState) -> DeviceConfigResult {
2029 match unsafe {
2030 ffi::libinput_device_config_3fg_drag_set_enabled(
2031 self.as_raw_mut(),
2032 match state {
2033 ThreeFingerDragState::Disabled => {
2034 ffi::libinput_config_3fg_drag_state_LIBINPUT_CONFIG_3FG_DRAG_DISABLED
2035 }
2036 ThreeFingerDragState::EnabledThreeFinger => {
2037 ffi::libinput_config_3fg_drag_state_LIBINPUT_CONFIG_3FG_DRAG_ENABLED_3FG
2038 }
2039 ThreeFingerDragState::EnabledFourFinger => {
2040 ffi::libinput_config_3fg_drag_state_LIBINPUT_CONFIG_3FG_DRAG_ENABLED_4FG
2041 }
2042 },
2043 )
2044 } {
2045 ffi::libinput_config_status_LIBINPUT_CONFIG_STATUS_SUCCESS => Ok(()),
2046 ffi::libinput_config_status_LIBINPUT_CONFIG_STATUS_UNSUPPORTED => {
2047 Err(DeviceConfigError::Unsupported)
2048 }
2049 ffi::libinput_config_status_LIBINPUT_CONFIG_STATUS_INVALID => {
2050 Err(DeviceConfigError::Invalid)
2051 }
2052 _ => panic!("libinput returned invalid 'libinput_config_status'"),
2053 }
2054 }
2055
2056 /// Return whether 3-finger drag is enabled or disabled on this device.
2057 #[cfg(feature = "libinput_1_28")]
2058 pub fn config_3fg_drag_get_enabled(&self) -> ThreeFingerDragState {
2059 match unsafe { ffi::libinput_device_config_3fg_drag_get_enabled(self.as_raw_mut()) } {
2060 ffi::libinput_config_3fg_drag_state_LIBINPUT_CONFIG_3FG_DRAG_DISABLED => {
2061 ThreeFingerDragState::Disabled
2062 }
2063 ffi::libinput_config_3fg_drag_state_LIBINPUT_CONFIG_3FG_DRAG_ENABLED_3FG => {
2064 ThreeFingerDragState::EnabledThreeFinger
2065 }
2066 ffi::libinput_config_3fg_drag_state_LIBINPUT_CONFIG_3FG_DRAG_ENABLED_4FG => {
2067 ThreeFingerDragState::EnabledFourFinger
2068 }
2069 _ => panic!("libinput returned invalid 'libinput_config_3fg_drag_state'"),
2070 }
2071 }
2072
2073 /// Return whether 3-finger drag is enabled or disabled by default on this device.
2074 #[cfg(feature = "libinput_1_28")]
2075 pub fn config_3fg_drag_get_default_enabled(&self) -> ThreeFingerDragState {
2076 match unsafe { ffi::libinput_device_config_3fg_drag_get_default_enabled(self.as_raw_mut()) }
2077 {
2078 ffi::libinput_config_3fg_drag_state_LIBINPUT_CONFIG_3FG_DRAG_DISABLED => {
2079 ThreeFingerDragState::Disabled
2080 }
2081 ffi::libinput_config_3fg_drag_state_LIBINPUT_CONFIG_3FG_DRAG_ENABLED_3FG => {
2082 ThreeFingerDragState::EnabledThreeFinger
2083 }
2084 ffi::libinput_config_3fg_drag_state_LIBINPUT_CONFIG_3FG_DRAG_ENABLED_4FG => {
2085 ThreeFingerDragState::EnabledFourFinger
2086 }
2087 _ => panic!("libinput returned invalid 'libinput_config_3fg_drag_state'"),
2088 }
2089 }
2090
2091 /// Set the finger number to button number mapping for
2092 /// tap-to-click.
2093 ///
2094 /// The default mapping on most devices is to have a 1, 2 and 3
2095 /// finger tap to map to the left, right and middle button,
2096 /// respectively. A device may permit changing the button mapping
2097 /// but disallow specific maps. In this case
2098 /// `DeviceConfigError::Disabled` is returned, the caller is
2099 /// expected to handle this case correctly.
2100 ///
2101 /// Changing the button mapping may not take effect immediately,
2102 /// the device may wait until it is in a neutral state before
2103 /// applying any changes.
2104 ///
2105 /// The mapping may be changed when tap-to-click is disabled. The
2106 /// new mapping takes effect when tap-to-click is enabled in the
2107 /// future.
2108 ///
2109 /// ## Note
2110 ///
2111 /// This will return `None` for devices where
2112 /// `config_tap_finger_count` returns 0.
2113 pub fn config_tap_set_button_map(&mut self, map: TapButtonMap) -> DeviceConfigResult {
2114 match unsafe {
2115 ffi::libinput_device_config_tap_set_button_map(
2116 self.as_raw_mut(),
2117 match map {
2118 TapButtonMap::LeftRightMiddle => {
2119 ffi::libinput_config_tap_button_map_LIBINPUT_CONFIG_TAP_MAP_LRM
2120 }
2121 TapButtonMap::LeftMiddleRight => {
2122 ffi::libinput_config_tap_button_map_LIBINPUT_CONFIG_TAP_MAP_LMR
2123 }
2124 },
2125 )
2126 } {
2127 ffi::libinput_config_status_LIBINPUT_CONFIG_STATUS_SUCCESS => Ok(()),
2128 ffi::libinput_config_status_LIBINPUT_CONFIG_STATUS_UNSUPPORTED => {
2129 Err(DeviceConfigError::Unsupported)
2130 }
2131 ffi::libinput_config_status_LIBINPUT_CONFIG_STATUS_INVALID => {
2132 Err(DeviceConfigError::Invalid)
2133 }
2134 _ => panic!("libinput returned invalid 'libinput_config_status'"),
2135 }
2136 }
2137
2138 /// Enable or disable tap-and-drag on this device.
2139 ///
2140 /// When enabled, a single-finger tap immediately followed by a
2141 /// finger down results in a button down event, subsequent finger
2142 /// motion thus triggers a drag. The button is released on finger
2143 /// up.
2144 /// See [Tap-and-drag](https://wayland.freedesktop.org/libinput/doc/latest/tapping.html#tapndrag)
2145 /// for more details.
2146 pub fn config_tap_set_drag_enabled(&mut self, enabled: bool) -> DeviceConfigResult {
2147 match unsafe {
2148 ffi::libinput_device_config_tap_set_drag_enabled(
2149 self.as_raw_mut(),
2150 if enabled {
2151 ffi::libinput_config_drag_state_LIBINPUT_CONFIG_DRAG_ENABLED
2152 } else {
2153 ffi::libinput_config_drag_state_LIBINPUT_CONFIG_DRAG_DISABLED
2154 },
2155 )
2156 } {
2157 ffi::libinput_config_status_LIBINPUT_CONFIG_STATUS_SUCCESS => Ok(()),
2158 ffi::libinput_config_status_LIBINPUT_CONFIG_STATUS_UNSUPPORTED => {
2159 Err(DeviceConfigError::Unsupported)
2160 }
2161 ffi::libinput_config_status_LIBINPUT_CONFIG_STATUS_INVALID => {
2162 Err(DeviceConfigError::Invalid)
2163 }
2164 _ => panic!("libinput returned invalid 'libinput_config_status'"),
2165 }
2166 }
2167
2168 /// Enable or disable drag-lock during tapping on this device.
2169 ///
2170 /// When enabled, a finger may be lifted and put back on the
2171 /// touchpad within a timeout and the drag process continues.
2172 /// When disabled, lifting the finger during a tap-and-drag will
2173 /// immediately stop the drag.
2174 /// See [Tap-and-drag](https://wayland.freedesktop.org/libinput/doc/latest/tapping.html#tapndrag)
2175 /// for details.
2176 ///
2177 /// Enabling drag lock on a device that has tapping disabled is
2178 /// permitted, but has no effect until tapping is enabled.
2179 pub fn config_tap_set_drag_lock_enabled(&mut self, state: DragLockState) -> DeviceConfigResult {
2180 match unsafe {
2181 ffi::libinput_device_config_tap_set_drag_lock_enabled(
2182 self.as_raw_mut(),
2183 match state {
2184 DragLockState::Disabled => {
2185 ffi::libinput_config_drag_lock_state_LIBINPUT_CONFIG_DRAG_LOCK_DISABLED
2186 }
2187 #[cfg(not(feature = "libinput_1_27"))]
2188 DragLockState::EnabledTimeout => {
2189 // legacy spelling for LIBINPUT_CONFIG_DRAG_LOCK_ENABLED_TIMEOUT
2190 ffi::libinput_config_drag_lock_state_LIBINPUT_CONFIG_DRAG_LOCK_ENABLED
2191 }
2192 #[cfg(feature = "libinput_1_27")]
2193 DragLockState::EnabledTimeout => {
2194 ffi::libinput_config_drag_lock_state_LIBINPUT_CONFIG_DRAG_LOCK_ENABLED_TIMEOUT
2195 }
2196 #[cfg(feature = "libinput_1_27")]
2197 DragLockState::EnabledSticky => {
2198 ffi::libinput_config_drag_lock_state_LIBINPUT_CONFIG_DRAG_LOCK_ENABLED_STICKY
2199 }
2200 },
2201 )
2202 } {
2203 ffi::libinput_config_status_LIBINPUT_CONFIG_STATUS_SUCCESS => Ok(()),
2204 ffi::libinput_config_status_LIBINPUT_CONFIG_STATUS_UNSUPPORTED => {
2205 Err(DeviceConfigError::Unsupported)
2206 }
2207 ffi::libinput_config_status_LIBINPUT_CONFIG_STATUS_INVALID => {
2208 Err(DeviceConfigError::Invalid)
2209 }
2210 _ => panic!("libinput returned invalid 'libinput_config_status'"),
2211 }
2212 }
2213
2214 /// Enable or disable tap-to-click on this device, with a default
2215 /// mapping of 1, 2, 3 finger tap mapping to left, right, middle
2216 /// click, respectively.
2217 ///
2218 /// Tapping is limited by the number of simultaneous touches
2219 /// supported by the device, see `config_tap_finger_count`.
2220 pub fn config_tap_set_enabled(&mut self, enabled: bool) -> DeviceConfigResult {
2221 match unsafe {
2222 ffi::libinput_device_config_tap_set_enabled(
2223 self.as_raw_mut(),
2224 if enabled {
2225 ffi::libinput_config_tap_state_LIBINPUT_CONFIG_TAP_ENABLED
2226 } else {
2227 ffi::libinput_config_tap_state_LIBINPUT_CONFIG_TAP_DISABLED
2228 },
2229 )
2230 } {
2231 ffi::libinput_config_status_LIBINPUT_CONFIG_STATUS_SUCCESS => Ok(()),
2232 ffi::libinput_config_status_LIBINPUT_CONFIG_STATUS_UNSUPPORTED => {
2233 Err(DeviceConfigError::Unsupported)
2234 }
2235 ffi::libinput_config_status_LIBINPUT_CONFIG_STATUS_INVALID => {
2236 Err(DeviceConfigError::Invalid)
2237 }
2238 _ => panic!("libinput returned invalid 'libinput_config_status'"),
2239 }
2240 }
2241}