From 24c8ba68bdfc5a728db06e3a778b2b4f43bca4e7 Mon Sep 17 00:00:00 2001 From: Arpit Singh Date: Fri, 25 Oct 2024 21:08:08 +0000 Subject: Check if cursor has moved out of viewport bounds in CursorController This CL updates CursorController to check if and which boundary the cursor has crossed. This will be used to enable cursor moving between different connected displays. Test: presubmit and manual Bug: 367660694 Flag: com.android.input.flags.connected_displays_cursor Change-Id: Ib559e0d72364f446269e73cfa1671ee9d2f715ac --- libs/input/PointerController.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'libs/input/PointerController.cpp') diff --git a/libs/input/PointerController.cpp b/libs/input/PointerController.cpp index 78d7d3a7051b..59397dab592f 100644 --- a/libs/input/PointerController.cpp +++ b/libs/input/PointerController.cpp @@ -138,15 +138,18 @@ std::mutex& PointerController::getLock() const { return mDisplayInfoListener->mLock; } -void PointerController::move(float deltaX, float deltaY) { +vec2 PointerController::move(float deltaX, float deltaY) { const ui::LogicalDisplayId displayId = mCursorController.getDisplayId(); - vec2 transformed; + ui::Transform transform; { std::scoped_lock lock(getLock()); - const auto& transform = getTransformForDisplayLocked(displayId); - transformed = transformWithoutTranslation(transform, {deltaX, deltaY}); + transform = getTransformForDisplayLocked(displayId); } - mCursorController.move(transformed.x, transformed.y); + + vec2 transformed = transformWithoutTranslation(transform, {deltaX, deltaY}); + + vec2 unconsumedDelta = mCursorController.move(transformed.x, transformed.y); + return transformWithoutTranslation(transform.inverse(), unconsumedDelta); } void PointerController::setPosition(float x, float y) { -- cgit v1.2.3-59-g8ed1b From a1d4fe00718abb40cdef39df7d15244e582409f9 Mon Sep 17 00:00:00 2001 From: "Liana Kazanova (xWF)" Date: Mon, 18 Nov 2024 19:14:42 +0000 Subject: Revert "Check if cursor has moved out of viewport bounds in Curs..." Revert submission 30111126-cd-cursor Reason for revert: DroidMonitor: Potential culprit for http://b/379706345 - verifying through ABTD before revert submission. This is part of the standard investigation process, and does not mean your CL will be reverted. Reverted changes: /q/submissionid:30111126-cd-cursor Change-Id: Ibff6c02be1359729802d4c85fa8dc0fdb4c75492 --- libs/input/MouseCursorController.cpp | 32 +++---- libs/input/MouseCursorController.h | 7 +- libs/input/PointerController.cpp | 13 ++- libs/input/PointerController.h | 4 +- libs/input/tests/PointerController_test.cpp | 131 ---------------------------- 5 files changed, 22 insertions(+), 165 deletions(-) (limited to 'libs/input/PointerController.cpp') diff --git a/libs/input/MouseCursorController.cpp b/libs/input/MouseCursorController.cpp index 4330f0addaa9..d993b8715260 100644 --- a/libs/input/MouseCursorController.cpp +++ b/libs/input/MouseCursorController.cpp @@ -28,15 +28,13 @@ #define INDENT " " #define INDENT2 " " -namespace android { - namespace { - // Time to spend fading out the pointer completely. const nsecs_t POINTER_FADE_DURATION = 500 * 1000000LL; // 500 ms - } // namespace +namespace android { + // --- MouseCursorController --- MouseCursorController::MouseCursorController(PointerControllerContext& context) @@ -66,21 +64,17 @@ MouseCursorController::~MouseCursorController() { mLocked.pointerSprite.clear(); } -vec2 MouseCursorController::move(float deltaX, float deltaY) { +void MouseCursorController::move(float deltaX, float deltaY) { #if DEBUG_MOUSE_CURSOR_UPDATES ALOGD("Move pointer by deltaX=%0.3f, deltaY=%0.3f", deltaX, deltaY); #endif if (deltaX == 0.0f && deltaY == 0.0f) { - return {}; + return; } - // When transition occurs, the MouseCursorController object may or may not be deleted, depending - // if there's another display on the other side of the transition. At this point we still need - // to move the cursor to the boundary. std::scoped_lock lock(mLock); - const vec2 pos{mLocked.pointerX + deltaX, mLocked.pointerY + deltaY}; - setPositionLocked(pos.x, pos.y); - return vec2{pos.x - mLocked.pointerX, pos.y - mLocked.pointerY}; + + setPositionLocked(mLocked.pointerX + deltaX, mLocked.pointerY + deltaY); } void MouseCursorController::setPosition(float x, float y) { @@ -88,26 +82,22 @@ void MouseCursorController::setPosition(float x, float y) { ALOGD("Set pointer position to x=%0.3f, y=%0.3f", x, y); #endif std::scoped_lock lock(mLock); - setPositionLocked(x, y); } -FloatRect MouseCursorController::getBoundsLocked() REQUIRES(mLock) { +void MouseCursorController::setPositionLocked(float x, float y) REQUIRES(mLock) { + const auto& v = mLocked.viewport; + if (!v.isValid()) return; + // The valid bounds for a mouse cursor. Since the right and bottom edges are considered outside // the display, clip the bounds by one pixel instead of letting the cursor get arbitrarily // close to the outside edge. - return FloatRect{ + const FloatRect bounds{ static_cast(mLocked.viewport.logicalLeft), static_cast(mLocked.viewport.logicalTop), static_cast(mLocked.viewport.logicalRight - 1), static_cast(mLocked.viewport.logicalBottom - 1), }; -} -void MouseCursorController::setPositionLocked(float x, float y) REQUIRES(mLock) { - const auto& v = mLocked.viewport; - if (!v.isValid()) return; - - const FloatRect bounds = getBoundsLocked(); mLocked.pointerX = std::max(bounds.left, std::min(bounds.right, x)); mLocked.pointerY = std::max(bounds.top, std::min(bounds.bottom, y)); diff --git a/libs/input/MouseCursorController.h b/libs/input/MouseCursorController.h index 10f0d7645105..12b31a8c531a 100644 --- a/libs/input/MouseCursorController.h +++ b/libs/input/MouseCursorController.h @@ -20,6 +20,9 @@ #include #include #include +#include +#include +#include #include #include @@ -40,8 +43,7 @@ public: MouseCursorController(PointerControllerContext& context); ~MouseCursorController(); - // Move the pointer and return unconsumed delta - vec2 move(float deltaX, float deltaY); + void move(float deltaX, float deltaY); void setPosition(float x, float y); FloatPoint getPosition() const; ui::LogicalDisplayId getDisplayId() const; @@ -111,7 +113,6 @@ private: bool doFadingAnimationLocked(nsecs_t timestamp); void startAnimationLocked(); - FloatRect getBoundsLocked(); }; } // namespace android diff --git a/libs/input/PointerController.cpp b/libs/input/PointerController.cpp index 59397dab592f..78d7d3a7051b 100644 --- a/libs/input/PointerController.cpp +++ b/libs/input/PointerController.cpp @@ -138,18 +138,15 @@ std::mutex& PointerController::getLock() const { return mDisplayInfoListener->mLock; } -vec2 PointerController::move(float deltaX, float deltaY) { +void PointerController::move(float deltaX, float deltaY) { const ui::LogicalDisplayId displayId = mCursorController.getDisplayId(); - ui::Transform transform; + vec2 transformed; { std::scoped_lock lock(getLock()); - transform = getTransformForDisplayLocked(displayId); + const auto& transform = getTransformForDisplayLocked(displayId); + transformed = transformWithoutTranslation(transform, {deltaX, deltaY}); } - - vec2 transformed = transformWithoutTranslation(transform, {deltaX, deltaY}); - - vec2 unconsumedDelta = mCursorController.move(transformed.x, transformed.y); - return transformWithoutTranslation(transform.inverse(), unconsumedDelta); + mCursorController.move(transformed.x, transformed.y); } void PointerController::setPosition(float x, float y) { diff --git a/libs/input/PointerController.h b/libs/input/PointerController.h index 69bef546b788..ee8d1211341f 100644 --- a/libs/input/PointerController.h +++ b/libs/input/PointerController.h @@ -51,7 +51,7 @@ public: ~PointerController() override; - vec2 move(float deltaX, float deltaY) override; + void move(float deltaX, float deltaY) override; void setPosition(float x, float y) override; FloatPoint getPosition() const override; ui::LogicalDisplayId getDisplayId() const override; @@ -165,7 +165,7 @@ public: ~TouchPointerController() override; - vec2 move(float, float) override { + void move(float, float) override { LOG_ALWAYS_FATAL("Should not be called"); } void setPosition(float, float) override { diff --git a/libs/input/tests/PointerController_test.cpp b/libs/input/tests/PointerController_test.cpp index 80c934a9bd95..5b00fca4d857 100644 --- a/libs/input/tests/PointerController_test.cpp +++ b/libs/input/tests/PointerController_test.cpp @@ -40,8 +40,6 @@ enum TestCursorType { CURSOR_TYPE_CUSTOM = -1, }; -static constexpr float EPSILON = MotionEvent::ROUNDING_PRECISION; - using ::testing::AllOf; using ::testing::Field; using ::testing::NiceMock; @@ -401,135 +399,6 @@ INSTANTIATE_TEST_SUITE_P(PointerControllerSkipScreenshotFlagTest, testing::Values(PointerControllerInterface::ControllerType::MOUSE, PointerControllerInterface::ControllerType::STYLUS)); -class MousePointerControllerTest : public PointerControllerTest { -protected: - MousePointerControllerTest() { - sp testPointerSprite(new NiceMock); - EXPECT_CALL(*mSpriteController, createSprite).WillOnce(Return(testPointerSprite)); - - // create a mouse pointer controller - mPointerController = - PointerController::create(mPolicy, mLooper, *mSpriteController, - PointerControllerInterface::ControllerType::MOUSE); - - // set display viewport - DisplayViewport viewport; - viewport.displayId = ui::LogicalDisplayId::DEFAULT; - viewport.logicalRight = 5; - viewport.logicalBottom = 5; - viewport.physicalRight = 5; - viewport.physicalBottom = 5; - viewport.deviceWidth = 5; - viewport.deviceHeight = 5; - mPointerController->setDisplayViewport(viewport); - } -}; - -struct MousePointerControllerTestParam { - vec2 startPosition; - vec2 delta; - vec2 endPosition; - vec2 unconsumedDelta; -}; - -class PointerControllerViewportTransitionTest - : public MousePointerControllerTest, - public testing::WithParamInterface {}; - -TEST_P(PointerControllerViewportTransitionTest, testPointerViewportTransition) { - const auto& params = GetParam(); - - mPointerController->setPosition(params.startPosition.x, params.startPosition.y); - auto unconsumedDelta = mPointerController->move(params.delta.x, params.delta.y); - - auto position = mPointerController->getPosition(); - EXPECT_NEAR(position.x, params.endPosition.x, EPSILON); - EXPECT_NEAR(position.y, params.endPosition.y, EPSILON); - EXPECT_NEAR(unconsumedDelta.x, params.unconsumedDelta.x, EPSILON); - EXPECT_NEAR(unconsumedDelta.y, params.unconsumedDelta.y, EPSILON); -} - -INSTANTIATE_TEST_SUITE_P(PointerControllerViewportTransitionTest, - PointerControllerViewportTransitionTest, - testing::Values( - // no transition - MousePointerControllerTestParam{{2.0f, 2.0f}, - {2.0f, 2.0f}, - {4.0f, 4.0f}, - {0.0f, 0.0f}}, - // right boundary - MousePointerControllerTestParam{{2.0f, 2.0f}, - {3.0f, 0.0f}, - {4.0f, 2.0f}, - {1.0f, 0.0f}}, - MousePointerControllerTestParam{{2.0f, 2.0f}, - {3.0f, -1.0f}, - {4.0f, 1.0f}, - {1.0f, 0.0f}}, - MousePointerControllerTestParam{{2.0f, 2.0f}, - {3.0f, 1.0f}, - {4.0f, 3.0f}, - {1.0f, 0.0f}}, - // left boundary - MousePointerControllerTestParam{{2.0f, 2.0f}, - {-3.0f, 0.0f}, - {0.0f, 2.0f}, - {-1.0f, 0.0f}}, - MousePointerControllerTestParam{{2.0f, 2.0f}, - {-3.0f, -1.0f}, - {0.0f, 1.0f}, - {-1.0f, 0.0f}}, - MousePointerControllerTestParam{{2.0f, 2.0f}, - {-3.0f, 1.0f}, - {0.0f, 3.0f}, - {-1.0f, 0.0f}}, - // bottom boundary - MousePointerControllerTestParam{{2.0f, 2.0f}, - {0.0f, 3.0f}, - {2.0f, 4.0f}, - {0.0f, 1.0f}}, - MousePointerControllerTestParam{{2.0f, 2.0f}, - {-1.0f, 3.0f}, - {1.0f, 4.0f}, - {0.0f, 1.0f}}, - MousePointerControllerTestParam{{2.0f, 2.0f}, - {1.0f, 3.0f}, - {3.0f, 4.0f}, - {0.0f, 1.0f}}, - // top boundary - MousePointerControllerTestParam{{2.0f, 2.0f}, - {0.0f, -3.0f}, - {2.0f, 0.0f}, - {0.0f, -1.0f}}, - MousePointerControllerTestParam{{2.0f, 2.0f}, - {-1.0f, -3.0f}, - {1.0f, 0.0f}, - {0.0f, -1.0f}}, - MousePointerControllerTestParam{{2.0f, 2.0f}, - {1.0f, -3.0f}, - {3.0f, 0.0f}, - {0.0f, -1.0f}}, - // top-left corner - MousePointerControllerTestParam{{2.0f, 2.0f}, - {-3.0f, -3.0f}, - {0.0f, 0.0f}, - {-1.0f, -1.0f}}, - // top-right corner - MousePointerControllerTestParam{{2.0f, 2.0f}, - {3.0f, -3.0f}, - {4.0f, 0.0f}, - {1.0f, -1.0f}}, - // bottom-right corner - MousePointerControllerTestParam{{2.0f, 2.0f}, - {3.0f, 3.0f}, - {4.0f, 4.0f}, - {1.0f, 1.0f}}, - // bottom-left corner - MousePointerControllerTestParam{{2.0f, 2.0f}, - {-3.0f, 3.0f}, - {0.0f, 4.0f}, - {-1.0f, 1.0f}})); - class PointerControllerWindowInfoListenerTest : public Test {}; TEST_F(PointerControllerWindowInfoListenerTest, -- cgit v1.2.3-59-g8ed1b From 64a70881b3ca559559f416b54d2ec21dbb009fe4 Mon Sep 17 00:00:00 2001 From: Arpit Singh Date: Fri, 25 Oct 2024 21:08:08 +0000 Subject: Check if cursor has moved out of viewport bounds in CursorController This CL updates CursorController to check if and which boundary the cursor has crossed. This will be used to enable cursor moving between different connected displays. Test: atest inputflinger_tests Test: verify cursor can move between displays as expected Bug: 367660694 Flag: com.android.input.flags.connected_displays_cursor Change-Id: Ida11e897d4e6767549dcc40da5c83e4c6be178c9 --- libs/input/MouseCursorController.cpp | 34 +++++--- libs/input/MouseCursorController.h | 7 +- libs/input/PointerController.cpp | 14 +-- libs/input/PointerController.h | 4 +- libs/input/tests/PointerController_test.cpp | 131 ++++++++++++++++++++++++++++ 5 files changed, 168 insertions(+), 22 deletions(-) (limited to 'libs/input/PointerController.cpp') diff --git a/libs/input/MouseCursorController.cpp b/libs/input/MouseCursorController.cpp index d993b8715260..28d96e3e5bb1 100644 --- a/libs/input/MouseCursorController.cpp +++ b/libs/input/MouseCursorController.cpp @@ -28,12 +28,14 @@ #define INDENT " " #define INDENT2 " " +namespace android { + namespace { + // Time to spend fading out the pointer completely. const nsecs_t POINTER_FADE_DURATION = 500 * 1000000LL; // 500 ms -} // namespace -namespace android { +} // namespace // --- MouseCursorController --- @@ -64,17 +66,23 @@ MouseCursorController::~MouseCursorController() { mLocked.pointerSprite.clear(); } -void MouseCursorController::move(float deltaX, float deltaY) { +FloatPoint MouseCursorController::move(float deltaX, float deltaY) { #if DEBUG_MOUSE_CURSOR_UPDATES ALOGD("Move pointer by deltaX=%0.3f, deltaY=%0.3f", deltaX, deltaY); #endif if (deltaX == 0.0f && deltaY == 0.0f) { - return; + return {0, 0}; } + // When transition occurs, the MouseCursorController object may or may not be deleted, depending + // if there's another display on the other side of the transition. At this point we still need + // to move the cursor to the boundary. std::scoped_lock lock(mLock); - - setPositionLocked(mLocked.pointerX + deltaX, mLocked.pointerY + deltaY); + const FloatPoint position{mLocked.pointerX + deltaX, mLocked.pointerY + deltaY}; + setPositionLocked(position.x, position.y); + // The amount of the delta that was not consumed as a result of the cursor + // hitting the edge of the display. + return {position.x - mLocked.pointerX, position.y - mLocked.pointerY}; } void MouseCursorController::setPosition(float x, float y) { @@ -85,19 +93,23 @@ void MouseCursorController::setPosition(float x, float y) { setPositionLocked(x, y); } -void MouseCursorController::setPositionLocked(float x, float y) REQUIRES(mLock) { - const auto& v = mLocked.viewport; - if (!v.isValid()) return; - +FloatRect MouseCursorController::getBoundsLocked() REQUIRES(mLock) { // The valid bounds for a mouse cursor. Since the right and bottom edges are considered outside // the display, clip the bounds by one pixel instead of letting the cursor get arbitrarily // close to the outside edge. - const FloatRect bounds{ + return FloatRect{ static_cast(mLocked.viewport.logicalLeft), static_cast(mLocked.viewport.logicalTop), static_cast(mLocked.viewport.logicalRight - 1), static_cast(mLocked.viewport.logicalBottom - 1), }; +} + +void MouseCursorController::setPositionLocked(float x, float y) REQUIRES(mLock) { + const auto& v = mLocked.viewport; + if (!v.isValid()) return; + + const FloatRect bounds = getBoundsLocked(); mLocked.pointerX = std::max(bounds.left, std::min(bounds.right, x)); mLocked.pointerY = std::max(bounds.top, std::min(bounds.bottom, y)); diff --git a/libs/input/MouseCursorController.h b/libs/input/MouseCursorController.h index 12b31a8c531a..e14a55d938e6 100644 --- a/libs/input/MouseCursorController.h +++ b/libs/input/MouseCursorController.h @@ -20,9 +20,6 @@ #include #include #include -#include -#include -#include #include #include @@ -43,7 +40,8 @@ public: MouseCursorController(PointerControllerContext& context); ~MouseCursorController(); - void move(float deltaX, float deltaY); + // Move the pointer and return unconsumed delta + FloatPoint move(float deltaX, float deltaY); void setPosition(float x, float y); FloatPoint getPosition() const; ui::LogicalDisplayId getDisplayId() const; @@ -113,6 +111,7 @@ private: bool doFadingAnimationLocked(nsecs_t timestamp); void startAnimationLocked(); + FloatRect getBoundsLocked(); }; } // namespace android diff --git a/libs/input/PointerController.cpp b/libs/input/PointerController.cpp index 78d7d3a7051b..883bc2f0e0f3 100644 --- a/libs/input/PointerController.cpp +++ b/libs/input/PointerController.cpp @@ -138,15 +138,19 @@ std::mutex& PointerController::getLock() const { return mDisplayInfoListener->mLock; } -void PointerController::move(float deltaX, float deltaY) { +FloatPoint PointerController::move(float deltaX, float deltaY) { const ui::LogicalDisplayId displayId = mCursorController.getDisplayId(); - vec2 transformed; + ui::Transform transform; { std::scoped_lock lock(getLock()); - const auto& transform = getTransformForDisplayLocked(displayId); - transformed = transformWithoutTranslation(transform, {deltaX, deltaY}); + transform = getTransformForDisplayLocked(displayId); } - mCursorController.move(transformed.x, transformed.y); + + const vec2 transformed = transformWithoutTranslation(transform, {deltaX, deltaY}); + + const FloatPoint unconsumedDelta = mCursorController.move(transformed.x, transformed.y); + return FloatPoint(transformWithoutTranslation(transform.inverse(), + {unconsumedDelta.x, unconsumedDelta.y})); } void PointerController::setPosition(float x, float y) { diff --git a/libs/input/PointerController.h b/libs/input/PointerController.h index ee8d1211341f..d0b98384dd9d 100644 --- a/libs/input/PointerController.h +++ b/libs/input/PointerController.h @@ -51,7 +51,7 @@ public: ~PointerController() override; - void move(float deltaX, float deltaY) override; + FloatPoint move(float deltaX, float deltaY) override; void setPosition(float x, float y) override; FloatPoint getPosition() const override; ui::LogicalDisplayId getDisplayId() const override; @@ -165,7 +165,7 @@ public: ~TouchPointerController() override; - void move(float, float) override { + FloatPoint move(float, float) override { LOG_ALWAYS_FATAL("Should not be called"); } void setPosition(float, float) override { diff --git a/libs/input/tests/PointerController_test.cpp b/libs/input/tests/PointerController_test.cpp index 5b00fca4d857..80c934a9bd95 100644 --- a/libs/input/tests/PointerController_test.cpp +++ b/libs/input/tests/PointerController_test.cpp @@ -40,6 +40,8 @@ enum TestCursorType { CURSOR_TYPE_CUSTOM = -1, }; +static constexpr float EPSILON = MotionEvent::ROUNDING_PRECISION; + using ::testing::AllOf; using ::testing::Field; using ::testing::NiceMock; @@ -399,6 +401,135 @@ INSTANTIATE_TEST_SUITE_P(PointerControllerSkipScreenshotFlagTest, testing::Values(PointerControllerInterface::ControllerType::MOUSE, PointerControllerInterface::ControllerType::STYLUS)); +class MousePointerControllerTest : public PointerControllerTest { +protected: + MousePointerControllerTest() { + sp testPointerSprite(new NiceMock); + EXPECT_CALL(*mSpriteController, createSprite).WillOnce(Return(testPointerSprite)); + + // create a mouse pointer controller + mPointerController = + PointerController::create(mPolicy, mLooper, *mSpriteController, + PointerControllerInterface::ControllerType::MOUSE); + + // set display viewport + DisplayViewport viewport; + viewport.displayId = ui::LogicalDisplayId::DEFAULT; + viewport.logicalRight = 5; + viewport.logicalBottom = 5; + viewport.physicalRight = 5; + viewport.physicalBottom = 5; + viewport.deviceWidth = 5; + viewport.deviceHeight = 5; + mPointerController->setDisplayViewport(viewport); + } +}; + +struct MousePointerControllerTestParam { + vec2 startPosition; + vec2 delta; + vec2 endPosition; + vec2 unconsumedDelta; +}; + +class PointerControllerViewportTransitionTest + : public MousePointerControllerTest, + public testing::WithParamInterface {}; + +TEST_P(PointerControllerViewportTransitionTest, testPointerViewportTransition) { + const auto& params = GetParam(); + + mPointerController->setPosition(params.startPosition.x, params.startPosition.y); + auto unconsumedDelta = mPointerController->move(params.delta.x, params.delta.y); + + auto position = mPointerController->getPosition(); + EXPECT_NEAR(position.x, params.endPosition.x, EPSILON); + EXPECT_NEAR(position.y, params.endPosition.y, EPSILON); + EXPECT_NEAR(unconsumedDelta.x, params.unconsumedDelta.x, EPSILON); + EXPECT_NEAR(unconsumedDelta.y, params.unconsumedDelta.y, EPSILON); +} + +INSTANTIATE_TEST_SUITE_P(PointerControllerViewportTransitionTest, + PointerControllerViewportTransitionTest, + testing::Values( + // no transition + MousePointerControllerTestParam{{2.0f, 2.0f}, + {2.0f, 2.0f}, + {4.0f, 4.0f}, + {0.0f, 0.0f}}, + // right boundary + MousePointerControllerTestParam{{2.0f, 2.0f}, + {3.0f, 0.0f}, + {4.0f, 2.0f}, + {1.0f, 0.0f}}, + MousePointerControllerTestParam{{2.0f, 2.0f}, + {3.0f, -1.0f}, + {4.0f, 1.0f}, + {1.0f, 0.0f}}, + MousePointerControllerTestParam{{2.0f, 2.0f}, + {3.0f, 1.0f}, + {4.0f, 3.0f}, + {1.0f, 0.0f}}, + // left boundary + MousePointerControllerTestParam{{2.0f, 2.0f}, + {-3.0f, 0.0f}, + {0.0f, 2.0f}, + {-1.0f, 0.0f}}, + MousePointerControllerTestParam{{2.0f, 2.0f}, + {-3.0f, -1.0f}, + {0.0f, 1.0f}, + {-1.0f, 0.0f}}, + MousePointerControllerTestParam{{2.0f, 2.0f}, + {-3.0f, 1.0f}, + {0.0f, 3.0f}, + {-1.0f, 0.0f}}, + // bottom boundary + MousePointerControllerTestParam{{2.0f, 2.0f}, + {0.0f, 3.0f}, + {2.0f, 4.0f}, + {0.0f, 1.0f}}, + MousePointerControllerTestParam{{2.0f, 2.0f}, + {-1.0f, 3.0f}, + {1.0f, 4.0f}, + {0.0f, 1.0f}}, + MousePointerControllerTestParam{{2.0f, 2.0f}, + {1.0f, 3.0f}, + {3.0f, 4.0f}, + {0.0f, 1.0f}}, + // top boundary + MousePointerControllerTestParam{{2.0f, 2.0f}, + {0.0f, -3.0f}, + {2.0f, 0.0f}, + {0.0f, -1.0f}}, + MousePointerControllerTestParam{{2.0f, 2.0f}, + {-1.0f, -3.0f}, + {1.0f, 0.0f}, + {0.0f, -1.0f}}, + MousePointerControllerTestParam{{2.0f, 2.0f}, + {1.0f, -3.0f}, + {3.0f, 0.0f}, + {0.0f, -1.0f}}, + // top-left corner + MousePointerControllerTestParam{{2.0f, 2.0f}, + {-3.0f, -3.0f}, + {0.0f, 0.0f}, + {-1.0f, -1.0f}}, + // top-right corner + MousePointerControllerTestParam{{2.0f, 2.0f}, + {3.0f, -3.0f}, + {4.0f, 0.0f}, + {1.0f, -1.0f}}, + // bottom-right corner + MousePointerControllerTestParam{{2.0f, 2.0f}, + {3.0f, 3.0f}, + {4.0f, 4.0f}, + {1.0f, 1.0f}}, + // bottom-left corner + MousePointerControllerTestParam{{2.0f, 2.0f}, + {-3.0f, 3.0f}, + {0.0f, 4.0f}, + {-1.0f, 1.0f}})); + class PointerControllerWindowInfoListenerTest : public Test {}; TEST_F(PointerControllerWindowInfoListenerTest, -- cgit v1.2.3-59-g8ed1b From 1886eea92758e8c4d15ab4f3cdae54993d81d0d1 Mon Sep 17 00:00:00 2001 From: Arpit Singh Date: Mon, 18 Nov 2024 20:42:54 +0000 Subject: Expose current viewport transform of PointerController This CL adds API to expose the current viewport transform of the PointerController. This will be used by Choreographer to find the target display and cursor position in the topology, when cursor moves across the displays. Test: presubmit Bug: 367660694 Flag: com.android.input.flags.connected_displays_cursor Change-Id: If4fe9fade2bf55f29db377661820ef7a8ca73ba2 --- libs/input/PointerController.cpp | 5 +++++ libs/input/PointerController.h | 1 + 2 files changed, 6 insertions(+) (limited to 'libs/input/PointerController.cpp') diff --git a/libs/input/PointerController.cpp b/libs/input/PointerController.cpp index 883bc2f0e0f3..a713f1d1ed4d 100644 --- a/libs/input/PointerController.cpp +++ b/libs/input/PointerController.cpp @@ -299,6 +299,11 @@ void PointerController::clearSkipScreenshotFlags() { mCursorController.setSkipScreenshot(false); } +ui::Transform PointerController::getDisplayTransform() const { + std::scoped_lock lock(getLock()); + return getTransformForDisplayLocked(mLocked.pointerDisplayId); +} + void PointerController::doInactivityTimeout() { fade(Transition::GRADUAL); } diff --git a/libs/input/PointerController.h b/libs/input/PointerController.h index d0b98384dd9d..8b33190cd35f 100644 --- a/libs/input/PointerController.h +++ b/libs/input/PointerController.h @@ -67,6 +67,7 @@ public: void setCustomPointerIcon(const SpriteIcon& icon) override; void setSkipScreenshotFlagForDisplay(ui::LogicalDisplayId displayId) override; void clearSkipScreenshotFlags() override; + ui::Transform getDisplayTransform() const override; virtual void setInactivityTimeout(InactivityTimeout inactivityTimeout); void doInactivityTimeout(); -- cgit v1.2.3-59-g8ed1b From a09a94d83e421442f9c02166d3fde67c39a13a8c Mon Sep 17 00:00:00 2001 From: Arpit Singh Date: Tue, 26 Nov 2024 15:50:17 +0000 Subject: Refactor to replace FloatPoint by vec2 Using FloatPoint requires unnecessory conversion between vec2 and FloatPoint, which is inefficient. This CL replaces FloatPoint by vec2 everywhere. Test: atest inputflinger_tests Bug: 245989146 Flag: EXEMPT refactor Change-Id: I0bf9cd35392bff424ec65bbaa43918176d31de37 --- libs/input/MouseCursorController.cpp | 46 +++++++++++----------- libs/input/MouseCursorController.h | 11 +++--- libs/input/PointerController.cpp | 14 +++---- libs/input/PointerController.h | 8 ++-- ...om_android_server_input_InputManagerService.cpp | 8 ++-- 5 files changed, 41 insertions(+), 46 deletions(-) (limited to 'libs/input/PointerController.cpp') diff --git a/libs/input/MouseCursorController.cpp b/libs/input/MouseCursorController.cpp index 28d96e3e5bb1..65663d065b8e 100644 --- a/libs/input/MouseCursorController.cpp +++ b/libs/input/MouseCursorController.cpp @@ -49,8 +49,7 @@ MouseCursorController::MouseCursorController(PointerControllerContext& context) mLocked.lastFrameUpdatedTime = 0; mLocked.pointerFadeDirection = 0; - mLocked.pointerX = 0; - mLocked.pointerY = 0; + mLocked.pointerPosition = {0, 0}; mLocked.pointerAlpha = 0.0f; // pointer is initially faded mLocked.pointerSprite = mContext.getSpriteController().createSprite(); mLocked.updatePointerIcon = false; @@ -66,11 +65,11 @@ MouseCursorController::~MouseCursorController() { mLocked.pointerSprite.clear(); } -FloatPoint MouseCursorController::move(float deltaX, float deltaY) { +vec2 MouseCursorController::move(vec2 delta) { #if DEBUG_MOUSE_CURSOR_UPDATES ALOGD("Move pointer by deltaX=%0.3f, deltaY=%0.3f", deltaX, deltaY); #endif - if (deltaX == 0.0f && deltaY == 0.0f) { + if (delta.x == 0.0f && delta.y == 0.0f) { return {0, 0}; } @@ -78,19 +77,19 @@ FloatPoint MouseCursorController::move(float deltaX, float deltaY) { // if there's another display on the other side of the transition. At this point we still need // to move the cursor to the boundary. std::scoped_lock lock(mLock); - const FloatPoint position{mLocked.pointerX + deltaX, mLocked.pointerY + deltaY}; - setPositionLocked(position.x, position.y); + const vec2 targetPosition = mLocked.pointerPosition + delta; + setPositionLocked(targetPosition); // The amount of the delta that was not consumed as a result of the cursor // hitting the edge of the display. - return {position.x - mLocked.pointerX, position.y - mLocked.pointerY}; + return targetPosition - mLocked.pointerPosition; } -void MouseCursorController::setPosition(float x, float y) { +void MouseCursorController::setPosition(vec2 position) { #if DEBUG_MOUSE_CURSOR_UPDATES ALOGD("Set pointer position to x=%0.3f, y=%0.3f", x, y); #endif std::scoped_lock lock(mLock); - setPositionLocked(x, y); + setPositionLocked(position); } FloatRect MouseCursorController::getBoundsLocked() REQUIRES(mLock) { @@ -105,21 +104,21 @@ FloatRect MouseCursorController::getBoundsLocked() REQUIRES(mLock) { }; } -void MouseCursorController::setPositionLocked(float x, float y) REQUIRES(mLock) { +void MouseCursorController::setPositionLocked(vec2 position) REQUIRES(mLock) { const auto& v = mLocked.viewport; if (!v.isValid()) return; const FloatRect bounds = getBoundsLocked(); - mLocked.pointerX = std::max(bounds.left, std::min(bounds.right, x)); - mLocked.pointerY = std::max(bounds.top, std::min(bounds.bottom, y)); + mLocked.pointerPosition.x = std::max(bounds.left, std::min(bounds.right, position.x)); + mLocked.pointerPosition.y = std::max(bounds.top, std::min(bounds.bottom, position.y)); updatePointerLocked(); } -FloatPoint MouseCursorController::getPosition() const { +vec2 MouseCursorController::getPosition() const { std::scoped_lock lock(mLock); - return {mLocked.pointerX, mLocked.pointerY}; + return mLocked.pointerPosition; } ui::LogicalDisplayId MouseCursorController::getDisplayId() const { @@ -221,20 +220,21 @@ void MouseCursorController::setDisplayViewport(const DisplayViewport& viewport, if (viewport.isValid()) { // Use integer coordinates as the starting point for the cursor location. // We usually expect display sizes to be even numbers, so the flooring is precautionary. - mLocked.pointerX = std::floor((viewport.logicalLeft + viewport.logicalRight) / 2); - mLocked.pointerY = std::floor((viewport.logicalTop + viewport.logicalBottom) / 2); + mLocked.pointerPosition.x = + std::floor((viewport.logicalLeft + viewport.logicalRight) / 2); + mLocked.pointerPosition.y = + std::floor((viewport.logicalTop + viewport.logicalBottom) / 2); // Reload icon resources for density may be changed. loadResourcesLocked(getAdditionalMouseResources); } else { - mLocked.pointerX = 0; - mLocked.pointerY = 0; + mLocked.pointerPosition = {0, 0}; } } else if (oldViewport.orientation != viewport.orientation) { // Apply offsets to convert from the pixel top-left corner position to the pixel center. // This creates an invariant frame of reference that we can easily rotate when // taking into account that the pointer may be located at fractional pixel offsets. - float x = mLocked.pointerX + 0.5f; - float y = mLocked.pointerY + 0.5f; + float x = mLocked.pointerPosition.x + 0.5f; + float y = mLocked.pointerPosition.y + 0.5f; float temp; // Undo the previous rotation. @@ -279,8 +279,8 @@ void MouseCursorController::setDisplayViewport(const DisplayViewport& viewport, // Apply offsets to convert from the pixel center to the pixel top-left corner position // and save the results. - mLocked.pointerX = x - 0.5f; - mLocked.pointerY = y - 0.5f; + mLocked.pointerPosition.x = x - 0.5f; + mLocked.pointerPosition.y = y - 0.5f; } updatePointerLocked(); @@ -366,7 +366,7 @@ void MouseCursorController::updatePointerLocked() REQUIRES(mLock) { spriteController.openTransaction(); mLocked.pointerSprite->setLayer(Sprite::BASE_LAYER_POINTER); - mLocked.pointerSprite->setPosition(mLocked.pointerX, mLocked.pointerY); + mLocked.pointerSprite->setPosition(mLocked.pointerPosition.x, mLocked.pointerPosition.y); mLocked.pointerSprite->setDisplayId(mLocked.viewport.displayId); mLocked.pointerSprite->setSkipScreenshot(mLocked.skipScreenshot); diff --git a/libs/input/MouseCursorController.h b/libs/input/MouseCursorController.h index e14a55d938e6..7c674b53d620 100644 --- a/libs/input/MouseCursorController.h +++ b/libs/input/MouseCursorController.h @@ -41,9 +41,9 @@ public: ~MouseCursorController(); // Move the pointer and return unconsumed delta - FloatPoint move(float deltaX, float deltaY); - void setPosition(float x, float y); - FloatPoint getPosition() const; + vec2 move(vec2 delta); + void setPosition(vec2 position); + vec2 getPosition() const; ui::LogicalDisplayId getDisplayId() const; void fade(PointerControllerInterface::Transition transition); void unfade(PointerControllerInterface::Transition transition); @@ -81,8 +81,7 @@ private: nsecs_t lastFrameUpdatedTime; int32_t pointerFadeDirection; - float pointerX; - float pointerY; + vec2 pointerPosition; float pointerAlpha; sp pointerSprite; SpriteIcon pointerIcon; @@ -101,7 +100,7 @@ private: } mLocked GUARDED_BY(mLock); - void setPositionLocked(float x, float y); + void setPositionLocked(vec2 position); void updatePointerLocked(); diff --git a/libs/input/PointerController.cpp b/libs/input/PointerController.cpp index a713f1d1ed4d..0b81211ee666 100644 --- a/libs/input/PointerController.cpp +++ b/libs/input/PointerController.cpp @@ -138,7 +138,7 @@ std::mutex& PointerController::getLock() const { return mDisplayInfoListener->mLock; } -FloatPoint PointerController::move(float deltaX, float deltaY) { +vec2 PointerController::move(float deltaX, float deltaY) { const ui::LogicalDisplayId displayId = mCursorController.getDisplayId(); ui::Transform transform; { @@ -147,10 +147,7 @@ FloatPoint PointerController::move(float deltaX, float deltaY) { } const vec2 transformed = transformWithoutTranslation(transform, {deltaX, deltaY}); - - const FloatPoint unconsumedDelta = mCursorController.move(transformed.x, transformed.y); - return FloatPoint(transformWithoutTranslation(transform.inverse(), - {unconsumedDelta.x, unconsumedDelta.y})); + return transformWithoutTranslation(transform.inverse(), mCursorController.move(transformed)); } void PointerController::setPosition(float x, float y) { @@ -161,16 +158,15 @@ void PointerController::setPosition(float x, float y) { const auto& transform = getTransformForDisplayLocked(displayId); transformed = transform.transform(x, y); } - mCursorController.setPosition(transformed.x, transformed.y); + mCursorController.setPosition(transformed); } -FloatPoint PointerController::getPosition() const { +vec2 PointerController::getPosition() const { const ui::LogicalDisplayId displayId = mCursorController.getDisplayId(); const auto p = mCursorController.getPosition(); { std::scoped_lock lock(getLock()); - const auto& transform = getTransformForDisplayLocked(displayId); - return FloatPoint{transform.inverse().transform(p.x, p.y)}; + return getTransformForDisplayLocked(displayId).inverse().transform(p.x, p.y); } } diff --git a/libs/input/PointerController.h b/libs/input/PointerController.h index 8b33190cd35f..afd7215c7fba 100644 --- a/libs/input/PointerController.h +++ b/libs/input/PointerController.h @@ -51,9 +51,9 @@ public: ~PointerController() override; - FloatPoint move(float deltaX, float deltaY) override; + vec2 move(float deltaX, float deltaY) override; void setPosition(float x, float y) override; - FloatPoint getPosition() const override; + vec2 getPosition() const override; ui::LogicalDisplayId getDisplayId() const override; void fade(Transition transition) override; void unfade(Transition transition) override; @@ -166,13 +166,13 @@ public: ~TouchPointerController() override; - FloatPoint move(float, float) override { + vec2 move(float, float) override { LOG_ALWAYS_FATAL("Should not be called"); } void setPosition(float, float) override { LOG_ALWAYS_FATAL("Should not be called"); } - FloatPoint getPosition() const override { + vec2 getPosition() const override { LOG_ALWAYS_FATAL("Should not be called"); } ui::LogicalDisplayId getDisplayId() const override { diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp index 943019429c3f..5a457302108c 100644 --- a/services/core/jni/com_android_server_input_InputManagerService.cpp +++ b/services/core/jni/com_android_server_input_InputManagerService.cpp @@ -362,7 +362,7 @@ public: void setMotionClassifierEnabled(bool enabled); std::optional getBluetoothAddress(int32_t deviceId); void setStylusButtonMotionEventsEnabled(bool enabled); - FloatPoint getMouseCursorPosition(ui::LogicalDisplayId displayId); + vec2 getMouseCursorPosition(ui::LogicalDisplayId displayId); void setStylusPointerIconEnabled(bool enabled); void setInputMethodConnectionIsActive(bool isActive); void setKeyRemapping(const std::map& keyRemapping); @@ -441,7 +441,7 @@ public: std::shared_ptr createPointerController( PointerControllerInterface::ControllerType type) override; void notifyPointerDisplayIdChanged(ui::LogicalDisplayId displayId, - const FloatPoint& position) override; + const vec2& position) override; void notifyMouseCursorFadedOnTyping() override; /* --- InputFilterPolicyInterface implementation --- */ @@ -871,7 +871,7 @@ std::shared_ptr NativeInputManager::createPointerCon } void NativeInputManager::notifyPointerDisplayIdChanged(ui::LogicalDisplayId pointerDisplayId, - const FloatPoint& position) { + const vec2& position) { // Notify the Reader so that devices can be reconfigured. { // acquire lock std::scoped_lock _l(mLock); @@ -2023,7 +2023,7 @@ void NativeInputManager::setStylusButtonMotionEventsEnabled(bool enabled) { InputReaderConfiguration::Change::STYLUS_BUTTON_REPORTING); } -FloatPoint NativeInputManager::getMouseCursorPosition(ui::LogicalDisplayId displayId) { +vec2 NativeInputManager::getMouseCursorPosition(ui::LogicalDisplayId displayId) { return mInputManager->getChoreographer().getMouseCursorPosition(displayId); } -- cgit v1.2.3-59-g8ed1b