[PATCH libinput 6/6] touchpad: use unaccelerated motion data for scrolling

Peter Hutterer peter.hutterer at who-t.net
Mon Aug 17 16:20:34 PDT 2015


For short and quick scroll gestures, those that should only trigger a few
lines of scroll the pointer acceleration is wildly unpredictable. Since we
average the motion of both fingers it's hard enough to intuitively predict
what the motion will be like. On top of that is the small threshold before we
start scrolling, so some of the initial motion gets swallowed before we
accelerate, making the next motion even more unpredictable.

The end result is that multiple seemingly identical finger motions cause
wildly different scroll motion.

Drop pointer acceleration for two-finger and edge scrolling. This makes short
scroll motions much more predictable and doesn't seem to have much effect on
long scroll motions. Plus, in natural scroll mode it really feels like the
content is stuck to your fingers now. Go wash your hands.

https://bugzilla.redhat.com/show_bug.cgi?id=1249365

Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
---
 src/evdev-mt-touchpad-edge-scroll.c |  3 ++-
 src/evdev-mt-touchpad-gestures.c    |  3 ++-
 src/evdev-mt-touchpad.c             | 12 ++++++++++++
 src/evdev-mt-touchpad.h             |  4 ++++
 src/filter.c                        | 23 ++++++++++++++++++++++-
 5 files changed, 42 insertions(+), 3 deletions(-)

diff --git a/src/evdev-mt-touchpad-edge-scroll.c b/src/evdev-mt-touchpad-edge-scroll.c
index eda62e4..b572a9f 100644
--- a/src/evdev-mt-touchpad-edge-scroll.c
+++ b/src/evdev-mt-touchpad-edge-scroll.c
@@ -390,7 +390,8 @@ tp_edge_scroll_post_events(struct tp_dispatch *tp, uint64_t time)
 		}
 
 		normalized = tp_get_delta(t);
-		normalized = tp_filter_motion(tp, &normalized, time);
+		/* scroll is not accelerated */
+		normalized = tp_filter_motion_unaccelerated(tp, &normalized, time);
 
 		switch (t->scroll.edge_state) {
 		case EDGE_SCROLL_TOUCH_STATE_NONE:
diff --git a/src/evdev-mt-touchpad-gestures.c b/src/evdev-mt-touchpad-gestures.c
index d82a6fb..cc26e2a 100644
--- a/src/evdev-mt-touchpad-gestures.c
+++ b/src/evdev-mt-touchpad-gestures.c
@@ -328,7 +328,8 @@ tp_gesture_twofinger_handle_state_scroll(struct tp_dispatch *tp, uint64_t time)
 		delta = tp_get_average_touches_delta(tp);
 	}
 
-	delta = tp_filter_motion(tp, &delta, time);
+	/* scroll is not accelerated */
+	delta = tp_filter_motion_unaccelerated(tp, &delta, time);
 
 	if (normalized_is_zero(delta))
 		return GESTURE_2FG_STATE_SCROLL;
diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c
index a32a771..aeb6c31 100644
--- a/src/evdev-mt-touchpad.c
+++ b/src/evdev-mt-touchpad.c
@@ -71,6 +71,18 @@ tp_filter_motion(struct tp_dispatch *tp,
 			       unaccelerated, tp, time);
 }
 
+struct normalized_coords
+tp_filter_motion_unaccelerated(struct tp_dispatch *tp,
+			       const struct normalized_coords *unaccelerated,
+			       uint64_t time)
+{
+	if (normalized_is_zero(*unaccelerated))
+		return *unaccelerated;
+
+	return filter_dispatch_constant(tp->device->pointer.filter,
+					unaccelerated, tp, time);
+}
+
 static inline void
 tp_motion_history_push(struct tp_touch *t)
 {
diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h
index 3bd8425..5f87c3f 100644
--- a/src/evdev-mt-touchpad.h
+++ b/src/evdev-mt-touchpad.h
@@ -395,6 +395,10 @@ struct normalized_coords
 tp_filter_motion(struct tp_dispatch *tp,
 		 const struct normalized_coords *unaccelerated,
 		 uint64_t time);
+struct normalized_coords
+tp_filter_motion_unaccelerated(struct tp_dispatch *tp,
+			       const struct normalized_coords *unaccelerated,
+			       uint64_t time);
 
 int
 tp_touch_active(struct tp_dispatch *tp, struct tp_touch *t);
diff --git a/src/filter.c b/src/filter.c
index 674b439..5df50d3 100644
--- a/src/filter.c
+++ b/src/filter.c
@@ -420,6 +420,19 @@ accelerator_filter_x230(struct motion_filter *filter,
 	return accelerated;
 }
 
+static struct normalized_coords
+touchpad_constant_filter(struct motion_filter *filter,
+			 const struct normalized_coords *unaccelerated,
+			 void *data, uint64_t time)
+{
+	struct normalized_coords normalized;
+
+	normalized.x = TP_MAGIC_SLOWDOWN * unaccelerated->x;
+	normalized.y = TP_MAGIC_SLOWDOWN * unaccelerated->y;
+
+	return normalized;
+}
+
 static void
 accelerator_restart(struct motion_filter *filter,
 		    void *data,
@@ -757,6 +770,14 @@ create_pointer_accelerator_filter_linear_low_dpi(int dpi)
 	return &filter->base;
 }
 
+struct motion_filter_interface accelerator_interface_touchpad = {
+	.filter = accelerator_filter,
+	.filter_constant = touchpad_constant_filter,
+	.restart = accelerator_restart,
+	.destroy = accelerator_destroy,
+	.set_speed = accelerator_set_speed,
+};
+
 struct motion_filter *
 create_pointer_accelerator_filter_touchpad(int dpi)
 {
@@ -766,7 +787,7 @@ create_pointer_accelerator_filter_touchpad(int dpi)
 	if (!filter)
 		return NULL;
 
-	filter->base.interface = &accelerator_interface;
+	filter->base.interface = &accelerator_interface_touchpad;
 	filter->profile = touchpad_accel_profile_linear;
 
 	return &filter->base;
-- 
2.4.3



More information about the wayland-devel mailing list