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

Commit a5ac1e54 authored by Siarhei Vishniakou's avatar Siarhei Vishniakou Committed by Android (Google) Code Review
Browse files

Merge "Allow multi-window multiple device streams" into main

parents bf7f2b1f 2899c55f
Loading
Loading
Loading
Loading
+147 −125
Original line number Diff line number Diff line
@@ -634,11 +634,10 @@ std::vector<TouchedWindow> getHoveringWindowsLocked(const TouchState* oldState,
                                                    const MotionEntry& entry) {
    std::vector<TouchedWindow> out;
    const int32_t maskedAction = MotionEvent::getActionMasked(entry.action);
    if (maskedAction != AMOTION_EVENT_ACTION_HOVER_ENTER &&
        maskedAction != AMOTION_EVENT_ACTION_HOVER_MOVE &&
        maskedAction != AMOTION_EVENT_ACTION_HOVER_EXIT) {
        // Not a hover event - don't need to do anything
        return out;

    if (maskedAction == AMOTION_EVENT_ACTION_SCROLL) {
        // ACTION_SCROLL events should not affect the hovering pointer dispatch
        return {};
    }

    // We should consider all hovering pointers here. But for now, just use the first one
@@ -1315,7 +1314,8 @@ std::vector<InputTarget> InputDispatcher::findOutsideTargetsLocked(
        if (info.inputConfig.test(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH)) {
            std::bitset<MAX_POINTER_ID + 1> pointerIds;
            pointerIds.set(pointerId);
            addWindowTargetLocked(windowHandle, InputTarget::Flags::DISPATCH_AS_OUTSIDE, pointerIds,
            addPointerWindowTargetLocked(windowHandle, InputTarget::Flags::DISPATCH_AS_OUTSIDE,
                                         pointerIds,
                                         /*firstDownTimeInTarget=*/std::nullopt, outsideTargets);
        }
    }
@@ -1821,7 +1821,7 @@ bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, std::shared_ptr<Key
    std::vector<InputTarget> inputTargets;
    addWindowTargetLocked(focusedWindow,
                          InputTarget::Flags::FOREGROUND | InputTarget::Flags::DISPATCH_AS_IS,
                          /*pointerIds=*/{}, getDownTime(*entry), inputTargets);
                          getDownTime(*entry), inputTargets);

    // Add monitor channels from event's or focused display.
    addGlobalMonitoringTargetsLocked(inputTargets, getTargetDisplayId(*entry));
@@ -1905,7 +1905,6 @@ bool InputDispatcher::dispatchMotionLocked(nsecs_t currentTime, std::shared_ptr<
    // Identify targets.
    std::vector<InputTarget> inputTargets;

    bool conflictingPointerActions = false;
    InputEventInjectionResult injectionResult;
    if (isPointerEvent) {
        // Pointer event.  (eg. touchscreen)
@@ -1917,8 +1916,7 @@ bool InputDispatcher::dispatchMotionLocked(nsecs_t currentTime, std::shared_ptr<
        }

        inputTargets =
                findTouchedWindowTargetsLocked(currentTime, *entry, &conflictingPointerActions,
                                               /*byref*/ injectionResult);
                findTouchedWindowTargetsLocked(currentTime, *entry, /*byref*/ injectionResult);
        LOG_ALWAYS_FATAL_IF(injectionResult != InputEventInjectionResult::SUCCEEDED &&
                            !inputTargets.empty());
    } else {
@@ -1930,7 +1928,7 @@ bool InputDispatcher::dispatchMotionLocked(nsecs_t currentTime, std::shared_ptr<
            addWindowTargetLocked(focusedWindow,
                                  InputTarget::Flags::FOREGROUND |
                                          InputTarget::Flags::DISPATCH_AS_IS,
                                  /*pointerIds=*/{}, getDownTime(*entry), inputTargets);
                                  getDownTime(*entry), inputTargets);
        }
    }
    if (injectionResult == InputEventInjectionResult::PENDING) {
@@ -1954,11 +1952,6 @@ bool InputDispatcher::dispatchMotionLocked(nsecs_t currentTime, std::shared_ptr<
    addGlobalMonitoringTargetsLocked(inputTargets, getTargetDisplayId(*entry));

    // Dispatch the motion.
    if (conflictingPointerActions) {
        CancelationOptions options(CancelationOptions::Mode::CANCEL_POINTER_EVENTS,
                                   "conflicting pointer actions");
        synthesizeCancelationEventsForAllConnectionsLocked(options);
    }
    dispatchEventLocked(currentTime, entry, inputTargets);
    return true;
}
@@ -2258,7 +2251,7 @@ std::vector<Monitor> InputDispatcher::selectResponsiveMonitorsLocked(
}

std::vector<InputTarget> InputDispatcher::findTouchedWindowTargetsLocked(
        nsecs_t currentTime, const MotionEntry& entry, bool* outConflictingPointerActions,
        nsecs_t currentTime, const MotionEntry& entry,
        InputEventInjectionResult& outInjectionResult) {
    ATRACE_CALL();

@@ -2283,20 +2276,13 @@ std::vector<InputTarget> InputDispatcher::findTouchedWindowTargetsLocked(
    }

    bool isSplit = shouldSplitTouch(tempTouchState, entry);
    bool switchedDevice = false;
    if (oldState != nullptr) {
        std::set<int32_t> oldActiveDevices = oldState->getActiveDeviceIds();
        const bool anotherDeviceIsActive =
                oldActiveDevices.count(entry.deviceId) == 0 && !oldActiveDevices.empty();
        switchedDevice |= anotherDeviceIsActive;
    }

    const bool isHoverAction = (maskedAction == AMOTION_EVENT_ACTION_HOVER_MOVE ||
                                maskedAction == AMOTION_EVENT_ACTION_HOVER_ENTER ||
                                maskedAction == AMOTION_EVENT_ACTION_HOVER_EXIT);
    // A DOWN could be generated from POINTER_DOWN if the initial pointers did not land into any
    // touchable windows.
    const bool wasDown = oldState != nullptr && oldState->isDown();
    const bool wasDown = oldState != nullptr && oldState->isDown(entry.deviceId);
    const bool isDown = (maskedAction == AMOTION_EVENT_ACTION_DOWN) ||
            (maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN && !wasDown);
    const bool newGesture = isDown || maskedAction == AMOTION_EVENT_ACTION_SCROLL ||
@@ -2304,34 +2290,19 @@ std::vector<InputTarget> InputDispatcher::findTouchedWindowTargetsLocked(
            maskedAction == AMOTION_EVENT_ACTION_HOVER_MOVE;
    const bool isFromMouse = isFromSource(entry.source, AINPUT_SOURCE_MOUSE);

    // If pointers are already down, let's finish the current gesture and ignore the new events
    // from another device. However, if the new event is a down event, let's cancel the current
    // touch and let the new one take over.
    if (switchedDevice && wasDown && !isDown) {
        LOG(INFO) << "Dropping event because a pointer for another device "
                  << " is already down in display " << displayId << ": " << entry.getDescription();
        // TODO(b/211379801): test multiple simultaneous input streams.
        outInjectionResult = InputEventInjectionResult::FAILED;
        return {}; // wrong device
    }

    if (newGesture) {
        // If a new gesture is starting, clear the touch state completely.
        tempTouchState.reset();
        isSplit = false;
    } else if (switchedDevice && maskedAction == AMOTION_EVENT_ACTION_MOVE) {
        ALOGI("Dropping move event because a pointer for a different device is already active "
              "in display %" PRId32,
              displayId);
        // TODO(b/211379801): test multiple simultaneous input streams.
        outInjectionResult = InputEventInjectionResult::FAILED;
        return {}; // wrong device
    }

    if (isDown && tempTouchState.hasHoveringPointers(entry.deviceId)) {
        // Compatibility behaviour: ACTION_DOWN causes HOVER_EXIT to get generated.
        tempTouchState.clearHoveringPointers(entry.deviceId);
    }

    if (isHoverAction) {
        // For hover actions, we will treat 'tempTouchState' as a new state, so let's erase
        // all of the existing hovering pointers and recompute.
        tempTouchState.clearHoveringPointers();
        tempTouchState.clearHoveringPointers(entry.deviceId);
    }

    if (newGesture || (isSplit && maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN)) {
@@ -2402,8 +2373,7 @@ std::vector<InputTarget> InputDispatcher::findTouchedWindowTargetsLocked(
                continue;
            }

            if (maskedAction == AMOTION_EVENT_ACTION_HOVER_ENTER ||
                maskedAction == AMOTION_EVENT_ACTION_HOVER_MOVE) {
            if (isHoverAction) {
                // The "windowHandle" is the target of this hovering pointer.
                tempTouchState.addHoveringPointerToWindow(windowHandle, entry.deviceId, pointerId);
            }
@@ -2426,31 +2396,24 @@ std::vector<InputTarget> InputDispatcher::findTouchedWindowTargetsLocked(
            }

            // Update the temporary touch state.
            std::bitset<MAX_POINTER_ID + 1> pointerIds;

            if (!isHoverAction) {
                std::bitset<MAX_POINTER_ID + 1> pointerIds;
                pointerIds.set(pointerId);
            }

                const bool isDownOrPointerDown = maskedAction == AMOTION_EVENT_ACTION_DOWN ||
                        maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN;

            // TODO(b/211379801): Currently, even if pointerIds are empty (hover case), we would
            // still add a window to the touch state. We should avoid doing that, but some of the
            // later checks ("at least one foreground window") rely on this in order to dispatch
            // the event properly, so that needs to be updated, possibly by looking at InputTargets.
            tempTouchState.addOrUpdateWindow(windowHandle, targetFlags, entry.deviceId, pointerIds,
                tempTouchState.addOrUpdateWindow(windowHandle, targetFlags, entry.deviceId,
                                                 pointerIds,
                                                 isDownOrPointerDown
                                                         ? std::make_optional(entry.eventTime)
                                                         : std::nullopt);

                // 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 (isDownOrPointerDown) {
                if (targetFlags.test(InputTarget::Flags::FOREGROUND) &&
                // 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 (isDownOrPointerDown && targetFlags.test(InputTarget::Flags::FOREGROUND) &&
                    windowHandle->getInfo()->inputConfig.test(
                            gui::WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER)) {
                    sp<WindowInfoHandle> wallpaper = findWallpaperWindowBelow(windowHandle);
@@ -2488,8 +2451,10 @@ std::vector<InputTarget> InputDispatcher::findTouchedWindowTargetsLocked(
        /* Case 2: Pointer move, up, cancel or non-splittable pointer down. */

        // If the pointer is not currently down, then ignore the event.
        if (!tempTouchState.isDown() && maskedAction != AMOTION_EVENT_ACTION_HOVER_EXIT) {
            LOG(INFO) << "Dropping event because the pointer is not down or we previously "
        if (!tempTouchState.isDown(entry.deviceId) &&
            maskedAction != AMOTION_EVENT_ACTION_HOVER_EXIT) {
            LOG(INFO) << "Dropping event because the pointer for device " << entry.deviceId
                      << " is not down or we previously "
                         "dropped the pointer down event in display "
                      << displayId << ": " << entry.getDescription();
            outInjectionResult = InputEventInjectionResult::FAILED;
@@ -2538,7 +2503,7 @@ std::vector<InputTarget> InputDispatcher::findTouchedWindowTargetsLocked(

            if (newTouchedWindowHandle != nullptr &&
                !haveSameToken(oldTouchedWindowHandle, newTouchedWindowHandle)) {
                ALOGD("Touch is slipping out of window %s into window %s in display %" PRId32,
                ALOGI("Touch is slipping out of window %s into window %s in display %" PRId32,
                      oldTouchedWindowHandle->getName().c_str(),
                      newTouchedWindowHandle->getName().c_str(), displayId);

@@ -2549,9 +2514,11 @@ std::vector<InputTarget> InputDispatcher::findTouchedWindowTargetsLocked(

                const TouchedWindow& touchedWindow =
                        tempTouchState.getTouchedWindow(oldTouchedWindowHandle);
                addWindowTargetLocked(oldTouchedWindowHandle,
                                      InputTarget::Flags::DISPATCH_AS_SLIPPERY_EXIT, pointerIds,
                                      touchedWindow.getDownTimeInTarget(entry.deviceId), targets);
                addPointerWindowTargetLocked(oldTouchedWindowHandle,
                                             InputTarget::Flags::DISPATCH_AS_SLIPPERY_EXIT,
                                             pointerIds,
                                             touchedWindow.getDownTimeInTarget(entry.deviceId),
                                             targets);

                // Make a slippery entrance into the new window.
                if (newTouchedWindowHandle->getInfo()->supportsSplitTouch()) {
@@ -2664,15 +2631,13 @@ std::vector<InputTarget> InputDispatcher::findTouchedWindowTargetsLocked(

    // Output targets from the touch state.
    for (const TouchedWindow& touchedWindow : tempTouchState.windows) {
        if (!touchedWindow.hasTouchingPointers(entry.deviceId) &&
            !touchedWindow.hasHoveringPointers(entry.deviceId)) {
            // Windows with hovering pointers are getting persisted inside TouchState.
            // Do not send this event to those windows.
        std::bitset<MAX_POINTER_ID + 1> touchingPointers =
                touchedWindow.getTouchingPointers(entry.deviceId);
        if (touchingPointers.none()) {
            continue;
        }

        addWindowTargetLocked(touchedWindow.windowHandle, touchedWindow.targetFlags,
                              touchedWindow.getTouchingPointers(entry.deviceId),
        addPointerWindowTargetLocked(touchedWindow.windowHandle, touchedWindow.targetFlags,
                                     touchingPointers,
                                     touchedWindow.getDownTimeInTarget(entry.deviceId), targets);
    }

@@ -2706,37 +2671,30 @@ std::vector<InputTarget> InputDispatcher::findTouchedWindowTargetsLocked(
    }

    outInjectionResult = InputEventInjectionResult::SUCCEEDED;
    // Drop the outside or hover touch windows since we will not care about them
    // in the next iteration.
    tempTouchState.filterNonAsIsTouchWindows();

    // Update final pieces of touch state if the injector had permission.
    if (switchedDevice) {
        if (DEBUG_FOCUS) {
            ALOGD("Conflicting pointer actions: Switched to a different device.");
    for (TouchedWindow& touchedWindow : tempTouchState.windows) {
        // Targets that we entered in a slippery way will now become AS-IS targets
        if (touchedWindow.targetFlags.test(InputTarget::Flags::DISPATCH_AS_SLIPPERY_ENTER)) {
            touchedWindow.targetFlags.clear(InputTarget::Flags::DISPATCH_AS_SLIPPERY_ENTER);
            touchedWindow.targetFlags |= InputTarget::Flags::DISPATCH_AS_IS;
        }
        *outConflictingPointerActions = true;
    }

    // Update final pieces of touch state if the injector had permission.
    if (isHoverAction) {
        // Started hovering, therefore no longer down.
        if (oldState && oldState->isDown()) {
            ALOGD_IF(DEBUG_FOCUS,
                     "Conflicting pointer actions: Hover received while pointer was down.");
            *outConflictingPointerActions = true;
        if (oldState && oldState->isDown(entry.deviceId)) {
            // Started hovering, but the device is already down: reject the hover event
            LOG(ERROR) << "Got hover event " << entry.getDescription()
                       << " but the device is already down " << oldState->dump();
            outInjectionResult = InputEventInjectionResult::FAILED;
            return {};
        }
    } else if (maskedAction == AMOTION_EVENT_ACTION_UP) {
        // Pointer went up.
        tempTouchState.removeTouchingPointer(entry.deviceId, entry.pointerProperties[0].id);
    } else if (maskedAction == AMOTION_EVENT_ACTION_CANCEL) {
        // All pointers up or canceled.
        tempTouchState.reset();
    } else if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {
        // First pointer went down.
        if (oldState && (oldState->isDown() || oldState->hasHoveringPointers())) {
            ALOGD("Conflicting pointer actions: Down received while already down or hovering.");
            *outConflictingPointerActions = true;
        }
        tempTouchState.removeAllPointersForDevice(entry.deviceId);
    } else if (maskedAction == AMOTION_EVENT_ACTION_POINTER_UP) {
        // One pointer went up.
        const int32_t pointerIndex = MotionEvent::getActionIndex(action);
@@ -2885,7 +2843,6 @@ std::optional<InputTarget> InputDispatcher::createInputTargetLocked(

void InputDispatcher::addWindowTargetLocked(const sp<WindowInfoHandle>& windowHandle,
                                            ftl::Flags<InputTarget::Flags> targetFlags,
                                            std::bitset<MAX_POINTER_ID + 1> pointerIds,
                                            std::optional<nsecs_t> firstDownTimeInTarget,
                                            std::vector<InputTarget>& inputTargets) const {
    std::vector<InputTarget>::iterator it =
@@ -2907,8 +2864,54 @@ void InputDispatcher::addWindowTargetLocked(const sp<WindowInfoHandle>& windowHa
        it = inputTargets.end() - 1;
    }

    ALOG_ASSERT(it->flags == targetFlags);
    ALOG_ASSERT(it->globalScaleFactor == windowInfo->globalScaleFactor);
    LOG_ALWAYS_FATAL_IF(it->flags != targetFlags);
    LOG_ALWAYS_FATAL_IF(it->globalScaleFactor != windowInfo->globalScaleFactor);
}

void InputDispatcher::addPointerWindowTargetLocked(
        const sp<android::gui::WindowInfoHandle>& windowHandle,
        ftl::Flags<InputTarget::Flags> targetFlags, std::bitset<MAX_POINTER_ID + 1> pointerIds,
        std::optional<nsecs_t> firstDownTimeInTarget, std::vector<InputTarget>& inputTargets) const
        REQUIRES(mLock) {
    if (pointerIds.none()) {
        for (const auto& target : inputTargets) {
            LOG(INFO) << "Target: " << target;
        }
        LOG(FATAL) << "No pointers specified for " << windowHandle->getName();
        return;
    }
    std::vector<InputTarget>::iterator it =
            std::find_if(inputTargets.begin(), inputTargets.end(),
                         [&windowHandle](const InputTarget& inputTarget) {
                             return inputTarget.inputChannel->getConnectionToken() ==
                                     windowHandle->getToken();
                         });

    // This is a hack, because the actual entry could potentially be an ACTION_DOWN event that
    // causes a HOVER_EXIT to be generated. That means that the same entry of ACTION_DOWN would
    // have DISPATCH_AS_HOVER_EXIT and DISPATCH_AS_IS. And therefore, we have to create separate
    // input targets for hovering pointers and for touching pointers.
    // If we picked an existing input target above, but it's for HOVER_EXIT - let's use a new
    // target instead.
    if (it != inputTargets.end() && it->flags.test(InputTarget::Flags::DISPATCH_AS_HOVER_EXIT)) {
        // Force the code below to create a new input target
        it = inputTargets.end();
    }

    const WindowInfo* windowInfo = windowHandle->getInfo();

    if (it == inputTargets.end()) {
        std::optional<InputTarget> target =
                createInputTargetLocked(windowHandle, targetFlags, firstDownTimeInTarget);
        if (!target) {
            return;
        }
        inputTargets.push_back(*target);
        it = inputTargets.end() - 1;
    }

    LOG_ALWAYS_FATAL_IF(it->flags != targetFlags);
    LOG_ALWAYS_FATAL_IF(it->globalScaleFactor != windowInfo->globalScaleFactor);

    it->addPointers(pointerIds, windowInfo->transform);
}
@@ -3366,6 +3369,27 @@ void InputDispatcher::enqueueDispatchEntryLocked(const std::shared_ptr<Connectio
                dispatchEntry->resolvedFlags |= AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
            }

            // Check if we need to cancel any of the ongoing gestures. We don't support multiple
            // devices being active at the same time in the same window, so if a new device is
            // active, cancel the gesture from the old device.

            std::unique_ptr<EventEntry> cancelEvent =
                    connection->inputState
                            .cancelConflictingInputStream(motionEntry,
                                                          dispatchEntry->resolvedAction);
            if (cancelEvent != nullptr) {
                LOG(INFO) << "Canceling pointers for device " << motionEntry.deviceId << " in "
                          << connection->getInputChannelName() << " with event "
                          << cancelEvent->getDescription();
                std::unique_ptr<DispatchEntry> cancelDispatchEntry =
                        createDispatchEntry(inputTarget, std::move(cancelEvent),
                                            InputTarget::Flags::DISPATCH_AS_IS);

                // Send these cancel events to the queue before sending the event from the new
                // device.
                connection->outboundQueue.emplace_back(std::move(cancelDispatchEntry));
            }

            if (!connection->inputState.trackMotion(motionEntry, dispatchEntry->resolvedAction,
                                                    dispatchEntry->resolvedFlags)) {
                LOG(WARNING) << "channel " << connection->getInputChannelName()
@@ -3975,7 +3999,7 @@ void InputDispatcher::synthesizeCancelationEventsForConnectionLocked(
                        : std::nullopt;
                if (const auto& window = getWindowHandleLocked(token, targetDisplay); window) {
                    addWindowTargetLocked(window, InputTarget::Flags::DISPATCH_AS_IS,
                                          /*pointerIds=*/{}, keyEntry.downTime, targets);
                                          keyEntry.downTime, targets);
                } else {
                    targets.emplace_back(fallbackTarget);
                }
@@ -3994,8 +4018,8 @@ void InputDispatcher::synthesizeCancelationEventsForConnectionLocked(
                         pointerIndex++) {
                        pointerIds.set(motionEntry.pointerProperties[pointerIndex].id);
                    }
                    addWindowTargetLocked(window, InputTarget::Flags::DISPATCH_AS_IS, pointerIds,
                                          motionEntry.downTime, targets);
                    addPointerWindowTargetLocked(window, InputTarget::Flags::DISPATCH_AS_IS,
                                                 pointerIds, motionEntry.downTime, targets);
                } else {
                    targets.emplace_back(fallbackTarget);
                    const auto it = mDisplayInfos.find(motionEntry.displayId);
@@ -4069,7 +4093,7 @@ void InputDispatcher::synthesizePointerDownEventsForConnectionLocked(
                         pointerIndex++) {
                        pointerIds.set(motionEntry.pointerProperties[pointerIndex].id);
                    }
                    addWindowTargetLocked(windowHandle, targetFlags, pointerIds,
                    addPointerWindowTargetLocked(windowHandle, targetFlags, pointerIds,
                                                 motionEntry.downTime, targets);
                } else {
                    targets.emplace_back(InputTarget{.inputChannel = connection->inputChannel,
@@ -5139,10 +5163,8 @@ void InputDispatcher::setInputWindowsLocked(
        for (size_t i = 0; i < state.windows.size();) {
            TouchedWindow& touchedWindow = state.windows[i];
            if (getWindowHandleLocked(touchedWindow.windowHandle) == nullptr) {
                if (DEBUG_FOCUS) {
                    ALOGD("Touched window was removed: %s in display %" PRId32,
                          touchedWindow.windowHandle->getName().c_str(), displayId);
                }
                LOG(INFO) << "Touched window was removed: " << touchedWindow.windowHandle->getName()
                          << " in display %" << displayId;
                std::shared_ptr<InputChannel> touchedInputChannel =
                        getInputChannelLocked(touchedWindow.windowHandle->getToken());
                if (touchedInputChannel != nullptr) {
@@ -5973,9 +5995,8 @@ status_t InputDispatcher::pilferPointersLocked(const sp<IBinder>& token) {
        return BAD_VALUE;
    }
    std::set<int32_t> deviceIds = windowPtr->getTouchingDeviceIds();
    if (deviceIds.size() != 1) {
        LOG(WARNING) << "Can't pilfer. Currently touching devices: " << dumpSet(deviceIds)
                     << " in window: " << windowPtr->dump();
    if (deviceIds.empty()) {
        LOG(WARNING) << "Can't pilfer: no touching devices in window: " << windowPtr->dump();
        return BAD_VALUE;
    }

@@ -6818,10 +6839,11 @@ void InputDispatcher::slipWallpaperTouch(ftl::Flags<InputTarget::Flags> targetFl

    if (oldWallpaper != nullptr) {
        const TouchedWindow& oldTouchedWindow = state.getTouchedWindow(oldWallpaper);
        addWindowTargetLocked(oldWallpaper,
        addPointerWindowTargetLocked(oldWallpaper,
                                     oldTouchedWindow.targetFlags |
                                             InputTarget::Flags::DISPATCH_AS_SLIPPERY_EXIT,
                              pointerIds, oldTouchedWindow.getDownTimeInTarget(deviceId), targets);
                                     pointerIds, oldTouchedWindow.getDownTimeInTarget(deviceId),
                                     targets);
        state.removeTouchingPointerFromWindow(deviceId, pointerId, oldWallpaper);
    }

+6 −2

File changed.

Preview size limit exceeded, changes collapsed.

+166 −18

File changed.

Preview size limit exceeded, changes collapsed.

+7 −0
Original line number Diff line number Diff line
@@ -48,6 +48,10 @@ public:
    // and should be skipped.
    bool trackMotion(const MotionEntry& entry, int32_t action, int32_t flags);

    // Create cancel events for the previous stream if the current motionEntry requires it.
    std::unique_ptr<EventEntry> cancelConflictingInputStream(const MotionEntry& motionEntry,
                                                             int32_t resolvedAction);

    // Synthesizes cancelation events for the current state and resets the tracked state.
    std::vector<std::unique_ptr<EventEntry>> synthesizeCancelationEvents(
            nsecs_t currentTime, const CancelationOptions& options);
@@ -123,6 +127,9 @@ private:

    static bool shouldCancelKey(const KeyMemento& memento, const CancelationOptions& options);
    static bool shouldCancelMotion(const MotionMemento& memento, const CancelationOptions& options);
    bool shouldCancelPreviousStream(const MotionEntry& motionEntry, int32_t resolvedAction) const;
    std::unique_ptr<MotionEntry> createCancelEntryForMemento(const MotionMemento& memento,
                                                             nsecs_t eventTime) const;

    // Synthesizes pointer cancel events for a particular set of pointers.
    std::vector<std::unique_ptr<MotionEntry>> synthesizeCancelationEventsForPointers(
+19 −18

File changed.

Preview size limit exceeded, changes collapsed.

Loading