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