diff options
-rw-r--r-- | services/inputflinger/dispatcher/InputDispatcher.cpp | 51 | ||||
-rw-r--r-- | services/inputflinger/dispatcher/InputState.cpp | 20 | ||||
-rw-r--r-- | services/inputflinger/dispatcher/InputState.h | 9 |
3 files changed, 51 insertions, 29 deletions
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index 8d0ff4ba20..fa02a330f9 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -3389,27 +3389,40 @@ void InputDispatcher::enqueueDispatchEntryLocked(const std::shared_ptr<Connectio dispatchEntry->resolvedFlags = resolvedFlags; if (resolvedAction != motionEntry.action) { + std::optional<std::vector<PointerProperties>> usingProperties; + std::optional<std::vector<PointerCoords>> usingCoords; + if (resolvedAction == AMOTION_EVENT_ACTION_HOVER_EXIT || + resolvedAction == AMOTION_EVENT_ACTION_CANCEL) { + // This is a HOVER_EXIT or an ACTION_CANCEL event that was synthesized by + // the dispatcher, and therefore the coordinates of this event are currently + // incorrect. These events should use the coordinates of the last dispatched + // ACTION_MOVE or HOVER_MOVE. We need to query InputState to get this data. + const bool hovering = resolvedAction == AMOTION_EVENT_ACTION_HOVER_EXIT; + std::optional<std::pair<std::vector<PointerProperties>, + std::vector<PointerCoords>>> + pointerInfo = + connection->inputState.getPointersOfLastEvent(motionEntry, + hovering); + if (pointerInfo) { + usingProperties = pointerInfo->first; + usingCoords = pointerInfo->second; + } + } // Generate a new MotionEntry with a new eventId using the resolved action and // flags. - resolvedMotion = - std::make_shared<MotionEntry>(mIdGenerator.nextId(), - motionEntry.injectionState, - motionEntry.eventTime, - motionEntry.deviceId, motionEntry.source, - motionEntry.displayId, - motionEntry.policyFlags, resolvedAction, - motionEntry.actionButton, resolvedFlags, - motionEntry.metaState, - motionEntry.buttonState, - motionEntry.classification, - motionEntry.edgeFlags, - motionEntry.xPrecision, - motionEntry.yPrecision, - motionEntry.xCursorPosition, - motionEntry.yCursorPosition, - motionEntry.downTime, - motionEntry.pointerProperties, - motionEntry.pointerCoords); + resolvedMotion = std::make_shared< + MotionEntry>(mIdGenerator.nextId(), motionEntry.injectionState, + motionEntry.eventTime, motionEntry.deviceId, + motionEntry.source, motionEntry.displayId, + motionEntry.policyFlags, resolvedAction, + motionEntry.actionButton, resolvedFlags, + motionEntry.metaState, motionEntry.buttonState, + motionEntry.classification, motionEntry.edgeFlags, + motionEntry.xPrecision, motionEntry.yPrecision, + motionEntry.xCursorPosition, motionEntry.yCursorPosition, + motionEntry.downTime, + usingProperties.value_or(motionEntry.pointerProperties), + usingCoords.value_or(motionEntry.pointerCoords)); if (ATRACE_ENABLED()) { std::string message = StringPrintf("Transmute MotionEvent(id=0x%" PRIx32 ") to MotionEvent(id=0x%" PRIx32 ").", diff --git a/services/inputflinger/dispatcher/InputState.cpp b/services/inputflinger/dispatcher/InputState.cpp index a4ac4fbe6c..1fec9b7599 100644 --- a/services/inputflinger/dispatcher/InputState.cpp +++ b/services/inputflinger/dispatcher/InputState.cpp @@ -195,6 +195,16 @@ bool InputState::trackMotion(const MotionEntry& entry, int32_t flags) { } } +std::optional<std::pair<std::vector<PointerProperties>, std::vector<PointerCoords>>> +InputState::getPointersOfLastEvent(const MotionEntry& entry, bool hovering) const { + ssize_t index = findMotionMemento(entry, hovering); + if (index == -1) { + return std::nullopt; + } + return std::make_pair(mMotionMementos[index].pointerProperties, + mMotionMementos[index].pointerCoords); +} + ssize_t InputState::findKeyMemento(const KeyEntry& entry) const { for (size_t i = 0; i < mKeyMementos.size(); i++) { const KeyMemento& memento = mKeyMementos[i]; @@ -311,16 +321,6 @@ bool InputState::shouldCancelPreviousStream(const MotionEntry& motionEntry) cons return true; } - // Use the previous stream cancellation logic to generate all HOVER_EXIT events. - // If this hover event was generated as a result of the pointer leaving the window, - // the HOVER_EXIT event should have the same coordinates as the previous - // HOVER_MOVE event in this stream. Ensure that all HOVER_EXITs have the same - // coordinates as the previous event by cancelling the stream here. With this approach, the - // HOVER_EXIT event is generated from the previous event. - if (actionMasked == AMOTION_EVENT_ACTION_HOVER_EXIT && lastMemento.hovering) { - return true; - } - // If the stream changes its source, just cancel the current gesture to be safe. It's // possible that the app isn't handling source changes properly if (motionEntry.source != lastMemento.source) { diff --git a/services/inputflinger/dispatcher/InputState.h b/services/inputflinger/dispatcher/InputState.h index b0e4209882..d49469ddc1 100644 --- a/services/inputflinger/dispatcher/InputState.h +++ b/services/inputflinger/dispatcher/InputState.h @@ -48,6 +48,15 @@ public: // and should be skipped. bool trackMotion(const MotionEntry& entry, int32_t flags); + /** + * Return the PointerProperties and the PointerCoords for the last event, if found. Return + * std::nullopt if not found. We should not return std::vector<PointerCoords> in isolation, + * because the pointers can technically be stored in the vector in any order, so the + * PointerProperties are needed to specify the order in which the pointer coords are stored. + */ + std::optional<std::pair<std::vector<PointerProperties>, std::vector<PointerCoords>>> + getPointersOfLastEvent(const MotionEntry& entry, bool hovering) const; + // Create cancel events for the previous stream if the current motionEntry requires it. std::unique_ptr<EventEntry> cancelConflictingInputStream(const MotionEntry& motionEntry); |