tp_filter_motion(tp, &dx, &dy, NULL, NULL, time);
evdev_post_scroll(tp->device, time, dx, dy);
+ tp->scroll.twofinger_state = TWOFINGER_SCROLL_STATE_ACTIVE;
+}
+
+static void
+tp_twofinger_stop_scroll(struct tp_dispatch *tp, uint64_t time)
+{
+ struct tp_touch *t, *ptr = NULL;
+ int nfingers_down = 0;
+
+ evdev_stop_scroll(tp->device, time);
+
+ /* If we were scrolling and now there's exactly 1 active finger,
+ switch back to pointer movement */
+ if (tp->scroll.twofinger_state == TWOFINGER_SCROLL_STATE_ACTIVE) {
+ tp_for_each_touch(tp, t) {
+ if (tp_touch_active(tp, t)) {
+ nfingers_down++;
+ if (ptr == NULL)
+ ptr = t;
+ }
+ }
+
+ if (nfingers_down == 1)
+ tp_set_pointer(tp, ptr);
+ }
+
+ tp->scroll.twofinger_state = TWOFINGER_SCROLL_STATE_NONE;
}
static int
nfingers_down++;
}
- if (nfingers_down != 2) {
- evdev_stop_scroll(tp->device, time);
- return 0;
+ if (nfingers_down == 2) {
+ tp_post_twofinger_scroll(tp, time);
+ return 1;
}
- tp_post_twofinger_scroll(tp, time);
- return 1;
+ tp_twofinger_stop_scroll(tp, time);
+
+ return 0;
}
static void
case LIBINPUT_CONFIG_SCROLL_NO_SCROLL:
break;
case LIBINPUT_CONFIG_SCROLL_2FG:
- evdev_stop_scroll(tp->device, time);
+ tp_twofinger_stop_scroll(tp, time);
break;
case LIBINPUT_CONFIG_SCROLL_EDGE:
tp_edge_scroll_stop_events(tp, time);
}
END_TEST
+START_TEST(touchpad_2fg_scroll_return_to_motion)
+{
+ struct litest_device *dev = litest_current_device();
+ struct libinput *li = dev->libinput;
+
+ litest_drain_events(li);
+
+ /* start with motion */
+ litest_touch_down(dev, 0, 70, 70);
+ litest_touch_move_to(dev, 0, 70, 70, 47, 50, 10, 0);
+ litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
+
+ /* 2fg scroll */
+ litest_touch_down(dev, 1, 53, 50);
+ litest_touch_move_to(dev, 0, 47, 50, 47, 70, 5, 0);
+ litest_touch_move_to(dev, 1, 53, 50, 53, 70, 5, 0);
+ litest_touch_up(dev, 1);
+ litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS);
+
+ litest_touch_move_to(dev, 0, 47, 70, 47, 50, 10, 0);
+ litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
+
+ /* back to 2fg scroll, lifting the other finger */
+ litest_touch_down(dev, 1, 50, 50);
+ litest_touch_move_to(dev, 0, 47, 50, 47, 70, 5, 0);
+ litest_touch_move_to(dev, 1, 53, 50, 53, 70, 5, 0);
+ litest_touch_up(dev, 0);
+ litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS);
+
+ /* move with second finger */
+ litest_touch_move_to(dev, 1, 53, 70, 53, 50, 10, 0);
+ litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
+
+ litest_touch_up(dev, 1);
+ litest_assert_empty_queue(li);
+}
+END_TEST
+
START_TEST(touchpad_scroll_natural_defaults)
{
struct litest_device *dev = litest_current_device();
litest_add("touchpad:scroll", touchpad_2fg_scroll, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
litest_add("touchpad:scroll", touchpad_2fg_scroll_slow_distance, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
+ litest_add("touchpad:scroll", touchpad_2fg_scroll_return_to_motion, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
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);