Add configuration interface for tap drag-lock

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@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
This commit is contained in:
Peter Hutterer 2015-06-16 17:02:02 +10:00
parent 3fcdba6ca6
commit 75581d5829
7 changed files with 171 additions and 6 deletions

View file

@ -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.

View file

@ -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;

View file

@ -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 {

View file

@ -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)
{

View file

@ -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
*

View file

@ -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;

View file

@ -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));