diff options
-rw-r--r-- | include/input/InputFlags.h | 5 | ||||
-rw-r--r-- | libs/input/InputFlags.cpp | 5 | ||||
-rw-r--r-- | services/inputflinger/PointerChoreographer.cpp | 28 | ||||
-rw-r--r-- | services/inputflinger/PointerChoreographer.h | 7 | ||||
-rw-r--r-- | services/inputflinger/tests/PointerChoreographer_test.cpp | 84 |
5 files changed, 120 insertions, 9 deletions
diff --git a/include/input/InputFlags.h b/include/input/InputFlags.h index 0e194eaeb8..4b42f775dd 100644 --- a/include/input/InputFlags.h +++ b/include/input/InputFlags.h @@ -25,6 +25,11 @@ public: * override. */ static bool connectedDisplaysCursorEnabled(); + + /** + * Check if both connectedDisplaysCursor and associatedDisplayCursorBugfix is enabled. + */ + static bool connectedDisplaysCursorAndAssociatedDisplayCursorBugfixEnabled(); }; } // namespace android diff --git a/libs/input/InputFlags.cpp b/libs/input/InputFlags.cpp index 555b1387ba..f866f9b8f0 100644 --- a/libs/input/InputFlags.cpp +++ b/libs/input/InputFlags.cpp @@ -39,4 +39,9 @@ bool InputFlags::connectedDisplaysCursorEnabled() { return com::android::input::flags::connected_displays_cursor(); } +bool InputFlags::connectedDisplaysCursorAndAssociatedDisplayCursorBugfixEnabled() { + return connectedDisplaysCursorEnabled() && + com::android::input::flags::connected_displays_associated_display_cursor_bugfix(); +} + } // namespace android
\ No newline at end of file diff --git a/services/inputflinger/PointerChoreographer.cpp b/services/inputflinger/PointerChoreographer.cpp index e06ff6b9c7..98b514ba73 100644 --- a/services/inputflinger/PointerChoreographer.cpp +++ b/services/inputflinger/PointerChoreographer.cpp @@ -132,7 +132,7 @@ PointerChoreographer::PointerChoreographer( }), mNextListener(listener), mPolicy(policy), - mDefaultMouseDisplayId(ui::LogicalDisplayId::DEFAULT), + mCurrentMouseDisplayId(ui::LogicalDisplayId::INVALID), mNotifiedPointerDisplayId(ui::LogicalDisplayId::INVALID), mShowTouchesEnabled(false), mStylusPointerIconEnabled(false), @@ -361,7 +361,7 @@ void PointerChoreographer::handleUnconsumedDeltaLocked(PointerControllerInterfac LOG(FATAL) << "A cursor already exists on destination display" << destinationViewport.displayId; } - mDefaultMouseDisplayId = destinationViewport.displayId; + mCurrentMouseDisplayId = destinationViewport.displayId; auto pcNode = mMousePointersByDisplay.extract(sourceDisplayId); pcNode.key() = destinationViewport.displayId; mMousePointersByDisplay.insert(std::move(pcNode)); @@ -609,9 +609,9 @@ void PointerChoreographer::setDisplayTopology(const DisplayTopologyGraph& displa // make primary display default mouse display, if it was not set or // the existing display was removed - if (mDefaultMouseDisplayId == ui::LogicalDisplayId::INVALID || - mTopology.graph.find(mDefaultMouseDisplayId) == mTopology.graph.end()) { - mDefaultMouseDisplayId = mTopology.primaryDisplayId; + if (mCurrentMouseDisplayId == ui::LogicalDisplayId::INVALID || + mTopology.graph.find(mCurrentMouseDisplayId) == mTopology.graph.end()) { + mCurrentMouseDisplayId = mTopology.primaryDisplayId; pointerDisplayChange = updatePointerControllersLocked(); } } // release lock @@ -665,7 +665,19 @@ const DisplayViewport* PointerChoreographer::findViewportByIdLocked( ui::LogicalDisplayId PointerChoreographer::getTargetMouseDisplayLocked( ui::LogicalDisplayId associatedDisplayId) const { - return associatedDisplayId.isValid() ? associatedDisplayId : mDefaultMouseDisplayId; + if (!InputFlags::connectedDisplaysCursorAndAssociatedDisplayCursorBugfixEnabled()) { + if (associatedDisplayId.isValid()) { + return associatedDisplayId; + } + return mCurrentMouseDisplayId.isValid() ? mCurrentMouseDisplayId + : ui::LogicalDisplayId::DEFAULT; + } + // Associated display is not included in the topology, return this associated display. + if (associatedDisplayId.isValid() && + mTopology.graph.find(associatedDisplayId) == mTopology.graph.end()) { + return associatedDisplayId; + } + return mCurrentMouseDisplayId.isValid() ? mCurrentMouseDisplayId : mTopology.primaryDisplayId; } std::pair<ui::LogicalDisplayId, PointerControllerInterface&> @@ -774,7 +786,7 @@ PointerChoreographer::PointerDisplayChange PointerChoreographer::calculatePointerDisplayChangeToNotify() { ui::LogicalDisplayId displayIdToNotify = ui::LogicalDisplayId::INVALID; vec2 cursorPosition = {0, 0}; - if (const auto it = mMousePointersByDisplay.find(mDefaultMouseDisplayId); + if (const auto it = mMousePointersByDisplay.find(mCurrentMouseDisplayId); it != mMousePointersByDisplay.end()) { const auto& pointerController = it->second; // Use the displayId from the pointerController, because it accurately reflects whether @@ -800,7 +812,7 @@ void PointerChoreographer::setDefaultMouseDisplayId(ui::LogicalDisplayId display { // acquire lock std::scoped_lock _l(getLock()); - mDefaultMouseDisplayId = displayId; + mCurrentMouseDisplayId = displayId; pointerDisplayChange = updatePointerControllersLocked(); } // release lock diff --git a/services/inputflinger/PointerChoreographer.h b/services/inputflinger/PointerChoreographer.h index 24351256ef..67bdca1bab 100644 --- a/services/inputflinger/PointerChoreographer.h +++ b/services/inputflinger/PointerChoreographer.h @@ -231,7 +231,12 @@ private: std::map<DeviceId, std::shared_ptr<PointerControllerInterface>> mDrawingTabletPointersByDevice GUARDED_BY(getLock()); - ui::LogicalDisplayId mDefaultMouseDisplayId GUARDED_BY(getLock()); + // In connected displays scenario, this tracks the latest display the cursor is at, within the + // DisplayTopology. By default, this will be set to topology primary display, and updated when + // mouse crossed to another display. + // In non-connected displays scenario, this will be treated as the default display cursor + // will be on, when mouse doesn't have associated display. + ui::LogicalDisplayId mCurrentMouseDisplayId GUARDED_BY(getLock()); ui::LogicalDisplayId mNotifiedPointerDisplayId GUARDED_BY(getLock()); std::vector<InputDeviceInfo> mInputDeviceInfos GUARDED_BY(getLock()); std::set<DeviceId> mMouseDevices GUARDED_BY(getLock()); diff --git a/services/inputflinger/tests/PointerChoreographer_test.cpp b/services/inputflinger/tests/PointerChoreographer_test.cpp index 3aad16f533..38d0679095 100644 --- a/services/inputflinger/tests/PointerChoreographer_test.cpp +++ b/services/inputflinger/tests/PointerChoreographer_test.cpp @@ -3072,6 +3072,90 @@ TEST_F(PointerChoreographerDisplayTopologyDefaultMouseDisplayTests, ASSERT_TRUE(pc->isPointerShown()); } +TEST_F(PointerChoreographerDisplayTopologyDefaultMouseDisplayTests, + UsePrimaryDisplayIfAssociatedDisplayIsInTopology) { + SCOPED_FLAG_OVERRIDE(connected_displays_cursor, true); + SCOPED_FLAG_OVERRIDE(connected_displays_associated_display_cursor_bugfix, true); + + // Add two displays + mChoreographer.setDisplayViewports( + {createViewport(FIRST_DISPLAY_ID), createViewport(SECOND_DISPLAY_ID)}); + setDisplayTopologyWithDisplays(/*primaryDisplayId=*/SECOND_DISPLAY_ID, + /*adjacentDisplays=*/{FIRST_DISPLAY_ID}); + + mChoreographer.notifyInputDevicesChanged( + {/*id=*/0, {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE, FIRST_DISPLAY_ID)}}); + + auto pc = assertPointerControllerCreated(ControllerType::MOUSE); + pc->assertViewportSet(SECOND_DISPLAY_ID); + ASSERT_TRUE(pc->isPointerShown()); +} + +TEST_F(PointerChoreographerDisplayTopologyDefaultMouseDisplayTests, + AllowCrossingDisplayEvenWithAssociatedDisplaySet) { + SCOPED_FLAG_OVERRIDE(connected_displays_cursor, true); + SCOPED_FLAG_OVERRIDE(connected_displays_associated_display_cursor_bugfix, true); + + // Add two displays + mChoreographer.setDisplayViewports( + {createViewport(FIRST_DISPLAY_ID), createViewport(SECOND_DISPLAY_ID)}); + setDisplayTopologyWithDisplays(/*primaryDisplayId=*/FIRST_DISPLAY_ID, + /*adjacentDisplays=*/{SECOND_DISPLAY_ID}); + + mChoreographer.notifyInputDevicesChanged( + {/*id=*/0, + {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE, SECOND_DISPLAY_ID)}}); + + auto pc = assertPointerControllerCreated(ControllerType::MOUSE); + pc->assertViewportSet(FIRST_DISPLAY_ID); + ASSERT_TRUE(pc->isPointerShown()); + + // Move cursor to the secondary display + auto pointerBuilder = PointerBuilder(/*id=*/0, ToolType::MOUSE) + .axis(AMOTION_EVENT_AXIS_RELATIVE_X, /*x=*/100) + .axis(AMOTION_EVENT_AXIS_RELATIVE_Y, /*y=*/0); + mChoreographer.notifyMotion( + MotionArgsBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE) + .pointer(pointerBuilder) + .deviceId(DEVICE_ID) + .displayId(ui::LogicalDisplayId::INVALID) + .build()); + + assertPointerControllerNotCreated(); + pc->assertViewportSet(SECOND_DISPLAY_ID); + ASSERT_TRUE(pc->isPointerShown()); +} + +TEST_F(PointerChoreographerDisplayTopologyDefaultMouseDisplayTests, + AddAssociatedDisplayCursorOutsideOfDisplayTopology) { + SCOPED_FLAG_OVERRIDE(connected_displays_cursor, true); + SCOPED_FLAG_OVERRIDE(connected_displays_associated_display_cursor_bugfix, true); + + // Add three displays, with only first and second display in DisplayTopolgoy + mChoreographer.setDisplayViewports({createViewport(FIRST_DISPLAY_ID), + createViewport(SECOND_DISPLAY_ID), + createViewport(THIRD_DISPLAY_ID)}); + setDisplayTopologyWithDisplays(/*primaryDisplayId=*/FIRST_DISPLAY_ID, + /*adjacentDisplays=*/{SECOND_DISPLAY_ID}); + + mChoreographer.notifyInputDevicesChanged( + {/*id=*/0, + {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE, + ui::LogicalDisplayId::INVALID)}}); + + auto pc = assertPointerControllerCreated(ControllerType::MOUSE); + pc->assertViewportSet(FIRST_DISPLAY_ID); + ASSERT_TRUE(pc->isPointerShown()); + + // Adds a new mouse associated with third display + mChoreographer.notifyInputDevicesChanged( + {/*id=*/1, {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE, THIRD_DISPLAY_ID)}}); + + pc = assertPointerControllerCreated(ControllerType::MOUSE); + pc->assertViewportSet(THIRD_DISPLAY_ID); + ASSERT_TRUE(pc->isPointerShown()); +} + class PointerChoreographerWindowInfoListenerTest : public testing::Test {}; TEST_F_WITH_FLAGS( |