diff options
| -rw-r--r-- | services/inputflinger/dispatcher/InputDispatcher.cpp | 154 | ||||
| -rw-r--r-- | services/inputflinger/dispatcher/InputDispatcher.h | 6 | ||||
| -rw-r--r-- | services/inputflinger/dispatcher/InputTarget.cpp | 39 | ||||
| -rw-r--r-- | services/inputflinger/dispatcher/InputTarget.h | 47 | ||||
| -rw-r--r-- | services/inputflinger/tests/InputDispatcher_test.cpp | 103 |
5 files changed, 59 insertions, 290 deletions
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index 0178811f0f..26c2d3f758 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -256,67 +256,6 @@ static bool isStaleEvent(nsecs_t currentTime, const EventEntry& entry) { return currentTime - entry.eventTime >= STALE_EVENT_TIMEOUT; } -static std::unique_ptr<DispatchEntry> createDispatchEntry(const InputTarget& inputTarget, - EventEntry* eventEntry, - int32_t inputTargetFlags) { - if (inputTarget.useDefaultPointerInfo()) { - const PointerInfo& pointerInfo = inputTarget.getDefaultPointerInfo(); - return std::make_unique<DispatchEntry>(eventEntry, // increments ref - inputTargetFlags, pointerInfo.xOffset, - pointerInfo.yOffset, inputTarget.globalScaleFactor, - pointerInfo.windowXScale, pointerInfo.windowYScale); - } - - ALOG_ASSERT(eventEntry->type == EventEntry::Type::MOTION); - const MotionEntry& motionEntry = static_cast<const MotionEntry&>(*eventEntry); - - PointerCoords pointerCoords[MAX_POINTERS]; - - // Use the first pointer information to normalize all other pointers. This could be any pointer - // as long as all other pointers are normalized to the same value and the final DispatchEntry - // uses the offset and scale for the normalized pointer. - const PointerInfo& firstPointerInfo = - inputTarget.pointerInfos[inputTarget.pointerIds.firstMarkedBit()]; - - // Iterate through all pointers in the event to normalize against the first. - for (uint32_t pointerIndex = 0; pointerIndex < motionEntry.pointerCount; pointerIndex++) { - const PointerProperties& pointerProperties = motionEntry.pointerProperties[pointerIndex]; - uint32_t pointerId = uint32_t(pointerProperties.id); - const PointerInfo& currPointerInfo = inputTarget.pointerInfos[pointerId]; - - // The scale factor is the ratio of the current pointers scale to the normalized scale. - float scaleXDiff = currPointerInfo.windowXScale / firstPointerInfo.windowXScale; - float scaleYDiff = currPointerInfo.windowYScale / firstPointerInfo.windowYScale; - - pointerCoords[pointerIndex].copyFrom(motionEntry.pointerCoords[pointerIndex]); - // First apply the current pointers offset to set the window at 0,0 - pointerCoords[pointerIndex].applyOffset(currPointerInfo.xOffset, currPointerInfo.yOffset); - // Next scale the coordinates. - pointerCoords[pointerIndex].scale(1, scaleXDiff, scaleYDiff); - // Lastly, offset the coordinates so they're in the normalized pointer's frame. - pointerCoords[pointerIndex].applyOffset(-firstPointerInfo.xOffset, - -firstPointerInfo.yOffset); - } - - MotionEntry* combinedMotionEntry = - new MotionEntry(motionEntry.sequenceNum, motionEntry.eventTime, motionEntry.deviceId, - motionEntry.source, motionEntry.displayId, motionEntry.policyFlags, - motionEntry.action, motionEntry.actionButton, motionEntry.flags, - motionEntry.metaState, motionEntry.buttonState, - motionEntry.classification, motionEntry.edgeFlags, - motionEntry.xPrecision, motionEntry.yPrecision, - motionEntry.xCursorPosition, motionEntry.yCursorPosition, - motionEntry.downTime, motionEntry.pointerCount, - motionEntry.pointerProperties, pointerCoords, 0 /* xOffset */, - 0 /* yOffset */); - - return std::make_unique<DispatchEntry>(combinedMotionEntry, // increments ref - inputTargetFlags, firstPointerInfo.xOffset, - firstPointerInfo.yOffset, inputTarget.globalScaleFactor, - firstPointerInfo.windowXScale, - firstPointerInfo.windowYScale); -} - // --- InputDispatcherThread --- class InputDispatcher::InputDispatcherThread : public Thread { @@ -1172,7 +1111,7 @@ void InputDispatcher::dispatchEventLocked(nsecs_t currentTime, EventEntry* event sp<Connection> connection = getConnectionLocked(inputTarget.inputChannel->getConnectionToken()); if (connection != nullptr) { - prepareDispatchCycleLocked(currentTime, connection, eventEntry, inputTarget); + prepareDispatchCycleLocked(currentTime, connection, eventEntry, &inputTarget); } else { if (DEBUG_FOCUS) { ALOGD("Dropping event delivery to target with channel '%s' because it " @@ -1846,34 +1785,23 @@ Unresponsive: void InputDispatcher::addWindowTargetLocked(const sp<InputWindowHandle>& windowHandle, int32_t targetFlags, BitSet32 pointerIds, std::vector<InputTarget>& inputTargets) { - std::vector<InputTarget>::iterator it = - std::find_if(inputTargets.begin(), inputTargets.end(), - [&windowHandle](const InputTarget& inputTarget) { - return inputTarget.inputChannel->getConnectionToken() == - windowHandle->getToken(); - }); - - const InputWindowInfo* windowInfo = windowHandle->getInfo(); - - if (it == inputTargets.end()) { - InputTarget inputTarget; - sp<InputChannel> inputChannel = getInputChannelLocked(windowHandle->getToken()); - if (inputChannel == nullptr) { - ALOGW("Window %s already unregistered input channel", windowHandle->getName().c_str()); - return; - } - inputTarget.inputChannel = inputChannel; - inputTarget.flags = targetFlags; - inputTarget.globalScaleFactor = windowInfo->globalScaleFactor; - inputTargets.push_back(inputTarget); - it = inputTargets.end() - 1; + sp<InputChannel> inputChannel = getInputChannelLocked(windowHandle->getToken()); + if (inputChannel == nullptr) { + ALOGW("Window %s already unregistered input channel", windowHandle->getName().c_str()); + return; } - ALOG_ASSERT(it->flags == targetFlags); - ALOG_ASSERT(it->globalScaleFactor == windowInfo->globalScaleFactor); - - it->addPointers(pointerIds, -windowInfo->frameLeft, -windowInfo->frameTop, - windowInfo->windowXScale, windowInfo->windowYScale); + const InputWindowInfo* windowInfo = windowHandle->getInfo(); + InputTarget target; + target.inputChannel = inputChannel; + target.flags = targetFlags; + target.xOffset = -windowInfo->frameLeft; + target.yOffset = -windowInfo->frameTop; + target.globalScaleFactor = windowInfo->globalScaleFactor; + target.windowXScale = windowInfo->windowXScale; + target.windowYScale = windowInfo->windowYScale; + target.pointerIds = pointerIds; + inputTargets.push_back(target); } void InputDispatcher::addGlobalMonitoringTargetsLocked(std::vector<InputTarget>& inputTargets, @@ -1896,7 +1824,10 @@ void InputDispatcher::addMonitoringTargetLocked(const Monitor& monitor, float xO InputTarget target; target.inputChannel = monitor.inputChannel; target.flags = InputTarget::FLAG_DISPATCH_AS_IS; - target.setDefaultPointerInfo(xOffset, yOffset, 1 /* windowXScale */, 1 /* windowYScale */); + target.xOffset = xOffset; + target.yOffset = yOffset; + target.pointerIds.clear(); + target.globalScaleFactor = 1.0f; inputTargets.push_back(target); } @@ -2114,7 +2045,7 @@ void InputDispatcher::pokeUserActivityLocked(const EventEntry& eventEntry) { void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection, EventEntry* eventEntry, - const InputTarget& inputTarget) { + const InputTarget* inputTarget) { if (ATRACE_ENABLED()) { std::string message = StringPrintf("prepareDispatchCycleLocked(inputChannel=%s, sequenceNum=%" PRIu32 ")", @@ -2125,9 +2056,9 @@ void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime, ALOGD("channel '%s' ~ prepareDispatchCycle - flags=0x%08x, " "xOffset=%f, yOffset=%f, globalScaleFactor=%f, " "windowScaleFactor=(%f, %f), pointerIds=0x%x", - connection->getInputChannelName().c_str(), inputTarget.flags, inputTarget.xOffset, - inputTarget.yOffset, inputTarget.globalScaleFactor, inputTarget.windowXScale, - inputTarget.windowYScale, inputTarget.pointerIds.value); + connection->getInputChannelName().c_str(), inputTarget->flags, inputTarget->xOffset, + inputTarget->yOffset, inputTarget->globalScaleFactor, inputTarget->windowXScale, + inputTarget->windowYScale, inputTarget->pointerIds.value); #endif // Skip this event if the connection status is not normal. @@ -2141,13 +2072,13 @@ void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime, } // Split a motion event if needed. - if (inputTarget.flags & InputTarget::FLAG_SPLIT) { + if (inputTarget->flags & InputTarget::FLAG_SPLIT) { ALOG_ASSERT(eventEntry->type == EventEntry::Type::MOTION); const MotionEntry& originalMotionEntry = static_cast<const MotionEntry&>(*eventEntry); - if (inputTarget.pointerIds.count() != originalMotionEntry.pointerCount) { + if (inputTarget->pointerIds.count() != originalMotionEntry.pointerCount) { MotionEntry* splitMotionEntry = - splitMotionEvent(originalMotionEntry, inputTarget.pointerIds); + splitMotionEvent(originalMotionEntry, inputTarget->pointerIds); if (!splitMotionEntry) { return; // split event was dropped } @@ -2169,7 +2100,7 @@ void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime, void InputDispatcher::enqueueDispatchEntriesLocked(nsecs_t currentTime, const sp<Connection>& connection, EventEntry* eventEntry, - const InputTarget& inputTarget) { + const InputTarget* inputTarget) { if (ATRACE_ENABLED()) { std::string message = StringPrintf("enqueueDispatchEntriesLocked(inputChannel=%s, sequenceNum=%" PRIu32 @@ -2202,7 +2133,7 @@ void InputDispatcher::enqueueDispatchEntriesLocked(nsecs_t currentTime, void InputDispatcher::enqueueDispatchEntryLocked(const sp<Connection>& connection, EventEntry* eventEntry, - const InputTarget& inputTarget, + const InputTarget* inputTarget, int32_t dispatchMode) { if (ATRACE_ENABLED()) { std::string message = StringPrintf("enqueueDispatchEntry(inputChannel=%s, dispatchMode=%s)", @@ -2210,7 +2141,7 @@ void InputDispatcher::enqueueDispatchEntryLocked(const sp<Connection>& connectio dispatchModeToString(dispatchMode).c_str()); ATRACE_NAME(message.c_str()); } - int32_t inputTargetFlags = inputTarget.flags; + int32_t inputTargetFlags = inputTarget->flags; if (!(inputTargetFlags & dispatchMode)) { return; } @@ -2218,8 +2149,11 @@ void InputDispatcher::enqueueDispatchEntryLocked(const sp<Connection>& connectio // This is a new event. // Enqueue a new dispatch entry onto the outbound queue for this connection. - std::unique_ptr<DispatchEntry> dispatchEntry = - createDispatchEntry(inputTarget, eventEntry, inputTargetFlags); + DispatchEntry* dispatchEntry = + new DispatchEntry(eventEntry, // increments ref + inputTargetFlags, inputTarget->xOffset, inputTarget->yOffset, + inputTarget->globalScaleFactor, inputTarget->windowXScale, + inputTarget->windowYScale); // Apply target flags and update the connection's input state. switch (eventEntry->type) { @@ -2234,6 +2168,7 @@ void InputDispatcher::enqueueDispatchEntryLocked(const sp<Connection>& connectio ALOGD("channel '%s' ~ enqueueDispatchEntryLocked: skipping inconsistent key event", connection->getInputChannelName().c_str()); #endif + delete dispatchEntry; return; // skip the inconsistent event } break; @@ -2280,11 +2215,12 @@ void InputDispatcher::enqueueDispatchEntryLocked(const sp<Connection>& connectio "event", connection->getInputChannelName().c_str()); #endif + delete dispatchEntry; return; // skip the inconsistent event } dispatchPointerDownOutsideFocus(motionEntry.source, dispatchEntry->resolvedAction, - inputTarget.inputChannel->getConnectionToken()); + inputTarget->inputChannel->getConnectionToken()); break; } @@ -2302,7 +2238,7 @@ void InputDispatcher::enqueueDispatchEntryLocked(const sp<Connection>& connectio } // Enqueue the dispatch entry. - connection->outboundQueue.push_back(dispatchEntry.release()); + connection->outboundQueue.push_back(dispatchEntry); traceOutboundQueueLength(connection); } @@ -2675,15 +2611,21 @@ void InputDispatcher::synthesizeCancelationEventsForConnectionLocked( getWindowHandleLocked(connection->inputChannel->getConnectionToken()); if (windowHandle != nullptr) { const InputWindowInfo* windowInfo = windowHandle->getInfo(); - target.setDefaultPointerInfo(-windowInfo->frameLeft, -windowInfo->frameTop, - windowInfo->windowXScale, windowInfo->windowYScale); + target.xOffset = -windowInfo->frameLeft; + target.yOffset = -windowInfo->frameTop; target.globalScaleFactor = windowInfo->globalScaleFactor; + target.windowXScale = windowInfo->windowXScale; + target.windowYScale = windowInfo->windowYScale; + } else { + target.xOffset = 0; + target.yOffset = 0; + target.globalScaleFactor = 1.0f; } target.inputChannel = connection->inputChannel; target.flags = InputTarget::FLAG_DISPATCH_AS_IS; enqueueDispatchEntryLocked(connection, cancelationEventEntry, // increments ref - target, InputTarget::FLAG_DISPATCH_AS_IS); + &target, InputTarget::FLAG_DISPATCH_AS_IS); cancelationEventEntry->release(); } diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h index 50b52502a0..f9eca01b2e 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.h +++ b/services/inputflinger/dispatcher/InputDispatcher.h @@ -378,13 +378,13 @@ private: // with the mutex held makes it easier to ensure that connection invariants are maintained. // If needed, the methods post commands to run later once the critical bits are done. void prepareDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection, - EventEntry* eventEntry, const InputTarget& inputTarget) + EventEntry* eventEntry, const InputTarget* inputTarget) REQUIRES(mLock); void enqueueDispatchEntriesLocked(nsecs_t currentTime, const sp<Connection>& connection, - EventEntry* eventEntry, const InputTarget& inputTarget) + EventEntry* eventEntry, const InputTarget* inputTarget) REQUIRES(mLock); void enqueueDispatchEntryLocked(const sp<Connection>& connection, EventEntry* eventEntry, - const InputTarget& inputTarget, int32_t dispatchMode) + const InputTarget* inputTarget, int32_t dispatchMode) REQUIRES(mLock); void startDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection) REQUIRES(mLock); diff --git a/services/inputflinger/dispatcher/InputTarget.cpp b/services/inputflinger/dispatcher/InputTarget.cpp index bd7cb3ed9b..80fa2cb995 100644 --- a/services/inputflinger/dispatcher/InputTarget.cpp +++ b/services/inputflinger/dispatcher/InputTarget.cpp @@ -42,43 +42,4 @@ std::string dispatchModeToString(int32_t dispatchMode) { return StringPrintf("%" PRId32, dispatchMode); } -void InputTarget::addPointers(BitSet32 newPointerIds, float xOffset, float yOffset, - float windowXScale, float windowYScale) { - // The pointerIds can be empty, but still a valid InputTarget. This can happen for Monitors - // and non splittable windows since we will just use all the pointers from the input event. - if (newPointerIds.isEmpty()) { - setDefaultPointerInfo(xOffset, yOffset, windowXScale, windowYScale); - return; - } - - // Ensure that the new set of pointers doesn't overlap with the current set of pointers. - ALOG_ASSERT((pointerIds & newPointerIds) == 0); - - pointerIds |= newPointerIds; - while (!newPointerIds.isEmpty()) { - int32_t pointerId = newPointerIds.clearFirstMarkedBit(); - pointerInfos[pointerId].xOffset = xOffset; - pointerInfos[pointerId].yOffset = yOffset; - pointerInfos[pointerId].windowXScale = windowXScale; - pointerInfos[pointerId].windowYScale = windowYScale; - } -} - -void InputTarget::setDefaultPointerInfo(float xOffset, float yOffset, float windowXScale, - float windowYScale) { - pointerIds.clear(); - pointerInfos[0].xOffset = xOffset; - pointerInfos[0].yOffset = yOffset; - pointerInfos[0].windowXScale = windowXScale; - pointerInfos[0].windowYScale = windowYScale; -} - -bool InputTarget::useDefaultPointerInfo() const { - return pointerIds.isEmpty(); -} - -const PointerInfo& InputTarget::getDefaultPointerInfo() const { - return pointerInfos[0]; -} - } // namespace android::inputdispatcher diff --git a/services/inputflinger/dispatcher/InputTarget.h b/services/inputflinger/dispatcher/InputTarget.h index fd98df1782..2e9bca251f 100644 --- a/services/inputflinger/dispatcher/InputTarget.h +++ b/services/inputflinger/dispatcher/InputTarget.h @@ -24,22 +24,6 @@ namespace android::inputdispatcher { /* - * Information about each pointer for an InputTarget. This includes offset and scale so - * all pointers can be normalized to a single offset and scale. - */ -struct PointerInfo { - // The x and y offset to add to a MotionEvent as it is delivered. - // (ignored for KeyEvents) - float xOffset = 0.0f; - float yOffset = 0.0f; - - // Scaling factor to apply to MotionEvent as it is delivered. - // (ignored for KeyEvents) - float windowXScale = 1.0f; - float windowYScale = 1.0f; -}; - -/* * An input target specifies how an input event is to be dispatched to a particular window * including the window's input channel, control flags, a timeout, and an X / Y offset to * be added to input event coordinates to compensate for the absolute position of the @@ -111,35 +95,20 @@ struct InputTarget { // Flags for the input target. int32_t flags = 0; + // The x and y offset to add to a MotionEvent as it is delivered. + // (ignored for KeyEvents) + float xOffset = 0.0f; + float yOffset = 0.0f; + // Scaling factor to apply to MotionEvent as it is delivered. // (ignored for KeyEvents) float globalScaleFactor = 1.0f; + float windowXScale = 1.0f; + float windowYScale = 1.0f; // The subset of pointer ids to include in motion events dispatched to this input target // if FLAG_SPLIT is set. - BitSet32 pointerIds; - // The data is stored by the pointerId. Use the marked bits in pointerIds to look up PointerInfo - // per pointerId. - PointerInfo pointerInfos[MAX_POINTERS]; - - void addPointers(BitSet32 pointerIds, float xOffset, float yOffset, float windowXScale, - float windowYScale); - void setDefaultPointerInfo(float xOffset, float yOffset, float windowXScale, - float windowYScale); - - /** - * Returns whether the default pointer information should be used. This will be true when the - * InputTarget doesn't have any bits set in the pointerIds bitset. This can happen for monitors - * and non splittable windows since we want all pointers for the EventEntry to go to this - * target. - */ - bool useDefaultPointerInfo() const; - - /** - * Returns the default PointerInfo object. This should be used when useDefaultPointerInfo is - * true. - */ - const PointerInfo& getDefaultPointerInfo() const; + BitSet32 pointerIds{}; }; std::string dispatchModeToString(int32_t dispatchMode); diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp index bd8d2a4d39..5ffc89d210 100644 --- a/services/inputflinger/tests/InputDispatcher_test.cpp +++ b/services/inputflinger/tests/InputDispatcher_test.cpp @@ -1439,107 +1439,4 @@ TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentScale) { consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, {expectedPoint}); } -TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentScale) { - mWindow2->setWindowScale(0.5f, 0.5f); - - // Touch Window 1 - std::vector<PointF> touchedPoints = {PointF{10, 10}}; - std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])}; - - NotifyMotionArgs motionArgs = - generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, - ADISPLAY_ID_DEFAULT, touchedPoints); - mDispatcher->notifyMotion(&motionArgs); - consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, expectedPoints); - - // Touch Window 2 - int32_t actionPointerDown = - AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT); - touchedPoints.emplace_back(PointF{150, 150}); - expectedPoints.emplace_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1])); - - motionArgs = generateMotionArgs(actionPointerDown, AINPUT_SOURCE_TOUCHSCREEN, - ADISPLAY_ID_DEFAULT, touchedPoints); - mDispatcher->notifyMotion(&motionArgs); - - // Consuming from window1 since it's the window that has the InputReceiver - consumeMotionEvent(mWindow1, actionPointerDown, expectedPoints); -} - -TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentScale) { - mWindow2->setWindowScale(0.5f, 0.5f); - - // Touch Window 1 - std::vector<PointF> touchedPoints = {PointF{10, 10}}; - std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])}; - - NotifyMotionArgs motionArgs = - generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, - ADISPLAY_ID_DEFAULT, touchedPoints); - mDispatcher->notifyMotion(&motionArgs); - consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, expectedPoints); - - // Touch Window 2 - int32_t actionPointerDown = - AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT); - touchedPoints.emplace_back(PointF{150, 150}); - expectedPoints.emplace_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1])); - - motionArgs = generateMotionArgs(actionPointerDown, AINPUT_SOURCE_TOUCHSCREEN, - ADISPLAY_ID_DEFAULT, touchedPoints); - mDispatcher->notifyMotion(&motionArgs); - - // Consuming from window1 since it's the window that has the InputReceiver - consumeMotionEvent(mWindow1, actionPointerDown, expectedPoints); - - // Move both windows - touchedPoints = {{20, 20}, {175, 175}}; - expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]), - getPointInWindow(mWindow2->getInfo(), touchedPoints[1])}; - - motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, - ADISPLAY_ID_DEFAULT, touchedPoints); - mDispatcher->notifyMotion(&motionArgs); - - consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_MOVE, expectedPoints); -} - -TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) { - mWindow1->setWindowScale(0.5f, 0.5f); - - // Touch Window 1 - std::vector<PointF> touchedPoints = {PointF{10, 10}}; - std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])}; - - NotifyMotionArgs motionArgs = - generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, - ADISPLAY_ID_DEFAULT, touchedPoints); - mDispatcher->notifyMotion(&motionArgs); - consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, expectedPoints); - - // Touch Window 2 - int32_t actionPointerDown = - AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT); - touchedPoints.emplace_back(PointF{150, 150}); - expectedPoints.emplace_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1])); - - motionArgs = generateMotionArgs(actionPointerDown, AINPUT_SOURCE_TOUCHSCREEN, - ADISPLAY_ID_DEFAULT, touchedPoints); - mDispatcher->notifyMotion(&motionArgs); - - // Consuming from window1 since it's the window that has the InputReceiver - consumeMotionEvent(mWindow1, actionPointerDown, expectedPoints); - - // Move both windows - touchedPoints = {{20, 20}, {175, 175}}; - expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]), - getPointInWindow(mWindow2->getInfo(), touchedPoints[1])}; - - motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, - ADISPLAY_ID_DEFAULT, touchedPoints); - mDispatcher->notifyMotion(&motionArgs); - - consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_MOVE, expectedPoints); -} - } // namespace android::inputdispatcher |