Loading services/inputflinger/dispatcher/InputDispatcher.cpp +4 −2 Original line number Diff line number Diff line Loading @@ -2507,7 +2507,7 @@ void InputDispatcher::finishDragAndDrop(int32_t displayId, float x, float y) { } void InputDispatcher::addDragEventLocked(const MotionEntry& entry) { if (!mDragState) { if (!mDragState || mDragState->dragWindow->getInfo()->displayId != entry.displayId) { return; } Loading Loading @@ -4765,9 +4765,11 @@ void InputDispatcher::setInputWindowsLocked( // If drag window is gone, it would receive a cancel event and broadcast the DRAG_END. We // could just clear the state here. if (mDragState && if (mDragState && mDragState->dragWindow->getInfo()->displayId == displayId && std::find(windowHandles.begin(), windowHandles.end(), mDragState->dragWindow) == windowHandles.end()) { ALOGI("Drag window went away: %s", mDragState->dragWindow->getName().c_str()); sendDropWindowCommandLocked(nullptr, 0, 0); mDragState.reset(); } } Loading services/inputflinger/tests/InputDispatcher_test.cpp +52 −0 Original line number Diff line number Diff line Loading @@ -6407,6 +6407,58 @@ TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) { mSecondWindow->consumeMotionMove(); } TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) { performDrag(); // Update window of second display. sp<FakeWindowHandle> windowInSecondary = new FakeWindowHandle(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID); mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}}); // Let second display has a touch state. ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(mDispatcher, MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN) .displayId(SECOND_DISPLAY_ID) .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER) .x(100) .y(100)) .build())); windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN, SECOND_DISPLAY_ID, 0 /* expectedFlag */); // Update window again. mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}}); // Move on window. ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {50, 50})) << "Inject motion event should return InputEventInjectionResult::SUCCEEDED"; mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT); mWindow->consumeDragEvent(false, 50, 50); mSecondWindow->assertNoEvents(); // Move to another window. ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {150, 50})) << "Inject motion event should return InputEventInjectionResult::SUCCEEDED"; mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT); mWindow->consumeDragEvent(true, 150, 50); mSecondWindow->consumeDragEvent(false, 50, 50); // drop to another window. ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {150, 50})) << "Inject motion event should return InputEventInjectionResult::SUCCEEDED"; mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken()); mWindow->assertNoEvents(); mSecondWindow->assertNoEvents(); } class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {}; TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) { Loading Loading
services/inputflinger/dispatcher/InputDispatcher.cpp +4 −2 Original line number Diff line number Diff line Loading @@ -2507,7 +2507,7 @@ void InputDispatcher::finishDragAndDrop(int32_t displayId, float x, float y) { } void InputDispatcher::addDragEventLocked(const MotionEntry& entry) { if (!mDragState) { if (!mDragState || mDragState->dragWindow->getInfo()->displayId != entry.displayId) { return; } Loading Loading @@ -4765,9 +4765,11 @@ void InputDispatcher::setInputWindowsLocked( // If drag window is gone, it would receive a cancel event and broadcast the DRAG_END. We // could just clear the state here. if (mDragState && if (mDragState && mDragState->dragWindow->getInfo()->displayId == displayId && std::find(windowHandles.begin(), windowHandles.end(), mDragState->dragWindow) == windowHandles.end()) { ALOGI("Drag window went away: %s", mDragState->dragWindow->getName().c_str()); sendDropWindowCommandLocked(nullptr, 0, 0); mDragState.reset(); } } Loading
services/inputflinger/tests/InputDispatcher_test.cpp +52 −0 Original line number Diff line number Diff line Loading @@ -6407,6 +6407,58 @@ TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) { mSecondWindow->consumeMotionMove(); } TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) { performDrag(); // Update window of second display. sp<FakeWindowHandle> windowInSecondary = new FakeWindowHandle(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID); mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}}); // Let second display has a touch state. ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(mDispatcher, MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN) .displayId(SECOND_DISPLAY_ID) .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER) .x(100) .y(100)) .build())); windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN, SECOND_DISPLAY_ID, 0 /* expectedFlag */); // Update window again. mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}}); // Move on window. ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {50, 50})) << "Inject motion event should return InputEventInjectionResult::SUCCEEDED"; mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT); mWindow->consumeDragEvent(false, 50, 50); mSecondWindow->assertNoEvents(); // Move to another window. ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {150, 50})) << "Inject motion event should return InputEventInjectionResult::SUCCEEDED"; mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT); mWindow->consumeDragEvent(true, 150, 50); mSecondWindow->consumeDragEvent(false, 50, 50); // drop to another window. ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {150, 50})) << "Inject motion event should return InputEventInjectionResult::SUCCEEDED"; mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken()); mWindow->assertNoEvents(); mSecondWindow->assertNoEvents(); } class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {}; TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) { Loading