diff options
author | 2023-04-11 15:46:30 +0000 | |
---|---|---|
committer | 2023-04-11 15:46:30 +0000 | |
commit | 71660f18f6312ce8fe2962e116d6a0533491c06f (patch) | |
tree | 5c1c37013e41ae21010efdbc096cd6cf6dd8ba6e | |
parent | eb11699af3aaf806e9bfd8f31a5e25bff63a0b2d (diff) | |
parent | e1e309ace801c81e36df47c0a6ca76b9ea279990 (diff) |
Merge "TouchInputMapper: Consume hovering pointers outside physical frame" into udc-dev
-rw-r--r-- | services/inputflinger/reader/mapper/TouchInputMapper.cpp | 23 | ||||
-rw-r--r-- | services/inputflinger/tests/InputReader_test.cpp | 48 |
2 files changed, 70 insertions, 1 deletions
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.cpp b/services/inputflinger/reader/mapper/TouchInputMapper.cpp index eb99438f08..c19737d672 100644 --- a/services/inputflinger/reader/mapper/TouchInputMapper.cpp +++ b/services/inputflinger/reader/mapper/TouchInputMapper.cpp @@ -1855,6 +1855,27 @@ std::list<NotifyArgs> TouchInputMapper::consumeRawTouches(nsecs_t when, nsecs_t } } + if (!mCurrentRawState.rawPointerData.hoveringIdBits.isEmpty() && + mCurrentRawState.rawPointerData.touchingIdBits.isEmpty() && + mDeviceMode != DeviceMode::UNSCALED) { + // We have hovering pointers, and there are no touching pointers. + bool hoveringPointersInFrame = false; + auto hoveringIds = mCurrentRawState.rawPointerData.hoveringIdBits; + while (!hoveringIds.isEmpty()) { + uint32_t id = hoveringIds.clearFirstMarkedBit(); + const auto& pointer = mCurrentRawState.rawPointerData.pointerForId(id); + if (isPointInsidePhysicalFrame(pointer.x, pointer.y)) { + hoveringPointersInFrame = true; + break; + } + } + if (!hoveringPointersInFrame) { + // All hovering pointers are outside the physical frame. + outConsumed = true; + return out; + } + } + if (mLastRawState.rawPointerData.touchingIdBits.isEmpty() && !mCurrentRawState.rawPointerData.touchingIdBits.isEmpty()) { // Pointer just went down. Check for virtual key press or off-screen touches. @@ -1865,7 +1886,7 @@ std::list<NotifyArgs> TouchInputMapper::consumeRawTouches(nsecs_t when, nsecs_t if (!isPointInsidePhysicalFrame(pointer.x, pointer.y) && mDeviceMode != DeviceMode::UNSCALED) { // If exactly one pointer went down, check for virtual key hit. - // Otherwise we will drop the entire stroke. + // Otherwise, we will drop the entire stroke. if (mCurrentRawState.rawPointerData.touchingIdBits.count() == 1) { const VirtualKey* virtualKey = findVirtualKeyHit(pointer.x, pointer.y); if (virtualKey) { diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp index 2223b35183..fb082da8e1 100644 --- a/services/inputflinger/tests/InputReader_test.cpp +++ b/services/inputflinger/tests/InputReader_test.cpp @@ -6735,6 +6735,54 @@ TEST_F(SingleTouchInputMapperTest, WhenDeviceTypeIsChangedToTouchNavigation_upda ASSERT_EQ(AINPUT_SOURCE_TOUCH_NAVIGATION, mDevice->getSources()); } +TEST_F(SingleTouchInputMapperTest, HoverEventsOutsidePhysicalFrameAreIgnored) { + // Initialize the device without setting device source to touch navigation. + addConfigurationProperty("touch.deviceType", "touchScreen"); + prepareDisplay(ui::ROTATION_0); + prepareButtons(); + prepareAxes(POSITION); + mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOOL_PEN, 0, AKEYCODE_UNKNOWN, 0); + + // Set a physical frame in the display viewport. + auto viewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL); + viewport->physicalLeft = 0; + viewport->physicalTop = 0; + viewport->physicalRight = DISPLAY_WIDTH / 2; + viewport->physicalBottom = DISPLAY_HEIGHT / 2; + mFakePolicy->updateViewport(*viewport); + configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO); + + SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>(); + + // Hovering inside the physical frame produces events. + processKey(mapper, BTN_TOOL_PEN, 1); + processMove(mapper, RAW_X_MIN + 1, RAW_Y_MIN + 1); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled( + WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER))); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled( + WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE))); + + // Leaving the physical frame ends the hovering gesture. + processMove(mapper, RAW_X_MAX - 1, RAW_Y_MAX - 1); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled( + WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT))); + + // Moving outside the physical frame does not produce events. + processMove(mapper, RAW_X_MAX - 2, RAW_Y_MAX - 2); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled()); + + // Re-entering the physical frame produces events. + processMove(mapper, RAW_X_MIN, RAW_Y_MIN); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled( + WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER))); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled( + WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE))); +} + // --- TouchDisplayProjectionTest --- class TouchDisplayProjectionTest : public SingleTouchInputMapperTest { |