diff options
author | 2023-11-23 12:12:25 +0000 | |
---|---|---|
committer | 2023-11-23 12:12:25 +0000 | |
commit | a9544f4860bb78312794672f11bb73fd9ea702cb (patch) | |
tree | 2b727fefb51fc295b496f729bec27731a1c1633d | |
parent | a10a97e65cd94eb2573b4d7cb10423ba295566ae (diff) | |
parent | 110ba32d8a1d99d2e6921f12756ca6005a05e0cf (diff) |
Merge "Fix broken Drag and Drop" into main
-rw-r--r-- | services/inputflinger/dispatcher/InputDispatcher.cpp | 19 | ||||
-rw-r--r-- | services/inputflinger/tests/InputDispatcher_test.cpp | 44 |
2 files changed, 53 insertions, 10 deletions
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index 54da8e809e..6ad3de0015 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -3980,16 +3980,6 @@ void InputDispatcher::synthesizeCancelationEventsForInputChannelLocked( void InputDispatcher::synthesizeCancelationEventsForConnectionLocked( const std::shared_ptr<Connection>& connection, const CancelationOptions& options) { - if ((options.mode == CancelationOptions::Mode::CANCEL_POINTER_EVENTS || - options.mode == CancelationOptions::Mode::CANCEL_ALL_EVENTS) && - mDragState && mDragState->dragWindow->getToken() == connection->inputChannel->getToken()) { - LOG(INFO) << __func__ - << ": Canceling drag and drop because the pointers for the drag window are being " - "canceled."; - sendDropWindowCommandLocked(nullptr, /*x=*/0, /*y=*/0); - mDragState.reset(); - } - if (connection->status == Connection::Status::BROKEN) { return; } @@ -4002,6 +3992,7 @@ void InputDispatcher::synthesizeCancelationEventsForConnectionLocked( if (cancelationEvents.empty()) { return; } + if (DEBUG_OUTBOUND_EVENT_DETAILS) { ALOGD("channel '%s' ~ Synthesized %zu cancelation events to bring channel back in sync " "with reality: %s, mode=%s.", @@ -4050,6 +4041,14 @@ void InputDispatcher::synthesizeCancelationEventsForConnectionLocked( pointerIndex++) { pointerIds.set(motionEntry.pointerProperties[pointerIndex].id); } + if (mDragState && mDragState->dragWindow->getToken() == token && + pointerIds.test(mDragState->pointerId)) { + LOG(INFO) << __func__ + << ": Canceling drag and drop because the pointers for the drag " + "window are being canceled."; + sendDropWindowCommandLocked(nullptr, /*x=*/0, /*y=*/0); + mDragState.reset(); + } addPointerWindowTargetLocked(window, InputTarget::Flags::DISPATCH_AS_IS, pointerIds, motionEntry.downTime, targets); } else { diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp index 29fdec7186..e22013327f 100644 --- a/services/inputflinger/tests/InputDispatcher_test.cpp +++ b/services/inputflinger/tests/InputDispatcher_test.cpp @@ -9660,6 +9660,50 @@ TEST_F(InputDispatcherDragTests, DragAndDrop) { mSecondWindow->assertNoEvents(); } +TEST_F(InputDispatcherDragTests, DragAndDropNotCancelledIfSomeOtherPointerIsPilfered) { + startDrag(); + + // No cancel event after drag start + mSpyWindow->assertNoEvents(); + + const MotionEvent secondFingerDownEvent = + MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN) + .eventTime(systemTime(SYSTEM_TIME_MONOTONIC)) + .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50)) + .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60)) + .build(); + ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, + injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT, + InputEventInjectionSync::WAIT_FOR_RESULT)) + << "Inject motion event should return InputEventInjectionResult::SUCCEEDED"; + + // Receives cancel for first pointer after next pointer down + mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL)); + mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN)); + mDragWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE)); + + mSpyWindow->assertNoEvents(); + + // Spy window calls pilfer pointers + EXPECT_EQ(OK, mDispatcher->pilferPointers(mSpyWindow->getToken())); + mDragWindow->assertNoEvents(); + + const MotionEvent firstFingerMoveEvent = + MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN) + .eventTime(systemTime(SYSTEM_TIME_MONOTONIC)) + .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(60).y(60)) + .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60)) + .build(); + ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, + injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT, + InputEventInjectionSync::WAIT_FOR_RESULT)) + << "Inject motion event should return InputEventInjectionResult::SUCCEEDED"; + + // Drag window should still receive the new event + mDragWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE)); + mDragWindow->assertNoEvents(); +} + TEST_F(InputDispatcherDragTests, StylusDragAndDrop) { startDrag(true, AINPUT_SOURCE_STYLUS); |