touchpad: use unaccelerated motion data for scrolling

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@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
This commit is contained in:
Peter Hutterer 2015-08-06 14:59:38 +10:00
parent d8c37a94c0
commit c8da19b50a
5 changed files with 42 additions and 3 deletions

View file

@ -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:

View file

@ -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;

View file

@ -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)
{

View file

@ -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);

View file

@ -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;