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
diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp
index 9fd25f9..3266b07 100644
--- a/libs/input/Input.cpp
+++ b/libs/input/Input.cpp
@@ -235,26 +235,14 @@
// --- 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,
- const PointerCoords* pointerCoords) {
+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;
mActionButton = actionButton;
@@ -267,6 +255,8 @@
mYOffset = yOffset;
mXPrecision = xPrecision;
mYPrecision = yPrecision;
+ mXCursorPosition = xCursorPosition;
+ mYCursorPosition = yCursorPosition;
mDownTime = downTime;
mPointerProperties.clear();
mPointerProperties.appendArray(pointerProperties, pointerCount);
@@ -288,6 +278,8 @@
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 @@
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 @@
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 @@
mYOffset = parcel->readFloat();
mXPrecision = parcel->readFloat();
mYPrecision = parcel->readFloat();
+ mXCursorPosition = parcel->readFloat();
+ mYCursorPosition = parcel->readFloat();
mDownTime = parcel->readInt64();
mPointerProperties.clear();
@@ -521,6 +534,8 @@
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++) {
diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp
index d02cb8e..904a6fe 100644
--- a/libs/input/InputTransport.cpp
+++ b/libs/input/InputTransport.cpp
@@ -191,6 +191,10 @@
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::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 @@
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 @@
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) {
diff --git a/libs/input/tests/InputEvent_test.cpp b/libs/input/tests/InputEvent_test.cpp
index 2b75c82..ec34f3e 100644
--- a/libs/input/tests/InputEvent_test.cpp
+++ b/libs/input/tests/InputEvent_test.cpp
@@ -255,11 +255,11 @@
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 @@
}
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 @@
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 @@
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*/,
- pointerCount, pointerProperties, pointerCoords);
+ 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
diff --git a/libs/input/tests/InputPublisherAndConsumer_test.cpp b/libs/input/tests/InputPublisherAndConsumer_test.cpp
index f2cd1be..a362f32 100644
--- a/libs/input/tests/InputPublisherAndConsumer_test.cpp
+++ b/libs/input/tests/InputPublisherAndConsumer_test.cpp
@@ -146,6 +146,8 @@
constexpr float yOffset = -20;
constexpr float xPrecision = 0.25;
constexpr float yPrecision = 0.5;
+ constexpr float xCursorPosition = 1.3;
+ constexpr float yCursorPosition = 50.6;
constexpr nsecs_t downTime = 3;
constexpr size_t pointerCount = 3;
constexpr nsecs_t eventTime = 4;
@@ -168,10 +170,12 @@
pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, 3.5 * i);
}
- status = mPublisher->publishMotionEvent(seq, deviceId, source, displayId, action, actionButton,
- flags, edgeFlags, metaState, buttonState, classification,
- xOffset, yOffset, xPrecision, yPrecision, downTime, eventTime, pointerCount,
- pointerProperties, pointerCoords);
+ status =
+ mPublisher->publishMotionEvent(seq, deviceId, source, displayId, action, actionButton,
+ flags, edgeFlags, metaState, buttonState, classification,
+ xOffset, yOffset, xPrecision, yPrecision,
+ xCursorPosition, yCursorPosition, downTime, eventTime,
+ pointerCount, pointerProperties, pointerCoords);
ASSERT_EQ(OK, status)
<< "publisher publishMotionEvent should return OK";
@@ -199,6 +203,10 @@
EXPECT_EQ(classification, motionEvent->getClassification());
EXPECT_EQ(xPrecision, motionEvent->getXPrecision());
EXPECT_EQ(yPrecision, motionEvent->getYPrecision());
+ EXPECT_EQ(xCursorPosition, motionEvent->getRawXCursorPosition());
+ EXPECT_EQ(yCursorPosition, motionEvent->getRawYCursorPosition());
+ EXPECT_EQ(xCursorPosition + xOffset, motionEvent->getXCursorPosition());
+ EXPECT_EQ(yCursorPosition + yOffset, motionEvent->getYCursorPosition());
EXPECT_EQ(downTime, motionEvent->getDownTime());
EXPECT_EQ(eventTime, motionEvent->getEventTime());
EXPECT_EQ(pointerCount, motionEvent->getPointerCount());
@@ -266,9 +274,11 @@
pointerCoords[i].clear();
}
- status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- MotionClassification::NONE, 0, 0, 0, 0, 0, 0,
- pointerCount, pointerProperties, pointerCoords);
+ status =
+ mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, MotionClassification::NONE,
+ 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
+ AMOTION_EVENT_INVALID_CURSOR_POSITION, 0, 0,
+ pointerCount, pointerProperties, pointerCoords);
ASSERT_EQ(BAD_VALUE, status)
<< "publisher publishMotionEvent should return BAD_VALUE";
}
@@ -279,9 +289,11 @@
PointerProperties pointerProperties[pointerCount];
PointerCoords pointerCoords[pointerCount];
- status = mPublisher->publishMotionEvent(1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- MotionClassification::NONE, 0, 0, 0, 0, 0, 0,
- pointerCount, pointerProperties, pointerCoords);
+ status =
+ mPublisher->publishMotionEvent(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, MotionClassification::NONE,
+ 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
+ AMOTION_EVENT_INVALID_CURSOR_POSITION, 0, 0,
+ pointerCount, pointerProperties, pointerCoords);
ASSERT_EQ(BAD_VALUE, status)
<< "publisher publishMotionEvent should return BAD_VALUE";
}
@@ -297,9 +309,11 @@
pointerCoords[i].clear();
}
- status = mPublisher->publishMotionEvent(1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- MotionClassification::NONE, 0, 0, 0, 0, 0, 0,
- pointerCount, pointerProperties, pointerCoords);
+ status =
+ mPublisher->publishMotionEvent(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, MotionClassification::NONE,
+ 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
+ AMOTION_EVENT_INVALID_CURSOR_POSITION, 0, 0,
+ pointerCount, pointerProperties, pointerCoords);
ASSERT_EQ(BAD_VALUE, status)
<< "publisher publishMotionEvent should return BAD_VALUE";
}
diff --git a/libs/input/tests/StructLayout_test.cpp b/libs/input/tests/StructLayout_test.cpp
index 62023fb..8d8cf06 100644
--- a/libs/input/tests/StructLayout_test.cpp
+++ b/libs/input/tests/StructLayout_test.cpp
@@ -64,8 +64,10 @@
CHECK_OFFSET(InputMessage::Body::Motion, yOffset, 68);
CHECK_OFFSET(InputMessage::Body::Motion, xPrecision, 72);
CHECK_OFFSET(InputMessage::Body::Motion, yPrecision, 76);
- CHECK_OFFSET(InputMessage::Body::Motion, pointerCount, 80);
- CHECK_OFFSET(InputMessage::Body::Motion, pointers, 88);
+ CHECK_OFFSET(InputMessage::Body::Motion, xCursorPosition, 80);
+ CHECK_OFFSET(InputMessage::Body::Motion, yCursorPosition, 84);
+ CHECK_OFFSET(InputMessage::Body::Motion, pointerCount, 88);
+ CHECK_OFFSET(InputMessage::Body::Motion, pointers, 96);
CHECK_OFFSET(InputMessage::Body::Finished, seq, 0);
CHECK_OFFSET(InputMessage::Body::Finished, handled, 4);
diff --git a/libs/input/tests/VelocityTracker_test.cpp b/libs/input/tests/VelocityTracker_test.cpp
index 368446f..968e2fa 100644
--- a/libs/input/tests/VelocityTracker_test.cpp
+++ b/libs/input/tests/VelocityTracker_test.cpp
@@ -176,12 +176,13 @@
EXPECT_EQ(pointerIndex, pointerCount);
MotionEvent event;
- event.initialize(0 /*deviceId*/, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID,
- action, 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*/, entry.eventTime.count(), pointerCount, properties, coords);
+ event.initialize(0 /*deviceId*/, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, action,
+ 0 /*actionButton*/, 0 /*flags*/, AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE,
+ 0 /*buttonState*/, MotionClassification::NONE, 0 /*xOffset*/,
+ 0 /*yOffset*/, 0 /*xPrecision*/, 0 /*yPrecision*/,
+ AMOTION_EVENT_INVALID_CURSOR_POSITION,
+ AMOTION_EVENT_INVALID_CURSOR_POSITION, 0 /*downTime*/,
+ entry.eventTime.count(), pointerCount, properties, coords);
events.emplace_back(event);
}