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

Commit b4ae6ece authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Fix wallpaper window multi-touch" into tm-qpr-dev

parents b8252965 ba703c3c
Loading
Loading
Loading
Loading
+139 −45
Original line number Diff line number Diff line
@@ -2196,8 +2196,31 @@ InputEventInjectionResult InputDispatcher::findTouchedWindowTargetsLocked(
            // Update the temporary touch state.
            BitSet32 pointerIds;
            pointerIds.markBit(entry.pointerProperties[pointerIndex].id);

            tempTouchState.addOrUpdateWindow(windowHandle, targetFlags, pointerIds);

            // If this is the pointer going down and the touched window has a wallpaper
            // then also add the touched wallpaper windows so they are locked in for the duration
            // of the touch gesture.
            // We do not collect wallpapers during HOVER_MOVE or SCROLL because the wallpaper
            // engine only supports touch events.  We would need to add a mechanism similar
            // to View.onGenericMotionEvent to enable wallpapers to handle these events.
            if (maskedAction == AMOTION_EVENT_ACTION_DOWN ||
                maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN) {
                if ((targetFlags & InputTarget::FLAG_FOREGROUND) &&
                    windowHandle->getInfo()->inputConfig.test(
                            gui::WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER)) {
                    sp<WindowInfoHandle> wallpaper = findWallpaperWindowBelow(windowHandle);
                    if (wallpaper != nullptr) {
                        int32_t wallpaperFlags = InputTarget::FLAG_WINDOW_IS_OBSCURED |
                                InputTarget::FLAG_WINDOW_IS_PARTIALLY_OBSCURED |
                                InputTarget::FLAG_DISPATCH_AS_IS;
                        if (isSplit) {
                            wallpaperFlags |= InputTarget::FLAG_SPLIT;
                        }
                        tempTouchState.addOrUpdateWindow(wallpaper, wallpaperFlags, pointerIds);
                    }
                }
            }
        }
    } else {
        /* Case 2: Pointer move, up, cancel or non-splittable pointer down. */
@@ -2274,6 +2297,10 @@ InputEventInjectionResult InputDispatcher::findTouchedWindowTargetsLocked(
                BitSet32 pointerIds;
                pointerIds.markBit(entry.pointerProperties[0].id);
                tempTouchState.addOrUpdateWindow(newTouchedWindowHandle, targetFlags, pointerIds);

                // Check if the wallpaper window should deliver the corresponding event.
                slipWallpaperTouch(targetFlags, oldTouchedWindowHandle, newTouchedWindowHandle,
                                   tempTouchState, pointerIds);
            }
        }

@@ -2379,39 +2406,6 @@ InputEventInjectionResult InputDispatcher::findTouchedWindowTargetsLocked(
        }
    }

    // If this is the first pointer going down and the touched window has a wallpaper
    // then also add the touched wallpaper windows so they are locked in for the duration
    // of the touch gesture.
    // We do not collect wallpapers during HOVER_MOVE or SCROLL because the wallpaper
    // engine only supports touch events.  We would need to add a mechanism similar
    // to View.onGenericMotionEvent to enable wallpapers to handle these events.
    if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {
        sp<WindowInfoHandle> foregroundWindowHandle =
                tempTouchState.getFirstForegroundWindowHandle();
        if (foregroundWindowHandle &&
            foregroundWindowHandle->getInfo()->inputConfig.test(
                    WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER)) {
            const std::vector<sp<WindowInfoHandle>>& windowHandles =
                    getWindowHandlesLocked(displayId);
            for (const sp<WindowInfoHandle>& windowHandle : windowHandles) {
                const WindowInfo* info = windowHandle->getInfo();
                if (info->displayId == displayId &&
                    windowHandle->getInfo()->inputConfig.test(
                            WindowInfo::InputConfig::IS_WALLPAPER)) {
                    BitSet32 pointerIds;
                    pointerIds.markBit(entry.pointerProperties[0].id);
                    tempTouchState
                            .addOrUpdateWindow(windowHandle,
                                               InputTarget::FLAG_WINDOW_IS_OBSCURED |
                                                       InputTarget::
                                                               FLAG_WINDOW_IS_PARTIALLY_OBSCURED |
                                                       InputTarget::FLAG_DISPATCH_AS_IS,
                                               pointerIds);
                }
            }
        }
    }

    // Success!  Output targets.
    injectionResult = InputEventInjectionResult::SUCCEEDED;

@@ -3685,7 +3679,7 @@ void InputDispatcher::synthesizeCancelationEventsForConnectionLocked(
}

void InputDispatcher::synthesizePointerDownEventsForConnectionLocked(
        const sp<Connection>& connection) {
        const sp<Connection>& connection, int32_t targetFlags) {
    if (connection->status == Connection::Status::BROKEN) {
        return;
    }
@@ -3713,7 +3707,7 @@ void InputDispatcher::synthesizePointerDownEventsForConnectionLocked(
        target.globalScaleFactor = windowInfo->globalScaleFactor;
    }
    target.inputChannel = connection->inputChannel;
    target.flags = InputTarget::FLAG_DISPATCH_AS_IS;
    target.flags = targetFlags;

    for (std::unique_ptr<EventEntry>& downEventEntry : downEvents) {
        switch (downEventEntry->type) {
@@ -3744,6 +3738,16 @@ void InputDispatcher::synthesizePointerDownEventsForConnectionLocked(
    startDispatchCycleLocked(currentTime, connection);
}

void InputDispatcher::synthesizeCancelationEventsForWindowLocked(
        const sp<WindowInfoHandle>& windowHandle, const CancelationOptions& options) {
    if (windowHandle != nullptr) {
        sp<Connection> wallpaperConnection = getConnectionLocked(windowHandle->getToken());
        if (wallpaperConnection != nullptr) {
            synthesizeCancelationEventsForConnectionLocked(wallpaperConnection, options);
        }
    }
}

std::unique_ptr<MotionEntry> InputDispatcher::splitMotionEvent(
        const MotionEntry& originalMotionEntry, BitSet32 pointerIds) {
    ALOG_ASSERT(pointerIds.value != 0);
@@ -4762,14 +4766,7 @@ void InputDispatcher::setInputWindowsLocked(
                        touchedWindow.windowHandle->getInfo()->inputConfig.test(
                                gui::WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER)) {
                        sp<WindowInfoHandle> wallpaper = state.getWallpaperWindow();
                        if (wallpaper != nullptr) {
                            sp<Connection> wallpaperConnection =
                                    getConnectionLocked(wallpaper->getToken());
                            if (wallpaperConnection != nullptr) {
                                synthesizeCancelationEventsForConnectionLocked(wallpaperConnection,
                                                                               options);
                            }
                        }
                        synthesizeCancelationEventsForWindowLocked(wallpaper, options);
                    }
                }
                state.windows.erase(state.windows.begin() + i);
@@ -5082,6 +5079,7 @@ bool InputDispatcher::transferTouchFocus(const sp<IBinder>& fromToken, const sp<
        // Erase old window.
        int32_t oldTargetFlags = touchedWindow->targetFlags;
        BitSet32 pointerIds = touchedWindow->pointerIds;
        sp<WindowInfoHandle> fromWindowHandle = touchedWindow->windowHandle;
        state->removeWindowByToken(fromToken);

        // Add new window.
@@ -5113,7 +5111,10 @@ bool InputDispatcher::transferTouchFocus(const sp<IBinder>& fromToken, const sp<
                    options(CancelationOptions::CANCEL_POINTER_EVENTS,
                            "transferring touch focus from this window to another window");
            synthesizeCancelationEventsForConnectionLocked(fromConnection, options);
            synthesizePointerDownEventsForConnectionLocked(toConnection);
            synthesizePointerDownEventsForConnectionLocked(toConnection, newTargetFlags);
            // Check if the wallpaper window should deliver the corresponding event.
            transferWallpaperTouch(oldTargetFlags, newTargetFlags, fromWindowHandle, toWindowHandle,
                                   *state, pointerIds);
        }

        if (DEBUG_FOCUS) {
@@ -6398,4 +6399,97 @@ void InputDispatcher::setMonitorDispatchingTimeoutForTest(std::chrono::nanosecon
    mMonitorDispatchingTimeout = timeout;
}

void InputDispatcher::slipWallpaperTouch(int32_t targetFlags,
                                         const sp<WindowInfoHandle>& oldWindowHandle,
                                         const sp<WindowInfoHandle>& newWindowHandle,
                                         TouchState& state, const BitSet32& pointerIds) {
    const bool oldHasWallpaper = oldWindowHandle->getInfo()->inputConfig.test(
            gui::WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER);
    const bool newHasWallpaper = (targetFlags & InputTarget::FLAG_FOREGROUND) &&
            newWindowHandle->getInfo()->inputConfig.test(
                    gui::WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER);
    const sp<WindowInfoHandle> oldWallpaper =
            oldHasWallpaper ? state.getWallpaperWindow() : nullptr;
    const sp<WindowInfoHandle> newWallpaper =
            newHasWallpaper ? findWallpaperWindowBelow(newWindowHandle) : nullptr;
    if (oldWallpaper == newWallpaper) {
        return;
    }

    if (oldWallpaper != nullptr) {
        state.addOrUpdateWindow(oldWallpaper, InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT,
                                BitSet32(0));
    }

    if (newWallpaper != nullptr) {
        state.addOrUpdateWindow(newWallpaper,
                                InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER |
                                        InputTarget::FLAG_WINDOW_IS_OBSCURED |
                                        InputTarget::FLAG_WINDOW_IS_PARTIALLY_OBSCURED,
                                pointerIds);
    }
}

void InputDispatcher::transferWallpaperTouch(int32_t oldTargetFlags, int32_t newTargetFlags,
                                             const sp<WindowInfoHandle> fromWindowHandle,
                                             const sp<WindowInfoHandle> toWindowHandle,
                                             TouchState& state, const BitSet32& pointerIds) {
    const bool oldHasWallpaper = (oldTargetFlags & InputTarget::FLAG_FOREGROUND) &&
            fromWindowHandle->getInfo()->inputConfig.test(
                    gui::WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER);
    const bool newHasWallpaper = (newTargetFlags & InputTarget::FLAG_FOREGROUND) &&
            toWindowHandle->getInfo()->inputConfig.test(
                    gui::WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER);

    const sp<WindowInfoHandle> oldWallpaper =
            oldHasWallpaper ? state.getWallpaperWindow() : nullptr;
    const sp<WindowInfoHandle> newWallpaper =
            newHasWallpaper ? findWallpaperWindowBelow(toWindowHandle) : nullptr;
    if (oldWallpaper == newWallpaper) {
        return;
    }

    if (oldWallpaper != nullptr) {
        CancelationOptions options(CancelationOptions::Mode::CANCEL_POINTER_EVENTS,
                                   "transferring touch focus to another window");
        state.removeWindowByToken(oldWallpaper->getToken());
        synthesizeCancelationEventsForWindowLocked(oldWallpaper, options);
    }

    if (newWallpaper != nullptr) {
        int32_t wallpaperFlags =
                oldTargetFlags & (InputTarget::FLAG_SPLIT | InputTarget::FLAG_DISPATCH_AS_IS);
        wallpaperFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED |
                InputTarget::FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
        state.addOrUpdateWindow(newWallpaper, wallpaperFlags, pointerIds);
        sp<Connection> wallpaperConnection = getConnectionLocked(newWallpaper->getToken());
        if (wallpaperConnection != nullptr) {
            sp<Connection> toConnection = getConnectionLocked(toWindowHandle->getToken());
            toConnection->inputState.mergePointerStateTo(wallpaperConnection->inputState);
            synthesizePointerDownEventsForConnectionLocked(wallpaperConnection, wallpaperFlags);
        }
    }
}

sp<WindowInfoHandle> InputDispatcher::findWallpaperWindowBelow(
        const sp<WindowInfoHandle>& windowHandle) const {
    const std::vector<sp<WindowInfoHandle>>& windowHandles =
            getWindowHandlesLocked(windowHandle->getInfo()->displayId);
    bool foundWindow = false;
    for (const sp<WindowInfoHandle>& otherHandle : windowHandles) {
        if (!foundWindow && otherHandle != windowHandle) {
            continue;
        }
        if (windowHandle == otherHandle) {
            foundWindow = true;
            continue;
        }

        if (otherHandle->getInfo()->inputConfig.test(WindowInfo::InputConfig::IS_WALLPAPER)) {
            return otherHandle;
        }
    }
    return nullptr;
}

} // namespace android::inputdispatcher
+18 −2
Original line number Diff line number Diff line
@@ -621,8 +621,12 @@ private:
                                                        const CancelationOptions& options)
            REQUIRES(mLock);

    void synthesizePointerDownEventsForConnectionLocked(const sp<Connection>& connection)
            REQUIRES(mLock);
    void synthesizePointerDownEventsForConnectionLocked(const sp<Connection>& connection,
                                                        int32_t targetFlags) REQUIRES(mLock);

    void synthesizeCancelationEventsForWindowLocked(
            const sp<android::gui::WindowInfoHandle>& windowHandle,
            const CancelationOptions& options) REQUIRES(mLock);

    // Splitting motion events across windows.
    std::unique_ptr<MotionEntry> splitMotionEvent(const MotionEntry& originalMotionEntry,
@@ -684,6 +688,18 @@ private:
    bool recentWindowsAreOwnedByLocked(int32_t pid, int32_t uid) REQUIRES(mLock);

    sp<InputReporterInterface> mReporter;

    void slipWallpaperTouch(int32_t targetFlags,
                            const sp<android::gui::WindowInfoHandle>& oldWindowHandle,
                            const sp<android::gui::WindowInfoHandle>& newWindowHandle,
                            TouchState& state, const BitSet32& pointerIds) REQUIRES(mLock);
    void transferWallpaperTouch(int32_t oldTargetFlags, int32_t newTargetFlags,
                                const sp<android::gui::WindowInfoHandle> fromWindowHandle,
                                const sp<android::gui::WindowInfoHandle> toWindowHandle,
                                TouchState& state, const BitSet32& pointerIds) REQUIRES(mLock);

    sp<android::gui::WindowInfoHandle> findWallpaperWindowBelow(
            const sp<android::gui::WindowInfoHandle>& windowHandle) const REQUIRES(mLock);
};

} // namespace android::inputdispatcher
+140 −61

File changed.

Preview size limit exceeded, changes collapsed.