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

Commit 6442d92b authored by Jeff Brown's avatar Jeff Brown Committed by Android (Google) Code Review
Browse files

Merge "Add support for transferring touch focus."

parents 3ce57747 e6504122
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);
+25 −0
Original line number Diff line number Diff line
@@ -77,6 +77,8 @@ public class InputManager {
    private static native InputDevice nativeGetInputDevice(int deviceId);
    private static native void nativeGetInputConfiguration(Configuration configuration);
    private static native int[] nativeGetInputDeviceIds();
    private static native boolean nativeTransferTouchFocus(InputChannel fromChannel,
            InputChannel toChannel);
    private static native String nativeDump();
    
    // Input event injection constants defined in InputDispatcher.h.
@@ -320,6 +322,29 @@ public class InputManager {
        nativeSetInputDispatchMode(enabled, frozen);
    }
    
    /**
     * Atomically transfers touch focus from one window to another as identified by
     * their input channels.  It is possible for multiple windows to have
     * touch focus if they support split touch dispatch
     * {@link android.view.WindowManager.LayoutParams#FLAG_SPLIT_TOUCH} but this
     * method only transfers touch focus of the specified window without affecting
     * other windows that may also have touch focus at the same time.
     * @param fromChannel The channel of a window that currently has touch focus.
     * @param toChannel The channel of the window that should receive touch focus in
     * place of the first.
     * @return True if the transfer was successful.  False if the window with the
     * specified channel did not actually have touch focus at the time of the request.
     */
    public boolean transferTouchFocus(InputChannel fromChannel, InputChannel toChannel) {
        if (fromChannel == null) {
            throw new IllegalArgumentException("fromChannel must not be null.");
        }
        if (toChannel == null) {
            throw new IllegalArgumentException("toChannel must not be null.");
        }
        return nativeTransferTouchFocus(fromChannel, toChannel);
    }
    
    public void dump(PrintWriter pw) {
        String dumpStr = nativeDump();
        if (dumpStr != null) {
+21 −0
Original line number Diff line number Diff line
@@ -1286,6 +1286,25 @@ static void android_server_InputManager_nativeGetInputConfiguration(JNIEnv* env,
    env->SetIntField(configObj, gConfigurationClassInfo.navigation, config.navigation);
}

static jboolean android_server_InputManager_nativeTransferTouchFocus(JNIEnv* env,
        jclass clazz, jobject fromChannelObj, jobject toChannelObj) {
    if (checkInputManagerUnitialized(env)) {
        return false;
    }

    sp<InputChannel> fromChannel =
            android_view_InputChannel_getInputChannel(env, fromChannelObj);
    sp<InputChannel> toChannel =
            android_view_InputChannel_getInputChannel(env, toChannelObj);

    if (fromChannel == NULL || toChannel == NULL) {
        return false;
    }

    return gNativeInputManager->getInputManager()->getDispatcher()->
            transferTouchFocus(fromChannel, toChannel);
}

static jstring android_server_InputManager_nativeDump(JNIEnv* env, jclass clazz) {
    if (checkInputManagerUnitialized(env)) {
        return NULL;
@@ -1334,6 +1353,8 @@ static JNINativeMethod gInputManagerMethods[] = {
            (void*) android_server_InputManager_nativeGetInputDeviceIds },
    { "nativeGetInputConfiguration", "(Landroid/content/res/Configuration;)V",
            (void*) android_server_InputManager_nativeGetInputConfiguration },
    { "nativeTransferTouchFocus", "(Landroid/view/InputChannel;Landroid/view/InputChannel;)Z",
            (void*) android_server_InputManager_nativeTransferTouchFocus },
    { "nativeDump", "()Ljava/lang/String;",
            (void*) android_server_InputManager_nativeDump },
};