Send ordinal values. These are unaccelerated values for the
various events that allow the client to choose which values
to use.

BUG=chromium-os:36802
TEST=On device

Change-Id: I7c3c0eba73dac16014bcea0fdd6bc43b5c69f5a5
Reviewed-on: https://gerrit.chromium.org/gerrit/42951
Tested-by: Dave Moore <davemoore@chromium.org>
Reviewed-by: Daniel Kurtz <djkurtz@chromium.org>
Commit-Queue: Dave Moore <davemoore@chromium.org>
diff --git a/src/cmt.c b/src/cmt.c
index fee2aac..b9730a2 100644
--- a/src/cmt.c
+++ b/src/cmt.c
@@ -27,6 +27,9 @@
 #error Unsupported XInput version. Major version 12 and above required.
 #endif
 
+#define AXIS_LABEL_PROP_ABS_DBL_ORDINAL_X   "Abs Dbl Ordinal X"
+#define AXIS_LABEL_PROP_ABS_DBL_ORDINAL_Y   "Abs Dbl Ordinal Y"
+
 #define AXIS_LABEL_PROP_ABS_FLING_STATE    "Abs Fling State"
 #define AXIS_LABEL_PROP_ABS_DBL_FLING_VX   "Abs Dbl Fling X Velocity"
 #define AXIS_LABEL_PROP_ABS_DBL_FLING_VY   "Abs Dbl Fling Y Velocity"
@@ -352,6 +355,8 @@
     static const char* axes_names[CMT_NUM_AXES] = {
         AXIS_LABEL_PROP_REL_X,
         AXIS_LABEL_PROP_REL_Y,
+        AXIS_LABEL_PROP_ABS_DBL_ORDINAL_X,
+        AXIS_LABEL_PROP_ABS_DBL_ORDINAL_Y,
         AXIS_LABEL_PROP_REL_HWHEEL,
         AXIS_LABEL_PROP_REL_WHEEL,
         AXIS_LABEL_PROP_ABS_FLING_STATE,
diff --git a/src/cmt.h b/src/cmt.h
index 866f5f4..81e1903 100644
--- a/src/cmt.h
+++ b/src/cmt.h
@@ -39,6 +39,8 @@
 enum CMT_AXIS {
     CMT_AXIS_X = 0,
     CMT_AXIS_Y,
+    CMT_AXIS_ORDINAL_X,
+    CMT_AXIS_ORDINAL_Y,
     CMT_AXIS_SCROLL_X,
     CMT_AXIS_SCROLL_Y,
     CMT_AXIS_FLING_STATE,
diff --git a/src/gesture.c b/src/gesture.c
index 9a0cbac..68e1e3f 100644
--- a/src/gesture.c
+++ b/src/gesture.c
@@ -228,6 +228,25 @@
     valuator_mask_set_double(mask, CMT_AXIS_DBL_END_TIME, end_time);
 }
 
+static void SetOrdinalValues(ValuatorMask* mask,
+                             DeviceIntPtr dev,
+                             float x,
+                             float y,
+                             BOOL is_absolute) {
+    if (!is_absolute) {
+        /*
+         * We send the movement axes as relative values, which causes the
+         * times to be sent as relative values too. This code computes the
+         * right relative values.
+         */
+        x -= dev->last.valuators[CMT_AXIS_ORDINAL_X];
+        y -= dev->last.valuators[CMT_AXIS_ORDINAL_Y];
+    }
+
+    valuator_mask_set_double(mask, CMT_AXIS_ORDINAL_X, x);
+    valuator_mask_set_double(mask, CMT_AXIS_ORDINAL_Y, y);
+}
+
 static void Gesture_Gesture_Ready(void* client_data,
                                   const struct Gesture* gesture)
 {
@@ -246,20 +265,32 @@
             break;
         case kGestureTypeMove: {
             const GestureMove* move = &gesture->details.move;
-            DBG(info, "Gesture Move: (%f, %f)\n", move->dx, move->dy);
+            DBG(info, "Gesture Move: (%f, %f) [%f, %f]\n",
+                move->dx, move->dy, move->ordinal_dx, move->ordinal_dy);
             valuator_mask_set_double(mask, CMT_AXIS_X, move->dx);
             valuator_mask_set_double(mask, CMT_AXIS_Y, move->dy);
             SetTimeValues(mask, gesture, dev, FALSE);
+            SetOrdinalValues(mask,
+                             dev,
+                             move->ordinal_dx,
+                             move->ordinal_dy,
+                             FALSE);
             xf86PostMotionEventM(dev, FALSE, mask);
             break;
         }
         case kGestureTypeScroll: {
             const GestureScroll* scroll = &gesture->details.scroll;
-            DBG(info, "Gesture Scroll: (%f, %f)\n", scroll->dx, scroll->dy);
+            DBG(info, "Gesture Scroll: (%f, %f) [%f, %f]\n",
+                scroll->dx, scroll->dy, scroll->ordinal_dx, scroll->ordinal_dy);
             valuator_mask_set_double(mask, CMT_AXIS_SCROLL_X, scroll->dx);
             valuator_mask_set_double(mask, CMT_AXIS_SCROLL_Y, scroll->dy);
             valuator_mask_set_double(mask, CMT_AXIS_FINGER_COUNT, 2.0);
             SetTimeValues(mask, gesture, dev, TRUE);
+            SetOrdinalValues(mask,
+                             dev,
+                             scroll->ordinal_dx,
+                             scroll->ordinal_dy,
+                             TRUE);
             xf86PostMotionEventM(dev, TRUE, mask);
             break;
         }
@@ -284,22 +315,34 @@
         }
         case kGestureTypeFling: {
             const GestureFling* fling = &gesture->details.fling;
-            DBG(info, "Gesture Fling: vx=%f vy=%f fling_state=%d\n",
-                fling->vx, fling->vy, fling->fling_state);
+            DBG(info, "Gesture Fling: (%f, %f) [%f, %f] fling_state=%d\n",
+                fling->vx, fling->vy, fling->ordinal_vx, fling->ordinal_vy,
+                fling->fling_state);
             valuator_mask_set_double(mask, CMT_AXIS_DBL_FLING_VX, fling->vx);
             valuator_mask_set_double(mask, CMT_AXIS_DBL_FLING_VY, fling->vy);
             valuator_mask_set(mask, CMT_AXIS_FLING_STATE, fling->fling_state);
             SetTimeValues(mask, gesture, dev, TRUE);
+            SetOrdinalValues(mask,
+                             dev,
+                             fling->ordinal_vx,
+                             fling->ordinal_vy,
+                             TRUE);
             xf86PostMotionEventM(dev, TRUE, mask);
             break;
         }
         case kGestureTypeSwipe: {
             const GestureSwipe* swipe = &gesture->details.swipe;
-            DBG(info, "Gesture Swipe: dx=%f dy=%f\n", swipe->dx, swipe->dy);
+            DBG(info, "Gesture Swipe: (%f, %f) [%f, %f]\n",
+                swipe->dx, swipe->dy, swipe->ordinal_dx, swipe->ordinal_dy);
             valuator_mask_set_double(mask, CMT_AXIS_SCROLL_X, swipe->dx);
             valuator_mask_set_double(mask, CMT_AXIS_SCROLL_Y, swipe->dy);
             valuator_mask_set_double(mask, CMT_AXIS_FINGER_COUNT, 3.0);
             SetTimeValues(mask, gesture, dev, TRUE);
+            SetOrdinalValues(mask,
+                             dev,
+                             swipe->ordinal_dx,
+                             swipe->ordinal_dy,
+                             TRUE);
             xf86PostMotionEventM(dev, TRUE, mask);
             break;
         }
@@ -314,7 +357,8 @@
             break;
         case kGestureTypePinch: {
             const GesturePinch* pinch = &gesture->details.pinch;
-            DBG(info, "Gesture Pinch: dz=%f\n", pinch->dz);
+            DBG(info, "Gesture Pinch: dz=%f [%f]\n",
+                pinch->dz, pinch->ordinal_dz);
             break;
         }
         default: