diff --git a/doc/tapping.dox b/doc/tapping.dox index 1337fc53..483219ad 100644 --- a/doc/tapping.dox +++ b/doc/tapping.dox @@ -29,17 +29,24 @@ libinput also supports "tap-and-drag" where a tap immediately followed by a finger down and that finger being held down emulates a button press. Moving the finger around can thus drag the selected item on the screen. +Optional is a feature called "drag lock". With drag lock disabled, lifting +the finger will stop any drag process. When enabled, libinput will ignore a +finger up event during a drag process, provided the finger is set down again +within a implementation-specific timeout. Drag lock can be enabled and +disabled with libinput_device_config_tap_set_drag_lock_enabled(). + @image html tap-n-drag.svg "Tap-and-drag process" The above diagram explains the process, a tap (a) followed by a finger held down (b) starts the drag process and logically holds the left mouse button down. A movement of the finger (c) will drag the selected item until the -finger is relased (e). If needed, the finger's position can be reset by -lifting and quickly setting it down again on the touchpad (d). This will be -interpreted as continuing move and is especially useful on small touchpads -or with slow pointer acceleration. -The release of the mouse buttons after the finger release (e) is triggered -by a timeout. To release the button immediately, simply tap again (f). +finger is relased (e). If needed and drag lock is enabled, the finger's +position can be reset by lifting and quickly setting it down again on the +touchpad (d). This will be interpreted as continuing move and is especially +useful on small touchpads or with slow pointer acceleration. +If drag lock is enabled, the release of the mouse buttons after the finger +release (e) is triggered by a timeout. To release the button immediately, +simply tap again (f). If two fingers are supported by the hardware, a second finger can be used to drag while the first is held in-place. diff --git a/src/evdev-mt-touchpad-tap.c b/src/evdev-mt-touchpad-tap.c index 2951ee6a..5d986ca8 100644 --- a/src/evdev-mt-touchpad-tap.c +++ b/src/evdev-mt-touchpad-tap.c @@ -845,6 +845,25 @@ tp_tap_config_get_default(struct libinput_device *device) return tp_tap_default(evdev); } +static enum libinput_config_status +tp_tap_config_set_draglock_enabled(struct libinput_device *device, + enum libinput_config_drag_lock_state enabled) +{ + return LIBINPUT_CONFIG_STATUS_UNSUPPORTED; +} + +static enum libinput_config_drag_lock_state +tp_tap_config_get_draglock_enabled(struct libinput_device *device) +{ + return LIBINPUT_CONFIG_DRAG_LOCK_ENABLED; +} + +static enum libinput_config_drag_lock_state +tp_tap_config_get_default_draglock_enabled(struct libinput_device *device) +{ + return LIBINPUT_CONFIG_DRAG_LOCK_ENABLED; +} + int tp_init_tap(struct tp_dispatch *tp) { @@ -852,6 +871,9 @@ tp_init_tap(struct tp_dispatch *tp) tp->tap.config.set_enabled = tp_tap_config_set_enabled; tp->tap.config.get_enabled = tp_tap_config_is_enabled; tp->tap.config.get_default = tp_tap_config_get_default; + tp->tap.config.set_draglock_enabled = tp_tap_config_set_draglock_enabled; + tp->tap.config.get_draglock_enabled = tp_tap_config_get_draglock_enabled; + tp->tap.config.get_default_draglock_enabled = tp_tap_config_get_default_draglock_enabled; tp->device->base.config.tap = &tp->tap.config; tp->tap.state = TAP_STATE_IDLE; diff --git a/src/libinput-private.h b/src/libinput-private.h index a7c8838c..5192b651 100644 --- a/src/libinput-private.h +++ b/src/libinput-private.h @@ -117,6 +117,11 @@ struct libinput_device_config_tap { enum libinput_config_tap_state enable); enum libinput_config_tap_state (*get_enabled)(struct libinput_device *device); enum libinput_config_tap_state (*get_default)(struct libinput_device *device); + + enum libinput_config_status (*set_draglock_enabled)(struct libinput_device *device, + enum libinput_config_drag_lock_state); + enum libinput_config_drag_lock_state (*get_draglock_enabled)(struct libinput_device *device); + enum libinput_config_drag_lock_state (*get_default_draglock_enabled)(struct libinput_device *device); }; struct libinput_device_config_calibration { diff --git a/src/libinput.c b/src/libinput.c index 7a097c01..319934ac 100644 --- a/src/libinput.c +++ b/src/libinput.c @@ -1736,6 +1736,39 @@ libinput_device_config_tap_get_default_enabled(struct libinput_device *device) return device->config.tap->get_default(device); } +LIBINPUT_EXPORT enum libinput_config_status +libinput_device_config_tap_set_drag_lock_enabled(struct libinput_device *device, + enum libinput_config_drag_lock_state enable) +{ + if (enable != LIBINPUT_CONFIG_DRAG_LOCK_ENABLED && + enable != LIBINPUT_CONFIG_DRAG_LOCK_DISABLED) + return LIBINPUT_CONFIG_STATUS_INVALID; + + if (libinput_device_config_tap_get_finger_count(device) == 0) + return enable ? LIBINPUT_CONFIG_STATUS_UNSUPPORTED : + LIBINPUT_CONFIG_STATUS_SUCCESS; + + return device->config.tap->set_draglock_enabled(device, enable); +} + +LIBINPUT_EXPORT enum libinput_config_drag_lock_state +libinput_device_config_tap_get_drag_lock_enabled(struct libinput_device *device) +{ + if (libinput_device_config_tap_get_finger_count(device) == 0) + return LIBINPUT_CONFIG_DRAG_LOCK_DISABLED; + + return device->config.tap->get_draglock_enabled(device); +} + +LIBINPUT_EXPORT enum libinput_config_drag_lock_state +libinput_device_config_tap_get_default_drag_lock_enabled(struct libinput_device *device) +{ + if (libinput_device_config_tap_get_finger_count(device) == 0) + return LIBINPUT_CONFIG_DRAG_LOCK_DISABLED; + + return device->config.tap->get_default_draglock_enabled(device); +} + LIBINPUT_EXPORT int libinput_device_config_calibration_has_matrix(struct libinput_device *device) { diff --git a/src/libinput.h b/src/libinput.h index 0d3200f3..240900b6 100644 --- a/src/libinput.h +++ b/src/libinput.h @@ -1911,6 +1911,85 @@ libinput_device_config_tap_get_enabled(struct libinput_device *device); enum libinput_config_tap_state libinput_device_config_tap_get_default_enabled(struct libinput_device *device); +/** + * @ingroup config + */ +enum libinput_config_drag_lock_state { + /** Drag lock is to be disabled, or is currently disabled */ + LIBINPUT_CONFIG_DRAG_LOCK_DISABLED, + /** Drag lock is to be enabled, or is currently disabled */ + LIBINPUT_CONFIG_DRAG_LOCK_ENABLED, +}; + +/** + * @ingroup config + * + * Enable or disable drag-lock during tapping on this device. When enabled, + * a finger may be lifted and put back on the touchpad within a timeout and + * the drag process continues. When disabled, lifting the finger during a + * tap-and-drag will immediately stop the drag. See @ref tapndrag for + * details. + * + * Enabling drag lock on a device that has tapping disabled is permitted, + * but has no effect until tapping is enabled. + * + * @param device The device to configure + * @param enable @ref LIBINPUT_CONFIG_DRAG_LOCK_ENABLED to enable drag lock + * or @ref LIBINPUT_CONFIG_DRAG_LOCK_DISABLED to disable drag lock + * + * @return A config status code. Disabling drag lock on a device that does not + * support tapping always succeeds. + * + * @see libinput_device_config_tap_get_drag_lock_enabled + * @see libinput_device_config_tap_get_default_drag_lock_enabled + */ +enum libinput_config_status +libinput_device_config_tap_set_drag_lock_enabled(struct libinput_device *device, + enum libinput_config_drag_lock_state enable); + +/** + * @ingroup config + * + * Check if drag-lock during tapping is enabled on this device. If the + * device does not support tapping, this function always returns + * @ref LIBINPUT_CONFIG_DRAG_LOCK_DISABLED. + * + * Drag lock may be enabled even when tapping is disabled. + * + * @param device The device to configure + * + * @retval LIBINPUT_CONFIG_DRAG_LOCK_ENABLED If drag lock is currently enabled + * @retval LIBINPUT_CONFIG_DRAG_LOCK_DISABLED If drag lock is currently disabled + * + * @see libinput_device_config_tap_set_drag_lock_enabled + * @see libinput_device_config_tap_get_default_drag_lock_enabled + */ +enum libinput_config_drag_lock_state +libinput_device_config_tap_get_drag_lock_enabled(struct libinput_device *device); + +/** + * @ingroup config + * + * Check if drag-lock during tapping is enabled by default on this device. + * If the device does not support tapping, this function always returns + * @ref LIBINPUT_CONFIG_DRAG_LOCK_DISABLED. + * + * Drag lock may be enabled by default even when tapping is disabled by + * default. + * + * @param device The device to configure + * + * @retval LIBINPUT_CONFIG_DRAG_LOCK_ENABLED If drag lock is enabled by + * default + * @retval LIBINPUT_CONFIG_DRAG_LOCK_DISABLED If drag lock is disabled by + * default + * + * @see libinput_device_config_tap_set_drag_lock_enabled + * @see libinput_device_config_tap_get_drag_lock_enabled + */ +enum libinput_config_drag_lock_state +libinput_device_config_tap_get_default_drag_lock_enabled(struct libinput_device *device); + /** * @ingroup config * diff --git a/src/libinput.sym b/src/libinput.sym index 9c11174b..2c023367 100644 --- a/src/libinput.sym +++ b/src/libinput.sym @@ -140,3 +140,9 @@ LIBINPUT_0.15.0 { global: libinput_device_keyboard_has_key; } LIBINPUT_0.14.0; + +LIBINPUT_0.19.0 { + libinput_device_config_tap_set_drag_lock_enabled; + libinput_device_config_tap_get_drag_lock_enabled; + libinput_device_config_tap_get_default_drag_lock_enabled; +} LIBINPUT_0.15.0; diff --git a/tools/libinput-list-devices.c b/tools/libinput-list-devices.c index d76e5db5..b3f7e2f9 100644 --- a/tools/libinput-list-devices.c +++ b/tools/libinput-list-devices.c @@ -78,6 +78,18 @@ tap_default(struct libinput_device *device) return "disabled"; } +static const char * +draglock_default(struct libinput_device *device) +{ + if (!libinput_device_config_tap_get_finger_count(device)) + return "n/a"; + + if (libinput_device_config_tap_get_default_drag_lock_enabled(device)) + return "enabled"; + else + return "disabled"; +} + static const char* left_handed_default(struct libinput_device *device) { @@ -238,6 +250,7 @@ print_device_notify(struct libinput_event *ev) printf("\n"); printf("Tap-to-click: %s\n", tap_default(dev)); + printf("Tap drag lock: %s\n", draglock_default(dev)); printf("Left-handed: %s\n", left_handed_default(dev)); printf("Nat.scrolling: %s\n", nat_scroll_default(dev)); printf("Middle emulation: %s\n", middle_emulation_default(dev));