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

Commit 744c559a authored by Jeff Brown's avatar Jeff Brown
Browse files

Add support for transferring touch focus.

Prerequisite for drag and drop.

Change-Id: Iedbe93ed0f3e1c4083130fe66b4ba06d416afce0
parent e4570389
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -355,6 +355,14 @@ public:
     */
    virtual void setInputDispatchMode(bool enabled, bool frozen) = 0;

    /* Transfers touch focus from the window associated with one channel to the
     * window associated with the other channel.
     *
     * Returns true on success.  False if the window did not actually have touch focus.
     */
    virtual bool transferTouchFocus(const sp<InputChannel>& fromChannel,
            const sp<InputChannel>& toChannel) = 0;

    /* Registers or unregister input channels that may be used as targets for input events.
     * If monitor is true, the channel will receive a copy of all input events.
     *
@@ -409,6 +417,9 @@ public:
    virtual void setFocusedApplication(const InputApplication* inputApplication);
    virtual void setInputDispatchMode(bool enabled, bool frozen);

    virtual bool transferTouchFocus(const sp<InputChannel>& fromChannel,
            const sp<InputChannel>& toChannel);

    virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel, bool monitor);
    virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel);

+64 −0
Original line number Diff line number Diff line
@@ -2464,6 +2464,70 @@ void InputDispatcher::setInputDispatchMode(bool enabled, bool frozen) {
    }
}

bool InputDispatcher::transferTouchFocus(const sp<InputChannel>& fromChannel,
        const sp<InputChannel>& toChannel) {
#if DEBUG_FOCUS
    LOGD("transferTouchFocus: fromChannel=%s, toChannel=%s",
            fromChannel->getName().string(), toChannel->getName().string());
#endif
    { // acquire lock
        AutoMutex _l(mLock);

        const InputWindow* fromWindow = getWindowLocked(fromChannel);
        const InputWindow* toWindow = getWindowLocked(toChannel);
        if (! fromWindow || ! toWindow) {
#if DEBUG_FOCUS
            LOGD("Cannot transfer focus because from or to window not found.");
#endif
            return false;
        }
        if (fromWindow == toWindow) {
#if DEBUG_FOCUS
            LOGD("Trivial transfer to same window.");
#endif
            return true;
        }

        bool found = false;
        for (size_t i = 0; i < mTouchState.windows.size(); i++) {
            const TouchedWindow& touchedWindow = mTouchState.windows[i];
            if (touchedWindow.window == fromWindow) {
                int32_t oldTargetFlags = touchedWindow.targetFlags;
                BitSet32 pointerIds = touchedWindow.pointerIds;

                mTouchState.windows.removeAt(i);

                int32_t newTargetFlags = 0;
                if (oldTargetFlags & InputTarget::FLAG_FOREGROUND) {
                    newTargetFlags |= InputTarget::FLAG_FOREGROUND;
                    if (toWindow->layoutParamsFlags & InputWindow::FLAG_SPLIT_TOUCH) {
                        newTargetFlags |= InputTarget::FLAG_SPLIT;
                    }
                }
                mTouchState.addOrUpdateWindow(toWindow, newTargetFlags, pointerIds);

                found = true;
                break;
            }
        }

        if (! found) {
#if DEBUG_FOCUS
            LOGD("Focus transfer failed because from window did not have focus.");
#endif
            return false;
        }

#if DEBUG_FOCUS
        logDispatchStateLocked();
#endif
    } // release lock

    // Wake up poll loop since it may need to make new input dispatching choices.
    mLooper->wake();
    return true;
}

void InputDispatcher::logDispatchStateLocked() {
    String8 dump;
    dumpDispatchStateLocked(dump);