Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 39b7ca29 authored by Harry Cutts's avatar Harry Cutts
Browse files

Report motion offsets for touchpad swipes

Adds two new axes, AXIS_GESTURE_X_OFFSET and AXIS_GESTURE_Y_OFFSET,
which report the movement of swipe gestures on the touchpad as a
fraction of the touchpad's size.

Bug: 246758376
Test: check axis values come through in a test app
Change-Id: I313410053a8db13273bd05a33d3a6a1f75081dae
parent f1f601e0
Loading
Loading
Loading
Loading
+16 −1
Original line number Diff line number Diff line
@@ -771,6 +771,21 @@ enum {
     * The interpretation of a generic axis is device-specific.
     */
    AMOTION_EVENT_AXIS_GENERIC_16 = 47,
    /**
     * Axis constant: X gesture offset axis of a motion event.
     *
     * - For a touch pad, reports the distance that a swipe gesture has moved in the X axis, as a
     *   proportion of the touch pad's size. For example, if a touch pad is 1000 units wide, and a
     *   swipe gesture starts at X = 500 then moves to X = 400, this axis would have a value of
     *   -0.1.
     */
    AMOTION_EVENT_AXIS_GESTURE_X_OFFSET = 48,
    /**
     * Axis constant: Y gesture offset axis of a motion event.
     *
     * The same as {@link AMOTION_EVENT_AXIS_GESTURE_X_OFFSET}, but for the Y axis.
     */
    AMOTION_EVENT_AXIS_GESTURE_Y_OFFSET = 49,

    /**
     * Note: This is not an "Axis constant". It does not represent any axis, nor should it be used
@@ -778,7 +793,7 @@ enum {
     * to make some computations (like iterating through all possible axes) cleaner.
     * Please update the value accordingly if you add a new axis.
     */
    AMOTION_EVENT_MAXIMUM_VALID_AXIS_VALUE = AMOTION_EVENT_AXIS_GENERIC_16,
    AMOTION_EVENT_MAXIMUM_VALID_AXIS_VALUE = AMOTION_EVENT_AXIS_GESTURE_Y_OFFSET,

    // NOTE: If you add a new axis here you must also add it to several other files.
    //       Refer to frameworks/base/core/java/android/view/MotionEvent.java for the full list.
+3 −1
Original line number Diff line number Diff line
@@ -391,7 +391,9 @@ namespace android {
    DEFINE_AXIS(GENERIC_13), \
    DEFINE_AXIS(GENERIC_14), \
    DEFINE_AXIS(GENERIC_15), \
    DEFINE_AXIS(GENERIC_16)
    DEFINE_AXIS(GENERIC_16), \
    DEFINE_AXIS(GESTURE_X_OFFSET), \
    DEFINE_AXIS(GESTURE_Y_OFFSET)

// NOTE: If you add new LEDs here, you must also add them to Input.h
#define LEDS_SEQUENCE \
+4 −1
Original line number Diff line number Diff line
@@ -263,8 +263,11 @@ static_assert(static_cast<common::Axis>(AMOTION_EVENT_AXIS_GENERIC_13) == common
static_assert(static_cast<common::Axis>(AMOTION_EVENT_AXIS_GENERIC_14) == common::Axis::GENERIC_14);
static_assert(static_cast<common::Axis>(AMOTION_EVENT_AXIS_GENERIC_15) == common::Axis::GENERIC_15);
static_assert(static_cast<common::Axis>(AMOTION_EVENT_AXIS_GENERIC_16) == common::Axis::GENERIC_16);
// TODO(hcutts): add GESTURE_X_OFFSET and GESTURE_Y_OFFSET.
// If you added a new axis, consider whether this should also be exposed as a HAL axis. Update the
// static_assert below and add the new axis here, or leave a comment summarizing your decision.
static_assert(static_cast<common::Axis>(AMOTION_EVENT_MAXIMUM_VALID_AXIS_VALUE) ==
              static_cast<common::Axis>(AMOTION_EVENT_AXIS_GENERIC_16));
              static_cast<common::Axis>(AMOTION_EVENT_AXIS_GESTURE_Y_OFFSET));

static common::VideoFrame getHalVideoFrame(const TouchVideoFrame& frame) {
    common::VideoFrame out;
+20 −10
Original line number Diff line number Diff line
@@ -3175,7 +3175,7 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, bool* outCancelPrevi
        mPointerGesture.referenceIdBits = mCurrentCookedState.fingerIdBits;

        // Add delta for all fingers and calculate a common movement delta.
        float commonDeltaX = 0, commonDeltaY = 0;
        int32_t commonDeltaRawX = 0, commonDeltaRawY = 0;
        BitSet32 commonIdBits(mLastCookedState.fingerIdBits.value &
                              mCurrentCookedState.fingerIdBits.value);
        for (BitSet32 idBits(commonIdBits); !idBits.isEmpty();) {
@@ -3188,11 +3188,11 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, bool* outCancelPrevi
            delta.dy += cpd.y - lpd.y;

            if (first) {
                commonDeltaX = delta.dx;
                commonDeltaY = delta.dy;
                commonDeltaRawX = delta.dx;
                commonDeltaRawY = delta.dy;
            } else {
                commonDeltaX = calculateCommonVector(commonDeltaX, delta.dx);
                commonDeltaY = calculateCommonVector(commonDeltaY, delta.dy);
                commonDeltaRawX = calculateCommonVector(commonDeltaRawX, delta.dx);
                commonDeltaRawY = calculateCommonVector(commonDeltaRawY, delta.dy);
            }
        }

@@ -3298,7 +3298,7 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, bool* outCancelPrevi
        // Move the reference points based on the overall group motion of the fingers
        // except in PRESS mode while waiting for a transition to occur.
        if (mPointerGesture.currentGestureMode != PointerGesture::Mode::PRESS &&
            (commonDeltaX || commonDeltaY)) {
            (commonDeltaRawX || commonDeltaRawY)) {
            for (BitSet32 idBits(mPointerGesture.referenceIdBits); !idBits.isEmpty();) {
                uint32_t id = idBits.clearFirstMarkedBit();
                PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id];
@@ -3306,11 +3306,11 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, bool* outCancelPrevi
                delta.dy = 0;
            }

            mPointerGesture.referenceTouchX += commonDeltaX;
            mPointerGesture.referenceTouchY += commonDeltaY;
            mPointerGesture.referenceTouchX += commonDeltaRawX;
            mPointerGesture.referenceTouchY += commonDeltaRawY;

            commonDeltaX *= mPointerXMovementScale;
            commonDeltaY *= mPointerYMovementScale;
            float commonDeltaX = commonDeltaRawX * mPointerXMovementScale;
            float commonDeltaY = commonDeltaRawY * mPointerYMovementScale;

            rotateDelta(mInputDeviceOrientation, &commonDeltaX, &commonDeltaY);
            mPointerVelocityControl.move(when, &commonDeltaX, &commonDeltaY);
@@ -3341,6 +3341,16 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, bool* outCancelPrevi
            mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y,
                                                                 mPointerGesture.referenceGestureY);
            mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
            if (mPointerGesture.currentGestureMode == PointerGesture::Mode::SWIPE) {
                float xOffset = static_cast<float>(commonDeltaRawX) /
                        (mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue);
                float yOffset = static_cast<float>(commonDeltaRawY) /
                        (mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue);
                mPointerGesture.currentGestureCoords[0]
                        .setAxisValue(AMOTION_EVENT_AXIS_GESTURE_X_OFFSET, xOffset);
                mPointerGesture.currentGestureCoords[0]
                        .setAxisValue(AMOTION_EVENT_AXIS_GESTURE_Y_OFFSET, yOffset);
            }
        } else if (mPointerGesture.currentGestureMode == PointerGesture::Mode::FREEFORM) {
            // FREEFORM mode.
            ALOGD_IF(DEBUG_GESTURES,
+46 −0
Original line number Diff line number Diff line
@@ -10085,6 +10085,52 @@ TEST_F(MultiTouchPointerModeTest, PointerGestureMaxSwipeWidthFreeform) {
                                                0, 0, 0, 0, 0));
}

TEST_F(MultiTouchPointerModeTest, TwoFingerSwipeOffsets) {
    preparePointerMode(25 /*xResolution*/, 25 /*yResolution*/);
    MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
    NotifyMotionArgs motionArgs;

    // Place two fingers down.
    int32_t x1 = 100, y1 = 125, x2 = 550, y2 = 125;

    processId(mapper, FIRST_TRACKING_ID);
    processPosition(mapper, x1, y1);
    processMTSync(mapper);
    processId(mapper, SECOND_TRACKING_ID);
    processPosition(mapper, x2, y2);
    processMTSync(mapper);
    processSync(mapper);

    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
    ASSERT_EQ(1U, motionArgs.pointerCount);
    ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
    ASSERT_EQ(MotionClassification::NONE, motionArgs.classification);
    ASSERT_EQ(0, motionArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_GESTURE_X_OFFSET));
    ASSERT_EQ(0, motionArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_GESTURE_Y_OFFSET));

    // Move the two fingers down and to the left.
    int32_t movingDistance = 200;
    x1 -= movingDistance;
    y1 += movingDistance;
    x2 -= movingDistance;
    y2 += movingDistance;

    processId(mapper, FIRST_TRACKING_ID);
    processPosition(mapper, x1, y1);
    processMTSync(mapper);
    processId(mapper, SECOND_TRACKING_ID);
    processPosition(mapper, x2, y2);
    processMTSync(mapper);
    processSync(mapper);

    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
    ASSERT_EQ(1U, motionArgs.pointerCount);
    ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
    ASSERT_EQ(MotionClassification::TWO_FINGER_SWIPE, motionArgs.classification);
    ASSERT_LT(motionArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_GESTURE_X_OFFSET), 0);
    ASSERT_GT(motionArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_GESTURE_Y_OFFSET), 0);
}

// --- JoystickInputMapperTest ---

class JoystickInputMapperTest : public InputMapperTest {