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

Commit 9f38881a authored by Prabir Pradhan's avatar Prabir Pradhan
Browse files

Apply translation/offset to events from pointer sources only

Non-pointer events from a relative motion device such as a trackball or
relative mouse (Pointer Capture) should be oriented in the same way as
the window it is directed to. We want them to be rotated if the window
transform has a rotation applied to it, but these relative events should
not be translated.

We only apply window translation to events from pointer sources because
they are the only ones that refer to absolute coordinates on the
display. We apply rotation for all motion events.

Bug: 179274888
Test: atest inputflinger_tests
Test: manual with test app
Change-Id: I8170697119d3d8e121b7b86de3201bac0edaaed9
parent d2c9e8e3
Loading
Loading
Loading
Loading
+21 −4
Original line number Diff line number Diff line
@@ -91,6 +91,19 @@ vec2 rotatePoint(const ui::Transform& transform, float x, float y, int32_t displ
    return xy;
}

vec2 applyTransformWithoutTranslation(const ui::Transform& transform, float x, float y) {
    const vec2 transformedXy = transform.transform(x, y);
    const vec2 transformedOrigin = transform.transform(0, 0);
    return transformedXy - transformedOrigin;
}

bool shouldDisregardWindowTranslation(uint32_t source) {
    // Pointer events are the only type of events that refer to absolute coordinates on the display,
    // so we should apply the entire window transform. For other types of events, we should make
    // sure to not apply the window translation/offset.
    return (source & AINPUT_SOURCE_CLASS_POINTER) == 0;
}

} // namespace

const char* motionClassificationToString(MotionClassification classification) {
@@ -509,7 +522,9 @@ float MotionEvent::getHistoricalRawAxisValue(int32_t axis, size_t pointerIndex,
    if (axis == AMOTION_EVENT_AXIS_X || axis == AMOTION_EVENT_AXIS_Y) {
        // For compatibility, convert raw coordinates into "oriented screen space". Once app
        // developers are educated about getRaw, we can consider removing this.
        const vec2 xy = rotatePoint(mTransform, coords->getX(), coords->getY(), mDisplayWidth,
        const vec2 xy = shouldDisregardWindowTranslation(mSource)
                ? rotatePoint(mTransform, coords->getX(), coords->getY())
                : rotatePoint(mTransform, coords->getX(), coords->getY(), mDisplayWidth,
                              mDisplayHeight);
        static_assert(AMOTION_EVENT_AXIS_X == 0 && AMOTION_EVENT_AXIS_Y == 1);
        return xy[axis];
@@ -523,7 +538,9 @@ float MotionEvent::getHistoricalAxisValue(int32_t axis, size_t pointerIndex,
    const PointerCoords* coords = getHistoricalRawPointerCoords(pointerIndex, historicalIndex);

    if (axis == AMOTION_EVENT_AXIS_X || axis == AMOTION_EVENT_AXIS_Y) {
        const vec2 xy = mTransform.transform(coords->getXYValue());
        const vec2 xy = shouldDisregardWindowTranslation(mSource)
                ? applyTransformWithoutTranslation(mTransform, coords->getX(), coords->getY())
                : mTransform.transform(coords->getXYValue());
        static_assert(AMOTION_EVENT_AXIS_X == 0 && AMOTION_EVENT_AXIS_Y == 1);
        return xy[axis];
    }
+21 −1
Original line number Diff line number Diff line
@@ -588,7 +588,7 @@ TEST_F(MotionEventTest, Transform) {
    }
    MotionEvent event;
    ui::Transform identityTransform;
    event.initialize(InputEvent::nextId(), 0 /*deviceId*/, AINPUT_SOURCE_UNKNOWN, DISPLAY_ID,
    event.initialize(InputEvent::nextId(), 0 /*deviceId*/, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID,
                     INVALID_HMAC, AMOTION_EVENT_ACTION_MOVE, 0 /*actionButton*/, 0 /*flags*/,
                     AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0 /*buttonState*/,
                     MotionClassification::NONE, identityTransform, 0 /*xPrecision*/,
@@ -683,6 +683,26 @@ TEST_F(MotionEventTest, ApplyTransform) {
    ASSERT_NEAR(event.getY(0), changedEvent.getY(0), 0.001);
}

TEST_F(MotionEventTest, NonPointerSourcesAreNotTranslated) {
    constexpr static auto NON_POINTER_SOURCES = {AINPUT_SOURCE_TRACKBALL,
                                                 AINPUT_SOURCE_MOUSE_RELATIVE,
                                                 AINPUT_SOURCE_JOYSTICK};
    for (uint32_t source : NON_POINTER_SOURCES) {
        // Create a rotate-90 transform with an offset (like a window which isn't fullscreen).
        ui::Transform xform(ui::Transform::ROT_90, 800, 400);
        xform.set(xform.tx() + 20, xform.ty() + 40);
        MotionEvent event = createTouchDownEvent(60, 100, xform);
        event.setSource(source);

        // Since this event comes from a non-pointer source, it should include rotation but not
        // translation/offset.
        ASSERT_EQ(-100, event.getX(0));
        ASSERT_EQ(60, event.getY(0));
        ASSERT_EQ(event.getRawX(0), event.getX(0));
        ASSERT_EQ(event.getRawY(0), event.getY(0));
    }
}

TEST_F(MotionEventTest, RawCompatTransform) {
    {
        // Make sure raw is raw regardless of transform translation.