Merge branch 'master' into tablet-support

This commit is contained in:
Peter Hutterer 2016-01-27 13:54:00 +10:00
commit ae41aa146d
13 changed files with 1165 additions and 709 deletions

View file

@ -28,12 +28,16 @@ libinput_device_config_tap_set_enabled() for details.
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.
Tap-and-drag is optional and can be enabled or disabled with
libinput_device_config_tap_set_drag_enabled(). Most devices have
tap-and-drag enabled by default.
Optional is a feature called "drag lock". With drag lock disabled, lifting
Also 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().
Note that drag lock only applies if tap-and-drag is be enabled.
@image html tap-n-drag.svg "Tap-and-drag process"

File diff suppressed because it is too large Load diff

Before

Width:  |  Height:  |  Size: 134 KiB

After

Width:  |  Height:  |  Size: 127 KiB

View file

@ -153,6 +153,7 @@ tp_tap_idle_handle_event(struct tp_dispatch *tp,
switch (event) {
case TAP_EVENT_TOUCH:
tp->tap.state = TAP_STATE_TOUCH;
tp->tap.first_press_time = time;
tp_tap_set_timer(tp, time);
break;
case TAP_EVENT_RELEASE:
@ -185,9 +186,14 @@ tp_tap_touch_handle_event(struct tp_dispatch *tp,
tp_tap_set_timer(tp, time);
break;
case TAP_EVENT_RELEASE:
tp->tap.state = TAP_STATE_TAPPED;
tp_tap_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_PRESSED);
tp_tap_set_timer(tp, time);
tp_tap_notify(tp, tp->tap.first_press_time, 1, LIBINPUT_BUTTON_STATE_PRESSED);
if (tp->tap.drag_enabled) {
tp->tap.state = TAP_STATE_TAPPED;
tp_tap_set_timer(tp, time);
} else {
tp_tap_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_RELEASED);
tp->tap.state = TAP_STATE_IDLE;
}
break;
case TAP_EVENT_TIMEOUT:
case TAP_EVENT_MOTION:
@ -928,6 +934,44 @@ tp_tap_config_get_default(struct libinput_device *device)
return tp_tap_default(evdev);
}
static enum libinput_config_status
tp_tap_config_set_drag_enabled(struct libinput_device *device,
enum libinput_config_drag_state enabled)
{
struct evdev_dispatch *dispatch = ((struct evdev_device *) device)->dispatch;
struct tp_dispatch *tp = NULL;
tp = container_of(dispatch, tp, base);
tp->tap.drag_enabled = enabled;
return LIBINPUT_CONFIG_STATUS_SUCCESS;
}
static enum libinput_config_drag_state
tp_tap_config_get_drag_enabled(struct libinput_device *device)
{
struct evdev_device *evdev = (struct evdev_device *)device;
struct tp_dispatch *tp = NULL;
tp = container_of(evdev->dispatch, tp, base);
return tp->tap.drag_enabled;
}
static inline enum libinput_config_drag_state
tp_drag_default(struct evdev_device *device)
{
return LIBINPUT_CONFIG_DRAG_ENABLED;
}
static enum libinput_config_drag_state
tp_tap_config_get_default_drag_enabled(struct libinput_device *device)
{
struct evdev_device *evdev = (struct evdev_device *)device;
return tp_drag_default(evdev);
}
static enum libinput_config_status
tp_tap_config_set_draglock_enabled(struct libinput_device *device,
enum libinput_config_drag_lock_state enabled)
@ -973,6 +1017,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_drag_enabled = tp_tap_config_set_drag_enabled;
tp->tap.config.get_drag_enabled = tp_tap_config_get_drag_enabled;
tp->tap.config.get_default_drag_enabled = tp_tap_config_get_default_drag_enabled;
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;
@ -980,6 +1027,7 @@ tp_init_tap(struct tp_dispatch *tp)
tp->tap.state = TAP_STATE_IDLE;
tp->tap.enabled = tp_tap_default(tp->device);
tp->tap.drag_enabled = tp_drag_default(tp->device);
tp->tap.drag_lock_enabled = tp_drag_lock_default(tp->device);
libinput_timer_init(&tp->tap.timer,

View file

@ -312,7 +312,9 @@ struct tp_dispatch {
struct libinput_timer timer;
enum tp_tap_state state;
uint32_t buttons_pressed;
uint64_t first_press_time;
bool drag_enabled;
bool drag_lock_enabled;
} tap;

View file

@ -145,6 +145,11 @@ struct libinput_device_config_tap {
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_drag_enabled)(struct libinput_device *device,
enum libinput_config_drag_state);
enum libinput_config_drag_state (*get_drag_enabled)(struct libinput_device *device);
enum libinput_config_drag_state (*get_default_drag_enabled)(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);

View file

@ -2898,6 +2898,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_enabled(struct libinput_device *device,
enum libinput_config_drag_state enable)
{
if (enable != LIBINPUT_CONFIG_DRAG_ENABLED &&
enable != LIBINPUT_CONFIG_DRAG_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_drag_enabled(device, enable);
}
LIBINPUT_EXPORT enum libinput_config_drag_state
libinput_device_config_tap_get_drag_enabled(struct libinput_device *device)
{
if (libinput_device_config_tap_get_finger_count(device) == 0)
return LIBINPUT_CONFIG_DRAG_DISABLED;
return device->config.tap->get_drag_enabled(device);
}
LIBINPUT_EXPORT enum libinput_config_drag_state
libinput_device_config_tap_get_default_drag_enabled(struct libinput_device *device)
{
if (libinput_device_config_tap_get_finger_count(device) == 0)
return LIBINPUT_CONFIG_DRAG_DISABLED;
return device->config.tap->get_default_drag_enabled(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)

View file

@ -3092,6 +3092,79 @@ 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
*
* A config status to distinguish or set dragging on a device. Currently
* implemented for tap-and-drag only, see
* libinput_device_config_tap_set_drag_enabled()
*/
enum libinput_config_drag_state {
/**
* Drag is to be disabled, or is
* currently disabled.
*/
LIBINPUT_CONFIG_DRAG_DISABLED,
/**
* Drag is to be enabled, or is
* currently enabled
*/
LIBINPUT_CONFIG_DRAG_ENABLED,
};
/**
* @ingroup config
*
* Enable or disable tap-and-drag on this device. When enabled, a
* single-finger tap immediately followed by a finger down results in a
* button down event, subsequent finger motion thus triggers a drag. The
* button is released on finger up. See @ref tapndrag for more details.
*
* @param device The device to configure
* @param enable @ref LIBINPUT_CONFIG_DRAG_ENABLED to enable, @ref
* LIBINPUT_CONFIG_DRAG_DISABLED to disable tap-and-drag
*
* @see libinput_device_config_tap_drag_get_enabled
* @see libinput_device_config_tap_drag_get_default_enabled
*/
enum libinput_config_status
libinput_device_config_tap_set_drag_enabled(struct libinput_device *device,
enum libinput_config_drag_state enable);
/**
* @ingroup config
*
* Return whether tap-and-drag is enabled or disabled on this device.
*
* @param device The device to check
* @retval LIBINPUT_CONFIG_DRAG_ENABLED if tap-and-drag is enabled
* @retval LIBINPUT_CONFIG_DRAG_DISABLED if tap-and-drag is
* disabled
*
* @see libinput_device_config_tap_drag_set_enabled
* @see libinput_device_config_tap_drag_get_default_enabled
*/
enum libinput_config_drag_state
libinput_device_config_tap_get_drag_enabled(struct libinput_device *device);
/**
* @ingroup config
*
* Return whether tap-and-drag is enabled or disabled by default on this
* device.
*
* @param device The device to check
* @retval LIBINPUT_CONFIG_DRAG_ENABLED if tap-and-drag is enabled by
* default
* @retval LIBINPUT_CONFIG_DRAG_DISABLED if tap-and-drag is
* disabled by default
*
* @see libinput_device_config_tap_drag_set_enabled
* @see libinput_device_config_tap_drag_get_enabled
*/
enum libinput_config_drag_state
libinput_device_config_tap_get_default_drag_enabled(struct libinput_device *device);
/**
* @ingroup config
*/

View file

@ -181,6 +181,12 @@ LIBINPUT_1.1 {
libinput_device_config_accel_set_profile;
} LIBINPUT_0.21.0;
LIBINPUT_1.2 {
libinput_device_config_tap_get_drag_enabled;
libinput_device_config_tap_get_default_drag_enabled;
libinput_device_config_tap_set_drag_enabled;
} LIBINPUT_1.1;
/* tablet APIs, they are not part of any stable API promise yet.
* keep them separate */
LIBINPUT_TABLET_SUPPORT {
@ -232,4 +238,4 @@ LIBINPUT_TABLET_SUPPORT {
libinput_tablet_tool_ref;
libinput_tablet_tool_set_user_data;
libinput_tablet_tool_unref;
} LIBINPUT_1.1;
} LIBINPUT_1.2;

View file

@ -537,6 +537,30 @@ litest_disable_tap(struct libinput_device *device)
litest_assert_int_eq(status, expected);
}
static inline void
litest_enable_tap_drag(struct libinput_device *device)
{
enum libinput_config_status status, expected;
expected = LIBINPUT_CONFIG_STATUS_SUCCESS;
status = libinput_device_config_tap_set_drag_enabled(device,
LIBINPUT_CONFIG_DRAG_ENABLED);
litest_assert_int_eq(status, expected);
}
static inline void
litest_disable_tap_drag(struct libinput_device *device)
{
enum libinput_config_status status, expected;
expected = LIBINPUT_CONFIG_STATUS_SUCCESS;
status = libinput_device_config_tap_set_drag_enabled(device,
LIBINPUT_CONFIG_DRAG_DISABLED);
litest_assert_int_eq(status, expected);
}
static inline bool
litest_has_2fg_scroll(struct litest_device *dev)
{

View file

@ -1723,6 +1723,187 @@ START_TEST(touchpad_tap_invalid)
}
END_TEST
START_TEST(touchpad_drag_default_disabled)
{
struct litest_device *dev = litest_current_device();
/* this test is only run on specific devices */
ck_assert_int_eq(libinput_device_config_tap_get_default_drag_enabled(dev->libinput_device),
LIBINPUT_CONFIG_DRAG_DISABLED);
}
END_TEST
START_TEST(touchpad_drag_default_enabled)
{
struct litest_device *dev = litest_current_device();
/* this test is only run on specific devices */
ck_assert_int_eq(libinput_device_config_tap_get_default_drag_enabled(dev->libinput_device),
LIBINPUT_CONFIG_DRAG_ENABLED);
}
END_TEST
START_TEST(touchpad_drag_config_invalid)
{
struct litest_device *dev = litest_current_device();
ck_assert_int_eq(libinput_device_config_tap_set_drag_enabled(dev->libinput_device, 2),
LIBINPUT_CONFIG_STATUS_INVALID);
ck_assert_int_eq(libinput_device_config_tap_set_drag_enabled(dev->libinput_device, -1),
LIBINPUT_CONFIG_STATUS_INVALID);
}
END_TEST
START_TEST(touchpad_drag_config_enabledisable)
{
struct litest_device *dev = litest_current_device();
enum libinput_config_drag_state state;
litest_enable_tap(dev->libinput_device);
litest_disable_tap_drag(dev->libinput_device);
state = libinput_device_config_tap_get_drag_enabled(dev->libinput_device);
ck_assert_int_eq(state, LIBINPUT_CONFIG_DRAG_DISABLED);
litest_enable_tap_drag(dev->libinput_device);
state = libinput_device_config_tap_get_drag_enabled(dev->libinput_device);
ck_assert_int_eq(state, LIBINPUT_CONFIG_DRAG_ENABLED);
/* same thing with tapping disabled */
litest_enable_tap(dev->libinput_device);
litest_disable_tap_drag(dev->libinput_device);
state = libinput_device_config_tap_get_drag_enabled(dev->libinput_device);
ck_assert_int_eq(state, LIBINPUT_CONFIG_DRAG_DISABLED);
litest_enable_tap_drag(dev->libinput_device);
state = libinput_device_config_tap_get_drag_enabled(dev->libinput_device);
ck_assert_int_eq(state, LIBINPUT_CONFIG_DRAG_ENABLED);
}
END_TEST
START_TEST(touchpad_drag_disabled)
{
struct litest_device *dev = litest_current_device();
struct libinput *li = dev->libinput;
litest_enable_tap(dev->libinput_device);
litest_disable_tap_drag(dev->libinput_device);
litest_drain_events(li);
litest_touch_down(dev, 0, 50, 50);
litest_touch_up(dev, 0);
libinput_dispatch(li);
litest_touch_down(dev, 0, 50, 50);
litest_touch_move_to(dev, 0, 50, 50, 90, 90, 10, 0);
litest_touch_up(dev, 0);
libinput_dispatch(li);
litest_assert_button_event(li,
BTN_LEFT,
LIBINPUT_BUTTON_STATE_PRESSED);
litest_assert_button_event(li,
BTN_LEFT,
LIBINPUT_BUTTON_STATE_RELEASED);
litest_assert_only_typed_events(li,
LIBINPUT_EVENT_POINTER_MOTION);
}
END_TEST
START_TEST(touchpad_drag_disabled_immediate)
{
struct litest_device *dev = litest_current_device();
struct libinput *li = dev->libinput;
struct libinput_event *ev;
struct libinput_event_pointer *ptrev;
uint64_t press_time, release_time;
litest_enable_tap(dev->libinput_device);
litest_disable_tap_drag(dev->libinput_device);
litest_drain_events(li);
litest_touch_down(dev, 0, 50, 50);
msleep(10); /* to force a time difference */
libinput_dispatch(li);
litest_touch_up(dev, 0);
libinput_dispatch(li);
ev = libinput_get_event(li);
ptrev = litest_is_button_event(ev,
BTN_LEFT,
LIBINPUT_BUTTON_STATE_PRESSED);
press_time = libinput_event_pointer_get_time(ptrev);
libinput_event_destroy(ev);
ev = libinput_get_event(li);
ptrev = litest_is_button_event(ev,
BTN_LEFT,
LIBINPUT_BUTTON_STATE_RELEASED);
release_time = libinput_event_pointer_get_time(ptrev);
libinput_event_destroy(ev);
ck_assert_int_gt(release_time, press_time);
}
END_TEST
START_TEST(touchpad_drag_disabled_multitap_no_drag)
{
struct litest_device *dev = litest_current_device();
struct libinput *li = dev->libinput;
struct libinput_event *event;
struct libinput_event_pointer *ptrev;
uint32_t oldtime = 0,
curtime;
int range = _i, /* looped test */
ntaps;
litest_enable_tap(dev->libinput_device);
litest_disable_tap_drag(dev->libinput_device);
litest_drain_events(li);
for (ntaps = 0; ntaps <= range; ntaps++) {
litest_touch_down(dev, 0, 50, 50);
litest_touch_up(dev, 0);
libinput_dispatch(li);
msleep(10);
}
libinput_dispatch(li);
litest_touch_down(dev, 0, 50, 50);
litest_touch_move_to(dev, 0, 50, 50, 70, 50, 10, 4);
libinput_dispatch(li);
for (ntaps = 0; ntaps <= range; ntaps++) {
event = libinput_get_event(li);
ptrev = litest_is_button_event(event,
BTN_LEFT,
LIBINPUT_BUTTON_STATE_PRESSED);
curtime = libinput_event_pointer_get_time(ptrev);
libinput_event_destroy(event);
ck_assert_int_gt(curtime, oldtime);
event = libinput_get_event(li);
ptrev = litest_is_button_event(event,
BTN_LEFT,
LIBINPUT_BUTTON_STATE_RELEASED);
curtime = libinput_event_pointer_get_time(ptrev);
libinput_event_destroy(event);
ck_assert_int_ge(curtime, oldtime);
oldtime = curtime;
}
litest_assert_only_typed_events(li,
LIBINPUT_EVENT_POINTER_MOTION);
litest_assert_empty_queue(li);
}
END_TEST
START_TEST(touchpad_drag_lock_default_disabled)
{
struct litest_device *dev = litest_current_device();
@ -1838,4 +2019,11 @@ litest_setup_tests(void)
litest_add("tap:draglock", touchpad_drag_lock_default_disabled, LITEST_TOUCHPAD, LITEST_ANY);
litest_add("tap:draglock", touchpad_drag_lock_default_unavailable, LITEST_ANY, LITEST_TOUCHPAD);
litest_add("tap:drag", touchpad_drag_default_disabled, LITEST_ANY, LITEST_TOUCHPAD);
litest_add("tap:drag", touchpad_drag_default_enabled, LITEST_TOUCHPAD, LITEST_BUTTON);
litest_add("tap:drag", touchpad_drag_config_invalid, LITEST_TOUCHPAD, LITEST_ANY);
litest_add("tap:drag", touchpad_drag_config_enabledisable, LITEST_TOUCHPAD, LITEST_ANY);
litest_add("tap:drag", touchpad_drag_disabled, LITEST_TOUCHPAD, LITEST_ANY);
litest_add("tap:drag", touchpad_drag_disabled_immediate, LITEST_TOUCHPAD, LITEST_ANY);
litest_add_ranged("tap:drag", touchpad_drag_disabled_multitap_no_drag, LITEST_TOUCHPAD, LITEST_ANY, &multitap_range);
}

View file

@ -47,6 +47,18 @@ tap_default(struct libinput_device *device)
return "disabled";
}
static const char *
drag_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_enabled(device))
return "enabled";
else
return "disabled";
}
static const char *
draglock_default(struct libinput_device *device)
{
@ -263,6 +275,7 @@ print_device_notify(struct libinput_event *ev)
printf("\n");
printf("Tap-to-click: %s\n", tap_default(dev));
printf("Tap-and-drag: %s\n", drag_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));

View file

@ -45,6 +45,8 @@ enum options {
OPT_VERBOSE,
OPT_TAP_ENABLE,
OPT_TAP_DISABLE,
OPT_DRAG_ENABLE,
OPT_DRAG_DISABLE,
OPT_DRAG_LOCK_ENABLE,
OPT_DRAG_LOCK_DISABLE,
OPT_NATURAL_SCROLL_ENABLE,
@ -82,6 +84,8 @@ tools_usage()
"Features:\n"
"--enable-tap\n"
"--disable-tap.... enable/disable tapping\n"
"--enable-drag\n"
"--disable-drag.... enable/disable tap-n-drag\n"
"--enable-drag-lock\n"
"--disable-drag-lock.... enable/disable tapping drag lock\n"
"--enable-natural-scrolling\n"
@ -117,6 +121,7 @@ tools_init_context(struct tools_context *context)
memset(options, 0, sizeof(*options));
options->tapping = -1;
options->drag = -1;
options->drag_lock = -1;
options->natural_scroll = -1;
options->left_handed = -1;
@ -147,6 +152,8 @@ tools_parse_args(int argc, char **argv, struct tools_context *context)
{ "verbose", 0, 0, OPT_VERBOSE },
{ "enable-tap", 0, 0, OPT_TAP_ENABLE },
{ "disable-tap", 0, 0, OPT_TAP_DISABLE },
{ "enable-drag", 0, 0, OPT_DRAG_ENABLE },
{ "disable-drag", 0, 0, OPT_DRAG_DISABLE },
{ "enable-drag-lock", 0, 0, OPT_DRAG_LOCK_ENABLE },
{ "disable-drag-lock", 0, 0, OPT_DRAG_LOCK_DISABLE },
{ "enable-natural-scrolling", 0, 0, OPT_NATURAL_SCROLL_ENABLE },
@ -199,6 +206,12 @@ tools_parse_args(int argc, char **argv, struct tools_context *context)
case OPT_TAP_DISABLE:
options->tapping = 0;
break;
case OPT_DRAG_ENABLE:
options->drag = 1;
break;
case OPT_DRAG_DISABLE:
options->drag = 0;
break;
case OPT_DRAG_LOCK_ENABLE:
options->drag_lock = 1;
break;
@ -438,6 +451,9 @@ tools_device_apply_config(struct libinput_device *device,
{
if (options->tapping != -1)
libinput_device_config_tap_set_enabled(device, options->tapping);
if (options->drag != -1)
libinput_device_config_tap_set_drag_enabled(device,
options->drag);
if (options->drag_lock != -1)
libinput_device_config_tap_set_drag_lock_enabled(device,
options->drag_lock);

View file

@ -39,6 +39,7 @@ struct tools_options {
int verbose;
int tapping;
int drag;
int drag_lock;
int natural_scroll;
int left_handed;