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

Commit 1f068004 authored by Rob Carr's avatar Rob Carr Committed by Android (Google) Code Review
Browse files

Merge "WindowManager: Support focus for SurfacePackage overlays"

parents 03a46a1f 47857a0a
Loading
Loading
Loading
Loading
+52 −0
Original line number Diff line number Diff line
@@ -93,6 +93,18 @@ class EmbeddedWindowController {
        return embeddedWindow != null ? embeddedWindow.mHostWindowState : null;
    }

    boolean isOverlay(IBinder inputToken) {
        EmbeddedWindow embeddedWindow = mWindows.get(inputToken);
        return embeddedWindow != null ? embeddedWindow.getIsOverlay() : false;
    }

    void setIsOverlay(IBinder inputToken) {
        EmbeddedWindow embeddedWindow = mWindows.get(inputToken);
        if (embeddedWindow != null) {
            embeddedWindow.setIsOverlay();
        }
    }

    void remove(IWindow client) {
        for (int i = mWindows.size() - 1; i >= 0; i--) {
            if (mWindows.valueAt(i).mClient.asBinder() == client.asBinder()) {
@@ -138,6 +150,12 @@ class EmbeddedWindowController {
        public Session mSession;
        InputChannel mInputChannel;
        final int mWindowType;
        // Track whether the EmbeddedWindow is a system hosted overlay via
        // {@link OverlayHost}. In the case of client hosted overlays, the client
        // view hierarchy will take care of invoking requestEmbeddedWindowFocus
        // but for system hosted overlays we have to do this via tapOutsideDetection
        // and this variable is mostly used for tracking that.
        boolean mIsOverlay = false;

        /**
         * @param session  calling session to check ownership of the window
@@ -216,5 +234,39 @@ class EmbeddedWindowController {
        public int getPid() {
            return mOwnerPid;
        }

        void setIsOverlay() {
            mIsOverlay = true;
        }
        boolean getIsOverlay() {
            return mIsOverlay;
        }

        /**
         * System hosted overlays need the WM to invoke grantEmbeddedWindowFocus and
         * so we need to participate inside handlePointerDownOutsideFocus logic
         * however client hosted overlays will rely on the hosting view hierarchy
         * to grant and revoke focus, and so the server side logic is not needed.
         */
        @Override
        public boolean receiveFocusFromTapOutside() {
            return mIsOverlay;
        }

        private void handleTap(boolean grantFocus) {
            if (mInputChannel != null) {
                mWmService.grantEmbeddedWindowFocus(mSession, mInputChannel.getToken(), grantFocus);
            }
        }

        @Override
        public void handleTapOutsideFocusOutsideSelf() {
            handleTap(false);
        }

        @Override
        public void handleTapOutsideFocusInsideSelf() {
            handleTap(true);
        }
    }
}
+11 −0
Original line number Diff line number Diff line
@@ -36,5 +36,16 @@ interface InputTarget {

    /* Owning pid of the target. */
    int getPid();

    /**
     * Indicates whether a target should receive focus from server side
     * tap outside focus detection. For example, this is false in the case of
     * EmbeddedWindows in a client view hierarchy, where the client will do internal
     * tap detection and invoke grantEmbeddedWindowFocus itself
     */
    boolean receiveFocusFromTapOutside();

    void handleTapOutsideFocusInsideSelf();
    void handleTapOutsideFocusOutsideSelf();
}
+2 −0
Original line number Diff line number Diff line
@@ -74,6 +74,8 @@ class OverlayHost {
        requireOverlaySurfaceControl();
        mOverlays.add(p);

        mWmService.mEmbeddedWindowController.setIsOverlay(p.getInputToken());

        SurfaceControl.Transaction t = mWmService.mTransactionFactory.get();
        t.reparent(p.getSurfaceControl(), mSurfaceControl)
            .show(p.getSurfaceControl());
+11 −16
Original line number Diff line number Diff line
@@ -738,6 +738,8 @@ public class WindowManagerService extends IWindowManager.Stub
    final WindowContextListenerController mWindowContextListenerController =
            new WindowContextListenerController();

    private InputTarget mFocusedInputTarget;

    @VisibleForTesting
    final class SettingsObserver extends ContentObserver {
        private final Uri mDisplayInversionEnabledUri =
@@ -5011,6 +5013,7 @@ public class WindowManagerService extends IWindowManager.Stub
                Slog.v(TAG_WM, "Unknown focus tokens, dropping reportFocusChanged");
                return;
            }
            mFocusedInputTarget = newTarget;

            mAccessibilityController.onFocusChanged(lastTarget, newTarget);
            ProtoLog.i(WM_DEBUG_FOCUS_LIGHT, "Focus changing: %s -> %s", lastTarget, newTarget);
@@ -8170,21 +8173,14 @@ public class WindowManagerService extends IWindowManager.Stub
    }

    private void onPointerDownOutsideFocusLocked(IBinder touchedToken) {
        WindowState touchedWindow = mInputToWindowMap.get(touchedToken);
        if (touchedWindow == null) {
            // if a user taps outside the currently focused window onto an embedded window, treat
            // it as if the host window was tapped.
            touchedWindow = mEmbeddedWindowController.getHostWindow(touchedToken);
        }

        if (touchedWindow == null || !touchedWindow.canReceiveKeys(true /* fromUserTouch */)) {
        InputTarget t = getInputTargetFromToken(touchedToken);
        if (t == null || !t.receiveFocusFromTapOutside()) {
            // If the window that received the input event cannot receive keys, don't move the
            // display it's on to the top since that window won't be able to get focus anyway.
            return;
        }

        if (mRecentsAnimationController != null
                && mRecentsAnimationController.getTargetAppMainWindow() == touchedWindow) {
            && mRecentsAnimationController.getTargetAppMainWindow() == t) {
            // If there is an active recents animation and touched window is the target, then ignore
            // the touch. The target already handles touches using its own input monitor and we
            // don't want to trigger any lifecycle changes from focusing another window.
@@ -8194,13 +8190,11 @@ public class WindowManagerService extends IWindowManager.Stub
        }

        ProtoLog.i(WM_DEBUG_FOCUS_LIGHT, "onPointerDownOutsideFocusLocked called on %s",
                touchedWindow);
        final DisplayContent displayContent = touchedWindow.getDisplayContent();
        if (!displayContent.isOnTop()) {
            displayContent.getParent().positionChildAt(WindowContainer.POSITION_TOP, displayContent,
                    true /* includingParents */);
                t);
        if (mFocusedInputTarget != t && mFocusedInputTarget != null) {
            mFocusedInputTarget.handleTapOutsideFocusOutsideSelf();
        }
        handleTaskFocusChange(touchedWindow.getTask(), touchedWindow.mActivityRecord);
        t.handleTapOutsideFocusInsideSelf();
    }

    @VisibleForTesting
@@ -8777,4 +8771,5 @@ public class WindowManagerService extends IWindowManager.Stub

        mTaskTransitionSpec = null;
    }

}
+20 −0
Original line number Diff line number Diff line
@@ -5985,4 +5985,24 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
    boolean isTrustedOverlay() {
        return mInputWindowHandle.isTrustedOverlay();
    }

    public boolean receiveFocusFromTapOutside() {
        return canReceiveKeys(true);
    }

    @Override
    public void handleTapOutsideFocusOutsideSelf() {
        // Nothing to do here since raising the other window will naturally take care of
        // us loosing focus
    }

    @Override
    public void handleTapOutsideFocusInsideSelf() {
        final DisplayContent displayContent = getDisplayContent();
        if (!displayContent.isOnTop()) {
            displayContent.getParent().positionChildAt(WindowContainer.POSITION_TOP, displayContent,
                    true /* includingParents */);
        }
        mWmService.handleTaskFocusChange(getTask(), mActivityRecord);
    }
}