@@ -5836,52 +5836,33 @@ bool InputDispatcher::transferTouchGesture(const sp<IBinder>& fromToken, const s
58365836 { // acquire lock
58375837 std::scoped_lock _l (mLock );
58385838
5839- // Find the target touch state and touched window by fromToken.
5840- auto [state, touchedWindow, displayId] =
5841- findTouchStateWindowAndDisplay (fromToken, mTouchStates .mTouchStatesByDisplay );
5839+ ScopedSyntheticEventTracer traceContext (mTracer );
5840+ CancelationOptions options (CancelationOptions::Mode::CANCEL_POINTER_EVENTS,
5841+ " transferring touch from this window to another window" ,
5842+ traceContext.getTracker ());
58425843
5843- if (state == nullptr || touchedWindow == nullptr ) {
5844- ALOGD (" Touch transfer failed because from window is not being touched." );
5845- return false ;
5846- }
5847- std::set<DeviceId> deviceIds = touchedWindow->getTouchingDeviceIds ();
5848- if (deviceIds.size () != 1 ) {
5849- LOG (INFO) << " Can't transfer touch. Currently touching devices: "
5850- << dumpContainer (deviceIds) << " for window: " << touchedWindow->dump ();
5844+ auto result = mTouchStates .transferTouchGesture (fromToken, toToken, mWindowInfos ,
5845+ mConnectionManager );
5846+ if (!result.has_value ()) {
58515847 return false ;
58525848 }
5853- const DeviceId deviceId = *deviceIds.begin ();
58545849
5855- const sp<WindowInfoHandle> fromWindowHandle = touchedWindow->windowHandle ;
5856- const sp<WindowInfoHandle> toWindowHandle =
5857- mWindowInfos .findWindowHandle (toToken, displayId);
5858- if (!toWindowHandle) {
5859- ALOGW (" Cannot transfer touch because the transfer target window was not found." );
5860- return false ;
5861- }
5850+ const auto [toWindowHandle, deviceId, pointers, cancellations, pointerDowns] =
5851+ result.value ();
58625852
5863- if (DEBUG_FOCUS) {
5864- ALOGD (" %s: fromWindowHandle=%s, toWindowHandle=%s" , __func__,
5865- touchedWindow->windowHandle ->getName ().c_str (),
5866- toWindowHandle->getName ().c_str ());
5853+ for (const auto & cancellationArgs : cancellations) {
5854+ LOG_ALWAYS_FATAL_IF (cancellationArgs.mode !=
5855+ CancelationOptions::Mode::CANCEL_POINTER_EVENTS);
5856+ LOG_ALWAYS_FATAL_IF (cancellationArgs.deviceId .has_value ());
5857+ synthesizeCancelationEventsForWindowLocked (cancellationArgs.windowHandle , options);
58675858 }
58685859
5869- // Erase old window.
5870- ftl::Flags<InputTarget::Flags> oldTargetFlags = touchedWindow->targetFlags ;
5871- std::vector<PointerProperties> pointers = touchedWindow->getTouchingPointers (deviceId);
5872- state->removeWindowByToken (fromToken);
5873-
5874- // Add new window.
5875- nsecs_t downTimeInTarget = now ();
5876- ftl::Flags<InputTarget::Flags> newTargetFlags =
5877- oldTargetFlags & (InputTarget::Flags::SPLIT);
5878- if (canReceiveForegroundTouches (*toWindowHandle->getInfo ())) {
5879- newTargetFlags |= InputTarget::Flags::FOREGROUND;
5860+ for (const auto & pointerDownArgs : pointerDowns) {
5861+ synthesizePointerDownEventsForConnectionLocked (pointerDownArgs.downTimeInTarget ,
5862+ pointerDownArgs.connection ,
5863+ pointerDownArgs.targetFlags ,
5864+ traceContext.getTracker ());
58805865 }
5881- // Transferring touch focus using this API should not effect the focused window.
5882- newTargetFlags |= InputTarget::Flags::NO_FOCUS_CHANGE;
5883- state->addOrUpdateWindow (toWindowHandle, InputTarget::DispatchMode::AS_IS, newTargetFlags,
5884- deviceId, pointers, downTimeInTarget);
58855866
58865867 // Store the dragging window.
58875868 if (isDragDrop) {
@@ -5894,53 +5875,92 @@ bool InputDispatcher::transferTouchGesture(const sp<IBinder>& fromToken, const s
58945875 const size_t id = pointers.begin ()->id ;
58955876 mDragState = std::make_unique<DragState>(toWindowHandle, deviceId, id);
58965877 }
5897-
5898- // Synthesize cancel for old window and down for new window.
5899- ScopedSyntheticEventTracer traceContext (mTracer );
5900- std::shared_ptr<Connection> fromConnection = mConnectionManager .getConnection (fromToken);
5901- std::shared_ptr<Connection> toConnection = mConnectionManager .getConnection (toToken);
5902- if (fromConnection != nullptr && toConnection != nullptr ) {
5903- fromConnection->inputState .mergePointerStateTo (toConnection->inputState );
5904- CancelationOptions options (CancelationOptions::Mode::CANCEL_POINTER_EVENTS,
5905- " transferring touch from this window to another window" ,
5906- traceContext.getTracker ());
5907- synthesizeCancelationEventsForWindowLocked (fromWindowHandle, options, fromConnection);
5908-
5909- // Check if the wallpaper window should deliver the corresponding event.
5910- const auto [cancellations, pointerDowns] =
5911- mTouchStates .transferWallpaperTouch (fromWindowHandle, toWindowHandle, displayId,
5912- deviceId, pointers, oldTargetFlags,
5913- newTargetFlags, mWindowInfos ,
5914- mConnectionManager );
5915- for (const auto & cancellationArgs : cancellations) {
5916- // touch should be cancelled for old wallpaper window
5917- LOG_ALWAYS_FATAL_IF (cancellationArgs.mode !=
5918- CancelationOptions::Mode::CANCEL_POINTER_EVENTS);
5919- synthesizeCancelationEventsForWindowLocked (cancellationArgs.windowHandle , options);
5920- }
5921- for (const auto & pointerDownArgs : pointerDowns) {
5922- // expect pointer down on new the wallpaper window
5923- synthesizePointerDownEventsForConnectionLocked (pointerDownArgs.downTimeInTarget ,
5924- pointerDownArgs.connection ,
5925- pointerDownArgs.targetFlags ,
5926- traceContext.getTracker ());
5927- }
5928-
5929- // Because new window may have a wallpaper window, it will merge input state from it
5930- // parent window, after this the firstNewPointerIdx in input state will be reset, then
5931- // it will cause new move event be thought inconsistent, so we should synthesize the
5932- // down event after it reset.
5933- synthesizePointerDownEventsForConnectionLocked (downTimeInTarget, toConnection,
5934- newTargetFlags,
5935- traceContext.getTracker ());
5936- }
59375878 } // release lock
59385879
59395880 // Wake up poll loop since it may need to make new input dispatching choices.
59405881 mLooper ->wake ();
59415882 return true ;
59425883}
59435884
5885+ std::optional<std::tuple<sp<gui::WindowInfoHandle>, DeviceId, std::vector<PointerProperties>,
5886+ std::list<InputDispatcher::DispatcherTouchState::CancellationArgs>,
5887+ std::list<InputDispatcher::DispatcherTouchState::PointerDownArgs>>>
5888+ InputDispatcher::DispatcherTouchState::transferTouchGesture (const sp<android::IBinder>& fromToken,
5889+ const sp<android::IBinder>& toToken,
5890+ const DispatcherWindowInfo& windowInfos,
5891+ const ConnectionManager& connections) {
5892+ // Find the target touch state and touched window by fromToken.
5893+ auto touchStateWindowAndDisplay = findTouchStateWindowAndDisplay (fromToken);
5894+ if (!touchStateWindowAndDisplay.has_value ()) {
5895+ ALOGD (" Touch transfer failed because from window is not being touched." );
5896+ return std::nullopt ;
5897+ }
5898+
5899+ auto [state, touchedWindow, displayId] = touchStateWindowAndDisplay.value ();
5900+ std::set<DeviceId> deviceIds = touchedWindow.getTouchingDeviceIds ();
5901+ if (deviceIds.size () != 1 ) {
5902+ LOG (INFO) << " Can't transfer touch. Currently touching devices: "
5903+ << dumpContainer (deviceIds) << " for window: " << touchedWindow.dump ();
5904+ return std::nullopt ;
5905+ }
5906+ const DeviceId deviceId = *deviceIds.begin ();
5907+
5908+ const sp<WindowInfoHandle> fromWindowHandle = touchedWindow.windowHandle ;
5909+ const sp<WindowInfoHandle> toWindowHandle = windowInfos.findWindowHandle (toToken, displayId);
5910+ if (!toWindowHandle) {
5911+ ALOGW (" Cannot transfer touch because the transfer target window was not found." );
5912+ return std::nullopt ;
5913+ }
5914+
5915+ if (DEBUG_FOCUS) {
5916+ ALOGD (" %s: fromWindowHandle=%s, toWindowHandle=%s" , __func__,
5917+ fromWindowHandle->getName ().c_str (), toWindowHandle->getName ().c_str ());
5918+ }
5919+
5920+ // Erase old window.
5921+ ftl::Flags<InputTarget::Flags> oldTargetFlags = touchedWindow.targetFlags ;
5922+ std::vector<PointerProperties> pointers = touchedWindow.getTouchingPointers (deviceId);
5923+ state.removeWindowByToken (fromToken);
5924+
5925+ // Add new window.
5926+ nsecs_t downTimeInTarget = now ();
5927+ ftl::Flags<InputTarget::Flags> newTargetFlags = oldTargetFlags & (InputTarget::Flags::SPLIT);
5928+ if (canReceiveForegroundTouches (*toWindowHandle->getInfo ())) {
5929+ newTargetFlags |= InputTarget::Flags::FOREGROUND;
5930+ }
5931+ // Transferring touch focus using this API should not effect the focused window.
5932+ newTargetFlags |= InputTarget::Flags::NO_FOCUS_CHANGE;
5933+ state.addOrUpdateWindow (toWindowHandle, InputTarget::DispatchMode::AS_IS, newTargetFlags,
5934+ deviceId, pointers, downTimeInTarget);
5935+
5936+ // Synthesize cancel for old window and down for new window.
5937+ std::shared_ptr<Connection> fromConnection = connections.getConnection (fromToken);
5938+ std::shared_ptr<Connection> toConnection = connections.getConnection (toToken);
5939+ std::list<CancellationArgs> cancellations;
5940+ std::list<PointerDownArgs> pointerDowns;
5941+ if (fromConnection != nullptr && toConnection != nullptr ) {
5942+ fromConnection->inputState .mergePointerStateTo (toConnection->inputState );
5943+ cancellations.emplace_back (fromWindowHandle,
5944+ CancelationOptions::Mode::CANCEL_POINTER_EVENTS, std::nullopt );
5945+
5946+ // Check if the wallpaper window should deliver the corresponding event.
5947+ auto [wallpaperCancellations, wallpaperPointerDowns] =
5948+ transferWallpaperTouch (fromWindowHandle, toWindowHandle, state, deviceId, pointers,
5949+ oldTargetFlags, newTargetFlags, windowInfos, connections);
5950+
5951+ cancellations.splice (cancellations.end (), wallpaperCancellations);
5952+ pointerDowns.splice (pointerDowns.end (), wallpaperPointerDowns);
5953+
5954+ // Because new window may have a wallpaper window, it will merge input state from it
5955+ // parent window, after this the firstNewPointerIdx in input state will be reset, then
5956+ // it will cause new move event be thought inconsistent, so we should synthesize the
5957+ // down event after it reset.
5958+ pointerDowns.emplace_back (downTimeInTarget, toConnection, newTargetFlags);
5959+ }
5960+
5961+ return std::make_tuple (toWindowHandle, deviceId, pointers, cancellations, pointerDowns);
5962+ }
5963+
59445964/* *
59455965 * Get the touched foreground window on the given display.
59465966 * Return null if there are no windows touched on that display, or if more than one foreground
@@ -7176,13 +7196,11 @@ std::pair<std::list<InputDispatcher::DispatcherTouchState::CancellationArgs>,
71767196 std::list<InputDispatcher::DispatcherTouchState::PointerDownArgs>>
71777197InputDispatcher::DispatcherTouchState::transferWallpaperTouch (
71787198 const sp<gui::WindowInfoHandle> fromWindowHandle,
7179- const sp<gui::WindowInfoHandle> toWindowHandle, ui::LogicalDisplayId displayId ,
7199+ const sp<gui::WindowInfoHandle> toWindowHandle, TouchState& state ,
71807200 android::DeviceId deviceId, const std::vector<PointerProperties>& pointers,
71817201 ftl::Flags<InputTarget::Flags> oldTargetFlags,
71827202 ftl::Flags<InputTarget::Flags> newTargetFlags, const DispatcherWindowInfo& windowInfos,
71837203 const ConnectionManager& connections) {
7184- TouchState& state = getTouchState (displayId);
7185-
71867204 const bool oldHasWallpaper = oldTargetFlags.test (InputTarget::Flags::FOREGROUND) &&
71877205 fromWindowHandle->getInfo ()->inputConfig .test (
71887206 gui::WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER);
@@ -7478,10 +7496,17 @@ void InputDispatcher::DispatcherTouchState::clear() {
74787496 mTouchStatesByDisplay .clear ();
74797497}
74807498
7481- TouchState& InputDispatcher::DispatcherTouchState::getTouchState (ui::LogicalDisplayId displayId) {
7482- auto touchStateIt = mTouchStatesByDisplay .find (displayId);
7483- LOG_ALWAYS_FATAL_IF (touchStateIt == mTouchStatesByDisplay .end ());
7484- return touchStateIt->second ;
7499+ std::optional<std::tuple<TouchState&, TouchedWindow&, ui::LogicalDisplayId>>
7500+ InputDispatcher::DispatcherTouchState::findTouchStateWindowAndDisplay (
7501+ const sp<android::IBinder>& token) {
7502+ for (auto & [displayId, state] : mTouchStatesByDisplay ) {
7503+ for (TouchedWindow& w : state.windows ) {
7504+ if (w.windowHandle ->getToken () == token) {
7505+ return std::make_tuple (std::ref (state), std::ref (w), displayId);
7506+ }
7507+ }
7508+ }
7509+ return std::nullopt ;
74857510}
74867511
74877512} // namespace android::inputdispatcher
0 commit comments