Skip to content

Commit f282c31

Browse files
author
Arpit Singh
committed
[4/n CD Cursor] Use Pointer's display transform for motion events
We assume window's display id always matches pointer's display which is no longer true. This can lead to motion events being incorrectly transformed. In this CL we update raw transform to use pointer's display instead to ensure raw coordinates are always in pointer's display coordinate space. Test: atest inputflinger_tests Bug: 362719483 Flag: com.android.input.flags.connected_displays_cursor Change-Id: If450ae1697bfac852b18c46a983ee75183f4c940
1 parent 7a6bfc5 commit f282c31

3 files changed

Lines changed: 69 additions & 43 deletions

File tree

services/inputflinger/dispatcher/InputDispatcher.cpp

Lines changed: 49 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1491,13 +1491,11 @@ std::vector<InputTarget> InputDispatcher::DispatcherTouchState::findOutsideTarge
14911491
if (info.inputConfig.test(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH)) {
14921492
std::bitset<MAX_POINTER_ID + 1> pointerIds;
14931493
pointerIds.set(pointerId);
1494-
DispatcherTouchState::addPointerWindowTarget(windowHandle,
1495-
InputTarget::DispatchMode::OUTSIDE,
1496-
ftl::Flags<InputTarget::Flags>(),
1497-
pointerIds,
1498-
/*firstDownTimeInTarget=*/std::nullopt,
1499-
connections, windowInfos, dump,
1500-
outsideTargets);
1494+
addPointerWindowTarget(windowHandle, InputTarget::DispatchMode::OUTSIDE,
1495+
ftl::Flags<InputTarget::Flags>(), pointerIds,
1496+
/*firstDownTimeInTarget=*/std::nullopt,
1497+
/*pointerDisplayId=*/std::nullopt, connections, windowInfos,
1498+
dump, outsideTargets);
15011499
}
15021500
}
15031501
return outsideTargets;
@@ -2612,12 +2610,12 @@ InputDispatcher::DispatcherTouchState::findTouchedWindowTargets(
26122610

26132611
const TouchedWindow& touchedWindow =
26142612
tempTouchState.getTouchedWindow(oldTouchedWindowHandle);
2615-
DispatcherTouchState::
2616-
addPointerWindowTarget(oldTouchedWindowHandle,
2617-
InputTarget::DispatchMode::SLIPPERY_EXIT,
2618-
ftl::Flags<InputTarget::Flags>(), pointerIds,
2619-
touchedWindow.getDownTimeInTarget(entry.deviceId),
2620-
connections, windowInfos, dump, targets);
2613+
addPointerWindowTarget(oldTouchedWindowHandle,
2614+
InputTarget::DispatchMode::SLIPPERY_EXIT,
2615+
ftl::Flags<InputTarget::Flags>(), pointerIds,
2616+
touchedWindow.getDownTimeInTarget(entry.deviceId),
2617+
/*pointerDisplayId=*/std::nullopt, connections, windowInfos,
2618+
dump, targets);
26212619

26222620
// Make a slippery entrance into the new window.
26232621

@@ -2666,12 +2664,11 @@ InputDispatcher::DispatcherTouchState::findTouchedWindowTargets(
26662664
std::bitset<MAX_POINTER_ID + 1> pointerIds;
26672665
pointerIds.set(entry.pointerProperties[0].id);
26682666
for (const TouchedWindow& touchedWindow : hoveringWindows) {
2669-
DispatcherTouchState::addPointerWindowTarget(touchedWindow.windowHandle,
2670-
touchedWindow.dispatchMode,
2671-
touchedWindow.targetFlags, pointerIds,
2672-
touchedWindow.getDownTimeInTarget(
2673-
entry.deviceId),
2674-
connections, windowInfos, dump, targets);
2667+
addPointerWindowTarget(touchedWindow.windowHandle, touchedWindow.dispatchMode,
2668+
touchedWindow.targetFlags, pointerIds,
2669+
touchedWindow.getDownTimeInTarget(entry.deviceId),
2670+
/*pointerDisplayId=*/std::nullopt, connections, windowInfos,
2671+
dump, targets);
26752672
}
26762673
}
26772674

@@ -2724,13 +2721,11 @@ InputDispatcher::DispatcherTouchState::findTouchedWindowTargets(
27242721
if (touchingPointers.empty()) {
27252722
continue;
27262723
}
2727-
DispatcherTouchState::addPointerWindowTarget(touchedWindow.windowHandle,
2728-
touchedWindow.dispatchMode,
2729-
touchedWindow.targetFlags,
2730-
getPointerIds(touchingPointers),
2731-
touchedWindow.getDownTimeInTarget(
2732-
entry.deviceId),
2733-
connections, windowInfos, dump, targets);
2724+
addPointerWindowTarget(touchedWindow.windowHandle, touchedWindow.dispatchMode,
2725+
touchedWindow.targetFlags, getPointerIds(touchingPointers),
2726+
touchedWindow.getDownTimeInTarget(entry.deviceId),
2727+
/*pointerDisplayId=*/displayId, connections, windowInfos, dump,
2728+
targets);
27342729
}
27352730

27362731
// During targeted injection, only allow owned targets to receive events
@@ -2933,8 +2928,9 @@ void InputDispatcher::DispatcherTouchState::addPointerWindowTarget(
29332928
const sp<android::gui::WindowInfoHandle>& windowHandle,
29342929
InputTarget::DispatchMode dispatchMode, ftl::Flags<InputTarget::Flags> targetFlags,
29352930
std::bitset<MAX_POINTER_ID + 1> pointerIds, std::optional<nsecs_t> firstDownTimeInTarget,
2936-
const ConnectionManager& connections, const DispatcherWindowInfo& windowInfos,
2937-
std::function<void()> dump, std::vector<InputTarget>& inputTargets) {
2931+
std::optional<ui::LogicalDisplayId> pointerDisplayId, const ConnectionManager& connections,
2932+
const DispatcherWindowInfo& windowInfos, std::function<void()> dump,
2933+
std::vector<InputTarget>& inputTargets) {
29382934
if (pointerIds.none()) {
29392935
for (const auto& target : inputTargets) {
29402936
LOG(INFO) << "Target: " << target;
@@ -2969,7 +2965,8 @@ void InputDispatcher::DispatcherTouchState::addPointerWindowTarget(
29692965
}
29702966
inputTargets.push_back(
29712967
createInputTarget(connection, windowHandle, dispatchMode, targetFlags,
2972-
windowInfos.getRawTransform(*windowHandle->getInfo()),
2968+
windowInfos.getRawTransform(*windowHandle->getInfo(),
2969+
pointerDisplayId),
29732970
firstDownTimeInTarget));
29742971
it = inputTargets.end() - 1;
29752972
}
@@ -4172,8 +4169,9 @@ void InputDispatcher::synthesizeCancelationEventsForConnectionLocked(
41724169
DispatcherTouchState::
41734170
addPointerWindowTarget(window, InputTarget::DispatchMode::AS_IS,
41744171
ftl::Flags<InputTarget::Flags>(), pointerIds,
4175-
motionEntry.downTime, mConnectionManager,
4176-
mWindowInfos,
4172+
motionEntry.downTime,
4173+
/*pointerDisplayId=*/std::nullopt,
4174+
mConnectionManager, mWindowInfos,
41774175
std::bind_front(&InputDispatcher::
41784176
logDispatchStateLocked,
41794177
this),
@@ -4259,6 +4257,7 @@ void InputDispatcher::synthesizePointerDownEventsForConnectionLocked(
42594257
DispatcherTouchState::
42604258
addPointerWindowTarget(windowHandle, InputTarget::DispatchMode::AS_IS,
42614259
targetFlags, pointerIds, motionEntry.downTime,
4260+
/*pointerDisplayId=*/std::nullopt,
42624261
mConnectionManager, mWindowInfos,
42634262
std::bind_front(&InputDispatcher::
42644263
logDispatchStateLocked,
@@ -5171,13 +5170,24 @@ ui::Transform InputDispatcher::DispatcherWindowInfo::getDisplayTransform(
51715170
}
51725171

51735172
ui::Transform InputDispatcher::DispatcherWindowInfo::getRawTransform(
5174-
const android::gui::WindowInfo& windowInfo) const {
5173+
const android::gui::WindowInfo& windowInfo,
5174+
std::optional<ui::LogicalDisplayId> pointerDisplayId) const {
5175+
// TODO(b/383092013): Handle TOPOLOGY_AWARE window flag.
5176+
// For now, we assume all windows are topology-aware and can handle cross-display streams.
5177+
if (com::android::input::flags::connected_displays_cursor() && pointerDisplayId.has_value() &&
5178+
*pointerDisplayId != windowInfo.displayId) {
5179+
// Sending pointer to a different display than the window. This is a
5180+
// cross-display drag gesture, so always use the new display's transform.
5181+
return getDisplayTransform(*pointerDisplayId);
5182+
}
51755183
// If the window has a cloneLayerStackTransform, always use it as the transform for the "getRaw"
5176-
// APIs. If not, fall back to using the DisplayInfo transform of the window's display.
5177-
return (input_flags::use_cloned_screen_coordinates_as_raw() &&
5178-
windowInfo.cloneLayerStackTransform)
5179-
? *windowInfo.cloneLayerStackTransform
5180-
: getDisplayTransform(windowInfo.displayId);
5184+
// APIs. If not, fall back to using the DisplayInfo transform of the window's display
5185+
bool useClonedScreenCoordinates = (input_flags::use_cloned_screen_coordinates_as_raw() &&
5186+
windowInfo.cloneLayerStackTransform);
5187+
if (useClonedScreenCoordinates) {
5188+
return *windowInfo.cloneLayerStackTransform;
5189+
}
5190+
return getDisplayTransform(windowInfo.displayId);
51815191
}
51825192

51835193
ui::LogicalDisplayId InputDispatcher::DispatcherWindowInfo::getPrimaryDisplayId(
@@ -7100,7 +7110,8 @@ void InputDispatcher::DispatcherTouchState::slipWallpaperTouch(
71007110
oldTouchedWindow.targetFlags,
71017111
getPointerIds(pointers),
71027112
oldTouchedWindow.getDownTimeInTarget(deviceId),
7103-
connections, windowInfos, dump, targets);
7113+
/*pointerDisplayId=*/std::nullopt, connections,
7114+
windowInfos, dump, targets);
71047115
state.removeTouchingPointerFromWindow(deviceId, pointerProperties.id, oldWallpaper);
71057116
}
71067117

services/inputflinger/dispatcher/InputDispatcher.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -307,8 +307,11 @@ class InputDispatcher : public android::InputDispatcherInterface {
307307
// Get the transform for display, returns Identity-transform if display is missing.
308308
ui::Transform getDisplayTransform(ui::LogicalDisplayId displayId) const;
309309

310-
// Get the raw transform to use for motion events going to the given window.
311-
ui::Transform getRawTransform(const android::gui::WindowInfo&) const;
310+
// Get the raw transform to use for motion events going to the given window. Optionally a
311+
// pointer displayId may be supplied if pointer is on a different display from the window.
312+
ui::Transform getRawTransform(
313+
const android::gui::WindowInfo& windowInfo,
314+
std::optional<ui::LogicalDisplayId> pointerDisplayId = std::nullopt) const;
312315

313316
// Lookup for WindowInfoHandle from token and optionally a display-id. In cases where
314317
// display-id is not provided lookup is done for all displays.
@@ -379,6 +382,7 @@ class InputDispatcher : public android::InputDispatcherInterface {
379382
ftl::Flags<InputTarget::Flags> targetFlags,
380383
std::bitset<MAX_POINTER_ID + 1> pointerIds,
381384
std::optional<nsecs_t> firstDownTimeInTarget,
385+
std::optional<ui::LogicalDisplayId> pointerDisplayId,
382386
const ConnectionManager& connections,
383387
const DispatcherWindowInfo& windowInfos,
384388
std::function<void()> dump,

services/inputflinger/tests/InputDispatcher_test.cpp

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15207,7 +15207,17 @@ class InputDispatcherConnectedDisplayTest : public InputDispatcherTest {
1520715207
"Window", DISPLAY_ID);
1520815208
mWindow->setFrame({0, 0, 100, 100});
1520915209

15210-
mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
15210+
gui::DisplayInfo displayInfo1;
15211+
displayInfo1.displayId = DISPLAY_ID;
15212+
15213+
ui::Transform transform(ui::Transform::ROT_270, /*logicalDisplayWidth=*/500,
15214+
/*logicalDisplayHeight=*/500);
15215+
gui::DisplayInfo displayInfo2;
15216+
displayInfo2.displayId = SECOND_DISPLAY_ID;
15217+
displayInfo2.transform = transform;
15218+
15219+
mDispatcher->onWindowInfosChanged(
15220+
{{*mWindow->getInfo()}, {displayInfo1, displayInfo2}, 0, 0});
1521115221
}
1521215222
};
1521315223

@@ -15250,8 +15260,9 @@ TEST_F(InputDispatcherConnectedDisplayTest, MultiDisplayMouseGesture) {
1525015260
.buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
1525115261
.pointer(PointerBuilder(0, ToolType::MOUSE).x(70).y(70))
1525215262
.build());
15263+
// events should be delivered with the second displayId and in corrosponding coordinate space
1525315264
mWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
15254-
WithDisplayId(SECOND_DISPLAY_ID), WithRawCoords(70, 70)));
15265+
WithDisplayId(SECOND_DISPLAY_ID), WithRawCoords(70, 430)));
1525515266

1525615267
// pointer-up
1525715268
mDispatcher->notifyMotion(
@@ -15262,7 +15273,7 @@ TEST_F(InputDispatcherConnectedDisplayTest, MultiDisplayMouseGesture) {
1526215273
.pointer(PointerBuilder(0, ToolType::MOUSE).x(70).y(70))
1526315274
.build());
1526415275
mWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
15265-
WithDisplayId(SECOND_DISPLAY_ID), WithRawCoords(70, 70)));
15276+
WithDisplayId(SECOND_DISPLAY_ID), WithRawCoords(70, 430)));
1526615277

1526715278
mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
1526815279
.displayId(SECOND_DISPLAY_ID)

0 commit comments

Comments
 (0)