MotionEvent: Rotate relative axes according to window orientation

We rotate the X and Y coordinates of MotionEvents when the window
transform also contains a rotation. This means we should rotate the
relative axes (AXIS_RELATIVE_{X,Y}) as well, making sure not to
translate these relative values.

Bug: 179274888
Test: libinput_tests
Test: manual with test app
Change-Id: I8c716b14ee2b3cd5362f4e9f1554ee37d6875c2d
diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp
index e83341a..f1ccce1 100644
--- a/libs/input/Input.cpp
+++ b/libs/input/Input.cpp
@@ -318,6 +318,8 @@
     scaleAxisValue(*this, AMOTION_EVENT_AXIS_TOUCH_MINOR, globalScaleFactor);
     scaleAxisValue(*this, AMOTION_EVENT_AXIS_TOOL_MAJOR, globalScaleFactor);
     scaleAxisValue(*this, AMOTION_EVENT_AXIS_TOOL_MINOR, globalScaleFactor);
+    scaleAxisValue(*this, AMOTION_EVENT_AXIS_RELATIVE_X, windowXScale);
+    scaleAxisValue(*this, AMOTION_EVENT_AXIS_RELATIVE_Y, windowYScale);
 }
 
 void PointerCoords::scale(float globalScaleFactor) {
@@ -386,6 +388,15 @@
     setAxisValue(AMOTION_EVENT_AXIS_X, xy.x);
     setAxisValue(AMOTION_EVENT_AXIS_Y, xy.y);
 
+    if (BitSet64::hasBit(bits, AMOTION_EVENT_AXIS_RELATIVE_X) ||
+        BitSet64::hasBit(bits, AMOTION_EVENT_AXIS_RELATIVE_Y)) {
+        const ui::Transform rotation(transform.getOrientation());
+        const vec2 relativeXy = rotation.transform(getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X),
+                                                   getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y));
+        setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, relativeXy.x);
+        setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, relativeXy.y);
+    }
+
     if (BitSet64::hasBit(bits, AMOTION_EVENT_AXIS_ORIENTATION)) {
         const float val = getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION);
         setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, transformAngle(transform, val));
@@ -530,6 +541,15 @@
         return xy[axis];
     }
 
+    if (axis == AMOTION_EVENT_AXIS_RELATIVE_X || axis == AMOTION_EVENT_AXIS_RELATIVE_Y) {
+        // For compatibility, since we convert raw coordinates into "oriented screen space", we
+        // need to convert the relative axes into the same orientation for consistency.
+        const vec2 relativeXy =
+                rotatePoint(mTransform, coords->getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X),
+                            coords->getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y));
+        return axis == AMOTION_EVENT_AXIS_RELATIVE_X ? relativeXy.x : relativeXy.y;
+    }
+
     return coords->getAxisValue(axis);
 }
 
@@ -545,6 +565,16 @@
         return xy[axis];
     }
 
+    if (axis == AMOTION_EVENT_AXIS_RELATIVE_X || axis == AMOTION_EVENT_AXIS_RELATIVE_Y) {
+        const vec2 relativeXy =
+                applyTransformWithoutTranslation(mTransform,
+                                                 coords->getAxisValue(
+                                                         AMOTION_EVENT_AXIS_RELATIVE_X),
+                                                 coords->getAxisValue(
+                                                         AMOTION_EVENT_AXIS_RELATIVE_Y));
+        return axis == AMOTION_EVENT_AXIS_RELATIVE_X ? relativeXy.x : relativeXy.y;
+    }
+
     return coords->getAxisValue(axis);
 }