On Thu, Dec 04, 2014 at 11:44:09AM +0800, Jonas Ådahl wrote: > For certain applications (such as FPS games) it is necessary to use > unaccelerated motion events (the motion vector that is passed to the > acceleration filter) to get a more natural feeling. Supply this > information by passing both accelerated and unaccelerated motion > vectors to the existing motion event. > > Note that the unaccelerated motion event is not equivalent to 'raw' > events as read from devices. > > Signed-off-by: Jonas Ådahl <jad...@gmail.com> > --- > > Changes since v1: > > Renamed non-accelerated to unaccelerated and don't abbreviate in the > public API. > > Made the tested motion vectors longer in order to have the acceleration > to potentially affect it. > > Improved documentation (assumes 1000 DPI patch has been applied). > > For tests assuming valid accelerated motion vectors, wait for a motion > vector with a length more than zero.
Reviewed-by: Peter Hutterer <peter.hutte...@who-t.net> for both with a minor nitpick below. > src/evdev-mt-touchpad-edge-scroll.c | 2 +- > src/evdev-mt-touchpad.c | 20 ++++++-- > src/evdev-mt-touchpad.h | 4 +- > src/evdev.c | 19 ++++++-- > src/libinput-private.h | 4 +- > src/libinput.c | 22 ++++++++- > src/libinput.h | 42 +++++++++++++++++ > test/pointer.c | 91 > +++++++++++++++++++++++++++++++++---- > test/touchpad.c | 8 +++- > 9 files changed, 188 insertions(+), 24 deletions(-) > > diff --git a/src/evdev-mt-touchpad-edge-scroll.c > b/src/evdev-mt-touchpad-edge-scroll.c > index 1dca0ea..d68fc68 100644 > --- a/src/evdev-mt-touchpad-edge-scroll.c > +++ b/src/evdev-mt-touchpad-edge-scroll.c > @@ -338,7 +338,7 @@ tp_edge_scroll_post_events(struct tp_dispatch *tp, > uint64_t time) > } > > tp_get_delta(t, &dx, &dy); > - tp_filter_motion(tp, &dx, &dy, time); > + tp_filter_motion(tp, &dx, &dy, NULL, NULL, time); > > if (fabs(*delta) < t->scroll.threshold) > continue; > diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c > index 8f76ddb..15120da 100644 > --- a/src/evdev-mt-touchpad.c > +++ b/src/evdev-mt-touchpad.c > @@ -58,13 +58,20 @@ tp_motion_history_offset(struct tp_touch *t, int offset) > > void > tp_filter_motion(struct tp_dispatch *tp, > - double *dx, double *dy, uint64_t time) > + double *dx, double *dy, > + double *dx_unaccel, double *dy_unaccel, > + uint64_t time) > { > struct motion_params motion; > > motion.dx = *dx * tp->accel.x_scale_coeff; > motion.dy = *dy * tp->accel.y_scale_coeff; > > + if (dx_unaccel) > + *dx_unaccel = motion.dx; > + if (dy_unaccel) > + *dy_unaccel = motion.dy; > + > if (motion.dx != 0.0 || motion.dy != 0.0) > filter_dispatch(tp->device->pointer.filter, &motion, tp, time); > > @@ -426,7 +433,7 @@ tp_post_twofinger_scroll(struct tp_dispatch *tp, uint64_t > time) > dx /= nchanged; > dy /= nchanged; > > - tp_filter_motion(tp, &dx, &dy, time); > + tp_filter_motion(tp, &dx, &dy, NULL, NULL, time); > > evdev_post_scroll(tp->device, time, dx, dy); > } > @@ -586,6 +593,7 @@ tp_post_events(struct tp_dispatch *tp, uint64_t time) > struct tp_touch *t = tp_current_touch(tp); > double dx, dy; > int filter_motion = 0; > + double dx_unaccel, dy_unaccel; > > /* Only post (top) button events while suspended */ > if (tp->device->suspended) { > @@ -617,10 +625,12 @@ tp_post_events(struct tp_dispatch *tp, uint64_t time) > return; > > tp_get_delta(t, &dx, &dy); > - tp_filter_motion(tp, &dx, &dy, time); > + tp_filter_motion(tp, &dx, &dy, &dx_unaccel, &dy_unaccel, time); > > - if (dx != 0.0 || dy != 0.0) > - pointer_notify_motion(&tp->device->base, time, dx, dy); > + if (dx != 0.0 || dy != 0.0 || dx_unaccel != 0.0 || dy_unaccel != 0.0) { > + pointer_notify_motion(&tp->device->base, time, > + dx, dy, dx_unaccel, dy_unaccel); > + } > } > > static void > diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h > index b2603b4..da9c091 100644 > --- a/src/evdev-mt-touchpad.h > +++ b/src/evdev-mt-touchpad.h > @@ -276,7 +276,9 @@ tp_set_pointer(struct tp_dispatch *tp, struct tp_touch > *t); > > void > tp_filter_motion(struct tp_dispatch *tp, > - double *dx, double *dy, uint64_t time); > + double *dx, double *dy, > + double *dx_unaccel, double *dy_unaccel, > + uint64_t time); > > int > tp_tap_handle_state(struct tp_dispatch *tp, uint64_t time); > diff --git a/src/evdev.c b/src/evdev.c > index 908a8ba..1942539 100644 > --- a/src/evdev.c > +++ b/src/evdev.c > @@ -198,6 +198,7 @@ evdev_flush_pending_event(struct evdev_device *device, > uint64_t time) > { > struct libinput *libinput = device->base.seat->libinput; > struct motion_params motion; > + double dx_unaccel, dy_unaccel; > int32_t cx, cy; > int32_t x, y; > int slot; > @@ -211,8 +212,10 @@ evdev_flush_pending_event(struct evdev_device *device, > uint64_t time) > case EVDEV_NONE: > return; > case EVDEV_RELATIVE_MOTION: > - motion.dx = device->rel.dx / ((double)device->dpi / > DEFAULT_MOUSE_DPI); > - motion.dy = device->rel.dy / ((double)device->dpi / > DEFAULT_MOUSE_DPI); > + dx_unaccel = device->rel.dx / ((double) device->dpi / > + DEFAULT_MOUSE_DPI); > + dy_unaccel = device->rel.dy / ((double) device->dpi / > + DEFAULT_MOUSE_DPI); > device->rel.dx = 0; > device->rel.dy = 0; > > @@ -221,17 +224,23 @@ evdev_flush_pending_event(struct evdev_device *device, > uint64_t time) > hw_is_key_down(device, device->scroll.button)) { > if (device->scroll.button_scroll_active) > evdev_post_scroll(device, time, > - motion.dx, motion.dy); > + dx_unaccel, dy_unaccel); > break; > } > > /* Apply pointer acceleration. */ > + motion.dx = dx_unaccel; > + motion.dy = dy_unaccel; > filter_dispatch(device->pointer.filter, &motion, device, time); > > - if (motion.dx == 0.0 && motion.dy == 0.0) > + if (motion.dx == 0.0 && motion.dy == 0.0 && > + dx_unaccel == 0.0 && dy_unaccel == 0.0) { > break; > + } > > - pointer_notify_motion(base, time, motion.dx, motion.dy); > + pointer_notify_motion(base, time, > + motion.dx, motion.dy, > + dx_unaccel, dy_unaccel); > break; > case EVDEV_ABSOLUTE_MT_DOWN: > if (!(device->seat_caps & EVDEV_DEVICE_TOUCH)) > diff --git a/src/libinput-private.h b/src/libinput-private.h > index 4a9bd54..b36dc95 100644 > --- a/src/libinput-private.h > +++ b/src/libinput-private.h > @@ -259,7 +259,9 @@ void > pointer_notify_motion(struct libinput_device *device, > uint64_t time, > double dx, > - double dy); > + double dy, > + double dx_noaccel, > + double dy_noaccel); > > void > pointer_notify_motion_absolute(struct libinput_device *device, > diff --git a/src/libinput.c b/src/libinput.c > index c318eee..40305c7 100644 > --- a/src/libinput.c > +++ b/src/libinput.c > @@ -59,6 +59,8 @@ struct libinput_event_pointer { > uint32_t time; > double x; > double y; > + double dx_unaccel; > + double dy_unaccel; > uint32_t button; > uint32_t seat_button_count; > enum libinput_button_state state; > @@ -304,6 +306,20 @@ libinput_event_pointer_get_dy(struct > libinput_event_pointer *event) > } > > LIBINPUT_EXPORT double > +libinput_event_pointer_get_dx_unaccelerated( > + struct libinput_event_pointer *event) > +{ > + return event->dx_unaccel; > +} > + > +LIBINPUT_EXPORT double > +libinput_event_pointer_get_dy_unaccelerated( > + struct libinput_event_pointer *event) > +{ > + return event->dy_unaccel; > +} > + > +LIBINPUT_EXPORT double > libinput_event_pointer_get_absolute_x(struct libinput_event_pointer *event) > { > struct evdev_device *device = > @@ -885,7 +901,9 @@ void > pointer_notify_motion(struct libinput_device *device, > uint64_t time, > double dx, > - double dy) > + double dy, > + double dx_unaccel, > + double dy_unaccel) > { > struct libinput_event_pointer *motion_event; > > @@ -897,6 +915,8 @@ pointer_notify_motion(struct libinput_device *device, > .time = time, > .x = dx, > .y = dy, > + .dx_unaccel = dx_unaccel, > + .dy_unaccel = dy_unaccel, > }; > > post_device_event(device, time, > diff --git a/src/libinput.h b/src/libinput.h > index a60d41e..c014b00 100644 > --- a/src/libinput.h > +++ b/src/libinput.h > @@ -558,6 +558,48 @@ libinput_event_pointer_get_dy(struct > libinput_event_pointer *event); > /** > * @ingroup event_pointer > * > + * Return the relative delta of the unaccelerated motion vector of the > + * current event. For pointer events that are not of type > + * LIBINPUT_EVENT_POINTER_MOTION, this function returns 0. this and the one below needs @ref prefixed. > + * > + * Relative unaccelerated motion deltas are normalized to represent those of > a > + * device with 1000dpi resolution. See @ref motion_normalization for more > + * details. Note that unaccelerated events do not equivalent to 'raw' events s/do not/are not/ > + * as read from the device. > + * > + * @note It is an application bug to call this function for events other than > + * LIBINPUT_EVENT_POINTER_MOTION. @ref here too these three go for the get_dy as well. Cheers, Peter > + * > + * @return the unaccelerated relative x movement since the last event > + */ > +double > +libinput_event_pointer_get_dx_unaccelerated( > + struct libinput_event_pointer *event); > + > +/** > + * @ingroup event_pointer > + * > + * Return the relative delta of the unaccelerated motion vector of the > + * current event. For pointer events that are not of type > + * LIBINPUT_EVENT_POINTER_MOTION, this function returns 0. > + * > + * Relative unaccelerated motion deltas are normalized to represent those of > a > + * device with 1000dpi resolution. See @ref motion_normalization for more > + * details. Note that unaccelerated events do not equivalent to 'raw' events > + * as read from the device. > + * > + * @note It is an application bug to call this function for events other than > + * LIBINPUT_EVENT_POINTER_MOTION. > + * > + * @return the unaccelerated relative y movement since the last event > + */ > +double > +libinput_event_pointer_get_dy_unaccelerated( > + struct libinput_event_pointer *event); > + > +/** > + * @ingroup event_pointer > + * > * Return the current absolute x coordinate of the pointer event, in mm from > * the top left corner of the device. To get the corresponding output screen > * coordinate, use libinput_event_pointer_get_absolute_x_transformed(). > diff --git a/test/pointer.c b/test/pointer.c > index 206accd..dfed6b7 100644 > --- a/test/pointer.c > +++ b/test/pointer.c > @@ -29,15 +29,43 @@ > #include <libinput.h> > #include <math.h> > #include <unistd.h> > +#include <values.h> > > #include "libinput-util.h" > #include "litest.h" > > +static struct libinput_event_pointer * > +get_accelerated_motion_event(struct libinput *li) > +{ > + struct libinput_event *event; > + struct libinput_event_pointer *ptrev; > + > + while (1) { > + event = libinput_get_event(li); > + ck_assert_notnull(event); > + ck_assert_int_eq(libinput_event_get_type(event), > + LIBINPUT_EVENT_POINTER_MOTION); > + > + ptrev = libinput_event_get_pointer_event(event); > + ck_assert_notnull(ptrev); > + > + if (fabs(libinput_event_pointer_get_dx(ptrev)) < DBL_MIN && > + fabs(libinput_event_pointer_get_dy(ptrev)) < DBL_MIN) { > + libinput_event_destroy(event); > + continue; > + } > + > + return ptrev; > + } > + > + ck_abort_msg("No accelerated pointer motion event found"); > + return NULL; > +} > + > static void > test_relative_event(struct litest_device *dev, int dx, int dy) > { > struct libinput *li = dev->libinput; > - struct libinput_event *event; > struct libinput_event_pointer *ptrev; > double ev_dx, ev_dy; > double expected_dir; > @@ -56,12 +84,7 @@ test_relative_event(struct litest_device *dev, int dx, int > dy) > > libinput_dispatch(li); > > - event = libinput_get_event(li); > - ck_assert(event != NULL); > - ck_assert_int_eq(libinput_event_get_type(event), > LIBINPUT_EVENT_POINTER_MOTION); > - > - ptrev = libinput_event_get_pointer_event(event); > - ck_assert(ptrev != NULL); > + ptrev = get_accelerated_motion_event(li); > > expected_length = sqrt(4 * dx*dx + 4 * dy*dy); > expected_dir = atan2(dx, dy); > @@ -78,7 +101,7 @@ test_relative_event(struct litest_device *dev, int dx, int > dy) > * indifference). */ > ck_assert(fabs(expected_dir - actual_dir) < M_PI_2); > > - libinput_event_destroy(event); > + libinput_event_destroy(libinput_event_pointer_get_base_event(ptrev)); > > litest_drain_events(dev->libinput); > } > @@ -140,6 +163,57 @@ START_TEST(pointer_motion_absolute) > END_TEST > > static void > +test_unaccel_event(struct litest_device *dev, int dx, int dy) > +{ > + struct libinput *li = dev->libinput; > + struct libinput_event *event; > + struct libinput_event_pointer *ptrev; > + double ev_dx, ev_dy; > + > + litest_event(dev, EV_REL, REL_X, dx); > + litest_event(dev, EV_REL, REL_Y, dy); > + litest_event(dev, EV_SYN, SYN_REPORT, 0); > + > + libinput_dispatch(li); > + > + event = libinput_get_event(li); > + ck_assert_notnull(event); > + ck_assert_int_eq(libinput_event_get_type(event), > + LIBINPUT_EVENT_POINTER_MOTION); > + > + ptrev = libinput_event_get_pointer_event(event); > + ck_assert(ptrev != NULL); > + > + ev_dx = libinput_event_pointer_get_dx_unaccelerated(ptrev); > + ev_dy = libinput_event_pointer_get_dy_unaccelerated(ptrev); > + > + ck_assert_int_eq(dx, ev_dx); > + ck_assert_int_eq(dy, ev_dy); > + > + libinput_event_destroy(event); > + > + litest_drain_events(dev->libinput); > +} > + > +START_TEST(pointer_motion_unaccel) > +{ > + struct litest_device *dev = litest_current_device(); > + > + litest_drain_events(dev->libinput); > + > + test_unaccel_event(dev, 10, 0); > + test_unaccel_event(dev, 10, 10); > + test_unaccel_event(dev, 10, -10); > + test_unaccel_event(dev, 0, 10); > + > + test_unaccel_event(dev, -10, 0); > + test_unaccel_event(dev, -10, 10); > + test_unaccel_event(dev, -10, -10); > + test_unaccel_event(dev, 0, -10); > +} > +END_TEST > + > +static void > test_button_event(struct litest_device *dev, unsigned int button, int state) > { > struct libinput *li = dev->libinput; > @@ -652,6 +726,7 @@ int main (int argc, char **argv) { > > litest_add("pointer:motion", pointer_motion_relative, LITEST_RELATIVE, > LITEST_ANY); > litest_add("pointer:motion", pointer_motion_absolute, LITEST_ABSOLUTE, > LITEST_ANY); > + litest_add("pointer:motion", pointer_motion_unaccel, LITEST_RELATIVE, > LITEST_ANY); > litest_add("pointer:button", pointer_button, LITEST_BUTTON, > LITEST_CLICKPAD); > litest_add_no_device("pointer:button_auto_release", > pointer_button_auto_release); > litest_add("pointer:scroll", pointer_scroll_wheel, LITEST_WHEEL, > LITEST_ANY); > diff --git a/test/touchpad.c b/test/touchpad.c > index 2b79aaf..934674c 100644 > --- a/test/touchpad.c > +++ b/test/touchpad.c > @@ -1173,8 +1173,12 @@ START_TEST(clickpad_softbutton_left_2nd_fg_move) > x = libinput_event_pointer_get_dx(p); > y = libinput_event_pointer_get_dy(p); > > - ck_assert(x > 0); > - ck_assert(y == 0); > + /* Ignore events only containing an unaccelerated motion > + * vector. */ > + if (x != 0 || y != 0) { > + ck_assert(x > 0); > + ck_assert(y == 0); > + } > > libinput_event_destroy(event); > libinput_dispatch(li); > -- > 1.8.5.1 > > _______________________________________________ > wayland-devel mailing list > wayland-devel@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/wayland-devel > _______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel