Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4b9b1a1d authored by Prabir Pradhan's avatar Prabir Pradhan
Browse files

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
parent fa2c69f6
Loading
Loading
Loading
Loading
+23 −16
Original line number Diff line number Diff line
@@ -5195,6 +5195,7 @@ void InputDispatcher::setInputWindowsLocked(

    // Copy old handles for release if they are no longer present.
    const std::vector<sp<WindowInfoHandle>> oldWindowHandles = getWindowHandlesLocked(displayId);
    const sp<WindowInfoHandle> removedFocusedWindowHandle = getFocusedWindowHandleLocked(displayId);

    updateWindowHandlesForDisplayLocked(windowInfoHandles, displayId);

@@ -5203,7 +5204,7 @@ void InputDispatcher::setInputWindowsLocked(
    std::optional<FocusResolver::FocusChanges> changes =
            mFocusResolver.setInputWindows(displayId, windowHandles);
    if (changes) {
        onFocusChangedLocked(*changes);
        onFocusChangedLocked(*changes, removedFocusedWindowHandle);
    }

    std::unordered_map<int32_t, TouchState>::iterator stateIt =
@@ -5325,14 +5326,16 @@ void InputDispatcher::setFocusedDisplay(int32_t displayId) {
            sp<IBinder> oldFocusedWindowToken =
                    mFocusResolver.getFocusedWindowToken(mFocusedDisplayId);
            if (oldFocusedWindowToken != nullptr) {
                std::shared_ptr<Connection> connection = getConnectionLocked(oldFocusedWindowToken);
                if (connection != nullptr) {
                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;
                    synthesizeCancelationEventsForConnectionLocked(connection, options);
                }
                synthesizeCancelationEventsForWindowLocked(windowHandle, options);
            }
            mFocusedDisplayId = displayId;

@@ -6682,16 +6685,20 @@ void InputDispatcher::setFocusedWindow(const FocusRequest& request) {
    mLooper->wake();
}

void InputDispatcher::onFocusChangedLocked(const FocusResolver::FocusChanges& changes) {
void InputDispatcher::onFocusChangedLocked(const FocusResolver::FocusChanges& changes,
                                           const sp<WindowInfoHandle> removedFocusedWindowHandle) {
    if (changes.oldFocus) {
        std::shared_ptr<Connection> focusedConnection = getConnectionLocked(changes.oldFocus);
        if (focusedConnection) {
        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");
            synthesizeCancelationEventsForConnectionLocked(focusedConnection, options);
        synthesizeCancelationEventsForWindowLocked(resolvedWindow, options);
        enqueueFocusEventLocked(changes.oldFocus, /*hasFocus=*/false, changes.reason);
    }
    }
    if (changes.newFocus) {
        resetNoFocusedWindowTimeoutLocked();
        enqueueFocusEventLocked(changes.newFocus, /*hasFocus=*/true, changes.reason);
+3 −1
Original line number Diff line number Diff line
@@ -653,7 +653,9 @@ private:
                                        bool handled, nsecs_t consumeTime) REQUIRES(mLock);
    void doInterceptKeyBeforeDispatchingCommand(const sp<IBinder>& focusedWindowToken,
                                                const KeyEntry& entry) REQUIRES(mLock);
    void onFocusChangedLocked(const FocusResolver::FocusChanges& changes) REQUIRES(mLock);
    void onFocusChangedLocked(const FocusResolver::FocusChanges& changes,
                              const sp<gui::WindowInfoHandle> removedFocusedWindowHandle = nullptr)
            REQUIRES(mLock);
    void sendFocusChangedCommandLocked(const sp<IBinder>& oldToken, const sp<IBinder>& newToken)
            REQUIRES(mLock);
    void sendDropWindowCommandLocked(const sp<IBinder>& token, float x, float y) REQUIRES(mLock);