Skip to content

Commit d02eebc

Browse files
Treehugger RobotAndroid (Google) Code Review
authored andcommitted
Merge "InputDispatcher: Provide a way to transfer the entire gesture" into main
2 parents a6e2d76 + 93b2749 commit d02eebc

File tree

9 files changed

+227
-26
lines changed

9 files changed

+227
-26
lines changed

libs/input/input_flags.aconfig

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,16 @@ flag {
112112
bug: "330752824"
113113
}
114114

115+
flag {
116+
name: "allow_transfer_of_entire_gesture"
117+
namespace: "input"
118+
description: "When calling 'transferTouchGesture', the entire gesture (including new POINTER_DOWN events from the same device) will be automatically transferred to the destination window"
119+
bug: "397979572"
120+
metadata {
121+
purpose: PURPOSE_BUGFIX
122+
}
123+
}
124+
115125
flag {
116126
name: "enable_keyboard_classifier"
117127
namespace: "input"

services/inputflinger/dispatcher/InputDispatcher.cpp

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2510,6 +2510,24 @@ InputDispatcher::DispatcherTouchState::findTouchedWindowTargets(
25102510
return injectionError(InputEventInjectionResult::TARGET_MISMATCH);
25112511
}
25122512

2513+
if (newTouchedWindowHandle != nullptr &&
2514+
maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN) {
2515+
// Check if this should be redirected to another window, in case this window previously
2516+
// called 'transferTouch' for this gesture.
2517+
const auto it =
2518+
std::find_if(tempTouchState.windows.begin(), tempTouchState.windows.end(),
2519+
[&](const TouchedWindow& touchedWindow) {
2520+
return touchedWindow.forwardingWindowToken ==
2521+
newTouchedWindowHandle->getToken() &&
2522+
touchedWindow.hasTouchingPointers(entry.deviceId);
2523+
});
2524+
if (it != tempTouchState.windows.end()) {
2525+
LOG(INFO) << "Forwarding pointer from " << newTouchedWindowHandle->getName()
2526+
<< " to " << it->windowHandle->getName();
2527+
newTouchedWindowHandle = it->windowHandle;
2528+
}
2529+
}
2530+
25132531
std::vector<sp<WindowInfoHandle>> newTouchedWindows =
25142532
findTouchedSpyWindowsAt(displayId, x, y, isStylus, entry.deviceId, mWindowInfos);
25152533
if (newTouchedWindowHandle != nullptr) {
@@ -2550,7 +2568,8 @@ InputDispatcher::DispatcherTouchState::findTouchedWindowTargets(
25502568
isDownOrPointerDown
25512569
? std::make_optional(
25522570
entry.eventTime)
2553-
: std::nullopt);
2571+
: std::nullopt,
2572+
/*forwardingWindowToken=*/nullptr);
25542573
if (!addResult.ok()) {
25552574
LOG(ERROR) << "Error while processing " << entry << " for "
25562575
<< windowHandle->getName();
@@ -2577,7 +2596,8 @@ InputDispatcher::DispatcherTouchState::findTouchedWindowTargets(
25772596
tempTouchState.addOrUpdateWindow(wallpaper,
25782597
InputTarget::DispatchMode::AS_IS,
25792598
wallpaperFlags, entry.deviceId, {pointer},
2580-
entry.eventTime);
2599+
entry.eventTime,
2600+
/*forwardingWindowToken=*/nullptr);
25812601
}
25822602
}
25832603
}
@@ -2676,7 +2696,8 @@ InputDispatcher::DispatcherTouchState::findTouchedWindowTargets(
26762696
tempTouchState.addOrUpdateWindow(newTouchedWindowHandle,
26772697
InputTarget::DispatchMode::SLIPPERY_ENTER,
26782698
targetFlags, entry.deviceId, {pointer},
2679-
entry.eventTime);
2699+
entry.eventTime,
2700+
/*forwardingWindowToken=*/nullptr);
26802701

26812702
// Check if the wallpaper window should deliver the corresponding event.
26822703
slipWallpaperTouch(targetFlags, oldTouchedWindowHandle, newTouchedWindowHandle,
@@ -5833,7 +5854,7 @@ void InputDispatcher::setMaximumObscuringOpacityForTouch(float opacity) {
58335854
}
58345855

58355856
bool InputDispatcher::transferTouchGesture(const sp<IBinder>& fromToken, const sp<IBinder>& toToken,
5836-
bool isDragDrop) {
5857+
bool isDragDrop, bool transferEntireGesture) {
58375858
if (fromToken == toToken) {
58385859
LOG_IF(INFO, DEBUG_FOCUS) << "Trivial transfer to same window.";
58395860
return true;
@@ -5847,7 +5868,7 @@ bool InputDispatcher::transferTouchGesture(const sp<IBinder>& fromToken, const s
58475868
"transferring touch from this window to another window",
58485869
traceContext.getTracker());
58495870

5850-
auto result = mTouchStates.transferTouchGesture(fromToken, toToken);
5871+
auto result = mTouchStates.transferTouchGesture(fromToken, toToken, transferEntireGesture);
58515872
if (!result.has_value()) {
58525873
return false;
58535874
}
@@ -5891,7 +5912,8 @@ std::optional<std::tuple<sp<gui::WindowInfoHandle>, DeviceId, std::vector<Pointe
58915912
std::list<InputDispatcher::DispatcherTouchState::CancellationArgs>,
58925913
std::list<InputDispatcher::DispatcherTouchState::PointerDownArgs>>>
58935914
InputDispatcher::DispatcherTouchState::transferTouchGesture(const sp<android::IBinder>& fromToken,
5894-
const sp<android::IBinder>& toToken) {
5915+
const sp<android::IBinder>& toToken,
5916+
bool transferEntireGesture) {
58955917
// Find the target touch state and touched window by fromToken.
58965918
auto touchStateWindowAndDisplay = findTouchStateWindowAndDisplay(fromToken);
58975919
if (!touchStateWindowAndDisplay.has_value()) {
@@ -5934,8 +5956,12 @@ InputDispatcher::DispatcherTouchState::transferTouchGesture(const sp<android::IB
59345956
}
59355957
// Transferring touch focus using this API should not effect the focused window.
59365958
newTargetFlags |= InputTarget::Flags::NO_FOCUS_CHANGE;
5959+
sp<IBinder> forwardingWindowToken;
5960+
if (transferEntireGesture && com::android::input::flags::allow_transfer_of_entire_gesture()) {
5961+
forwardingWindowToken = fromToken;
5962+
}
59375963
state.addOrUpdateWindow(toWindowHandle, InputTarget::DispatchMode::AS_IS, newTargetFlags,
5938-
deviceId, pointers, downTimeInTarget);
5964+
deviceId, pointers, downTimeInTarget, forwardingWindowToken);
59395965

59405966
// Synthesize cancel for old window and down for new window.
59415967
std::shared_ptr<Connection> fromConnection = mConnectionManager.getConnection(fromToken);
@@ -6017,7 +6043,8 @@ bool InputDispatcher::transferTouchOnDisplay(const sp<IBinder>& destChannelToken
60176043
fromToken = from->getToken();
60186044
} // release lock
60196045

6020-
return transferTouchGesture(fromToken, destChannelToken);
6046+
return transferTouchGesture(fromToken, destChannelToken, /*isDragDrop=*/false,
6047+
/*transferEntireGesture=*/false);
60216048
}
60226049

60236050
void InputDispatcher::resetAndDropEverythingLocked(const char* reason) {
@@ -7195,7 +7222,8 @@ void InputDispatcher::DispatcherTouchState::slipWallpaperTouch(
71957222
state.addOrUpdateWindow(newWallpaper, InputTarget::DispatchMode::SLIPPERY_ENTER,
71967223
InputTarget::Flags::WINDOW_IS_OBSCURED |
71977224
InputTarget::Flags::WINDOW_IS_PARTIALLY_OBSCURED,
7198-
deviceId, pointers, entry.eventTime);
7225+
deviceId, pointers, entry.eventTime,
7226+
/*forwardingWindowToken=*/nullptr);
71997227
}
72007228
}
72017229

@@ -7236,7 +7264,8 @@ InputDispatcher::DispatcherTouchState::transferWallpaperTouch(
72367264
wallpaperFlags |= InputTarget::Flags::WINDOW_IS_OBSCURED |
72377265
InputTarget::Flags::WINDOW_IS_PARTIALLY_OBSCURED;
72387266
state.addOrUpdateWindow(newWallpaper, InputTarget::DispatchMode::AS_IS, wallpaperFlags,
7239-
deviceId, pointers, downTimeInTarget);
7267+
deviceId, pointers, downTimeInTarget,
7268+
/*forwardingWindowToken=*/nullptr);
72407269
std::shared_ptr<Connection> wallpaperConnection =
72417270
mConnectionManager.getConnection(newWallpaper->getToken());
72427271
if (wallpaperConnection != nullptr) {

services/inputflinger/dispatcher/InputDispatcher.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ class InputDispatcher : public android::InputDispatcherInterface {
127127
void setMaximumObscuringOpacityForTouch(float opacity) override;
128128

129129
bool transferTouchGesture(const sp<IBinder>& fromToken, const sp<IBinder>& toToken,
130-
bool isDragDrop = false) override;
130+
bool isDragDrop, bool transferEntireGesture) override;
131131
bool transferTouchOnDisplay(const sp<IBinder>& destChannelToken,
132132
ui::LogicalDisplayId displayId) override;
133133

@@ -440,7 +440,8 @@ class InputDispatcher : public android::InputDispatcherInterface {
440440
std::optional<
441441
std::tuple<sp<gui::WindowInfoHandle>, DeviceId, std::vector<PointerProperties>,
442442
std::list<CancellationArgs>, std::list<PointerDownArgs>>>
443-
transferTouchGesture(const sp<IBinder>& fromToken, const sp<IBinder>& toToken);
443+
transferTouchGesture(const sp<IBinder>& fromToken, const sp<IBinder>& toToken,
444+
bool transferEntireGesture);
444445

445446
base::Result<std::list<CancellationArgs>, status_t> pilferPointers(
446447
const sp<IBinder>& token, const Connection& requestingConnection);

services/inputflinger/dispatcher/TouchState.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ android::base::Result<void> TouchState::addOrUpdateWindow(
7474
const sp<WindowInfoHandle>& windowHandle, InputTarget::DispatchMode dispatchMode,
7575
ftl::Flags<InputTarget::Flags> targetFlags, DeviceId deviceId,
7676
const std::vector<PointerProperties>& touchingPointers,
77-
std::optional<nsecs_t> firstDownTimeInTarget) {
77+
std::optional<nsecs_t> firstDownTimeInTarget, sp<IBinder> forwardingWindowToken) {
7878
if (touchingPointers.empty()) {
7979
LOG(FATAL) << __func__ << "No pointers specified for " << windowHandle->getName();
8080
return android::base::Error();
@@ -88,6 +88,7 @@ android::base::Result<void> TouchState::addOrUpdateWindow(
8888
if (touchedWindow.windowHandle == windowHandle) {
8989
touchedWindow.dispatchMode = dispatchMode;
9090
touchedWindow.targetFlags |= targetFlags;
91+
touchedWindow.forwardingWindowToken = forwardingWindowToken;
9192
// For cases like hover enter/exit or DISPATCH_AS_OUTSIDE a touch window might not have
9293
// downTime set initially. Need to update existing window when a pointer is down for the
9394
// window.
@@ -103,6 +104,7 @@ android::base::Result<void> TouchState::addOrUpdateWindow(
103104
touchedWindow.windowHandle = windowHandle;
104105
touchedWindow.dispatchMode = dispatchMode;
105106
touchedWindow.targetFlags = targetFlags;
107+
touchedWindow.forwardingWindowToken = forwardingWindowToken;
106108
touchedWindow.addTouchingPointers(deviceId, touchingPointers);
107109
if (firstDownTimeInTarget) {
108110
touchedWindow.trySetDownTimeInTarget(deviceId, *firstDownTimeInTarget);

services/inputflinger/dispatcher/TouchState.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ struct TouchState {
4747
const sp<android::gui::WindowInfoHandle>& windowHandle,
4848
InputTarget::DispatchMode dispatchMode, ftl::Flags<InputTarget::Flags> targetFlags,
4949
DeviceId deviceId, const std::vector<PointerProperties>& touchingPointers,
50-
std::optional<nsecs_t> firstDownTimeInTarget);
50+
std::optional<nsecs_t> firstDownTimeInTarget, sp<IBinder> forwardingWindowToken);
5151
void addHoveringPointerToWindow(const sp<android::gui::WindowInfoHandle>& windowHandle,
5252
DeviceId deviceId, const PointerProperties& pointer, float x,
5353
float y);

services/inputflinger/dispatcher/TouchedWindow.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -331,9 +331,9 @@ std::string TouchedWindow::dump() const {
331331
std::string out;
332332
std::string deviceStates =
333333
dumpMap(mDeviceStates, constToString, TouchedWindow::deviceStateToString);
334-
out += StringPrintf("name='%s', targetFlags=%s, mDeviceStates=%s\n",
334+
out += StringPrintf("name='%s', targetFlags=%s, forwardingWindowToken=%p, mDeviceStates=%s\n",
335335
windowHandle->getName().c_str(), targetFlags.string().c_str(),
336-
deviceStates.c_str());
336+
forwardingWindowToken.get(), deviceStates.c_str());
337337
return out;
338338
}
339339

services/inputflinger/dispatcher/TouchedWindow.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@ struct TouchedWindow {
3434
InputTarget::DispatchMode dispatchMode = InputTarget::DispatchMode::AS_IS;
3535
ftl::Flags<InputTarget::Flags> targetFlags;
3636

37+
// If another window has transferred touches to this window, and wants to continue sending the
38+
// rest of the gesture to this window, store the token of the originating (transferred-from)
39+
// window here.
40+
sp<IBinder> forwardingWindowToken;
41+
3742
// Hovering
3843
bool hasHoveringPointers() const;
3944
bool hasHoveringPointers(DeviceId deviceId) const;
@@ -76,7 +81,7 @@ struct TouchedWindow {
7681
};
7782

7883
std::vector<DeviceId> eraseHoveringPointersIf(
79-
std::function<bool(const PointerProperties&, float /*x*/, float /*y*/)> condition);
84+
std::function<bool(const PointerProperties&, float x, float y)> condition);
8085

8186
private:
8287
struct DeviceState {

services/inputflinger/dispatcher/include/InputDispatcherInterface.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ class InputDispatcherInterface : public InputListenerInterface {
148148
* Returns true on success. False if the window did not actually have an active touch gesture.
149149
*/
150150
virtual bool transferTouchGesture(const sp<IBinder>& fromToken, const sp<IBinder>& toToken,
151-
bool isDragDrop) = 0;
151+
bool isDragDrop, bool transferEntireGesture) = 0;
152152

153153
/**
154154
* Transfer a touch gesture to the provided channel, no matter where the current touch is.

0 commit comments

Comments
 (0)