Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 03fcdf8e authored by Prabir Pradhan's avatar Prabir Pradhan Committed by Automerger Merge Worker
Browse files

Merge "Cancel drag and drop when pointers are canceled for the drag window"...

Merge "Cancel drag and drop when pointers are canceled for the drag window" into main am: 939393d9 am: 1e17f427

Original change: https://android-review.googlesource.com/c/platform/frameworks/native/+/2658296



Change-Id: I04ec72f040a0eb259d3153616a42e4744877374d
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents 462dc34a 1e17f427
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -3900,6 +3900,16 @@ 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;
    }
+69 −0
Original line number Diff line number Diff line
@@ -8752,6 +8752,75 @@ TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
    mSecondWindow->assertNoEvents();
}

/**
 * Start drag and drop with a pointer whose id is not 0, cancel the current touch, and ensure drag
 * and drop is also canceled. Then inject a simple gesture, and ensure dispatcher does not crash.
 */
TEST_F(InputDispatcherDragTests, DragAndDropFinishedWhenCancelCurrentTouch) {
    // Down on second window
    ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
              injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
                               {150, 50}))
            << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";

    ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionDown());
    ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionDown());

    // Down on first window
    const MotionEvent secondFingerDownEvent =
            MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
                    .displayId(ADISPLAY_ID_DEFAULT)
                    .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
                    .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
                    .build();
    ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
              injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
                                InputEventInjectionSync::WAIT_FOR_RESULT))
            << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
    ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
    ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionMove());
    ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionPointerDown(1));

    // Start drag on first window
    ASSERT_TRUE(startDrag(/*sendDown=*/false, AINPUT_SOURCE_TOUCHSCREEN));

    // Trigger cancel
    mDispatcher->cancelCurrentTouch();
    ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionCancel());
    ASSERT_NO_FATAL_FAILURE(mDragWindow->consumeMotionCancel());
    ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionCancel());

    ASSERT_TRUE(mDispatcher->waitForIdle());
    // The D&D finished with nullptr
    mFakePolicy->assertDropTargetEquals(nullptr);

    // Remove drag window
    mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});

    // Inject a simple gesture, ensure dispatcher not crashed
    ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
              injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
                               PointF{50, 50}))
            << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
    ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());

    const MotionEvent moveEvent =
            MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
                    .displayId(ADISPLAY_ID_DEFAULT)
                    .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
                    .build();
    ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
              injectMotionEvent(mDispatcher, moveEvent, INJECT_EVENT_TIMEOUT,
                                InputEventInjectionSync::WAIT_FOR_RESULT))
            << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
    ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionMove());

    ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
              injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {50, 50}))
            << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
    ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionUp());
}

class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};

TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {