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

Commit 05702787 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Fix PointerMotionFilter coordinates when a display is rotated" into main

parents 81e10b77 e033119b
Loading
Loading
Loading
Loading
+12 −7
Original line number Diff line number Diff line
@@ -298,9 +298,7 @@ void PointerChoreographer::processPointerDeviceMotionEventLocked(NotifyMotionArg
                                                                 PointerControllerInterface& pc) {
    const float deltaX = newArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X);
    const float deltaY = newArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y);
    vec2 filteredDelta =
            filterPointerMotionForAccessibilityLocked(pc.getPosition(), vec2{deltaX, deltaY},
                                                      newArgs.displayId);
    const vec2 filteredDelta = filterPointerMotionForAccessibilityLocked(pc, vec2{deltaX, deltaY});
    vec2 unconsumedDelta = pc.move(filteredDelta.x, filteredDelta.y);
    if (InputFlags::connectedDisplaysCursorEnabled() &&
        (std::abs(unconsumedDelta.x) > 0 || std::abs(unconsumedDelta.y) > 0)) {
@@ -1067,18 +1065,25 @@ PointerChoreographer::findDestinationDisplayLocked(const ui::LogicalDisplayId so
}

vec2 PointerChoreographer::filterPointerMotionForAccessibilityLocked(
        const vec2& current, const vec2& delta, const ui::LogicalDisplayId& displayId) {
        const PointerControllerInterface& pc, const vec2& delta) {
    if (!mPointerMotionFilterEnabled) {
        return delta;
    }
    std::optional<vec2> filterResult =
            mPolicy.filterPointerMotionForAccessibility(current, delta, displayId);

    // PointerController.getPosition and mouse delta are both in physical display coordinates.
    // PointerMotionFilter in Java expects coordinates in logical display coordinates.
    const auto& displayTransform = pc.getDisplayTransform();
    const vec2 current = displayTransform.transform(pc.getPosition());
    const vec2 deltaInDisplay = transformWithoutTranslation(displayTransform, delta);
    const ui::LogicalDisplayId displayId = pc.getDisplayId();
    const std::optional<vec2> filterResult =
            mPolicy.filterPointerMotionForAccessibility(current, deltaInDisplay, displayId);
    if (!filterResult.has_value()) {
        // Disable filter when there's any error.
        mPointerMotionFilterEnabled = false;
        return delta;
    }
    return *filterResult;
    return transformWithoutTranslation(displayTransform.inverse(), *filterResult);
}

// --- PointerChoreographer::PointerChoreographerDisplayInfoListener ---
+2 −3
Original line number Diff line number Diff line
@@ -182,9 +182,8 @@ private:
                                 const DisplayTopologyPosition sourceBoundary,
                                 int32_t sourceCursorOffsetPx) const REQUIRES(getLock());

    vec2 filterPointerMotionForAccessibilityLocked(const vec2& current, const vec2& delta,
                                                   const ui::LogicalDisplayId& displayId)
            REQUIRES(getLock());
    vec2 filterPointerMotionForAccessibilityLocked(const PointerControllerInterface& pc,
                                                   const vec2& delta) REQUIRES(getLock());

    /* Topology is initialized with default-constructed value, which is an empty topology. Till we
     * receive setDisplayTopology call.
+5 −1
Original line number Diff line number Diff line
@@ -36,6 +36,10 @@ const std::map<ui::LogicalDisplayId, std::vector<int32_t>>& FakePointerControlle
    return mSpotsByDisplay;
}

void FakePointerController::setTransform(ui::Transform transform) {
    mTransform = transform;
}

void FakePointerController::setPosition(float x, float y) {
    if (!mEnabled) return;

@@ -196,7 +200,7 @@ void FakePointerController::clearSpots() {
}

ui::Transform FakePointerController::getDisplayTransform() const {
    return ui::Transform();
    return mTransform;
}

} // namespace android
+2 −0
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@ public:
    void setBounds(float minX, float minY, float maxX, float maxY);
    void clearBounds();
    const std::map<ui::LogicalDisplayId, std::vector<int32_t>>& getSpots();
    void setTransform(ui::Transform transform);

    void setPosition(float x, float y) override;
    vec2 getPosition() const override;
@@ -81,6 +82,7 @@ private:
    bool mIsPointerShown{false};
    std::optional<PointerIconStyle> mIconStyle;
    std::optional<PointerIconStyle> mCustomIconStyle;
    ui::Transform mTransform{};

    std::map<ui::LogicalDisplayId, std::vector<int32_t>> mSpotsByDisplay;
    std::unordered_set<ui::LogicalDisplayId> mDisplaysToSkipScreenshot;
+52 −20
Original line number Diff line number Diff line
@@ -76,14 +76,21 @@ static InputDeviceInfo generateTestDeviceInfo(int32_t deviceId, uint32_t source,
    return info;
}

DisplayViewport createViewport(ui::LogicalDisplayId displayId, int32_t width = DISPLAY_WIDTH,
                               int32_t height = DISPLAY_HEIGHT,
                               ui::Rotation orientation = ui::ROTATION_0) {
    DisplayViewport viewport;
    viewport.displayId = displayId;
    viewport.logicalRight = width;
    viewport.logicalBottom = height;
    viewport.orientation = orientation;
    return viewport;
}

static std::vector<DisplayViewport> createViewports(std::vector<ui::LogicalDisplayId> displayIds) {
    std::vector<DisplayViewport> viewports;
    for (auto displayId : displayIds) {
        DisplayViewport viewport;
        viewport.displayId = displayId;
        viewport.logicalRight = DISPLAY_WIDTH;
        viewport.logicalBottom = DISPLAY_HEIGHT;
        viewports.push_back(viewport);
        viewports.push_back(createViewport(displayId));
    }
    return viewports;
}
@@ -1907,6 +1914,44 @@ TEST_F(PointerChoreographerTest, A11yPointerMotionFilterTouchpad) {
                                                    WithRelativeMotion(10, 20)));
}

TEST_F(PointerChoreographerTest, A11yPointerMotionFilterApplyTransform) {
    mChoreographer.setDisplayViewports(
            {createViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_90)});
    setDefaultMouseDisplayId(DISPLAY_ID);
    mChoreographer.notifyInputDevicesChanged(
            {/*id=*/0,
             {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE,
                                     ui::LogicalDisplayId::INVALID)}});
    auto pc = assertPointerControllerCreated(ControllerType::MOUSE);
    ASSERT_EQ(DISPLAY_ID, pc->getDisplayId());

    pc->setTransform(ui::Transform(ui::Transform::toRotationFlags(ui::ROTATION_90), DISPLAY_HEIGHT,
                                   DISPLAY_WIDTH));
    pc->setPosition(200, 700); // (100, 200) in the logical display space.
    mChoreographer.setAccessibilityPointerMotionFilterEnabled(true);

    // Pointer moves (10, 20) in the physical space, which is (-20, 10) in the logical space.
    EXPECT_CALL(mMockPolicy,
                filterPointerMotionForAccessibility(testing::Eq(vec2{100, 200}),
                                                    testing::Eq(vec2{-20.f, 10.f}),
                                                    testing::Eq(DISPLAY_ID)))
            .Times(1)
            .WillOnce(testing::Return(vec2{-12, 6}));

    mChoreographer.notifyMotion(
            MotionArgsBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
                    .pointer(MOUSE_POINTER)
                    .deviceId(DEVICE_ID)
                    .displayId(ui::LogicalDisplayId::INVALID)
                    .build());

    // Cursor position is decided by filtered delta, but pointer coord's relative values are kept.
    pc->assertPosition(206, 712);
    mTestListener.assertNotifyMotionWasCalled(AllOf(WithCoords(206, 712), WithDisplayId(DISPLAY_ID),
                                                    WithCursorPosition(206, 712),
                                                    WithRelativeMotion(10, 20)));
}

TEST_F(PointerChoreographerTest, A11yPointerMotionFilterNotFilterTouch) {
    mChoreographer.notifyInputDevicesChanged(
            {/*id=*/0, {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID)}});
@@ -2744,18 +2789,7 @@ TEST_P(PointerVisibilityAndTouchpadTapStateOnKeyPressTestFixture, TestMetaKeyCom
    metaKeyCombinationDoesNotHidePointer(*pc, AKEYCODE_A, AKEYCODE_META_RIGHT);
}

class PointerChoreographerDisplayTopologyTests : public PointerChoreographerTest {
protected:
    DisplayViewport createViewport(ui::LogicalDisplayId displayId, int32_t width, int32_t height,
                                   ui::Rotation orientation) {
        DisplayViewport viewport;
        viewport.displayId = displayId;
        viewport.logicalRight = width;
        viewport.logicalBottom = height;
        viewport.orientation = orientation;
        return viewport;
    }
};
using PointerChoreographerDisplayTopologyTests = PointerChoreographerTest;

using PointerChoreographerDisplayTopologyCursorTestFixtureParam =
        std::tuple<std::string_view /*name*/, int32_t /*source device*/,
@@ -2976,9 +3010,7 @@ protected:
    static constexpr int32_t DISPLAY_HEIGHT = 100;

    DisplayViewport createViewport(ui::LogicalDisplayId displayId) {
        return PointerChoreographerDisplayTopologyTests::createViewport(displayId, DISPLAY_WIDTH,
                                                                        DISPLAY_HEIGHT,
                                                                        ui::ROTATION_0);
        return ::android::createViewport(displayId, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0);
    }

    void setDisplayTopologyWithDisplays(