@@ -1267,14 +1267,9 @@ void InputDispatcher::dispatchOnceInnerLocked(nsecs_t& nextWakeupTime) {
12671267 if (dropReason == DropReason::NOT_DROPPED && isStaleEvent (currentTime, *motionEntry)) {
12681268 // The event is stale. However, only drop stale events if there isn't an ongoing
12691269 // gesture. That would allow us to complete the processing of the current stroke.
1270- const auto touchStateIt =
1271- mTouchStates .mTouchStatesByDisplay .find (motionEntry->displayId );
1272- if (touchStateIt != mTouchStates .mTouchStatesByDisplay .end ()) {
1273- const TouchState& touchState = touchStateIt->second ;
1274- if (!touchState.hasTouchingPointers (motionEntry->deviceId ) &&
1275- !touchState.hasHoveringPointers (motionEntry->deviceId )) {
1276- dropReason = DropReason::STALE;
1277- }
1270+ if (!mTouchStates .hasTouchingOrHoveringPointers (motionEntry->displayId ,
1271+ motionEntry->deviceId )) {
1272+ dropReason = DropReason::STALE;
12781273 }
12791274 }
12801275 if (dropReason == DropReason::NOT_DROPPED && mNextUnblockedEvent ) {
@@ -1716,9 +1711,7 @@ bool InputDispatcher::dispatchDeviceResetLocked(nsecs_t currentTime,
17161711 synthesizeCancelationEventsForAllConnectionsLocked (options);
17171712
17181713 // Remove all active pointers from this device
1719- for (auto & [_, touchState] : mTouchStates .mTouchStatesByDisplay ) {
1720- touchState.removeAllPointersForDevice (entry.deviceId );
1721- }
1714+ mTouchStates .removeAllPointersForDevice (entry.deviceId );
17221715 return true ;
17231716}
17241717
@@ -4581,13 +4574,8 @@ void InputDispatcher::notifyMotion(const NotifyMotionArgs& args) {
45814574 if (!(policyFlags & POLICY_FLAG_PASS_TO_USER)) {
45824575 // Set the flag anyway if we already have an ongoing gesture. That would allow us to
45834576 // complete the processing of the current stroke.
4584- const auto touchStateIt = mTouchStates .mTouchStatesByDisplay .find (args.displayId );
4585- if (touchStateIt != mTouchStates .mTouchStatesByDisplay .end ()) {
4586- const TouchState& touchState = touchStateIt->second ;
4587- if (touchState.hasTouchingPointers (args.deviceId ) ||
4588- touchState.hasHoveringPointers (args.deviceId )) {
4589- policyFlags |= POLICY_FLAG_PASS_TO_USER;
4590- }
4577+ if (mTouchStates .hasTouchingOrHoveringPointers (args.displayId , args.deviceId )) {
4578+ policyFlags |= POLICY_FLAG_PASS_TO_USER;
45914579 }
45924580 }
45934581
@@ -4893,13 +4881,8 @@ InputEventInjectionResult InputDispatcher::injectInputEvent(const InputEvent* ev
48934881 if (!(policyFlags & POLICY_FLAG_PASS_TO_USER)) {
48944882 // Set the flag anyway if we already have an ongoing motion gesture. That
48954883 // would allow us to complete the processing of the current stroke.
4896- const auto touchStateIt = mTouchStates .mTouchStatesByDisplay .find (displayId);
4897- if (touchStateIt != mTouchStates .mTouchStatesByDisplay .end ()) {
4898- const TouchState& touchState = touchStateIt->second ;
4899- if (touchState.hasTouchingPointers (resolvedDeviceId) ||
4900- touchState.hasHoveringPointers (resolvedDeviceId)) {
4901- policyFlags |= POLICY_FLAG_PASS_TO_USER;
4902- }
4884+ if (mTouchStates .hasTouchingOrHoveringPointers (displayId, resolvedDeviceId)) {
4885+ policyFlags |= POLICY_FLAG_PASS_TO_USER;
49034886 }
49044887 }
49054888
@@ -5470,72 +5453,38 @@ void InputDispatcher::setInputWindowsLocked(
54705453 onFocusChangedLocked (*changes, traceContext.getTracker (), removedFocusedWindowHandle);
54715454 }
54725455
5473- if (const auto & it = mTouchStates .mTouchStatesByDisplay .find (displayId);
5474- it != mTouchStates .mTouchStatesByDisplay .end ()) {
5475- TouchState& state = it->second ;
5476- for (size_t i = 0 ; i < state.windows .size ();) {
5477- TouchedWindow& touchedWindow = state.windows [i];
5478- if (mWindowInfos .isWindowPresent (touchedWindow.windowHandle )) {
5479- i++;
5480- continue ;
5481- }
5482- LOG (INFO) << " Touched window was removed: " << touchedWindow.windowHandle ->getName ()
5483- << " in display %" << displayId;
5484- CancelationOptions options (CancelationOptions::Mode::CANCEL_POINTER_EVENTS,
5485- " touched window was removed" , traceContext.getTracker ());
5486- synthesizeCancelationEventsForWindowLocked (touchedWindow.windowHandle , options);
5487- // Since we are about to drop the touch, cancel the events for the wallpaper as
5488- // well.
5489- if (touchedWindow.targetFlags .test (InputTarget::Flags::FOREGROUND) &&
5490- touchedWindow.windowHandle ->getInfo ()->inputConfig .test (
5491- gui::WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER)) {
5492- for (const DeviceId deviceId : touchedWindow.getTouchingDeviceIds ()) {
5493- if (const auto & ww = state.getWallpaperWindow (deviceId); ww != nullptr ) {
5494- options.deviceId = deviceId;
5495- synthesizeCancelationEventsForWindowLocked (ww, options);
5496- }
5497- }
5498- }
5499- state.windows .erase (state.windows .begin () + i);
5500- }
5501-
5502- // If drag window is gone, it would receive a cancel event and broadcast the DRAG_END. We
5503- // could just clear the state here.
5504- if (mDragState && mDragState ->dragWindow ->getInfo ()->displayId == displayId &&
5505- std::find (windowHandles.begin (), windowHandles.end (), mDragState ->dragWindow ) ==
5506- windowHandles.end ()) {
5507- ALOGI (" Drag window went away: %s" , mDragState ->dragWindow ->getName ().c_str ());
5508- sendDropWindowCommandLocked (nullptr , 0 , 0 );
5509- mDragState .reset ();
5456+ CancelationOptions pointerCancellationOptions (CancelationOptions::Mode::CANCEL_POINTER_EVENTS,
5457+ " touched window was removed" ,
5458+ traceContext.getTracker ());
5459+ CancelationOptions hoverCancellationOptions (CancelationOptions::Mode::CANCEL_HOVER_EVENTS,
5460+ " WindowInfo changed" , traceContext.getTracker ());
5461+ const std::list<DispatcherTouchState::CancellationArgs> cancellations =
5462+ mTouchStates .updateFromWindowInfo (displayId, mWindowInfos );
5463+ for (const auto & cancellationArgs : cancellations) {
5464+ switch (cancellationArgs.mode ) {
5465+ case CancelationOptions::Mode::CANCEL_POINTER_EVENTS:
5466+ pointerCancellationOptions.deviceId = cancellationArgs.deviceId ;
5467+ synthesizeCancelationEventsForWindowLocked (cancellationArgs.windowHandle ,
5468+ pointerCancellationOptions);
5469+ break ;
5470+ case CancelationOptions::Mode::CANCEL_HOVER_EVENTS:
5471+ hoverCancellationOptions.deviceId = cancellationArgs.deviceId ;
5472+ synthesizeCancelationEventsForWindowLocked (cancellationArgs.windowHandle ,
5473+ hoverCancellationOptions);
5474+ break ;
5475+ default :
5476+ LOG_ALWAYS_FATAL (" Unexpected cancellation Mode" );
55105477 }
55115478 }
55125479
5513- // Check if the hovering should stop because the window is no longer eligible to receive it
5514- // (for example, if the touchable region changed)
5515- if (const auto & it = mTouchStates .mTouchStatesByDisplay .find (displayId);
5516- it != mTouchStates .mTouchStatesByDisplay .end ()) {
5517- TouchState& state = it->second ;
5518- for (TouchedWindow& touchedWindow : state.windows ) {
5519- std::vector<DeviceId> erasedDevices = touchedWindow.eraseHoveringPointersIf (
5520- [this , displayId, &touchedWindow](const PointerProperties& properties, float x,
5521- float y) REQUIRES (mLock ) {
5522- const bool isStylus = properties.toolType == ToolType::STYLUS;
5523- const ui::Transform displayTransform =
5524- mWindowInfos .getDisplayTransform (displayId);
5525- const bool stillAcceptsTouch =
5526- windowAcceptsTouchAt (*touchedWindow.windowHandle ->getInfo (),
5527- displayId, x, y, isStylus, displayTransform);
5528- return !stillAcceptsTouch;
5529- });
5530-
5531- for (DeviceId deviceId : erasedDevices) {
5532- CancelationOptions options (CancelationOptions::Mode::CANCEL_HOVER_EVENTS,
5533- " WindowInfo changed" ,
5534- traceContext.getTracker ());
5535- options.deviceId = deviceId;
5536- synthesizeCancelationEventsForWindowLocked (touchedWindow.windowHandle , options);
5537- }
5538- }
5480+ // If drag window is gone, it would receive a cancel event and broadcast the DRAG_END. We
5481+ // could just clear the state here.
5482+ if (mDragState && mDragState ->dragWindow ->getInfo ()->displayId == displayId &&
5483+ std::find (windowHandles.begin (), windowHandles.end (), mDragState ->dragWindow ) ==
5484+ windowHandles.end ()) {
5485+ ALOGI (" Drag window went away: %s" , mDragState ->dragWindow ->getName ().c_str ());
5486+ sendDropWindowCommandLocked (nullptr , 0 , 0 );
5487+ mDragState .reset ();
55395488 }
55405489
55415490 // Release information for windows that are no longer present.
@@ -5552,6 +5501,76 @@ void InputDispatcher::setInputWindowsLocked(
55525501 }
55535502}
55545503
5504+ std::list<InputDispatcher::DispatcherTouchState::CancellationArgs>
5505+ InputDispatcher::DispatcherTouchState::updateFromWindowInfo (
5506+ ui::LogicalDisplayId displayId, const DispatcherWindowInfo& windowInfos) {
5507+ std::list<CancellationArgs> cancellations;
5508+ if (const auto & it = mTouchStatesByDisplay .find (displayId); it != mTouchStatesByDisplay .end ()) {
5509+ TouchState& state = it->second ;
5510+ cancellations = eraseRemovedWindowsFromWindowInfo (state, displayId, windowInfos);
5511+ cancellations.splice (cancellations.end (),
5512+ updateHoveringStateFromWindowInfo (state, displayId, windowInfos));
5513+ }
5514+ return cancellations;
5515+ }
5516+
5517+ std::list<InputDispatcher::DispatcherTouchState::CancellationArgs>
5518+ InputDispatcher::DispatcherTouchState::eraseRemovedWindowsFromWindowInfo (
5519+ TouchState& state, ui::LogicalDisplayId displayId,
5520+ const DispatcherWindowInfo& windowInfos) {
5521+ std::list<CancellationArgs> cancellations;
5522+ for (auto it = state.windows .begin (); it != state.windows .end ();) {
5523+ TouchedWindow& touchedWindow = *it;
5524+ if (windowInfos.isWindowPresent (touchedWindow.windowHandle )) {
5525+ it++;
5526+ continue ;
5527+ }
5528+ LOG (INFO) << " Touched window was removed: " << touchedWindow.windowHandle ->getName ()
5529+ << " in display %" << displayId;
5530+ cancellations.emplace_back (touchedWindow.windowHandle ,
5531+ CancelationOptions::Mode::CANCEL_POINTER_EVENTS, std::nullopt );
5532+ // Since we are about to drop the touch, cancel the events for the wallpaper as well.
5533+ if (touchedWindow.targetFlags .test (InputTarget::Flags::FOREGROUND) &&
5534+ touchedWindow.windowHandle ->getInfo ()->inputConfig .test (
5535+ gui::WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER)) {
5536+ for (const DeviceId deviceId : touchedWindow.getTouchingDeviceIds ()) {
5537+ if (const auto & ww = state.getWallpaperWindow (deviceId); ww != nullptr ) {
5538+ cancellations.emplace_back (ww, CancelationOptions::Mode::CANCEL_POINTER_EVENTS,
5539+ deviceId);
5540+ }
5541+ }
5542+ }
5543+ it = state.windows .erase (it);
5544+ }
5545+ return cancellations;
5546+ }
5547+
5548+ std::list<InputDispatcher::DispatcherTouchState::CancellationArgs>
5549+ InputDispatcher::DispatcherTouchState::updateHoveringStateFromWindowInfo (
5550+ TouchState& state, ui::LogicalDisplayId displayId,
5551+ const DispatcherWindowInfo& windowInfos) {
5552+ std::list<CancellationArgs> cancellations;
5553+ // Check if the hovering should stop because the window is no longer eligible to receive it
5554+ // (for example, if the touchable region changed)
5555+ ui::Transform displayTransform = windowInfos.getDisplayTransform (displayId);
5556+ for (TouchedWindow& touchedWindow : state.windows ) {
5557+ std::vector<DeviceId> erasedDevices = touchedWindow.eraseHoveringPointersIf (
5558+ [&](const PointerProperties& properties, float x, float y) {
5559+ const bool isStylus = properties.toolType == ToolType::STYLUS;
5560+ const bool stillAcceptsTouch =
5561+ windowAcceptsTouchAt (*touchedWindow.windowHandle ->getInfo (), displayId,
5562+ x, y, isStylus, displayTransform);
5563+ return !stillAcceptsTouch;
5564+ });
5565+
5566+ for (DeviceId deviceId : erasedDevices) {
5567+ cancellations.emplace_back (touchedWindow.windowHandle ,
5568+ CancelationOptions::Mode::CANCEL_HOVER_EVENTS, deviceId);
5569+ }
5570+ }
5571+ return cancellations;
5572+ }
5573+
55555574void InputDispatcher::setFocusedApplication (
55565575 ui::LogicalDisplayId displayId,
55575576 const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle) {
@@ -5978,7 +5997,7 @@ void InputDispatcher::resetAndDropEverythingLocked(const char* reason) {
59785997 resetNoFocusedWindowTimeoutLocked ();
59795998
59805999 mAnrTracker .clear ();
5981- mTouchStates .mTouchStatesByDisplay . clear ();
6000+ mTouchStates .clear ();
59826001}
59836002
59846003void InputDispatcher::logDispatchStateLocked () const {
@@ -6036,15 +6055,7 @@ void InputDispatcher::dumpDispatchStateLocked(std::string& dump) const {
60366055 dump += mFocusResolver .dump ();
60376056 dump += dumpPointerCaptureStateLocked ();
60386057
6039- if (!mTouchStates .mTouchStatesByDisplay .empty ()) {
6040- dump += StringPrintf (INDENT " TouchStatesByDisplay:\n " );
6041- for (const auto & [displayId, state] : mTouchStates .mTouchStatesByDisplay ) {
6042- std::string touchStateDump = addLinePrefix (state.dump (), INDENT2);
6043- dump += INDENT2 + displayId.toString () + " : " + touchStateDump;
6044- }
6045- } else {
6046- dump += INDENT " TouchStates: <no displays touched>\n " ;
6047- }
6058+ dump += addLinePrefix (mTouchStates .dump (), INDENT);
60486059
60496060 if (mDragState ) {
60506061 dump += StringPrintf (INDENT " DragState:\n " );
@@ -7093,7 +7104,7 @@ void InputDispatcher::cancelCurrentTouch() {
70937104 " cancel current touch" , traceContext.getTracker ());
70947105 synthesizeCancelationEventsForAllConnectionsLocked (options);
70957106
7096- mTouchStates .mTouchStatesByDisplay . clear ();
7107+ mTouchStates .clear ();
70977108 }
70987109 // Wake up poll loop since there might be work to do.
70997110 mLooper ->wake ();
@@ -7228,18 +7239,7 @@ bool InputDispatcher::isPointerInWindow(const sp<android::IBinder>& token,
72287239 ui::LogicalDisplayId displayId, DeviceId deviceId,
72297240 int32_t pointerId) {
72307241 std::scoped_lock _l (mLock );
7231- auto touchStateIt = mTouchStates .mTouchStatesByDisplay .find (displayId);
7232- if (touchStateIt == mTouchStates .mTouchStatesByDisplay .end ()) {
7233- return false ;
7234- }
7235- for (const TouchedWindow& window : touchStateIt->second .windows ) {
7236- if (window.windowHandle ->getToken () == token &&
7237- (window.hasTouchingPointer (deviceId, pointerId) ||
7238- window.hasHoveringPointer (deviceId, pointerId))) {
7239- return true ;
7240- }
7241- }
7242- return false ;
7242+ return mTouchStates .isPointerInWindow (token, displayId, deviceId, pointerId);
72437243}
72447244
72457245void InputDispatcher::setInputMethodConnectionIsActive (bool isActive) {
@@ -7403,4 +7403,56 @@ ftl::Flags<InputTarget::Flags> InputDispatcher::DispatcherTouchState::getTargetF
74037403 return targetFlags;
74047404}
74057405
7406+ bool InputDispatcher::DispatcherTouchState::hasTouchingOrHoveringPointers (
7407+ ui::LogicalDisplayId displayId, int32_t deviceId) const {
7408+ const auto touchStateIt = mTouchStatesByDisplay .find (displayId);
7409+ if (touchStateIt == mTouchStatesByDisplay .end ()) {
7410+ return false ;
7411+ }
7412+ return touchStateIt->second .hasTouchingPointers (deviceId) ||
7413+ touchStateIt->second .hasHoveringPointers (deviceId);
7414+ }
7415+
7416+ bool InputDispatcher::DispatcherTouchState::isPointerInWindow (const sp<android::IBinder>& token,
7417+ ui::LogicalDisplayId displayId,
7418+ android::DeviceId deviceId,
7419+ int32_t pointerId) const {
7420+ const auto touchStateIt = mTouchStatesByDisplay .find (displayId);
7421+ if (touchStateIt == mTouchStatesByDisplay .end ()) {
7422+ return false ;
7423+ }
7424+ for (const TouchedWindow& window : touchStateIt->second .windows ) {
7425+ if (window.windowHandle ->getToken () == token &&
7426+ (window.hasTouchingPointer (deviceId, pointerId) ||
7427+ window.hasHoveringPointer (deviceId, pointerId))) {
7428+ return true ;
7429+ }
7430+ }
7431+ return false ;
7432+ }
7433+
7434+ std::string InputDispatcher::DispatcherTouchState::dump () const {
7435+ std::string dump;
7436+ if (!mTouchStatesByDisplay .empty ()) {
7437+ dump += StringPrintf (" TouchStatesByDisplay:\n " );
7438+ for (const auto & [displayId, state] : mTouchStatesByDisplay ) {
7439+ std::string touchStateDump = addLinePrefix (state.dump (), INDENT);
7440+ dump += INDENT + displayId.toString () + " : " + touchStateDump;
7441+ }
7442+ } else {
7443+ dump += " TouchStates: <no displays touched>\n " ;
7444+ }
7445+ return dump;
7446+ }
7447+
7448+ void InputDispatcher::DispatcherTouchState::removeAllPointersForDevice (android::DeviceId deviceId) {
7449+ for (auto & [_, touchState] : mTouchStatesByDisplay ) {
7450+ touchState.removeAllPointersForDevice (deviceId);
7451+ }
7452+ }
7453+
7454+ void InputDispatcher::DispatcherTouchState::clear () {
7455+ mTouchStatesByDisplay .clear ();
7456+ }
7457+
74067458} // namespace android::inputdispatcher
0 commit comments