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

Reply via email to