Loading services/inputflinger/dispatcher/DragState.h +6 −2 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ #pragma once #include <gui/WindowInfo.h> #include <input/Input.h> #include <utils/StrongPointer.h> #include <string> Loading @@ -25,8 +26,9 @@ namespace android { namespace inputdispatcher { struct DragState { DragState(const sp<android::gui::WindowInfoHandle>& windowHandle, int32_t pointerId) : dragWindow(windowHandle), pointerId(pointerId) {} DragState(const sp<android::gui::WindowInfoHandle>& windowHandle, DeviceId deviceId, int32_t pointerId) : dragWindow(windowHandle), deviceId(deviceId), pointerId(pointerId) {} void dump(std::string& dump, const char* prefix = ""); // The window being dragged. Loading @@ -37,6 +39,8 @@ struct DragState { bool isStartDrag = false; // Indicate if the stylus button is down at the start of the drag. bool isStylusButtonDownAtStart = false; // Indicate which device started this drag and drop. const DeviceId deviceId; // Indicate which pointer id is tracked by the drag and drop. const int32_t pointerId; }; Loading services/inputflinger/dispatcher/InputDispatcher.cpp +3 −2 Original line number Diff line number Diff line Loading @@ -2870,7 +2870,8 @@ void InputDispatcher::finishDragAndDrop(ui::LogicalDisplayId displayId, float x, } void InputDispatcher::addDragEventLocked(const MotionEntry& entry) { if (!mDragState || mDragState->dragWindow->getInfo()->displayId != entry.displayId) { if (!mDragState || mDragState->dragWindow->getInfo()->displayId != entry.displayId || mDragState->deviceId != entry.deviceId) { return; } Loading Loading @@ -5758,7 +5759,7 @@ bool InputDispatcher::transferTouchGesture(const sp<IBinder>& fromToken, const s } // Track the pointer id for drag window and generate the drag state. const size_t id = pointers.begin()->id; mDragState = std::make_unique<DragState>(toWindowHandle, id); mDragState = std::make_unique<DragState>(toWindowHandle, deviceId, id); } // Synthesize cancel for old window and down for new window. Loading services/inputflinger/tests/InputDispatcher_test.cpp +81 −0 Original line number Diff line number Diff line Loading @@ -12192,6 +12192,87 @@ TEST_F(InputDispatcherDragTests, NoDragAndDropWithHoveringPointer) { << "Drag and drop should not work with a hovering pointer"; } /** * Two devices, we use the second pointer of Device A to start the drag, during the drag process, if * we perform a click using Device B, the dispatcher should work well. */ TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouchAndMultiDevice) { const DeviceId deviceA = 1; const DeviceId deviceB = 2; // First down on second window with deviceA. mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN) .deviceId(deviceA) .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50)) .build()); mSecondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA), WithDisplayId(ui::LogicalDisplayId::DEFAULT))); // Second down on first window with deviceA mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN) .deviceId(deviceA) .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50)) .pointer(PointerBuilder(1, ToolType::FINGER).x(50).y(50)) .build()); mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA), WithDisplayId(ui::LogicalDisplayId::DEFAULT))); mSecondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceA), WithDisplayId(ui::LogicalDisplayId::DEFAULT))); // Perform drag and drop from first window. ASSERT_TRUE(startDrag(/*sendDown=*/false)); // Click first window with device B, we should ensure dispatcher work well. mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE) .deviceId(deviceB) .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50)) .build()); mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB), WithDisplayId(ui::LogicalDisplayId::DEFAULT))); mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE) .deviceId(deviceB) .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50)) .build()); mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDeviceId(deviceB), WithDisplayId(ui::LogicalDisplayId::DEFAULT))); // Move with device A. mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN) .deviceId(deviceA) .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(51)) .pointer(PointerBuilder(1, ToolType::FINGER).x(51).y(51)) .build()); mDragWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceA), WithDisplayId(ui::LogicalDisplayId::DEFAULT), WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE))); mWindow->consumeDragEvent(false, 51, 51); mSecondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceA), WithDisplayId(ui::LogicalDisplayId::DEFAULT))); // Releasing the drag pointer should cause drop. mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN) .deviceId(deviceA) .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(51)) .pointer(PointerBuilder(1, ToolType::FINGER).x(51).y(51)) .build()); mDragWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDeviceId(deviceA), WithDisplayId(ui::LogicalDisplayId::DEFAULT), WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE))); mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindow->getToken()); mSecondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceA), WithDisplayId(ui::LogicalDisplayId::DEFAULT))); // Release all pointers. mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN) .deviceId(deviceA) .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(51)) .build()); mSecondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDeviceId(deviceA), WithDisplayId(ui::LogicalDisplayId::DEFAULT))); mWindow->assertNoEvents(); } class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {}; TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) { Loading
services/inputflinger/dispatcher/DragState.h +6 −2 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ #pragma once #include <gui/WindowInfo.h> #include <input/Input.h> #include <utils/StrongPointer.h> #include <string> Loading @@ -25,8 +26,9 @@ namespace android { namespace inputdispatcher { struct DragState { DragState(const sp<android::gui::WindowInfoHandle>& windowHandle, int32_t pointerId) : dragWindow(windowHandle), pointerId(pointerId) {} DragState(const sp<android::gui::WindowInfoHandle>& windowHandle, DeviceId deviceId, int32_t pointerId) : dragWindow(windowHandle), deviceId(deviceId), pointerId(pointerId) {} void dump(std::string& dump, const char* prefix = ""); // The window being dragged. Loading @@ -37,6 +39,8 @@ struct DragState { bool isStartDrag = false; // Indicate if the stylus button is down at the start of the drag. bool isStylusButtonDownAtStart = false; // Indicate which device started this drag and drop. const DeviceId deviceId; // Indicate which pointer id is tracked by the drag and drop. const int32_t pointerId; }; Loading
services/inputflinger/dispatcher/InputDispatcher.cpp +3 −2 Original line number Diff line number Diff line Loading @@ -2870,7 +2870,8 @@ void InputDispatcher::finishDragAndDrop(ui::LogicalDisplayId displayId, float x, } void InputDispatcher::addDragEventLocked(const MotionEntry& entry) { if (!mDragState || mDragState->dragWindow->getInfo()->displayId != entry.displayId) { if (!mDragState || mDragState->dragWindow->getInfo()->displayId != entry.displayId || mDragState->deviceId != entry.deviceId) { return; } Loading Loading @@ -5758,7 +5759,7 @@ bool InputDispatcher::transferTouchGesture(const sp<IBinder>& fromToken, const s } // Track the pointer id for drag window and generate the drag state. const size_t id = pointers.begin()->id; mDragState = std::make_unique<DragState>(toWindowHandle, id); mDragState = std::make_unique<DragState>(toWindowHandle, deviceId, id); } // Synthesize cancel for old window and down for new window. Loading
services/inputflinger/tests/InputDispatcher_test.cpp +81 −0 Original line number Diff line number Diff line Loading @@ -12192,6 +12192,87 @@ TEST_F(InputDispatcherDragTests, NoDragAndDropWithHoveringPointer) { << "Drag and drop should not work with a hovering pointer"; } /** * Two devices, we use the second pointer of Device A to start the drag, during the drag process, if * we perform a click using Device B, the dispatcher should work well. */ TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouchAndMultiDevice) { const DeviceId deviceA = 1; const DeviceId deviceB = 2; // First down on second window with deviceA. mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN) .deviceId(deviceA) .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50)) .build()); mSecondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA), WithDisplayId(ui::LogicalDisplayId::DEFAULT))); // Second down on first window with deviceA mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN) .deviceId(deviceA) .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50)) .pointer(PointerBuilder(1, ToolType::FINGER).x(50).y(50)) .build()); mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA), WithDisplayId(ui::LogicalDisplayId::DEFAULT))); mSecondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceA), WithDisplayId(ui::LogicalDisplayId::DEFAULT))); // Perform drag and drop from first window. ASSERT_TRUE(startDrag(/*sendDown=*/false)); // Click first window with device B, we should ensure dispatcher work well. mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE) .deviceId(deviceB) .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50)) .build()); mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB), WithDisplayId(ui::LogicalDisplayId::DEFAULT))); mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE) .deviceId(deviceB) .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50)) .build()); mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDeviceId(deviceB), WithDisplayId(ui::LogicalDisplayId::DEFAULT))); // Move with device A. mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN) .deviceId(deviceA) .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(51)) .pointer(PointerBuilder(1, ToolType::FINGER).x(51).y(51)) .build()); mDragWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceA), WithDisplayId(ui::LogicalDisplayId::DEFAULT), WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE))); mWindow->consumeDragEvent(false, 51, 51); mSecondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceA), WithDisplayId(ui::LogicalDisplayId::DEFAULT))); // Releasing the drag pointer should cause drop. mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN) .deviceId(deviceA) .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(51)) .pointer(PointerBuilder(1, ToolType::FINGER).x(51).y(51)) .build()); mDragWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDeviceId(deviceA), WithDisplayId(ui::LogicalDisplayId::DEFAULT), WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE))); mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindow->getToken()); mSecondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceA), WithDisplayId(ui::LogicalDisplayId::DEFAULT))); // Release all pointers. mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN) .deviceId(deviceA) .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(51)) .build()); mSecondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDeviceId(deviceA), WithDisplayId(ui::LogicalDisplayId::DEFAULT))); mWindow->assertNoEvents(); } class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {}; TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {