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

Commit 280d19b9 authored by Arpit Singh's avatar Arpit Singh Committed by Android (Google) Code Review
Browse files

Merge "Check if cursor has moved out of viewport bounds in CursorController" into main

parents 593dabb0 24c8ba68
Loading
Loading
Loading
Loading
+21 −11
Original line number Diff line number Diff line
@@ -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,21 @@ MouseCursorController::~MouseCursorController() {
    mLocked.pointerSprite.clear();
}

void MouseCursorController::move(float deltaX, float deltaY) {
vec2 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);

    setPositionLocked(mLocked.pointerX + deltaX, mLocked.pointerY + deltaY);
    const vec2 pos{mLocked.pointerX + deltaX, mLocked.pointerY + deltaY};
    setPositionLocked(pos.x, pos.y);
    return vec2{pos.x - mLocked.pointerX, pos.y - mLocked.pointerY};
}

void MouseCursorController::setPosition(float x, float y) {
@@ -82,22 +88,26 @@ 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);
}

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<float>(mLocked.viewport.logicalLeft),
            static_cast<float>(mLocked.viewport.logicalTop),
            static_cast<float>(mLocked.viewport.logicalRight - 1),
            static_cast<float>(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));

+3 −4
Original line number Diff line number Diff line
@@ -20,9 +20,6 @@
#include <gui/DisplayEventReceiver.h>
#include <input/DisplayViewport.h>
#include <input/Input.h>
#include <utils/BitSet.h>
#include <utils/Looper.h>
#include <utils/RefBase.h>

#include <functional>
#include <map>
@@ -43,7 +40,8 @@ public:
    MouseCursorController(PointerControllerContext& context);
    ~MouseCursorController();

    void move(float deltaX, float deltaY);
    // Move the pointer and return unconsumed delta
    vec2 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
+8 −5
Original line number Diff line number Diff line
@@ -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) {
+2 −2
Original line number Diff line number Diff line
@@ -51,7 +51,7 @@ public:

    ~PointerController() override;

    void move(float deltaX, float deltaY) override;
    vec2 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 {
    vec2 move(float, float) override {
        LOG_ALWAYS_FATAL("Should not be called");
    }
    void setPosition(float, float) override {
+131 −0
Original line number Diff line number Diff line
@@ -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<MockSprite> testPointerSprite(new NiceMock<MockSprite>);
        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<MousePointerControllerTestParam> {};

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,