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

Commit 00f511d3 authored by Garfield Tan's avatar Garfield Tan
Browse files

Dispatch mouse events to window under the cursor.

This CL adds cursor positions to NotifyMotionArgs, MotionEntry,
InputMessage motion body and MotionEvent.

Bug: 134788085
Test: The window under the cursor always responds to the gesture.
Test: atest inputflinger_tests
Test: atest libinput_tests
Change-Id: I8ea460ed8738ffc3a5e997215685889cc1e1f2fe
parent eb6ab629
Loading
Loading
Loading
Loading
+27 −21
Original line number Diff line number Diff line
@@ -24,12 +24,14 @@
 */

#include <android/input.h>
#include <stdint.h>
#include <utils/BitSet.h>
#include <utils/KeyedVector.h>
#include <utils/RefBase.h>
#include <utils/Timers.h>
#include <utils/Vector.h>
#include <stdint.h>

#include <limits>

/*
 * Additional private constants not defined in ndk/ui/input.h.
@@ -246,6 +248,13 @@ enum class MotionClassification : uint8_t {
 */
const char* motionClassificationToString(MotionClassification classification);

/**
 * Invalid value for cursor position. Used for non-mouse events, tests and injected events. Don't
 * use it for direct comparison with any other value, because NaN isn't equal to itself according to
 * IEEE 754. Use isnan() instead to check if a cursor position is valid.
 */
constexpr float AMOTION_EVENT_INVALID_CURSOR_POSITION = std::numeric_limits<float>::quiet_NaN();

/*
 * Pointer coordinate data.
 */
@@ -459,6 +468,14 @@ public:

    inline float getYPrecision() const { return mYPrecision; }

    inline float getRawXCursorPosition() const { return mXCursorPosition; }

    float getXCursorPosition() const;

    inline float getRawYCursorPosition() const { return mYCursorPosition; }

    float getYCursorPosition() const;

    inline nsecs_t getDownTime() const { return mDownTime; }

    inline void setDownTime(nsecs_t downTime) { mDownTime = downTime; }
@@ -600,25 +617,12 @@ public:

    ssize_t findPointerIndex(int32_t pointerId) const;

    void initialize(
            int32_t deviceId,
            int32_t source,
            int32_t displayId,
            int32_t action,
            int32_t actionButton,
            int32_t flags,
            int32_t edgeFlags,
            int32_t metaState,
            int32_t buttonState,
            MotionClassification classification,
            float xOffset,
            float yOffset,
            float xPrecision,
            float yPrecision,
            nsecs_t downTime,
            nsecs_t eventTime,
            size_t pointerCount,
            const PointerProperties* pointerProperties,
    void initialize(int32_t deviceId, int32_t source, int32_t displayId, int32_t action,
                    int32_t actionButton, int32_t flags, int32_t edgeFlags, int32_t metaState,
                    int32_t buttonState, MotionClassification classification, float xOffset,
                    float yOffset, float xPrecision, float yPrecision, float mXCursorPosition,
                    float mYCursorPosition, nsecs_t downTime, nsecs_t eventTime,
                    size_t pointerCount, const PointerProperties* pointerProperties,
                    const PointerCoords* pointerCoords);

    void copyFrom(const MotionEvent* other, bool keepHistory);
@@ -669,6 +673,8 @@ protected:
    float mYOffset;
    float mXPrecision;
    float mYPrecision;
    float mXCursorPosition;
    float mYCursorPosition;
    nsecs_t mDownTime;
    Vector<PointerProperties> mPointerProperties;
    Vector<nsecs_t> mSampleEventTimes;
+10 −21
Original line number Diff line number Diff line
@@ -113,6 +113,8 @@ struct InputMessage {
            float yOffset;
            float xPrecision;
            float yPrecision;
            float xCursorPosition;
            float yCursorPosition;
            uint32_t pointerCount;
            uint32_t empty3;
            // Note that PointerCoords requires 8 byte alignment.
@@ -261,26 +263,13 @@ public:
     * Returns BAD_VALUE if seq is 0 or if pointerCount is less than 1 or greater than MAX_POINTERS.
     * Other errors probably indicate that the channel is broken.
     */
    status_t publishMotionEvent(
            uint32_t seq,
            int32_t deviceId,
            int32_t source,
            int32_t displayId,
            int32_t action,
            int32_t actionButton,
            int32_t flags,
            int32_t edgeFlags,
            int32_t metaState,
            int32_t buttonState,
            MotionClassification classification,
            float xOffset,
            float yOffset,
            float xPrecision,
            float yPrecision,
            nsecs_t downTime,
            nsecs_t eventTime,
            uint32_t pointerCount,
            const PointerProperties* pointerProperties,
    status_t publishMotionEvent(uint32_t seq, int32_t deviceId, int32_t source, int32_t displayId,
                                int32_t action, int32_t actionButton, int32_t flags,
                                int32_t edgeFlags, int32_t metaState, int32_t buttonState,
                                MotionClassification classification, float xOffset, float yOffset,
                                float xPrecision, float yPrecision, float xCursorPosition,
                                float yCursorPosition, nsecs_t downTime, nsecs_t eventTime,
                                uint32_t pointerCount, const PointerProperties* pointerProperties,
                                const PointerCoords* pointerCoords);

    /* Receives the finished signal from the consumer in reply to the original dispatch signal.
+35 −20
Original line number Diff line number Diff line
@@ -235,25 +235,13 @@ void PointerProperties::copyFrom(const PointerProperties& other) {

// --- MotionEvent ---

void MotionEvent::initialize(
        int32_t deviceId,
        int32_t source,
        int32_t displayId,
        int32_t action,
        int32_t actionButton,
        int32_t flags,
        int32_t edgeFlags,
        int32_t metaState,
        int32_t buttonState,
        MotionClassification classification,
        float xOffset,
        float yOffset,
        float xPrecision,
        float yPrecision,
        nsecs_t downTime,
        nsecs_t eventTime,
        size_t pointerCount,
        const PointerProperties* pointerProperties,
void MotionEvent::initialize(int32_t deviceId, int32_t source, int32_t displayId, int32_t action,
                             int32_t actionButton, int32_t flags, int32_t edgeFlags,
                             int32_t metaState, int32_t buttonState,
                             MotionClassification classification, float xOffset, float yOffset,
                             float xPrecision, float yPrecision, float xCursorPosition,
                             float yCursorPosition, nsecs_t downTime, nsecs_t eventTime,
                             size_t pointerCount, const PointerProperties* pointerProperties,
                             const PointerCoords* pointerCoords) {
    InputEvent::initialize(deviceId, source, displayId);
    mAction = action;
@@ -267,6 +255,8 @@ void MotionEvent::initialize(
    mYOffset = yOffset;
    mXPrecision = xPrecision;
    mYPrecision = yPrecision;
    mXCursorPosition = xCursorPosition;
    mYCursorPosition = yCursorPosition;
    mDownTime = downTime;
    mPointerProperties.clear();
    mPointerProperties.appendArray(pointerProperties, pointerCount);
@@ -288,6 +278,8 @@ void MotionEvent::copyFrom(const MotionEvent* other, bool keepHistory) {
    mYOffset = other->mYOffset;
    mXPrecision = other->mXPrecision;
    mYPrecision = other->mYPrecision;
    mXCursorPosition = other->mXCursorPosition;
    mYCursorPosition = other->mYCursorPosition;
    mDownTime = other->mDownTime;
    mPointerProperties = other->mPointerProperties;

@@ -312,6 +304,16 @@ void MotionEvent::addSample(
    mSamplePointerCoords.appendArray(pointerCoords, getPointerCount());
}

float MotionEvent::getXCursorPosition() const {
    const float rawX = getRawXCursorPosition();
    return rawX + mXOffset;
}

float MotionEvent::getYCursorPosition() const {
    const float rawY = getRawYCursorPosition();
    return rawY + mYOffset;
}

const PointerCoords* MotionEvent::getRawPointerCoords(size_t pointerIndex) const {
    return &mSamplePointerCoords[getHistorySize() * getPointerCount() + pointerIndex];
}
@@ -431,6 +433,15 @@ void MotionEvent::transform(const float matrix[9]) {
    float originX, originY;
    transformPoint(matrix, 0, 0, &originX, &originY);

    // Apply the transformation to cursor position.
    if (!isnan(mXCursorPosition) && !isnan(mYCursorPosition)) {
        float x = mXCursorPosition + oldXOffset;
        float y = mYCursorPosition + oldYOffset;
        transformPoint(matrix, x, y, &x, &y);
        mXCursorPosition = x - mXOffset;
        mYCursorPosition = y - mYOffset;
    }

    // Apply the transformation to all samples.
    size_t numSamples = mSamplePointerCoords.size();
    for (size_t i = 0; i < numSamples; i++) {
@@ -470,6 +481,8 @@ status_t MotionEvent::readFromParcel(Parcel* parcel) {
    mYOffset = parcel->readFloat();
    mXPrecision = parcel->readFloat();
    mYPrecision = parcel->readFloat();
    mXCursorPosition = parcel->readFloat();
    mYCursorPosition = parcel->readFloat();
    mDownTime = parcel->readInt64();

    mPointerProperties.clear();
@@ -521,6 +534,8 @@ status_t MotionEvent::writeToParcel(Parcel* parcel) const {
    parcel->writeFloat(mYOffset);
    parcel->writeFloat(mXPrecision);
    parcel->writeFloat(mYPrecision);
    parcel->writeFloat(mXCursorPosition);
    parcel->writeFloat(mYCursorPosition);
    parcel->writeInt64(mDownTime);

    for (size_t i = 0; i < pointerCount; i++) {
+22 −40
Original line number Diff line number Diff line
@@ -191,6 +191,10 @@ void InputMessage::getSanitizedCopy(InputMessage* msg) const {
            msg->body.motion.xPrecision = body.motion.xPrecision;
            // float yPrecision
            msg->body.motion.yPrecision = body.motion.yPrecision;
            // float xCursorPosition
            msg->body.motion.xCursorPosition = body.motion.xCursorPosition;
            // float yCursorPosition
            msg->body.motion.yCursorPosition = body.motion.yCursorPosition;
            // uint32_t pointerCount
            msg->body.motion.pointerCount = body.motion.pointerCount;
            //struct Pointer pointers[MAX_POINTERS]
@@ -465,26 +469,12 @@ status_t InputPublisher::publishKeyEvent(
}

status_t InputPublisher::publishMotionEvent(
        uint32_t seq,
        int32_t deviceId,
        int32_t source,
        int32_t displayId,
        int32_t action,
        int32_t actionButton,
        int32_t flags,
        int32_t edgeFlags,
        int32_t metaState,
        int32_t buttonState,
        MotionClassification classification,
        float xOffset,
        float yOffset,
        float xPrecision,
        float yPrecision,
        nsecs_t downTime,
        nsecs_t eventTime,
        uint32_t pointerCount,
        const PointerProperties* pointerProperties,
        const PointerCoords* pointerCoords) {
        uint32_t seq, int32_t deviceId, int32_t source, int32_t displayId, int32_t action,
        int32_t actionButton, int32_t flags, int32_t edgeFlags, int32_t metaState,
        int32_t buttonState, MotionClassification classification, float xOffset, float yOffset,
        float xPrecision, float yPrecision, float xCursorPosition, float yCursorPosition,
        nsecs_t downTime, nsecs_t eventTime, uint32_t pointerCount,
        const PointerProperties* pointerProperties, const PointerCoords* pointerCoords) {
    if (ATRACE_ENABLED()) {
        std::string message = StringPrintf(
                "publishMotionEvent(inputChannel=%s, action=%" PRId32 ")",
@@ -532,6 +522,8 @@ status_t InputPublisher::publishMotionEvent(
    msg.body.motion.yOffset = yOffset;
    msg.body.motion.xPrecision = xPrecision;
    msg.body.motion.yPrecision = yPrecision;
    msg.body.motion.xCursorPosition = xCursorPosition;
    msg.body.motion.yCursorPosition = yCursorPosition;
    msg.body.motion.downTime = downTime;
    msg.body.motion.eventTime = eventTime;
    msg.body.motion.pointerCount = pointerCount;
@@ -1135,26 +1127,16 @@ void InputConsumer::initializeMotionEvent(MotionEvent* event, const InputMessage
        pointerCoords[i].copyFrom(msg->body.motion.pointers[i].coords);
    }

    event->initialize(
            msg->body.motion.deviceId,
            msg->body.motion.source,
            msg->body.motion.displayId,
            msg->body.motion.action,
            msg->body.motion.actionButton,
            msg->body.motion.flags,
            msg->body.motion.edgeFlags,
            msg->body.motion.metaState,
            msg->body.motion.buttonState,
            msg->body.motion.classification,
            msg->body.motion.xOffset,
            msg->body.motion.yOffset,
            msg->body.motion.xPrecision,
            msg->body.motion.yPrecision,
            msg->body.motion.downTime,
            msg->body.motion.eventTime,
            pointerCount,
            pointerProperties,
            pointerCoords);
    event->initialize(msg->body.motion.deviceId, msg->body.motion.source,
                      msg->body.motion.displayId, msg->body.motion.action,
                      msg->body.motion.actionButton, msg->body.motion.flags,
                      msg->body.motion.edgeFlags, msg->body.motion.metaState,
                      msg->body.motion.buttonState, msg->body.motion.classification,
                      msg->body.motion.xOffset, msg->body.motion.yOffset,
                      msg->body.motion.xPrecision, msg->body.motion.yPrecision,
                      msg->body.motion.xCursorPosition, msg->body.motion.yCursorPosition,
                      msg->body.motion.downTime, msg->body.motion.eventTime, pointerCount,
                      pointerProperties, pointerCoords);
}

void InputConsumer::addSample(MotionEvent* event, const InputMessage* msg) {
+40 −12
Original line number Diff line number Diff line
@@ -255,11 +255,11 @@ void MotionEventTest::initializeEventWithHistory(MotionEvent* event) {
    pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, 27);
    pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, 28);
    event->initialize(2, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, AMOTION_EVENT_ACTION_MOVE, 0,
            AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED,
            AMOTION_EVENT_EDGE_FLAG_TOP, AMETA_ALT_ON, AMOTION_EVENT_BUTTON_PRIMARY,
            MotionClassification::NONE, X_OFFSET, Y_OFFSET, 2.0f, 2.1f,
            ARBITRARY_DOWN_TIME, ARBITRARY_EVENT_TIME,
            2, pointerProperties, pointerCoords);
                      AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED, AMOTION_EVENT_EDGE_FLAG_TOP,
                      AMETA_ALT_ON, AMOTION_EVENT_BUTTON_PRIMARY, MotionClassification::NONE,
                      X_OFFSET, Y_OFFSET, 2.0f, 2.1f, AMOTION_EVENT_INVALID_CURSOR_POSITION,
                      AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_DOWN_TIME,
                      ARBITRARY_EVENT_TIME, 2, pointerProperties, pointerCoords);

    pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 110);
    pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 111);
@@ -571,10 +571,11 @@ TEST_F(MotionEventTest, Transform) {
    }
    MotionEvent event;
    event.initialize(0 /*deviceId*/, AINPUT_SOURCE_UNKNOWN, DISPLAY_ID, AMOTION_EVENT_ACTION_MOVE,
            0 /*actionButton*/, 0 /*flags*/, AMOTION_EVENT_EDGE_FLAG_NONE,
            AMETA_NONE, 0 /*buttonState*/, MotionClassification::NONE,
            0 /*xOffset*/, 0 /*yOffset*/, 0 /*xPrecision*/, 0 /*yPrecision*/,
            0 /*downTime*/, 0 /*eventTime*/, pointerCount, pointerProperties, pointerCoords);
                     0 /*actionButton*/, 0 /*flags*/, AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE,
                     0 /*buttonState*/, MotionClassification::NONE, 0 /*xOffset*/, 0 /*yOffset*/,
                     0 /*xPrecision*/, 0 /*yPrecision*/, 3 + RADIUS /*xCursorPosition*/,
                     2 /*yCursorPosition*/, 0 /*downTime*/, 0 /*eventTime*/, pointerCount,
                     pointerProperties, pointerCoords);
    float originalRawX = 0 + 3;
    float originalRawY = -RADIUS + 2;

@@ -602,6 +603,10 @@ TEST_F(MotionEventTest, Transform) {
        ASSERT_NEAR(tanf(angle), tanf(event.getOrientation(i)), 0.1);
    }

    // Check cursor positions.
    ASSERT_NEAR(sinf(PI_180 * (90 + ROTATION)) * RADIUS, event.getXCursorPosition(), 0.001);
    ASSERT_NEAR(-cosf(PI_180 * (90 + ROTATION)) * RADIUS, event.getYCursorPosition(), 0.001);

    // Applying the transformation should preserve the raw X and Y of the first point.
    ASSERT_NEAR(originalRawX, event.getRawX(0), 0.001);
    ASSERT_NEAR(originalRawY, event.getRawY(0), 0.001);
@@ -626,11 +631,34 @@ TEST_F(MotionEventTest, Initialize_SetsClassification) {

    for (MotionClassification classification : classifications) {
        event.initialize(0 /*deviceId*/, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID,
                AMOTION_EVENT_ACTION_DOWN, 0, 0, AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0,
                classification, 0, 0, 0, 0, 0 /*downTime*/, 0 /*eventTime*/,
                         AMOTION_EVENT_ACTION_DOWN, 0, 0, AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE,
                         0, classification, 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
                         AMOTION_EVENT_INVALID_CURSOR_POSITION, 0 /*downTime*/, 0 /*eventTime*/,
                         pointerCount, pointerProperties, pointerCoords);
        ASSERT_EQ(classification, event.getClassification());
    }
}

TEST_F(MotionEventTest, Initialize_SetsCursorPosition) {
    MotionEvent event;
    constexpr size_t pointerCount = 1;
    PointerProperties pointerProperties[pointerCount];
    PointerCoords pointerCoords[pointerCount];
    for (size_t i = 0; i < pointerCount; i++) {
        pointerProperties[i].clear();
        pointerProperties[i].id = i;
        pointerCoords[i].clear();
    }

    event.initialize(0 /*deviceId*/, AINPUT_SOURCE_MOUSE, DISPLAY_ID, AMOTION_EVENT_ACTION_DOWN, 0,
                     0, AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE, 0,
                     0, 0, 0, 280 /*xCursorPosition*/, 540 /*yCursorPosition*/, 0 /*downTime*/,
                     0 /*eventTime*/, pointerCount, pointerProperties, pointerCoords);
    event.offsetLocation(20, 60);
    ASSERT_EQ(280, event.getRawXCursorPosition());
    ASSERT_EQ(540, event.getRawYCursorPosition());
    ASSERT_EQ(300, event.getXCursorPosition());
    ASSERT_EQ(600, event.getYCursorPosition());
}

} // namespace android
Loading