Set appropriate cursor position on viewport transition
This CL updates PointerChoreographer to set position of the cursor on
the destination display when cursor crosses the boundary.
Also updates the logic to lookup destination displays in topology to
account for size and offset of the display.
Test: presubmit and manual
Bug: 367660694
Flag: com.android.input.flags.connected_displays_cursor
Change-Id: I18e3bd925a44d541e34946494e7e1b9db0a2e786
diff --git a/services/inputflinger/PointerChoreographer.cpp b/services/inputflinger/PointerChoreographer.cpp
index 2434d2b..8eb6bdd 100644
--- a/services/inputflinger/PointerChoreographer.cpp
+++ b/services/inputflinger/PointerChoreographer.cpp
@@ -313,30 +313,89 @@
void PointerChoreographer::handleUnconsumedDeltaLocked(PointerControllerInterface& pc,
const FloatPoint& unconsumedDelta) {
+ // Display topology is in rotated coordinate space and Pointer controller returns and expects
+ // values in the un-rotated coordinate space. So we need to transform delta and cursor position
+ // back to the rotated coordinate space to lookup adjacent display in the display topology.
+ const auto& sourceDisplayTransform = pc.getDisplayTransform();
+ const vec2 rotatedUnconsumedDelta =
+ transformWithoutTranslation(sourceDisplayTransform,
+ {unconsumedDelta.x, unconsumedDelta.y});
+ const FloatPoint cursorPosition = pc.getPosition();
+ const vec2 rotatedCursorPosition =
+ sourceDisplayTransform.transform(cursorPosition.x, cursorPosition.y);
+
+ // To find out the boundary that cursor is crossing we are checking delta in x and y direction
+ // respectively. This prioritizes x direction over y.
+ // In practise, majority of cases we only have non-zero values in either x or y coordinates,
+ // except sometimes near the corners.
+ // In these cases this behaviour is not noticeable. We also do not apply unconsumed delta on
+ // the destination display for the same reason.
+ DisplayPosition sourceBoundary;
+ float cursorOffset = 0.0f;
+ if (rotatedUnconsumedDelta.x > 0) {
+ sourceBoundary = DisplayPosition::RIGHT;
+ cursorOffset = rotatedCursorPosition.y;
+ } else if (rotatedUnconsumedDelta.x < 0) {
+ sourceBoundary = DisplayPosition::LEFT;
+ cursorOffset = rotatedCursorPosition.y;
+ } else if (rotatedUnconsumedDelta.y > 0) {
+ sourceBoundary = DisplayPosition::BOTTOM;
+ cursorOffset = rotatedCursorPosition.x;
+ } else {
+ sourceBoundary = DisplayPosition::TOP;
+ cursorOffset = rotatedCursorPosition.x;
+ }
+
const ui::LogicalDisplayId sourceDisplayId = pc.getDisplayId();
- const auto& sourceViewport = *findViewportByIdLocked(sourceDisplayId);
- std::optional<const DisplayViewport*> destination =
- findDestinationDisplayLocked(sourceViewport, unconsumedDelta);
- if (!destination) {
- // no adjacent display
+ std::optional<std::pair<const DisplayViewport*, float /*offset*/>> destination =
+ findDestinationDisplayLocked(sourceDisplayId, sourceBoundary, cursorOffset);
+ if (!destination.has_value()) {
+ // No matching adjacent display
return;
}
- const DisplayViewport* destinationViewport = *destination;
-
- if (mMousePointersByDisplay.find(destinationViewport->displayId) !=
+ const DisplayViewport& destinationViewport = *destination->first;
+ const float destinationOffset = destination->second;
+ if (mMousePointersByDisplay.find(destinationViewport.displayId) !=
mMousePointersByDisplay.end()) {
LOG(FATAL) << "A cursor already exists on destination display"
- << destinationViewport->displayId;
+ << destinationViewport.displayId;
}
- mDefaultMouseDisplayId = destinationViewport->displayId;
+ mDefaultMouseDisplayId = destinationViewport.displayId;
auto pcNode = mMousePointersByDisplay.extract(sourceDisplayId);
- pcNode.key() = destinationViewport->displayId;
+ pcNode.key() = destinationViewport.displayId;
mMousePointersByDisplay.insert(std::move(pcNode));
- // This will place cursor at the center of the target display for now
- // TODO (b/367660694) place the cursor at the appropriate position in destination display
- pc.setDisplayViewport(*destinationViewport);
+ // Before updating the viewport and moving the cursor to appropriate location in the destination
+ // viewport, we need to temporarily hide the cursor. This will prevent it from appearing at the
+ // center of the display in any intermediate frames.
+ pc.fade(PointerControllerInterface::Transition::IMMEDIATE);
+ pc.setDisplayViewport(destinationViewport);
+ vec2 destinationPosition =
+ calculateDestinationPosition(destinationViewport, cursorOffset - destinationOffset,
+ sourceBoundary);
+
+ // Transform position back to un-rotated coordinate space before sending it to controller
+ destinationPosition = pc.getDisplayTransform().inverse().transform(destinationPosition.x,
+ destinationPosition.y);
+ pc.setPosition(destinationPosition.x, destinationPosition.y);
+ pc.unfade(PointerControllerInterface::Transition::IMMEDIATE);
+}
+
+vec2 PointerChoreographer::calculateDestinationPosition(const DisplayViewport& destinationViewport,
+ float pointerOffset,
+ DisplayPosition sourceBoundary) {
+ // destination is opposite of the source boundary
+ switch (sourceBoundary) {
+ case DisplayPosition::RIGHT:
+ return {0, pointerOffset}; // left edge
+ case DisplayPosition::TOP:
+ return {pointerOffset, destinationViewport.logicalBottom}; // bottom edge
+ case DisplayPosition::LEFT:
+ return {destinationViewport.logicalRight, pointerOffset}; // right edge
+ case DisplayPosition::BOTTOM:
+ return {pointerOffset, 0}; // top edge
+ }
}
void PointerChoreographer::processDrawingTabletEventLocked(const android::NotifyMotionArgs& args) {
@@ -951,10 +1010,11 @@
// create a fake topology assuming following order
// default-display (top-edge) -> next-display (right-edge) -> next-display (right-edge) ...
- // ┌─────────┬─────────┐
- // │ next │ next 2 │ ...
- // ├─────────┼─────────┘
- // │ default │
+ // This also adds a 100px offset on corresponding edge for better manual testing
+ // ┌────────┐
+ // │ next ├─────────┐
+ // ┌─└───────┐┤ next 2 │ ...
+ // │ default │└─────────┘
// └─────────┘
mTopology.clear();
@@ -965,13 +1025,15 @@
continue;
}
if (previousDisplay == ui::LogicalDisplayId::DEFAULT) {
- mTopology[previousDisplay].push_back({displayInfo.displayId, DisplayPosition::TOP, 0});
+ mTopology[previousDisplay].push_back(
+ {displayInfo.displayId, DisplayPosition::TOP, 100});
mTopology[displayInfo.displayId].push_back(
- {previousDisplay, DisplayPosition::BOTTOM, 0});
+ {previousDisplay, DisplayPosition::BOTTOM, -100});
} else {
mTopology[previousDisplay].push_back(
- {displayInfo.displayId, DisplayPosition::RIGHT, 0});
- mTopology[displayInfo.displayId].push_back({previousDisplay, DisplayPosition::LEFT, 0});
+ {displayInfo.displayId, DisplayPosition::RIGHT, 100});
+ mTopology[displayInfo.displayId].push_back(
+ {previousDisplay, DisplayPosition::LEFT, -100});
}
previousDisplay = displayInfo.displayId;
}
@@ -982,34 +1044,17 @@
}
}
-std::optional<const DisplayViewport*> PointerChoreographer::findDestinationDisplayLocked(
- const DisplayViewport& sourceViewport, const FloatPoint& unconsumedDelta) const {
- DisplayPosition sourceBoundary;
- if (unconsumedDelta.x > 0) {
- sourceBoundary = DisplayPosition::RIGHT;
- } else if (unconsumedDelta.x < 0) {
- sourceBoundary = DisplayPosition::LEFT;
- } else if (unconsumedDelta.y > 0) {
- sourceBoundary = DisplayPosition::BOTTOM;
- } else {
- sourceBoundary = DisplayPosition::TOP;
- }
-
- // Choreographer works in un-rotate coordinate space so we need to rotate boundary by viewport
- // orientation to find the rotated boundary
- constexpr int MOD = ftl::to_underlying(ui::Rotation::ftl_last) + 1;
- sourceBoundary = static_cast<DisplayPosition>(
- (ftl::to_underlying(sourceBoundary) + ftl::to_underlying(sourceViewport.orientation)) %
- MOD);
-
- const auto& destination = mTopology.find(sourceViewport.displayId);
- if (destination == mTopology.end()) {
+std::optional<std::pair<const DisplayViewport*, float /*offset*/>>
+PointerChoreographer::findDestinationDisplayLocked(const ui::LogicalDisplayId sourceDisplayId,
+ const DisplayPosition sourceBoundary,
+ float cursorOffset) const {
+ const auto& sourceNode = mTopology.find(sourceDisplayId);
+ if (sourceNode == mTopology.end()) {
// Topology is likely out of sync with viewport info, wait for it to be updated
- LOG(WARNING) << "Source display missing from topology " << sourceViewport.displayId;
+ LOG(WARNING) << "Source display missing from topology " << sourceDisplayId;
return std::nullopt;
}
-
- for (const auto& adjacentDisplay : destination->second) {
+ for (const AdjacentDisplay& adjacentDisplay : sourceNode->second) {
if (adjacentDisplay.position != sourceBoundary) {
continue;
}
@@ -1018,11 +1063,18 @@
if (destinationViewport == nullptr) {
// Topology is likely out of sync with viewport info, wait for them to be updated
LOG(WARNING) << "Cannot find viewport for adjacent display "
- << adjacentDisplay.displayId << "of source display "
- << sourceViewport.displayId;
- break;
+ << adjacentDisplay.displayId << "of source display " << sourceDisplayId;
+ continue;
}
- return destinationViewport;
+ // target position must be within target display boundary
+ const int32_t edgeSize =
+ sourceBoundary == DisplayPosition::TOP || sourceBoundary == DisplayPosition::BOTTOM
+ ? (destinationViewport->logicalRight - destinationViewport->logicalLeft)
+ : (destinationViewport->logicalBottom - destinationViewport->logicalTop);
+ if (cursorOffset >= adjacentDisplay.offsetPx &&
+ cursorOffset <= adjacentDisplay.offsetPx + edgeSize) {
+ return std::make_pair(destinationViewport, adjacentDisplay.offsetPx);
+ }
}
return std::nullopt;
}
diff --git a/services/inputflinger/PointerChoreographer.h b/services/inputflinger/PointerChoreographer.h
index a969935..4ca7323 100644
--- a/services/inputflinger/PointerChoreographer.h
+++ b/services/inputflinger/PointerChoreographer.h
@@ -114,11 +114,11 @@
void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs& args) override;
// TODO(b/362719483) remove these when real topology is available
- enum class DisplayPosition : int32_t {
- RIGHT = 0,
- TOP = 1,
- LEFT = 2,
- BOTTOM = 3,
+ enum class DisplayPosition {
+ RIGHT,
+ TOP,
+ LEFT,
+ BOTTOM,
ftl_last = BOTTOM,
};
@@ -177,9 +177,12 @@
void populateFakeDisplayTopologyLocked(const std::vector<gui::DisplayInfo>& displayInfos)
REQUIRES(getLock());
- std::optional<const DisplayViewport*> findDestinationDisplayLocked(
- const DisplayViewport& sourceViewport, const FloatPoint& unconsumedDelta) const
- REQUIRES(getLock());
+ std::optional<std::pair<const DisplayViewport*, float /*offset*/>> findDestinationDisplayLocked(
+ const ui::LogicalDisplayId sourceDisplayId, const DisplayPosition sourceBoundary,
+ float cursorOffset) const REQUIRES(getLock());
+
+ static vec2 calculateDestinationPosition(const DisplayViewport& destinationViewport,
+ float pointerOffset, DisplayPosition sourceBoundary);
std::unordered_map<ui::LogicalDisplayId, std::vector<AdjacentDisplay>> mTopology
GUARDED_BY(getLock());
diff --git a/services/inputflinger/include/PointerControllerInterface.h b/services/inputflinger/include/PointerControllerInterface.h
index 3391f79..abca209 100644
--- a/services/inputflinger/include/PointerControllerInterface.h
+++ b/services/inputflinger/include/PointerControllerInterface.h
@@ -73,7 +73,7 @@
virtual std::string dump() = 0;
/* Move the pointer and return unconsumed delta if the pointer has crossed the current
- * viewport bounds .
+ * viewport bounds.
*
* Return value may be used to move pointer to corresponding adjacent display, if it exists in
* the display-topology */
@@ -149,6 +149,8 @@
/* Resets the flag to skip screenshot of the pointer indicators for all displays. */
virtual void clearSkipScreenshotFlags() = 0;
+
+ virtual ui::Transform getDisplayTransform() const = 0;
};
} // namespace android
diff --git a/services/inputflinger/tests/FakePointerController.cpp b/services/inputflinger/tests/FakePointerController.cpp
index c1606a7..f53e63b 100644
--- a/services/inputflinger/tests/FakePointerController.cpp
+++ b/services/inputflinger/tests/FakePointerController.cpp
@@ -195,4 +195,8 @@
mSpotsByDisplay.clear();
}
+ui::Transform FakePointerController::getDisplayTransform() const {
+ return ui::Transform();
+}
+
} // namespace android
diff --git a/services/inputflinger/tests/FakePointerController.h b/services/inputflinger/tests/FakePointerController.h
index 04adff8..0ee3123 100644
--- a/services/inputflinger/tests/FakePointerController.h
+++ b/services/inputflinger/tests/FakePointerController.h
@@ -48,6 +48,7 @@
void setSkipScreenshotFlagForDisplay(ui::LogicalDisplayId displayId) override;
void clearSkipScreenshotFlags() override;
void fade(Transition) override;
+ ui::Transform getDisplayTransform() const override;
void assertViewportSet(ui::LogicalDisplayId displayId);
void assertViewportNotSet();
diff --git a/services/inputflinger/tests/PointerChoreographer_test.cpp b/services/inputflinger/tests/PointerChoreographer_test.cpp
index f427658..453c156 100644
--- a/services/inputflinger/tests/PointerChoreographer_test.cpp
+++ b/services/inputflinger/tests/PointerChoreographer_test.cpp
@@ -2604,8 +2604,9 @@
using PointerChoreographerDisplayTopologyTestFixtureParam =
std::tuple<std::string_view /*name*/, int32_t /*source device*/,
ControllerType /*PointerController*/, ToolType /*pointer tool type*/,
- FloatPoint /*source position */, FloatPoint /*hover move X/Y */,
- ui::LogicalDisplayId /*destination display*/>;
+ FloatPoint /*source position*/, FloatPoint /*hover move X/Y*/,
+ ui::LogicalDisplayId /*destination display*/,
+ FloatPoint /*destination position*/>;
class PointerChoreographerDisplayTopologyTestFixture
: public PointerChoreographerTest,
@@ -2616,6 +2617,7 @@
static constexpr ui::LogicalDisplayId DISPLAY_RIGHT_ID = ui::LogicalDisplayId{30};
static constexpr ui::LogicalDisplayId DISPLAY_BOTTOM_ID = ui::LogicalDisplayId{40};
static constexpr ui::LogicalDisplayId DISPLAY_LEFT_ID = ui::LogicalDisplayId{50};
+ static constexpr ui::LogicalDisplayId DISPLAY_TOP_RIGHT_CORNER_ID = ui::LogicalDisplayId{60};
PointerChoreographerDisplayTopologyTestFixture() {
com::android::input::flags::connected_displays_cursor(true);
@@ -2623,35 +2625,41 @@
protected:
std::vector<DisplayViewport> mViewports{
- createViewport(DISPLAY_CENTER_ID, /*width*/ 100, /*height*/ 100),
- createViewport(DISPLAY_TOP_ID, /*width*/ 90, /*height*/ 90),
- createViewport(DISPLAY_RIGHT_ID, /*width*/ 90, /*height*/ 90),
- createViewport(DISPLAY_BOTTOM_ID, /*width*/ 90, /*height*/ 90),
- createViewport(DISPLAY_LEFT_ID, /*width*/ 90, /*height*/ 90),
+ createViewport(DISPLAY_CENTER_ID, /*width*/ 100, /*height*/ 100, ui::ROTATION_0),
+ createViewport(DISPLAY_TOP_ID, /*width*/ 90, /*height*/ 90, ui::ROTATION_0),
+ createViewport(DISPLAY_RIGHT_ID, /*width*/ 90, /*height*/ 90, ui::ROTATION_90),
+ createViewport(DISPLAY_BOTTOM_ID, /*width*/ 90, /*height*/ 90, ui::ROTATION_180),
+ createViewport(DISPLAY_LEFT_ID, /*width*/ 90, /*height*/ 90, ui::ROTATION_270),
+ createViewport(DISPLAY_TOP_RIGHT_CORNER_ID, /*width*/ 90, /*height*/ 90,
+ ui::ROTATION_0),
};
std::unordered_map<ui::LogicalDisplayId, std::vector<PointerChoreographer::AdjacentDisplay>>
mTopology{
{DISPLAY_CENTER_ID,
- {{DISPLAY_TOP_ID, PointerChoreographer::DisplayPosition::TOP, 0.0f},
- {DISPLAY_RIGHT_ID, PointerChoreographer::DisplayPosition::RIGHT, 0.0f},
- {DISPLAY_BOTTOM_ID, PointerChoreographer::DisplayPosition::BOTTOM, 0.0f},
- {DISPLAY_LEFT_ID, PointerChoreographer::DisplayPosition::LEFT, 0.0f}}},
+ {{DISPLAY_TOP_ID, PointerChoreographer::DisplayPosition::TOP, 10.0f},
+ {DISPLAY_RIGHT_ID, PointerChoreographer::DisplayPosition::RIGHT, 10.0f},
+ {DISPLAY_BOTTOM_ID, PointerChoreographer::DisplayPosition::BOTTOM, 10.0f},
+ {DISPLAY_LEFT_ID, PointerChoreographer::DisplayPosition::LEFT, 10.0f},
+ {DISPLAY_TOP_RIGHT_CORNER_ID, PointerChoreographer::DisplayPosition::RIGHT,
+ -90.0f}}},
};
private:
- DisplayViewport createViewport(ui::LogicalDisplayId displayId, int32_t width, int32_t height) {
+ 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;
}
};
TEST_P(PointerChoreographerDisplayTopologyTestFixture, PointerChoreographerDisplayTopologyTest) {
const auto& [_, device, pointerControllerType, pointerToolType, initialPosition, hoverMove,
- destinationDisplay] = GetParam();
+ destinationDisplay, destinationPosition] = GetParam();
mChoreographer.setDisplayViewports(mViewports);
mChoreographer.setDefaultMouseDisplayId(
@@ -2681,42 +2689,86 @@
.build());
// Check that the PointerController updated the position and the pointer is shown.
- // TODO(b/362719483) assert pointer controller position here
ASSERT_TRUE(pc->isPointerShown());
ASSERT_EQ(pc->getDisplayId(), destinationDisplay);
+ auto position = pc->getPosition();
+ ASSERT_EQ(position.x, destinationPosition.x);
+ ASSERT_EQ(position.y, destinationPosition.y);
// Check that x-y coordinates, displayId and cursor position are correctly updated.
- // TODO(b/362719483) assert Coords and cursor position here
- mTestListener.assertNotifyMotionWasCalled(WithDisplayId(destinationDisplay));
+ mTestListener.assertNotifyMotionWasCalled(
+ AllOf(WithCoords(destinationPosition.x, destinationPosition.y),
+ WithDisplayId(destinationDisplay),
+ WithCursorPosition(destinationPosition.x, destinationPosition.y)));
}
INSTANTIATE_TEST_SUITE_P(
PointerChoreographerTest, PointerChoreographerDisplayTopologyTestFixture,
testing::Values(
+ // Note: Upon viewport transition cursor will be positioned at the boundary of the
+ // destination, as we drop any unconsumed delta.
std::make_tuple("UnchangedDisplay", AINPUT_SOURCE_MOUSE, ControllerType::MOUSE,
ToolType::MOUSE, FloatPoint(50, 50) /* initial x/y */,
FloatPoint(25, 25) /* delta x/y */,
- PointerChoreographerDisplayTopologyTestFixture::DISPLAY_CENTER_ID),
- std::make_tuple("TransitionToRightDisplay", AINPUT_SOURCE_MOUSE,
+ PointerChoreographerDisplayTopologyTestFixture::DISPLAY_CENTER_ID,
+ FloatPoint(75, 75) /* destination x/y */),
+ std::make_tuple(
+ "TransitionToRightDisplay", AINPUT_SOURCE_MOUSE, ControllerType::MOUSE,
+ ToolType::MOUSE, FloatPoint(50, 50) /* initial x/y */,
+ FloatPoint(100, 25) /* delta x/y */,
+ PointerChoreographerDisplayTopologyTestFixture::DISPLAY_RIGHT_ID,
+ FloatPoint(0, 50 + 25 - 10) /* Left edge: (0, source + delta - offset) */),
+ std::make_tuple(
+ "TransitionToLeftDisplay", AINPUT_SOURCE_MOUSE, ControllerType::MOUSE,
+ ToolType::MOUSE, FloatPoint(50, 50) /* initial x/y */,
+ FloatPoint(-100, 25) /* delta x/y */,
+ PointerChoreographerDisplayTopologyTestFixture::DISPLAY_LEFT_ID,
+ FloatPoint(90,
+ 50 + 25 - 10) /* Right edge: (width, source + delta - offset*/),
+ std::make_tuple(
+ "TransitionToTopDisplay", AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_TOUCHPAD,
+ ControllerType::MOUSE, ToolType::FINGER,
+ FloatPoint(50, 50) /* initial x/y */, FloatPoint(25, -100) /* delta x/y */,
+ PointerChoreographerDisplayTopologyTestFixture::DISPLAY_TOP_ID,
+ FloatPoint(50 + 25 - 10,
+ 90) /* Bottom edge: (source + delta - offset, height) */),
+ std::make_tuple(
+ "TransitionToBottomDisplay", AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_TOUCHPAD,
+ ControllerType::MOUSE, ToolType::FINGER,
+ FloatPoint(50, 50) /* initial x/y */, FloatPoint(25, 100) /* delta x/y */,
+ PointerChoreographerDisplayTopologyTestFixture::DISPLAY_BOTTOM_ID,
+ FloatPoint(50 + 25 - 10, 0) /* Top edge: (source + delta - offset, 0) */),
+ std::make_tuple("NoTransitionAtTopOffset", AINPUT_SOURCE_MOUSE,
ControllerType::MOUSE, ToolType::MOUSE,
- FloatPoint(50, 50) /* initial x/y */,
- FloatPoint(100, 25) /* delta x/y */,
- PointerChoreographerDisplayTopologyTestFixture::DISPLAY_RIGHT_ID),
- std::make_tuple("TransitionToLeftDisplay", AINPUT_SOURCE_MOUSE,
+ FloatPoint(5, 50) /* initial x/y */,
+ FloatPoint(0, -100) /* Move Up */,
+ PointerChoreographerDisplayTopologyTestFixture::DISPLAY_CENTER_ID,
+ FloatPoint(5, 0) /* Top edge */),
+ std::make_tuple("NoTransitionAtRightOffset", AINPUT_SOURCE_MOUSE,
ControllerType::MOUSE, ToolType::MOUSE,
- FloatPoint(50, 50) /* initial x/y */,
- FloatPoint(-100, 25) /* delta x/y */,
- PointerChoreographerDisplayTopologyTestFixture::DISPLAY_LEFT_ID),
- std::make_tuple("TransitionToTopDisplay",
+ FloatPoint(95, 5) /* initial x/y */,
+ FloatPoint(100, 0) /* Move Right */,
+ PointerChoreographerDisplayTopologyTestFixture::DISPLAY_CENTER_ID,
+ FloatPoint(99, 5) /* Top edge */),
+ std::make_tuple("NoTransitionAtBottomOffset",
AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_TOUCHPAD, ControllerType::MOUSE,
- ToolType::FINGER, FloatPoint(50, 50) /* initial x/y */,
- FloatPoint(25, -100) /* delta x/y */,
- PointerChoreographerDisplayTopologyTestFixture::DISPLAY_TOP_ID),
- std::make_tuple("TransitionToBottomDisplay",
+ ToolType::FINGER, FloatPoint(5, 95) /* initial x/y */,
+ FloatPoint(0, 100) /* Move Down */,
+ PointerChoreographerDisplayTopologyTestFixture::DISPLAY_CENTER_ID,
+ FloatPoint(5, 99) /* Bottom edge */),
+ std::make_tuple("NoTransitionAtLeftOffset",
AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_TOUCHPAD, ControllerType::MOUSE,
- ToolType::FINGER, FloatPoint(50, 50) /* initial x/y */,
- FloatPoint(25, 100) /* delta x/y */,
- PointerChoreographerDisplayTopologyTestFixture::DISPLAY_BOTTOM_ID)),
+ ToolType::FINGER, FloatPoint(5, 5) /* initial x/y */,
+ FloatPoint(-100, 0) /* Move Left */,
+ PointerChoreographerDisplayTopologyTestFixture::DISPLAY_CENTER_ID,
+ FloatPoint(0, 5) /* Left edge */),
+ std::make_tuple(
+ "TransitionAtTopRightCorner", AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_TOUCHPAD,
+ ControllerType::MOUSE, ToolType::FINGER,
+ FloatPoint(95, 5) /* initial x/y */,
+ FloatPoint(10, -10) /* Move dignally to top right corner */,
+ PointerChoreographerDisplayTopologyTestFixture::DISPLAY_TOP_RIGHT_CORNER_ID,
+ FloatPoint(0, 90) /* bottom left corner */)),
[](const testing::TestParamInfo<PointerChoreographerDisplayTopologyTestFixtureParam>& p) {
return std::string{std::get<0>(p.param)};
});