[PATCH libinput 2/5] Add configuration interface for tap drag-lock

Peter Hutterer peter.hutterer at who-t.net
Sun Jun 21 21:54:26 PDT 2015


In some applications, notably Inkscape, where it is common to frequently drag
objects a short distance the default to drag-lock always-on is frustrating for
users.
Make it configurable, with the current default to "on".
New API:
  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

Any device capable of tapping is capable of drag lock, there is no explicit
availability check for drag lock. Configuration is independent, drag lock may
be enabled when tapping is disabled.

In the tests, enable/disable drag-lock explicitly where the tests depend
on it.

https://bugs.freedesktop.org/show_bug.cgi?id=90928

Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
---
 doc/tapping.dox               | 19 +++++++----
 src/evdev-mt-touchpad-tap.c   | 22 ++++++++++++
 src/libinput-private.h        |  5 +++
 src/libinput.c                | 33 ++++++++++++++++++
 src/libinput.h                | 79 +++++++++++++++++++++++++++++++++++++++++++
 src/libinput.sym              |  6 ++++
 tools/libinput-list-devices.c | 13 +++++++
 7 files changed, 171 insertions(+), 6 deletions(-)

diff --git a/doc/tapping.dox b/doc/tapping.dox
index 1337fc5..483219a 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 2951ee6..5d986ca 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 a7c8838..5192b65 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 7a097c0..319934a 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 0d3200f..240900b 100644
--- a/src/libinput.h
+++ b/src/libinput.h
@@ -1913,6 +1913,85 @@ 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
  *
  * Check if the device can be calibrated via a calibration matrix.
  *
diff --git a/src/libinput.sym b/src/libinput.sym
index 9c11174..2c02336 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 d76e5db..b3f7e2f 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));
-- 
2.4.3



More information about the wayland-devel mailing list