From d5876bad04b61e2dcf97abf1e66a3df18163a8e7 Mon Sep 17 00:00:00 2001 From: Siarhei Vishniakou Date: Mon, 15 May 2023 17:58:34 -0700 Subject: Create new input targets for hover events Hover events don't need to reuse the existing input targets in order to lump events with some pointers into others. It's possible that we need to send the same pointer as both DISPATCH_AS_HOVER_EXIT and as DISPATCH_AS_HOVER_ENTER from the dispatcher for the same input channel. This is the case when we are hovering over two windows with the same input token. Since the windows may have different transforms, we should re-start the hovering gesture. Bug: 263319225 Test: m inputflinger_tests && $ANDROID_HOST_OUT/nativetest64/inputflinger_tests/inputflinger_tests Change-Id: I2bd90c9893183c0526128b124b983654e0e6a37c --- .../inputflinger/dispatcher/InputDispatcher.cpp | 14 ++++++++++--- .../inputflinger/tests/InputDispatcher_test.cpp | 23 ++++++++++++++++++++++ 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index 9125fe49e0..bdd45dc9b4 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -2561,9 +2561,17 @@ std::vector InputDispatcher::findTouchedWindowTargetsLocked( std::vector hoveringWindows = getHoveringWindowsLocked(oldState, tempTouchState, entry); for (const TouchedWindow& touchedWindow : hoveringWindows) { - addWindowTargetLocked(touchedWindow.windowHandle, touchedWindow.targetFlags, - touchedWindow.pointerIds, touchedWindow.firstDownTimeInTarget, - targets); + std::optional target = + createInputTargetLocked(touchedWindow.windowHandle, touchedWindow.targetFlags, + touchedWindow.firstDownTimeInTarget); + if (!target) { + continue; + } + // Hardcode to single hovering pointer for now. + std::bitset pointerIds; + pointerIds.set(entry.pointerProperties[0].id); + target->addPointers(pointerIds, touchedWindow.windowHandle->getInfo()->transform); + targets.push_back(*target); } } diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp index 3f2658a71d..017f10baf8 100644 --- a/services/inputflinger/tests/InputDispatcher_test.cpp +++ b/services/inputflinger/tests/InputDispatcher_test.cpp @@ -6592,6 +6592,29 @@ TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}}); } +/** + * When hover starts in one window and continues into the other, there should be a HOVER_EXIT and + * a HOVER_ENTER generated, even if the windows have the same token. This is because the new window + * that the pointer is hovering over may have a different transform. + */ +TEST_F(InputDispatcherMultiWindowSameTokenTests, HoverIntoClone) { + mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}}); + + // Start hover in window 1 + mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_TOUCHSCREEN, + ADISPLAY_ID_DEFAULT, {{50, 50}})); + consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER, + {getPointInWindow(mWindow1->getInfo(), PointF{50, 50})}); + + // Move hover to window 2. + mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_TOUCHSCREEN, + ADISPLAY_ID_DEFAULT, {{150, 150}})); + + consumeMotionEvent(mWindow1, ACTION_HOVER_EXIT, {{50, 50}}); + consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER, + {getPointInWindow(mWindow2->getInfo(), PointF{150, 150})}); +} + class InputDispatcherSingleWindowAnr : public InputDispatcherTest { virtual void SetUp() override { InputDispatcherTest::SetUp(); -- cgit v1.2.3-59-g8ed1b