For certain applications (such as FPS games) it is necessary to use non-accelerated 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 non-accelerated motion vectors to the existing motion event.
Note that the non-accelerated motion event is not equivalent to 'raw' events as read from devices. Signed-off-by: Jonas Ådahl <jad...@gmail.com> --- 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 | 20 +++++++++++++- src/libinput.h | 30 +++++++++++++++++++++ test/pointer.c | 52 +++++++++++++++++++++++++++++++++++++ 8 files changed, 137 insertions(+), 14 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..ff76fe2 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_noaccel, double *dy_noaccel, + 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_noaccel) + *dx_noaccel = motion.dx; + if (dy_noaccel) + *dy_noaccel = 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_noaccel, dy_noaccel; /* 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_noaccel, &dy_noaccel, 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_noaccel != 0.0 || dy_noaccel != 0.0) { + pointer_notify_motion(&tp->device->base, time, + dx, dy, dx_noaccel, dy_noaccel); + } } static void diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h index b2603b4..ea77062 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_noaccel, double *dy_noaccel, + 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..f7d88c4 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_noaccel, dy_noaccel; 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_noaccel = device->rel.dx / ((double) device->dpi / + DEFAULT_MOUSE_DPI); + dy_noaccel = 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_noaccel, dx_noaccel); break; } /* Apply pointer acceleration. */ + motion.dx = dx_noaccel; + motion.dy = dy_noaccel; 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_noaccel == 0.0 && dy_noaccel == 0.0) { break; + } - pointer_notify_motion(base, time, motion.dx, motion.dy); + pointer_notify_motion(base, time, + motion.dx, motion.dy, + dx_noaccel, dy_noaccel); 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..f179de8 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_noaccel; + double dy_noaccel; uint32_t button; uint32_t seat_button_count; enum libinput_button_state state; @@ -304,6 +306,18 @@ libinput_event_pointer_get_dy(struct libinput_event_pointer *event) } LIBINPUT_EXPORT double +libinput_event_pointer_get_dx_noaccel(struct libinput_event_pointer *event) +{ + return event->dx_noaccel; +} + +LIBINPUT_EXPORT double +libinput_event_pointer_get_dy_noaccel(struct libinput_event_pointer *event) +{ + return event->dy_noaccel; +} + +LIBINPUT_EXPORT double libinput_event_pointer_get_absolute_x(struct libinput_event_pointer *event) { struct evdev_device *device = @@ -885,7 +899,9 @@ void pointer_notify_motion(struct libinput_device *device, uint64_t time, double dx, - double dy) + double dy, + double dx_noaccel, + double dy_noaccel) { struct libinput_event_pointer *motion_event; @@ -897,6 +913,8 @@ pointer_notify_motion(struct libinput_device *device, .time = time, .x = dx, .y = dy, + .dx_noaccel = dx_noaccel, + .dy_noaccel = dy_noaccel, }; post_device_event(device, time, diff --git a/src/libinput.h b/src/libinput.h index 26d94ff..08fef8c 100644 --- a/src/libinput.h +++ b/src/libinput.h @@ -497,6 +497,36 @@ libinput_event_pointer_get_dy(struct libinput_event_pointer *event); /** * @ingroup event_pointer * + * Return the relative delta of the non-accelerated motion vector of the + * current event. For pointer events that are not of type + * LIBINPUT_EVENT_POINTER_MOTION, this function returns 0. + * + * @note It is an application bug to call this function for events other than + * LIBINPUT_EVENT_POINTER_MOTION. + * + * @return the non-accelerated relative x movement since the last event + */ +double +libinput_event_pointer_get_dx_noaccel(struct libinput_event_pointer *event); + +/** + * @ingroup event_pointer + * + * Return the relative delta of the non-accelerated motion vector of the + * current event. For pointer events that are not of type + * LIBINPUT_EVENT_POINTER_MOTION, this function returns 0. + * + * @note It is an application bug to call this function for events other than + * LIBINPUT_EVENT_POINTER_MOTION. + * + * @return the non-accelerated relative y movement since the last event + */ +double +libinput_event_pointer_get_dy_noaccel(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..9de414c 100644 --- a/test/pointer.c +++ b/test/pointer.c @@ -140,6 +140,57 @@ START_TEST(pointer_motion_absolute) END_TEST static void +test_noaccel_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(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); + + ev_dx = libinput_event_pointer_get_dx_noaccel(ptrev); + ev_dy = libinput_event_pointer_get_dy_noaccel(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_noaccel) +{ + struct litest_device *dev = litest_current_device(); + + litest_drain_events(dev->libinput); + + test_noaccel_event(dev, 1, 0); + test_noaccel_event(dev, 1, 1); + test_noaccel_event(dev, 1, -1); + test_noaccel_event(dev, 0, 1); + + test_noaccel_event(dev, -1, 0); + test_noaccel_event(dev, -1, 1); + test_noaccel_event(dev, -1, -1); + test_noaccel_event(dev, 0, -1); +} +END_TEST + +static void test_button_event(struct litest_device *dev, unsigned int button, int state) { struct libinput *li = dev->libinput; @@ -652,6 +703,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_noaccel, 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); -- 1.8.5.1 _______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel