@@ -165,6 +165,8 @@ constexpr int LOGTAG_INPUT_INTERACTION = 62000;
165165constexpr int LOGTAG_INPUT_FOCUS = 62001 ;
166166constexpr int LOGTAG_INPUT_CANCEL = 62003 ;
167167
168+ static const bool USE_TOPOLOGY = com::android::input::flags::connected_displays_cursor();
169+
168170const ui::Transform kIdentityTransform ;
169171
170172inline nsecs_t now () {
@@ -919,6 +921,13 @@ std::string dumpWindowForTouchOcclusion(const WindowInfo& info, bool isTouchedWi
919921 binderToString (info.applicationInfo .token ).c_str ());
920922}
921923
924+ bool isMouseOrTouchpad (uint32_t sources) {
925+ // Check if this is a mouse or touchpad, but not a drawing tablet.
926+ return isFromSource (sources, AINPUT_SOURCE_MOUSE_RELATIVE) ||
927+ (isFromSource (sources, AINPUT_SOURCE_MOUSE) &&
928+ !isFromSource (sources, AINPUT_SOURCE_STYLUS));
929+ }
930+
922931} // namespace
923932
924933// --- InputDispatcher ---
@@ -2387,12 +2396,11 @@ InputDispatcher::DispatcherTouchState::findTouchedWindowTargets(
23872396 const int32_t maskedAction = MotionEvent::getActionMasked (action);
23882397
23892398 // Copy current touch state into tempTouchState.
2390- // This state will be used to update mTouchStatesByDisplay at the end of this function.
2399+ // This state will be used to update saved touch state at the end of this function.
23912400 // If no state for the specified display exists, then our initial state will be empty.
2392- const TouchState* oldState = nullptr ;
2401+ const TouchState* oldState = getTouchStateForMotionEntry (entry) ;
23932402 TouchState tempTouchState;
2394- if (const auto it = mTouchStatesByDisplay .find (displayId); it != mTouchStatesByDisplay .end ()) {
2395- oldState = &(it->second );
2403+ if (oldState != nullptr ) {
23962404 tempTouchState = *oldState;
23972405 }
23982406
@@ -2779,16 +2787,12 @@ InputDispatcher::DispatcherTouchState::findTouchedWindowTargets(
27792787 if (maskedAction != AMOTION_EVENT_ACTION_SCROLL) {
27802788 if (displayId >= ui::LogicalDisplayId::DEFAULT) {
27812789 tempTouchState.clearWindowsWithoutPointers ();
2782- mTouchStatesByDisplay [displayId] = tempTouchState;
2790+ saveTouchStateForMotionEntry (entry, std::move ( tempTouchState)) ;
27832791 } else {
2784- mTouchStatesByDisplay . erase (displayId );
2792+ eraseTouchStateForMotionEntry (entry );
27852793 }
27862794 }
27872795
2788- if (tempTouchState.windows .empty ()) {
2789- mTouchStatesByDisplay .erase (displayId);
2790- }
2791-
27922796 return targets;
27932797}
27942798
@@ -5439,12 +5443,13 @@ std::list<InputDispatcher::DispatcherTouchState::CancellationArgs>
54395443InputDispatcher::DispatcherTouchState::updateFromWindowInfo (
54405444 ui::LogicalDisplayId displayId, const DispatcherWindowInfo& windowInfos) {
54415445 std::list<CancellationArgs> cancellations;
5442- if ( const auto & it = mTouchStatesByDisplay . find (displayId); it != mTouchStatesByDisplay . end () ) {
5443- TouchState& state = it-> second ;
5444- cancellations = eraseRemovedWindowsFromWindowInfo (state, displayId, windowInfos);
5446+ forTouchAndCursorStatesOnDisplay (displayId, [&](TouchState& state ) {
5447+ cancellations. splice (cancellations. end (),
5448+ eraseRemovedWindowsFromWindowInfo (state, displayId, windowInfos) );
54455449 cancellations.splice (cancellations.end (),
54465450 updateHoveringStateFromWindowInfo (state, displayId, windowInfos));
5447- }
5451+ return false ;
5452+ });
54485453 return cancellations;
54495454}
54505455
@@ -5866,26 +5871,25 @@ InputDispatcher::DispatcherTouchState::transferTouchGesture(const sp<android::IB
58665871 */
58675872sp<WindowInfoHandle> InputDispatcher::DispatcherTouchState::findTouchedForegroundWindow (
58685873 ui::LogicalDisplayId displayId) const {
5869- const auto stateIt = mTouchStatesByDisplay .find (displayId);
5870- if (stateIt == mTouchStatesByDisplay .end ()) {
5871- ALOGI (" No touch state on display %s" , displayId.toString ().c_str ());
5872- return nullptr ;
5873- }
5874-
5875- const TouchState& state = stateIt->second ;
58765874 sp<WindowInfoHandle> touchedForegroundWindow;
5877- // If multiple foreground windows are touched, return nullptr
5878- for (const TouchedWindow& window : state.windows ) {
5879- if (window.targetFlags .test (InputTarget::Flags::FOREGROUND)) {
5880- if (touchedForegroundWindow != nullptr ) {
5881- ALOGI (" Two or more foreground windows: %s and %s" ,
5882- touchedForegroundWindow->getName ().c_str (),
5883- window.windowHandle ->getName ().c_str ());
5884- return nullptr ;
5875+ forTouchAndCursorStatesOnDisplay (displayId, [&](const TouchState& state) {
5876+ // If multiple foreground windows are touched, return nullptr
5877+ for (const TouchedWindow& window : state.windows ) {
5878+ if (window.targetFlags .test (InputTarget::Flags::FOREGROUND)) {
5879+ if (touchedForegroundWindow != nullptr ) {
5880+ ALOGI (" Two or more foreground windows: %s and %s" ,
5881+ touchedForegroundWindow->getName ().c_str (),
5882+ window.windowHandle ->getName ().c_str ());
5883+ touchedForegroundWindow = nullptr ;
5884+ return true ;
5885+ }
5886+ touchedForegroundWindow = window.windowHandle ;
58855887 }
5886- touchedForegroundWindow = window.windowHandle ;
58875888 }
5888- }
5889+ return false ;
5890+ });
5891+ ALOGI_IF (touchedForegroundWindow == nullptr ,
5892+ " No touch state or no touched foreground window on display %d" , displayId.val ());
58895893 return touchedForegroundWindow;
58905894}
58915895
@@ -7366,101 +7370,209 @@ ftl::Flags<InputTarget::Flags> InputDispatcher::DispatcherTouchState::getTargetF
73667370
73677371bool InputDispatcher::DispatcherTouchState::hasTouchingOrHoveringPointers (
73687372 ui::LogicalDisplayId displayId, int32_t deviceId) const {
7369- const auto touchStateIt = mTouchStatesByDisplay .find (displayId);
7370- if (touchStateIt == mTouchStatesByDisplay .end ()) {
7371- return false ;
7372- }
7373- return touchStateIt->second .hasTouchingPointers (deviceId) ||
7374- touchStateIt->second .hasHoveringPointers (deviceId);
7373+ bool hasTouchingOrHoveringPointers = false ;
7374+ forTouchAndCursorStatesOnDisplay (displayId, [&](const TouchState& state) {
7375+ hasTouchingOrHoveringPointers =
7376+ state.hasTouchingPointers (deviceId) || state.hasHoveringPointers (deviceId);
7377+ return hasTouchingOrHoveringPointers;
7378+ });
7379+ return hasTouchingOrHoveringPointers;
73757380}
73767381
73777382bool InputDispatcher::DispatcherTouchState::isPointerInWindow (const sp<android::IBinder>& token,
73787383 ui::LogicalDisplayId displayId,
73797384 android::DeviceId deviceId,
73807385 int32_t pointerId) const {
7381- const auto touchStateIt = mTouchStatesByDisplay . find (displayId) ;
7382- if (touchStateIt == mTouchStatesByDisplay . end () ) {
7383- return false ;
7384- }
7385- for ( const TouchedWindow& window : touchStateIt-> second . windows ) {
7386- if ( window.windowHandle -> getToken () == token &&
7387- (window. hasTouchingPointer (deviceId, pointerId) ||
7388- window. hasHoveringPointer (deviceId, pointerId))) {
7389- return true ;
7386+ bool isPointerInWindow = false ;
7387+ forTouchAndCursorStatesOnDisplay (displayId, [&]( const TouchState& state ) {
7388+ for ( const TouchedWindow& window : state. windows ) {
7389+ if (window. windowHandle -> getToken () == token &&
7390+ (window. hasTouchingPointer (deviceId, pointerId) ||
7391+ window.hasHoveringPointer (deviceId, pointerId))) {
7392+ isPointerInWindow = true ;
7393+ return true ;
7394+ }
73907395 }
7391- }
7392- return false ;
7396+ return false ;
7397+ });
7398+ return isPointerInWindow;
73937399}
73947400
73957401std::tuple<const sp<gui::WindowInfoHandle>&, ui::LogicalDisplayId>
73967402InputDispatcher::DispatcherTouchState::findExistingTouchedWindowHandleAndDisplay (
73977403 const sp<android::IBinder>& token) const {
7398- for (const auto & [displayId, state] : mTouchStatesByDisplay ) {
7404+ std::optional<std::tuple<const sp<gui::WindowInfoHandle>&, ui::LogicalDisplayId>>
7405+ touchedWindowHandleAndDisplay;
7406+ forAllTouchAndCursorStates ([&](ui::LogicalDisplayId displayId, const TouchState& state) {
73997407 for (const TouchedWindow& w : state.windows ) {
74007408 if (w.windowHandle ->getToken () == token) {
7401- return std::make_tuple (std::ref (w.windowHandle ), displayId);
7409+ touchedWindowHandleAndDisplay.emplace (std::ref (w.windowHandle ), displayId);
7410+ return true ;
74027411 }
74037412 }
7404- }
7405- LOG_ALWAYS_FATAL (" %s : Touch state is out of sync: No touched window for token" , __func__);
7413+ return false ;
7414+ });
7415+ LOG_ALWAYS_FATAL_IF (!touchedWindowHandleAndDisplay.has_value (),
7416+ " %s : Touch state is out of sync: No touched window for token" , __func__);
7417+ return touchedWindowHandleAndDisplay.value ();
74067418}
74077419
74087420void InputDispatcher::DispatcherTouchState::forAllTouchedWindows (
74097421 std::function<void (const sp<gui::WindowInfoHandle>&)> f) const {
7410- for ( const auto & [_, state] : mTouchStatesByDisplay ) {
7422+ forAllTouchAndCursorStates ([&](ui::LogicalDisplayId displayId, const TouchState& state ) {
74117423 for (const TouchedWindow& window : state.windows ) {
74127424 f (window.windowHandle );
74137425 }
7414- }
7426+ return false ;
7427+ });
74157428}
74167429
74177430void InputDispatcher::DispatcherTouchState::forAllTouchedWindowsOnDisplay (
74187431 ui::LogicalDisplayId displayId,
74197432 std::function<void (const sp<gui::WindowInfoHandle>&)> f) const {
7420- const auto touchStateIt = mTouchStatesByDisplay .find (displayId);
7421- if (touchStateIt == mTouchStatesByDisplay .end ()) {
7422- return ;
7423- }
7424- for (const TouchedWindow& window : touchStateIt->second .windows ) {
7425- f (window.windowHandle );
7426- }
7433+ forTouchAndCursorStatesOnDisplay (displayId, [&](const TouchState& state) {
7434+ for (const TouchedWindow& window : state.windows ) {
7435+ f (window.windowHandle );
7436+ }
7437+ return false ;
7438+ });
74277439}
74287440
74297441std::string InputDispatcher::DispatcherTouchState::dump () const {
74307442 std::string dump;
7431- if (!mTouchStatesByDisplay .empty ()) {
7432- dump += StringPrintf (" TouchStatesByDisplay:\n " );
7443+ if (mTouchStatesByDisplay .empty ()) {
7444+ dump += " TouchStatesByDisplay: <no displays touched>\n " ;
7445+ } else {
7446+ dump += " TouchStatesByDisplay:\n " ;
74337447 for (const auto & [displayId, state] : mTouchStatesByDisplay ) {
74347448 std::string touchStateDump = addLinePrefix (state.dump (), INDENT);
74357449 dump += INDENT + displayId.toString () + " : " + touchStateDump;
74367450 }
7451+ }
7452+ if (mCursorStateByDisplay .empty ()) {
7453+ dump += " CursorStatesByDisplay: <no displays touched by cursor>\n " ;
74377454 } else {
7438- dump += " TouchStates: <no displays touched>\n " ;
7455+ dump += " CursorStatesByDisplay:\n " ;
7456+ for (const auto & [displayId, state] : mCursorStateByDisplay ) {
7457+ std::string touchStateDump = addLinePrefix (state.dump (), INDENT);
7458+ dump += INDENT + displayId.toString () + " : " + touchStateDump;
7459+ }
74397460 }
74407461 return dump;
74417462}
74427463
74437464void InputDispatcher::DispatcherTouchState::removeAllPointersForDevice (android::DeviceId deviceId) {
7444- for (auto & [_, touchState] : mTouchStatesByDisplay ) {
7445- touchState.removeAllPointersForDevice (deviceId);
7446- }
7465+ forAllTouchAndCursorStates ([&](ui::LogicalDisplayId displayId, TouchState& state) {
7466+ state.removeAllPointersForDevice (deviceId);
7467+ return false ;
7468+ });
74477469}
74487470
74497471void InputDispatcher::DispatcherTouchState::clear () {
74507472 mTouchStatesByDisplay .clear ();
7473+ mCursorStateByDisplay .clear ();
7474+ }
7475+
7476+ void InputDispatcher::DispatcherTouchState::saveTouchStateForMotionEntry (
7477+ const android::inputdispatcher::MotionEntry& entry,
7478+ android::inputdispatcher::TouchState&& touchState) {
7479+ if (touchState.windows .empty ()) {
7480+ eraseTouchStateForMotionEntry (entry);
7481+ return ;
7482+ }
7483+
7484+ if (USE_TOPOLOGY && isMouseOrTouchpad (entry.source )) {
7485+ mCursorStateByDisplay [entry.displayId ] = std::move (touchState);
7486+ } else {
7487+ mTouchStatesByDisplay [entry.displayId ] = std::move (touchState);
7488+ }
7489+ }
7490+
7491+ void InputDispatcher::DispatcherTouchState::eraseTouchStateForMotionEntry (
7492+ const android::inputdispatcher::MotionEntry& entry) {
7493+ if (USE_TOPOLOGY && isMouseOrTouchpad (entry.source )) {
7494+ mCursorStateByDisplay .erase (entry.displayId );
7495+ } else {
7496+ mTouchStatesByDisplay .erase (entry.displayId );
7497+ }
7498+ }
7499+
7500+ const TouchState* InputDispatcher::DispatcherTouchState::getTouchStateForMotionEntry (
7501+ const android::inputdispatcher::MotionEntry& entry) const {
7502+ if (USE_TOPOLOGY && isMouseOrTouchpad (entry.source )) {
7503+ auto touchStateIt = mCursorStateByDisplay .find (entry.displayId );
7504+ if (touchStateIt != mCursorStateByDisplay .end ()) {
7505+ return &touchStateIt->second ;
7506+ }
7507+ } else {
7508+ auto touchStateIt = mTouchStatesByDisplay .find (entry.displayId );
7509+ if (touchStateIt != mTouchStatesByDisplay .end ()) {
7510+ return &touchStateIt->second ;
7511+ }
7512+ }
7513+ return nullptr ;
7514+ }
7515+
7516+ void InputDispatcher::DispatcherTouchState::forTouchAndCursorStatesOnDisplay (
7517+ ui::LogicalDisplayId displayId, std::function<bool (const TouchState&)> f) const {
7518+ const auto touchStateIt = mTouchStatesByDisplay .find (displayId);
7519+ if (touchStateIt != mTouchStatesByDisplay .end () && f (touchStateIt->second )) {
7520+ return ;
7521+ }
7522+
7523+ // TODO(b/383092013): This is currently not accounting for the "topology group" concept.
7524+ // Proper implementation requires looking tghrough all the displays in the topology group.
7525+ const auto cursorStateIt = mCursorStateByDisplay .find (displayId);
7526+ if (cursorStateIt != mCursorStateByDisplay .end ()) {
7527+ f (cursorStateIt->second );
7528+ }
7529+ }
7530+
7531+ void InputDispatcher::DispatcherTouchState::forTouchAndCursorStatesOnDisplay (
7532+ ui::LogicalDisplayId displayId, std::function<bool (TouchState&)> f) {
7533+ const_cast <const DispatcherTouchState&>(*this )
7534+ .forTouchAndCursorStatesOnDisplay (displayId, [&](const TouchState& state) {
7535+ return f (const_cast <TouchState&>(state));
7536+ });
7537+ }
7538+
7539+ void InputDispatcher::DispatcherTouchState::forAllTouchAndCursorStates (
7540+ std::function<bool (ui::LogicalDisplayId, const TouchState&)> f) const {
7541+ for (auto & [displayId, state] : mTouchStatesByDisplay ) {
7542+ if (f (displayId, state)) {
7543+ return ;
7544+ }
7545+ }
7546+ for (auto & [displayId, state] : mCursorStateByDisplay ) {
7547+ if (f (displayId, state)) {
7548+ return ;
7549+ }
7550+ }
7551+ }
7552+
7553+ void InputDispatcher::DispatcherTouchState::forAllTouchAndCursorStates (
7554+ std::function<bool (ui::LogicalDisplayId, TouchState&)> f) {
7555+ const_cast <const DispatcherTouchState&>(*this ).forAllTouchAndCursorStates (
7556+ [&](ui::LogicalDisplayId displayId, const TouchState& constState) {
7557+ return f (displayId, const_cast <TouchState&>(constState));
7558+ });
74517559}
74527560
74537561std::optional<std::tuple<TouchState&, TouchedWindow&, ui::LogicalDisplayId>>
74547562InputDispatcher::DispatcherTouchState::findTouchStateWindowAndDisplay (
74557563 const sp<android::IBinder>& token) {
7456- for (auto & [displayId, state] : mTouchStatesByDisplay ) {
7564+ std::optional<std::tuple<TouchState&, TouchedWindow&, ui::LogicalDisplayId>>
7565+ touchStateWindowAndDisplay;
7566+ forAllTouchAndCursorStates ([&](ui::LogicalDisplayId displayId, TouchState& state) {
74577567 for (TouchedWindow& w : state.windows ) {
74587568 if (w.windowHandle ->getToken () == token) {
7459- return std::make_tuple (std::ref (state), std::ref (w), displayId);
7569+ touchStateWindowAndDisplay.emplace (std::ref (state), std::ref (w), displayId);
7570+ return true ;
74607571 }
74617572 }
7462- }
7463- return std::nullopt ;
7573+ return false ;
7574+ });
7575+ return touchStateWindowAndDisplay;
74647576}
74657577
74667578bool InputDispatcher::DispatcherTouchState::isStylusActiveInDisplay (
0 commit comments