diff options
| author | 2023-10-31 18:30:54 +0000 | |
|---|---|---|
| committer | 2023-10-31 18:30:54 +0000 | |
| commit | 3ccc55d0e23424a8f98b155a34be51230030f11a (patch) | |
| tree | 2ad501e4a8a491771d6b0947b3eec35a37a42e41 | |
| parent | fdf6ab9e932909b2ed212ca2cbee78813aeef9db (diff) | |
| parent | 907ae738dae0ff389383d7acb496d939f1e62499 (diff) | |
Merge "Add POLICY_FLAG_PASS_TO_USER while hovering is active" into main
| -rw-r--r-- | services/inputflinger/dispatcher/InputDispatcher.cpp | 3 | ||||
| -rw-r--r-- | services/inputflinger/tests/InputDispatcher_test.cpp | 63 |
2 files changed, 65 insertions, 1 deletions
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index 8be72f67a9..d569077f2b 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -4437,7 +4437,8 @@ void InputDispatcher::notifyMotion(const NotifyMotionArgs& args) { const auto touchStateIt = mTouchStatesByDisplay.find(args.displayId); if (touchStateIt != mTouchStatesByDisplay.end()) { const TouchState& touchState = touchStateIt->second; - if (touchState.hasTouchingPointers(args.deviceId)) { + if (touchState.hasTouchingPointers(args.deviceId) || + touchState.hasHoveringPointers(args.deviceId)) { policyFlags |= POLICY_FLAG_PASS_TO_USER; } } diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp index 606dd6d14f..2509c60573 100644 --- a/services/inputflinger/tests/InputDispatcher_test.cpp +++ b/services/inputflinger/tests/InputDispatcher_test.cpp @@ -2167,6 +2167,69 @@ TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) { } /** + * Same as the above 'TwoPointerCancelInconsistentPolicy' test, but for hovers. + * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not + * interactive, it might stop sending this flag. + * We've already ensured the consistency of the touch event in this case, and we should also ensure + * the consistency of the hover event in this case. + * + * Test procedure: + * HOVER_ENTER -> HOVER_MOVE -> (stop sending POLICY_FLAG_PASS_TO_USER) -> HOVER_EXIT + * HOVER_ENTER -> HOVER_MOVE -> HOVER_EXIT + * + * We expect to receive two full streams of hover events. + */ +TEST_F(InputDispatcherTest, HoverEventInconsistentPolicy) { + std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>(); + + sp<FakeWindowHandle> window = + sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT); + window->setFrame(Rect(0, 0, 300, 300)); + + mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0}); + + mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS) + .policyFlags(DEFAULT_POLICY_FLAGS) + .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101)) + .build()); + window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)); + + mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS) + .policyFlags(DEFAULT_POLICY_FLAGS) + .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102)) + .build()); + window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE)); + + // Send hover exit without the default policy flags. + mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS) + .policyFlags(0) + .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102)) + .build()); + + window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT)); + + // Send a simple hover event stream, ensure dispatcher not crashed and window can receive + // right event. + mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS) + .policyFlags(DEFAULT_POLICY_FLAGS) + .pointer(PointerBuilder(0, ToolType::STYLUS).x(200).y(201)) + .build()); + window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)); + + mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS) + .policyFlags(DEFAULT_POLICY_FLAGS) + .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202)) + .build()); + window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE)); + + mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS) + .policyFlags(DEFAULT_POLICY_FLAGS) + .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202)) + .build()); + window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT)); +} + +/** * Two windows: a window on the left and a window on the right. * Mouse is hovered from the right window into the left window. * Next, we tap on the left window, where the cursor was last seen. |