diff --git a/doc/tapping.dox b/doc/tapping.dox index e7044005..82626821 100644 --- a/doc/tapping.dox +++ b/doc/tapping.dox @@ -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" diff --git a/doc/touchpad-tap-state-machine.svg b/doc/touchpad-tap-state-machine.svg index 92fdb2b7..1bf640ec 100644 --- a/doc/touchpad-tap-state-machine.svg +++ b/doc/touchpad-tap-state-machine.svg @@ -1,1210 +1,1253 @@ - + - - - - - - - + + + + + + + - + IDLE - + - + TOUCH - + - + first - + finger down - - - + + + - + finger up - - - + + + - + button 1 - + press - + - + timeout - - - + + + - + move > - + threshold - - - + + + - + second - + finger down - - - + + + - + TOUCH_2 - + - + second - + finger up - - - + + + - + button 2 - + press - + - + move > - + threshold - + - + timeout - - - - - + + + + + - + button 1 - + release - + - + button 2 - + release - - - - - + + + + + - + TAPPED - + - + timeout - - - + + + - + first - + finger down - - - + + + - + DRAGGING - + - + first - + finger up - + - + btn1 - + release - - - - - - - + + + + + + + - + IDLE - + - + third - + finger down - - - + + + - + TOUCH_3 - - - + + + - + button 3 - + press - + - + button 3 - + release - - - + + + - + move > - + threshold - - - + + + - + IDLE - + - + timeout - - - + + + - + first - + finger up - - - + + + - + IDLE - + - + fourth - + finger down - - - - - + + + + + - + DRAGGING_OR_DOUBLETAP - - - + + + - + timeout - - - + + + - + first - + finger up - - - + + + - + button 1 - + release - + - + button 1 - + press - + - + btn1 - + release - - - + + + - + second - + finger down - - - + + + - + move > - + threshold - - - - - + + + + + - + HOLD - + - + first - + finger up - - - - - + + + + + - + second - + finger down - - - - - + + + + + - + TOUCH_2_HOLD - + - + second - + finger up - - - + + + - + first - + finger up - - - - - - - + + + + + + + - + third - + finger down - - - - - - - + + + + + + + - + TOUCH_3_HOLD - - - + + + - + fourth - + finger down - + - + DEAD - - - - - - - + + + + + + + - + any finger up - + - + fourth - + finger up - + - + any finger up - - - - + + + + - - + + yes - + - + any finger up - - - - - - - - - + + + + + + + + + - + IDLE - + - + if finger - + count == 0 - - - - - - - + + + + + + + - + second - + finger up - + - + DRAGGING_2 - - - - - + + + + + - + first - + finger up - - - - - - - + + + + + + + - + second - + finger down - - - - - - - + + + + + + + - + third - + finger down - - - + + + - + btn1 - + release - - - + + + - + phys - + button - + press - - - - - - - - - - - - - + + + + + + + + + + + + + - + phys - + button - + press - - - + + + - + button 1 - + release - - - - - - - - - - - + + + + + + + + + + + - + DRAGGING_WAIT - + - + timeout - - - - - - - + + + + + + + - + first - + finger down - - - + + + - + TOUCH_TOUCH - + - + TOUCH_IDLE - - - - - - - - - + + + + + + + + + - + TOUCH_DEAD - - - - - - - - - + + + + + + + + + - + TOUCH_DEAD - - - - - - - + + + + + + + - + TOUCH_IDLE - - - + + + - + TOUCH_TOUCH - - - - - + + + + + - + TOUCH_IDLE - - - + + + - + TOUCH_IDLE - - - + + + - + TOUCH_TOUCH - - - + + + - + that finger - + TOUCH_IDLE - - - + + + - + TOUCH_DEAD - - - - - - - + + + + + + + - + that finger - + TOUCH_IDLE - - - - + + + + - - + + no - + - + TOUCH_TOUCH - - - + + + - + TOUCH_IDLE - + - + TOUCH_TOUCH - - - + + + - + TOUCH_DEAD - - - - - + + + + + - + TOUCH_IDLE - - - + + + - + TOUCH_TOUCH - + - + TOUCH_TOUCH - - - + + + - + TOUCH_IDLE - - - + + + - + TOUCH_IDLE - - - + + + - + TOUCH_TOUCH - - - + + + - + TOUCH_IDLE - - - + + + - + TOUCH_TOUCH - - - + + + - + that finger - + TOUCH_IDLE - - - + + + - + TOUCH_DEAD - - - + + + - + TOUCH_DEAD - + - + TOUCH_DEAD - + - + TOUCH_DEAD - - - + + + - + TOUCH_DEAD - - - + + + - + TOUCH_DEAD - - - + + + - + that finger state == - + TOUCH_TOUCH - + - + TOUCH_DEAD - - - + + + - + TOUCH_DEAD - + - + TOUCH_DEAD - + - + first - + finger down - + - + MULTITAP - - - - - + + + + + - + timeout - - - - - + + + + + - + IDLE - - - - - - - + + + + + + + - + MULTITAP_DOWN - + - + button 1 - + press - - - - - + + + + + - + first - + finger up - - - + + + - + button 1 - + release - - - + + + - + timeout - + - + second - + finger down - + - + move > - + threshold - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - + TOUCH_TOUCH - - - + + + - + TOUCH_IDLE - - - + + + - + phys - + button - + press - - - - - - - + + + + + + + - + DRAGGING_OR_TAP - + - + first - + finger up - - - + + + - + timeout - - - - - + + + + + - + move > - + threshold - - - - - - - - - - - + + + + + + + + + + + - + TOUCH_IDLE - - - - - - - - + + + + + + + + - -
+ +
drag lock
enabled?
- + [Not supported by viewer] - - - + + + - +
no
- + [Not supported by viewer]
- - - + + + - +
yes
- + [Not supported by viewer]
- + - + thumb - - - + + + - + TOUCH_DEAD - - - - - - - + + + + + + + - + TOUCH_2_RELEASE - + - + second - + finger up - - - + + + - + timeout - - - + + + - + move > - + threshold - - - - - - - - - + + + + + + + + + - + first - + finger down - - - - - + + + + + - + TOUCH_IDLE - - - + + + - + first - + finger up - - - - - + + + + + - + second - + finger down - - - + + + - + TOUCH_DEAD - + - + TOUCH_DEAD - - - - - - - - + + + + + + + + + + + + + +
+
+ no
+
+
+ + [Not supported by viewer] +
+
+ + + + + +
+
+ yes
+
+
+ + [Not supported by viewer] +
+
+ + + + +
+
+ drag
+ disabled?
+
+
+
+ + [Not supported by viewer] +
+
diff --git a/src/evdev-mt-touchpad-tap.c b/src/evdev-mt-touchpad-tap.c index 5556ee94..232cd6a5 100644 --- a/src/evdev-mt-touchpad-tap.c +++ b/src/evdev-mt-touchpad-tap.c @@ -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, diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h index 8564a103..0053122b 100644 --- a/src/evdev-mt-touchpad.h +++ b/src/evdev-mt-touchpad.h @@ -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; diff --git a/src/libinput-private.h b/src/libinput-private.h index 3dff3a84..bc7000d7 100644 --- a/src/libinput-private.h +++ b/src/libinput-private.h @@ -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); diff --git a/src/libinput.c b/src/libinput.c index aaeff9a3..2bcd416e 100644 --- a/src/libinput.c +++ b/src/libinput.c @@ -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) diff --git a/src/libinput.h b/src/libinput.h index 500224df..8ed5632b 100644 --- a/src/libinput.h +++ b/src/libinput.h @@ -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 */ diff --git a/src/libinput.sym b/src/libinput.sym index 666f3668..40143d8d 100644 --- a/src/libinput.sym +++ b/src/libinput.sym @@ -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; diff --git a/test/litest.h b/test/litest.h index 99f654af..4d965769 100644 --- a/test/litest.h +++ b/test/litest.h @@ -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) { diff --git a/test/touchpad-tap.c b/test/touchpad-tap.c index 7f23671f..8383aa93 100644 --- a/test/touchpad-tap.c +++ b/test/touchpad-tap.c @@ -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); } diff --git a/tools/libinput-list-devices.c b/tools/libinput-list-devices.c index 62eb915b..30bb2c43 100644 --- a/tools/libinput-list-devices.c +++ b/tools/libinput-list-devices.c @@ -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)); diff --git a/tools/shared.c b/tools/shared.c index 5fe5862c..29af9ef5 100644 --- a/tools/shared.c +++ b/tools/shared.c @@ -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); diff --git a/tools/shared.h b/tools/shared.h index 0065fcc0..14ed9ccb 100644 --- a/tools/shared.h +++ b/tools/shared.h @@ -39,6 +39,7 @@ struct tools_options { int verbose; int tapping; + int drag; int drag_lock; int natural_scroll; int left_handed;