From 4b9b1a1de40dd6fb02c6b26f63ee1e4755570bf6 Mon Sep 17 00:00:00 2001 From: Prabir Pradhan Date: Fri, 2 Feb 2024 00:16:17 +0000 Subject: InputDispatcher: Send cancellations from losing focus windows An input channel must have at least one focusable window to gain focus. When focus changes, we send cancellations for all of the non-pointer event streams going to the previously focused window. Send these cancellations to a window instead of directly to the channel so that events are always associated with a window. We track focus by token, and there can be more than one window for a token/input channel. For such cases, we pick the first window (i.e. the top-most window) with the focused token as the target, for convenience. Bug: 210460522 Test: atest inputflinger_tests Change-Id: I63990ccfca1f5ef013f6f08ce6336b4a961c20d6 --- .../inputflinger/dispatcher/InputDispatcher.cpp | 39 +++++++++++++--------- services/inputflinger/dispatcher/InputDispatcher.h | 4 ++- 2 files changed, 26 insertions(+), 17 deletions(-) diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index 9d744f6d58..229d699803 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -5195,6 +5195,7 @@ void InputDispatcher::setInputWindowsLocked( // Copy old handles for release if they are no longer present. const std::vector> oldWindowHandles = getWindowHandlesLocked(displayId); + const sp removedFocusedWindowHandle = getFocusedWindowHandleLocked(displayId); updateWindowHandlesForDisplayLocked(windowInfoHandles, displayId); @@ -5203,7 +5204,7 @@ void InputDispatcher::setInputWindowsLocked( std::optional changes = mFocusResolver.setInputWindows(displayId, windowHandles); if (changes) { - onFocusChangedLocked(*changes); + onFocusChangedLocked(*changes, removedFocusedWindowHandle); } std::unordered_map::iterator stateIt = @@ -5325,14 +5326,16 @@ void InputDispatcher::setFocusedDisplay(int32_t displayId) { sp oldFocusedWindowToken = mFocusResolver.getFocusedWindowToken(mFocusedDisplayId); if (oldFocusedWindowToken != nullptr) { - std::shared_ptr connection = getConnectionLocked(oldFocusedWindowToken); - if (connection != nullptr) { - CancelationOptions - options(CancelationOptions::Mode::CANCEL_NON_POINTER_EVENTS, - "The display which contains this window no longer has focus."); - options.displayId = ADISPLAY_ID_NONE; - synthesizeCancelationEventsForConnectionLocked(connection, options); + const auto windowHandle = + getWindowHandleLocked(oldFocusedWindowToken, mFocusedDisplayId); + if (windowHandle == nullptr) { + LOG(FATAL) << __func__ << ": Previously focused token did not have a window"; } + CancelationOptions + options(CancelationOptions::Mode::CANCEL_NON_POINTER_EVENTS, + "The display which contains this window no longer has focus."); + options.displayId = ADISPLAY_ID_NONE; + synthesizeCancelationEventsForWindowLocked(windowHandle, options); } mFocusedDisplayId = displayId; @@ -6682,15 +6685,19 @@ void InputDispatcher::setFocusedWindow(const FocusRequest& request) { mLooper->wake(); } -void InputDispatcher::onFocusChangedLocked(const FocusResolver::FocusChanges& changes) { +void InputDispatcher::onFocusChangedLocked(const FocusResolver::FocusChanges& changes, + const sp removedFocusedWindowHandle) { if (changes.oldFocus) { - std::shared_ptr focusedConnection = getConnectionLocked(changes.oldFocus); - if (focusedConnection) { - CancelationOptions options(CancelationOptions::Mode::CANCEL_NON_POINTER_EVENTS, - "focus left window"); - synthesizeCancelationEventsForConnectionLocked(focusedConnection, options); - enqueueFocusEventLocked(changes.oldFocus, /*hasFocus=*/false, changes.reason); - } + const auto resolvedWindow = removedFocusedWindowHandle != nullptr + ? removedFocusedWindowHandle + : getWindowHandleLocked(changes.oldFocus, changes.displayId); + if (resolvedWindow == nullptr) { + LOG(FATAL) << __func__ << ": Previously focused token did not have a window"; + } + CancelationOptions options(CancelationOptions::Mode::CANCEL_NON_POINTER_EVENTS, + "focus left window"); + synthesizeCancelationEventsForWindowLocked(resolvedWindow, options); + enqueueFocusEventLocked(changes.oldFocus, /*hasFocus=*/false, changes.reason); } if (changes.newFocus) { resetNoFocusedWindowTimeoutLocked(); diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h index dcd156675e..90a5250fc2 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.h +++ b/services/inputflinger/dispatcher/InputDispatcher.h @@ -653,7 +653,9 @@ private: bool handled, nsecs_t consumeTime) REQUIRES(mLock); void doInterceptKeyBeforeDispatchingCommand(const sp& focusedWindowToken, const KeyEntry& entry) REQUIRES(mLock); - void onFocusChangedLocked(const FocusResolver::FocusChanges& changes) REQUIRES(mLock); + void onFocusChangedLocked(const FocusResolver::FocusChanges& changes, + const sp removedFocusedWindowHandle = nullptr) + REQUIRES(mLock); void sendFocusChangedCommandLocked(const sp& oldToken, const sp& newToken) REQUIRES(mLock); void sendDropWindowCommandLocked(const sp& token, float x, float y) REQUIRES(mLock); -- cgit v1.2.3-59-g8ed1b