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

Commit 71f8281e authored by Taran Singh's avatar Taran Singh Committed by Android (Google) Code Review
Browse files

Merge "Move IME to a host display when target's display is reparented"

parents a3511ce6 1e5b1a84
Loading
Loading
Loading
Loading
+52 −0
Original line number Diff line number Diff line
@@ -122,6 +122,7 @@ import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS;
import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT;
import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION;
import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_SCREEN_ON;
import static com.android.server.wm.ProtoLogGroup.WM_ERROR;
import static com.android.server.wm.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
import static com.android.server.wm.RootWindowContainer.TAG_STATES;
import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
@@ -3416,6 +3417,57 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
                && mInputMethodTarget.mActivityRecord.matchParentBounds());
    }

    /**
     * Get IME target that should host IME when this display that is reparented to another
     * WindowState.
     * IME is never displayed in a child display.
     * Use {@link WindowState#getImeControlTarget()} when IME target window
     * which originally called
     * {@link android.view.inputmethod.InputMethodManager#showSoftInput(View, int)} is known.
     *
     * @return {@link WindowState} of host that controls IME.
     *         {@code null} when {@param dc} is not a virtual display.
     * @see DisplayContent#reparent
     */
    @Nullable
    WindowState getImeControlTarget() {
        WindowState imeTarget = mInputMethodTarget;
        if (imeTarget != null) {
            return imeTarget.getImeControlTarget();
        }

        return getInsetsStateController().getImeSourceProvider().getControlTarget().getWindow();
    }

    /**
     * Finds the window which can host IME if IME target cannot host it.
     * e.g. IME target cannot host IME when it's display has a parent display OR when display
     * doesn't support IME/system decorations.
     *
     * @param target current IME target.
     * @return {@link WindowState} that can host IME.
     * @see DisplayContent#getImeControlTarget()
     */
    WindowState getImeHostOrFallback(WindowState target) {
        if (target != null && target.getDisplayContent().canShowIme()) {
            return target;
        }

        // host is in non-default display that doesn't support system decor, default to
        // default display's StatusBar to control IME.
        // TODO: (b/148234093)find a better host OR control IME animation/visibility directly
        //  because it won't work when statusbar isn't available.
        return mWmService.getDefaultDisplayContentLocked().getDisplayPolicy().getStatusBar();
    }

    boolean canShowIme() {
        if (isUntrustedVirtualDisplay()) {
            return false;
        }
        return mWmService.mDisplayWindowSettings.shouldShowImeLocked(this)
                || mWmService.mForceDesktopModeOnExternalDisplays;
    }

    private void setInputMethodTarget(WindowState target, boolean targetWaitingAnim) {
        if (target == mInputMethodTarget && mInputMethodTargetWaitingAnim == targetWaitingAnim) {
            return;
+7 −0
Original line number Diff line number Diff line
@@ -25,6 +25,13 @@ import android.view.WindowInsets.Type.InsetsType;
interface InsetsControlTarget {
    void notifyInsetsControlChanged();

    /**
     * @return {@link WindowState} of this target, if any.
     */
    default WindowState getWindow() {
        return null;
    }

    /**
     * Instructs the control target to show inset sources.
     *
+6 −0
Original line number Diff line number Diff line
@@ -222,6 +222,12 @@ class InsetsSourceProvider {
            // to control the window for now.
            return;
        }
        if (target != null && target.getWindow() != null) {
            // ime control target could be a different window.
            // Refer WindowState#getImeControlTarget().
            target = target.getWindow().getImeControlTarget();
        }

        if (mWin == null) {
            mControlTarget = target;
            return;
+19 −25
Original line number Diff line number Diff line
@@ -6991,8 +6991,15 @@ public class WindowManagerService extends IWindowManager.Stub
            throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission");
        }
        boolean show;
        final DisplayContent dc = mRoot.getDisplayContent(displayId);
        if (dc == null) {
            ProtoLog.w(WM_ERROR,
                    "Attempted to get IME flag of a display that does not exist: %d",
                    displayId);
            return false;
        }
        synchronized (mGlobalLock) {
            show = shouldShowImeSystemWindowUncheckedLocked(displayId);
            show = dc.canShowIme();
        }

        return show;
@@ -7405,15 +7412,13 @@ public class WindowManagerService extends IWindowManager.Stub
        @Override
        public void showImePostLayout(IBinder imeTargetWindowToken) {
            synchronized (mGlobalLock) {
                final WindowState imeTarget = mWindowMap.get(imeTargetWindowToken);
                WindowState imeTarget = mWindowMap.get(imeTargetWindowToken);
                if (imeTarget == null) {
                    return;
                }
                final int displayId = imeTarget.getDisplayId();
                if (!shouldShowImeSystemWindowUncheckedLocked(displayId)) {
                    return;
                }
                imeTarget = imeTarget.getImeControlTarget();

                final int displayId = imeTarget.getDisplayId();
                mRoot.getDisplayContent(displayId).getInsetsStateController().getImeSourceProvider()
                        .scheduleShowImePostLayout(imeTarget);
            }
@@ -7423,12 +7428,16 @@ public class WindowManagerService extends IWindowManager.Stub
        public void hideIme(int displayId) {
            synchronized (mGlobalLock) {
                final DisplayContent dc = mRoot.getDisplayContent(displayId);
                if (dc != null && dc.mInputMethodTarget != null) {
                if (dc != null) {
                    WindowState imeTarget = dc.getImeControlTarget();
                    if (imeTarget == null) {
                        return;
                    }
                    // If there was a pending IME show(), reset it as IME has been
                    // requested to be hidden.
                    dc.getInsetsStateController().getImeSourceProvider().abortShowImePostLayout();
                    dc.mInputMethodControlTarget.hideInsets(WindowInsets.Type.ime(),
                            true /* fromIme */);
                    imeTarget.getDisplayContent().getInsetsStateController().getImeSourceProvider()
                            .abortShowImePostLayout();
                    imeTarget.hideInsets(WindowInsets.Type.ime(), true /* fromIme */);
                }
            }
        }
@@ -7936,21 +7945,6 @@ public class WindowManagerService extends IWindowManager.Stub
        return true;
    }

    private boolean shouldShowImeSystemWindowUncheckedLocked(final int displayId) {
        final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
        if (displayContent == null) {
            ProtoLog.w(WM_ERROR,
                    "Attempted to get IME flag of a display that does not exist: %d",
                    displayId);
            return false;
        }
        if (displayContent.isUntrustedVirtualDisplay()) {
            return false;
        }
        return mDisplayWindowSettings.shouldShowImeLocked(displayContent)
                || mForceDesktopModeOnExternalDisplays;
    }

    @Override
    public void getWindowInsets(WindowManager.LayoutParams attrs,
            int displayId, Rect outContentInsets, Rect outStableInsets,
+23 −0
Original line number Diff line number Diff line
@@ -3517,6 +3517,11 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
        }
    }

    @Override
    public WindowState getWindow() {
        return this;
    }

    @Override
    public void showInsets(@InsetsType int types, boolean fromIme) {
        try {
@@ -5334,6 +5339,24 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
        return false;
    }

    /**
     * Get IME target that should host IME when this window's display has a parent.
     * Note: IME is never hosted by a display that has a parent.
     * When window calling
     * {@link android.view.inputmethod.InputMethodManager#showSoftInput(View, int)} is unknown,
     * use {@link DisplayContent#getImeControlTarget()} instead.
     *
     * @return {@link WindowState} of host that controls the IME.
     *         When window is doesn't have a parent, it is returned as-is.
     */
    WindowState getImeControlTarget() {
        final DisplayContent dc = getDisplayContent();
        final WindowState parentWindow = dc.getParentWindow();

        // If target's display has a parent, IME is displayed in the parent display.
        return dc.getImeHostOrFallback(parentWindow != null ? parentWindow : this);
    }

    @Override
    void assignLayer(Transaction t, int layer) {
        // See comment in assignRelativeLayerForImeTargetChild
Loading