mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2026-05-05 07:38:10 +02:00
touchpad: allow edge scrolling on clickpads
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net> Reviewed-by: Hans de Goede <hdegoede@redhat.com>
This commit is contained in:
parent
77aca3c194
commit
abff4a1c24
5 changed files with 230 additions and 17 deletions
|
|
@ -55,10 +55,8 @@ scroll).
|
|||
Due to the layout of the edges, diagonal scrolling is not possible. The
|
||||
behavior of edge scrolling using both edges at the same time is undefined.
|
||||
|
||||
Edge scrolling conflicts with @ref clickpad_softbuttons and is
|
||||
not usually available on clickpads. See
|
||||
http://who-t.blogspot.com.au/2015/03/why-libinput-doesnt-support-edge.html
|
||||
for details.
|
||||
Edge scrolling overlaps with @ref clickpad_softbuttons. A physical click on
|
||||
a clickpad ends scrolling.
|
||||
|
||||
@section button_scrolling On-Button scrolling
|
||||
|
||||
|
|
|
|||
|
|
@ -941,6 +941,10 @@ tp_notify_clickpadbutton(struct tp_dispatch *tp,
|
|||
if (tp->device->suspended)
|
||||
return 0;
|
||||
|
||||
/* A button click always terminates edge scrolling, even if we
|
||||
* don't end up sending a button event. */
|
||||
tp_edge_scroll_stop_events(tp, time);
|
||||
|
||||
/*
|
||||
* If the user has requested clickfinger replace the button chosen
|
||||
* by the softbutton code with one based on the number of fingers.
|
||||
|
|
|
|||
|
|
@ -34,7 +34,6 @@
|
|||
|
||||
#define CASE_RETURN_STRING(a) case a: return #a
|
||||
|
||||
#define DEFAULT_SCROLL_LOCK_TIMEOUT 300 /* ms */
|
||||
/* Use a reasonably large threshold until locked into scrolling mode, to
|
||||
avoid accidentally locking in scrolling mode when trying to use the entire
|
||||
touchpad to move the pointer. The user can wait for the timeout to trigger
|
||||
|
|
@ -92,6 +91,23 @@ tp_touch_get_edge(struct tp_dispatch *tp, struct tp_touch *t)
|
|||
return edge;
|
||||
}
|
||||
|
||||
static inline void
|
||||
tp_edge_scroll_set_timer(struct tp_dispatch *tp,
|
||||
struct tp_touch *t)
|
||||
{
|
||||
const int DEFAULT_SCROLL_LOCK_TIMEOUT = 300; /* ms */
|
||||
/* if we use software buttons, we disable timeout-based
|
||||
* edge scrolling. A finger resting on the button areas is
|
||||
* likely there to trigger a button event.
|
||||
*/
|
||||
if (tp->buttons.click_method ==
|
||||
LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS)
|
||||
return;
|
||||
|
||||
libinput_timer_set(&t->scroll.timer,
|
||||
t->millis + DEFAULT_SCROLL_LOCK_TIMEOUT);
|
||||
}
|
||||
|
||||
static void
|
||||
tp_edge_scroll_set_state(struct tp_dispatch *tp,
|
||||
struct tp_touch *t,
|
||||
|
|
@ -108,8 +124,7 @@ tp_edge_scroll_set_state(struct tp_dispatch *tp,
|
|||
case EDGE_SCROLL_TOUCH_STATE_EDGE_NEW:
|
||||
t->scroll.edge = tp_touch_get_edge(tp, t);
|
||||
t->scroll.initial = t->point;
|
||||
libinput_timer_set(&t->scroll.timer,
|
||||
t->millis + DEFAULT_SCROLL_LOCK_TIMEOUT);
|
||||
tp_edge_scroll_set_timer(tp, t);
|
||||
break;
|
||||
case EDGE_SCROLL_TOUCH_STATE_EDGE:
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -1349,14 +1349,11 @@ tp_scroll_config_scroll_method_get_methods(struct libinput_device *device)
|
|||
{
|
||||
struct evdev_device *evdev = (struct evdev_device*)device;
|
||||
struct tp_dispatch *tp = (struct tp_dispatch*)evdev->dispatch;
|
||||
uint32_t methods = LIBINPUT_CONFIG_SCROLL_NO_SCROLL;
|
||||
uint32_t methods = LIBINPUT_CONFIG_SCROLL_EDGE;
|
||||
|
||||
if (tp->ntouches >= 2)
|
||||
methods |= LIBINPUT_CONFIG_SCROLL_2FG;
|
||||
|
||||
if (!tp->buttons.is_clickpad)
|
||||
methods |= LIBINPUT_CONFIG_SCROLL_EDGE;
|
||||
|
||||
return methods;
|
||||
}
|
||||
|
||||
|
|
|
|||
211
test/touchpad.c
211
test/touchpad.c
|
|
@ -1490,6 +1490,42 @@ START_TEST(touchpad_edge_scroll)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_scroll_defaults)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput_device *device = dev->libinput_device;
|
||||
struct libevdev *evdev = dev->evdev;
|
||||
enum libinput_config_scroll_method method, expected;
|
||||
enum libinput_config_status status;
|
||||
|
||||
method = libinput_device_config_scroll_get_methods(device);
|
||||
ck_assert(method & LIBINPUT_CONFIG_SCROLL_EDGE);
|
||||
if (libevdev_get_num_slots(evdev) > 1)
|
||||
ck_assert(method & LIBINPUT_CONFIG_SCROLL_2FG);
|
||||
|
||||
if (libevdev_get_num_slots(evdev) > 1)
|
||||
expected = LIBINPUT_CONFIG_SCROLL_2FG;
|
||||
else
|
||||
expected = LIBINPUT_CONFIG_SCROLL_EDGE;
|
||||
|
||||
method = libinput_device_config_scroll_get_method(device);
|
||||
ck_assert_int_eq(method, expected);
|
||||
method = libinput_device_config_scroll_get_default_method(device);
|
||||
ck_assert_int_eq(method, expected);
|
||||
|
||||
status = libinput_device_config_scroll_set_method(device,
|
||||
LIBINPUT_CONFIG_SCROLL_EDGE);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||
status = libinput_device_config_scroll_set_method(device,
|
||||
LIBINPUT_CONFIG_SCROLL_2FG);
|
||||
|
||||
if (libevdev_get_num_slots(evdev) > 1)
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||
else
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_UNSUPPORTED);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_edge_scroll_timeout)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
|
|
@ -1639,6 +1675,164 @@ START_TEST(touchpad_edge_scroll_no_2fg)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_edge_scroll_into_buttonareas)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
|
||||
enable_buttonareas(dev);
|
||||
enable_edge_scroll(dev);
|
||||
litest_drain_events(li);
|
||||
|
||||
litest_touch_down(dev, 0, 99, 40);
|
||||
litest_touch_move_to(dev, 0, 99, 40, 99, 95, 10, 0);
|
||||
litest_assert_only_typed_events(li,
|
||||
LIBINPUT_EVENT_POINTER_AXIS);
|
||||
/* in the button zone now, make sure we still get events */
|
||||
litest_touch_move_to(dev, 0, 99, 95, 99, 100, 10, 0);
|
||||
litest_assert_only_typed_events(li,
|
||||
LIBINPUT_EVENT_POINTER_AXIS);
|
||||
|
||||
/* and out of the zone again */
|
||||
litest_touch_move_to(dev, 0, 99, 100, 99, 70, 10, 0);
|
||||
litest_assert_only_typed_events(li,
|
||||
LIBINPUT_EVENT_POINTER_AXIS);
|
||||
|
||||
/* still out of the zone */
|
||||
litest_touch_move_to(dev, 0, 99, 70, 99, 50, 10, 0);
|
||||
litest_assert_only_typed_events(li,
|
||||
LIBINPUT_EVENT_POINTER_AXIS);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_edge_scroll_within_buttonareas)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
|
||||
enable_buttonareas(dev);
|
||||
enable_edge_scroll(dev);
|
||||
litest_drain_events(li);
|
||||
|
||||
litest_touch_down(dev, 0, 20, 99);
|
||||
|
||||
/* within left button */
|
||||
litest_touch_move_to(dev, 0, 20, 99, 40, 99, 10, 0);
|
||||
litest_assert_only_typed_events(li,
|
||||
LIBINPUT_EVENT_POINTER_AXIS);
|
||||
|
||||
/* over to right button */
|
||||
litest_touch_move_to(dev, 0, 40, 99, 60, 99, 10, 0);
|
||||
litest_assert_only_typed_events(li,
|
||||
LIBINPUT_EVENT_POINTER_AXIS);
|
||||
|
||||
/* within right button */
|
||||
litest_touch_move_to(dev, 0, 60, 99, 80, 99, 10, 0);
|
||||
litest_assert_only_typed_events(li,
|
||||
LIBINPUT_EVENT_POINTER_AXIS);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_edge_scroll_buttonareas_click_stops_scroll)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
struct libinput_event *event;
|
||||
struct libinput_event_pointer *ptrev;
|
||||
double val;
|
||||
|
||||
enable_buttonareas(dev);
|
||||
enable_edge_scroll(dev);
|
||||
litest_drain_events(li);
|
||||
|
||||
litest_touch_down(dev, 0, 20, 95);
|
||||
litest_touch_move_to(dev, 0, 20, 95, 70, 95, 10, 5);
|
||||
litest_assert_only_typed_events(li,
|
||||
LIBINPUT_EVENT_POINTER_AXIS);
|
||||
|
||||
litest_button_click(dev, BTN_LEFT, true);
|
||||
libinput_dispatch(li);
|
||||
|
||||
event = libinput_get_event(li);
|
||||
ptrev = litest_is_axis_event(event,
|
||||
LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL,
|
||||
LIBINPUT_POINTER_AXIS_SOURCE_FINGER);
|
||||
val = libinput_event_pointer_get_axis_value(ptrev,
|
||||
LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL);
|
||||
ck_assert(val == 0.0);
|
||||
libinput_event_destroy(event);
|
||||
|
||||
event = libinput_get_event(li);
|
||||
ptrev = litest_is_button_event(event,
|
||||
BTN_RIGHT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
|
||||
libinput_event_destroy(event);
|
||||
|
||||
/* within button areas -> no movement */
|
||||
litest_touch_move_to(dev, 0, 70, 95, 90, 95, 10, 0);
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
litest_button_click(dev, BTN_LEFT, false);
|
||||
|
||||
litest_assert_only_typed_events(li,
|
||||
LIBINPUT_EVENT_POINTER_BUTTON);
|
||||
|
||||
litest_touch_up(dev, 0);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_edge_scroll_clickfinger_click_stops_scroll)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
struct libinput_event *event;
|
||||
struct libinput_event_pointer *ptrev;
|
||||
double val;
|
||||
|
||||
enable_clickfinger(dev);
|
||||
enable_edge_scroll(dev);
|
||||
litest_drain_events(li);
|
||||
|
||||
litest_touch_down(dev, 0, 20, 95);
|
||||
litest_touch_move_to(dev, 0, 20, 95, 70, 95, 10, 5);
|
||||
litest_assert_only_typed_events(li,
|
||||
LIBINPUT_EVENT_POINTER_AXIS);
|
||||
|
||||
litest_button_click(dev, BTN_LEFT, true);
|
||||
libinput_dispatch(li);
|
||||
|
||||
event = libinput_get_event(li);
|
||||
ptrev = litest_is_axis_event(event,
|
||||
LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL,
|
||||
LIBINPUT_POINTER_AXIS_SOURCE_FINGER);
|
||||
val = libinput_event_pointer_get_axis_value(ptrev,
|
||||
LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL);
|
||||
ck_assert(val == 0.0);
|
||||
libinput_event_destroy(event);
|
||||
|
||||
event = libinput_get_event(li);
|
||||
ptrev = litest_is_button_event(event,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
|
||||
libinput_event_destroy(event);
|
||||
|
||||
/* clickfinger releases pointer -> expect movement */
|
||||
litest_touch_move_to(dev, 0, 70, 95, 90, 95, 10, 0);
|
||||
litest_assert_only_typed_events(li,
|
||||
LIBINPUT_EVENT_POINTER_MOTION);
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
litest_button_click(dev, BTN_LEFT, false);
|
||||
|
||||
litest_assert_only_typed_events(li,
|
||||
LIBINPUT_EVENT_POINTER_BUTTON);
|
||||
|
||||
litest_touch_up(dev, 0);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
static int
|
||||
touchpad_has_palm_detect_size(struct litest_device *dev)
|
||||
{
|
||||
|
|
@ -3522,12 +3716,17 @@ litest_setup_tests(void)
|
|||
litest_add("touchpad:scroll", touchpad_scroll_natural_defaults, LITEST_TOUCHPAD, LITEST_ANY);
|
||||
litest_add("touchpad:scroll", touchpad_scroll_natural_enable_config, LITEST_TOUCHPAD, LITEST_ANY);
|
||||
litest_add("touchpad:scroll", touchpad_scroll_natural, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
|
||||
litest_add("touchpad:scroll", touchpad_edge_scroll, LITEST_TOUCHPAD, LITEST_CLICKPAD);
|
||||
litest_add("touchpad:scroll", touchpad_edge_scroll_no_motion, LITEST_TOUCHPAD, LITEST_CLICKPAD);
|
||||
litest_add("touchpad:scroll", touchpad_edge_scroll_no_edge_after_motion, LITEST_TOUCHPAD, LITEST_CLICKPAD);
|
||||
litest_add("touchpad:scroll", touchpad_edge_scroll_timeout, LITEST_TOUCHPAD, LITEST_CLICKPAD);
|
||||
litest_add("touchpad:scroll", touchpad_edge_scroll_source, LITEST_TOUCHPAD, LITEST_CLICKPAD);
|
||||
litest_add("touchpad:scroll", touchpad_edge_scroll_no_2fg, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_CLICKPAD);
|
||||
litest_add("touchpad:scroll", touchpad_scroll_defaults, LITEST_TOUCHPAD, LITEST_ANY);
|
||||
litest_add("touchpad:scroll", touchpad_edge_scroll, LITEST_TOUCHPAD, LITEST_ANY);
|
||||
litest_add("touchpad:scroll", touchpad_edge_scroll_no_motion, LITEST_TOUCHPAD, LITEST_ANY);
|
||||
litest_add("touchpad:scroll", touchpad_edge_scroll_no_edge_after_motion, LITEST_TOUCHPAD, LITEST_ANY);
|
||||
litest_add("touchpad:scroll", touchpad_edge_scroll_timeout, LITEST_TOUCHPAD, LITEST_ANY);
|
||||
litest_add("touchpad:scroll", touchpad_edge_scroll_source, LITEST_TOUCHPAD, LITEST_ANY);
|
||||
litest_add("touchpad:scroll", touchpad_edge_scroll_no_2fg, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
|
||||
litest_add("touchpad:scroll", touchpad_edge_scroll_into_buttonareas, LITEST_CLICKPAD, LITEST_ANY);
|
||||
litest_add("touchpad:scroll", touchpad_edge_scroll_within_buttonareas, LITEST_CLICKPAD, LITEST_ANY);
|
||||
litest_add("touchpad:scroll", touchpad_edge_scroll_buttonareas_click_stops_scroll, LITEST_CLICKPAD, LITEST_ANY);
|
||||
litest_add("touchpad:scroll", touchpad_edge_scroll_clickfinger_click_stops_scroll, LITEST_CLICKPAD, LITEST_ANY);
|
||||
|
||||
litest_add("touchpad:palm", touchpad_palm_detect_at_edge, LITEST_TOUCHPAD, LITEST_ANY);
|
||||
litest_add("touchpad:palm", touchpad_palm_detect_at_bottom_corners, LITEST_TOUCHPAD, LITEST_CLICKPAD);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue