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

Commit 5c9d8a6f authored by Ming-Shin Lu's avatar Ming-Shin Lu
Browse files

Attach IME screenshot to non-app main window

In case when dismissing dialog styled application window
can see the IME animated with fade-out as a part of the dialog.

Bug: 201139553
Bug: 212570341
Test: manual as steps with launching a dialog:
   1) Launch Settings -> Network & internet -> Private DNS
   2) Tap the editor to show IME
   3) Press Cancel button to see if IME screenshot is anmating

Change-Id: Ib4c38736908be52f8cbcfe522f4515c5b9aa4e63
parent 5351be9e
Loading
Loading
Loading
Loading
+35 −8
Original line number Diff line number Diff line
@@ -131,6 +131,7 @@ import static com.android.server.wm.DisplayContentProto.SLEEP_TOKENS;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_ALL;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_RECENTS;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_WINDOW_ANIMATION;
import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
import static com.android.server.wm.WindowContainerChildProto.DISPLAY_CONTENT;
@@ -4014,10 +4015,14 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
        // If the IME target is the input target, before it changes, prepare the IME screenshot
        // for the last IME target when its task is applying app transition. This is for the
        // better IME transition to keep IME visibility when transitioning to the next task.
        if (mImeLayeringTarget != null && mImeLayeringTarget.inAppOrRecentsTransition()
                && mImeLayeringTarget == mImeInputTarget) {
        if (mImeLayeringTarget != null && mImeLayeringTarget == mImeInputTarget) {
            boolean nonAppImeTargetAnimatingExit = mImeLayeringTarget.mAnimatingExit
                    && mImeLayeringTarget.mAttrs.type != TYPE_BASE_APPLICATION
                    && mImeLayeringTarget.isSelfAnimating(0, ANIMATION_TYPE_WINDOW_ANIMATION);
            if (mImeLayeringTarget.inAppOrRecentsTransition() || nonAppImeTargetAnimatingExit) {
                showImeScreenshot();
            }
        }

        ProtoLog.i(WM_DEBUG_IME, "setInputMethodTarget %s", target);
        mImeLayeringTarget = target;
@@ -4078,6 +4083,10 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
            mImeTarget = imeTarget;
        }

        WindowState getImeTarget() {
            return mImeTarget;
        }

        private SurfaceControl createImeSurface(SurfaceControl.ScreenshotHardwareBuffer b,
                Transaction t) {
            final HardwareBuffer buffer = b.getHardwareBuffer();
@@ -4088,11 +4097,20 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
            }
            final WindowState imeWindow = mImeTarget.getDisplayContent().mInputMethodWindow;
            final ActivityRecord activity = mImeTarget.mActivityRecord;
            final SurfaceControl imeParent = mImeTarget.mAttrs.type == TYPE_BASE_APPLICATION
                    ? activity.getSurfaceControl()
                    : mImeTarget.getSurfaceControl();
            final SurfaceControl imeSurface = mSurfaceBuilder
                    .setName("IME-snapshot-surface")
                    .setBLASTLayer()
                    .setFormat(buffer.getFormat())
                    .setParent(activity.getSurfaceControl())
                    // Attaching IME snapshot to the associated IME layering target on the
                    // activity when:
                    // - The target is activity main window: attaching on top of the activity.
                    // - The target is non-activity main window (e.g. activity overlay or
                    // dialog-themed activity): attaching on top of the target since the layer has
                    // already above the activity.
                    .setParent(imeParent)
                    .setCallsite("DisplayContent.attachAndShowImeScreenshotOnTarget")
                    .build();
            // Make IME snapshot as trusted overlay
@@ -4101,9 +4119,17 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
            t.setBuffer(imeSurface, buffer);
            t.setColorSpace(activity.mSurfaceControl, ColorSpace.get(ColorSpace.Named.SRGB));
            t.setLayer(imeSurface, 1);
            t.setPosition(imeSurface, imeWindow.getFrame().left - mImeTarget.getFrame().left,
                    imeWindow.getFrame().top - mImeTarget.getFrame().top);

            final Point surfacePosition = new Point(
                    imeWindow.getFrame().left - mImeTarget.getFrame().left,
                    imeWindow.getFrame().top - mImeTarget.getFrame().top);
            if (imeParent == activity.getSurfaceControl()) {
                t.setPosition(imeSurface, surfacePosition.x, surfacePosition.y);
            } else {
                surfacePosition.offset(mImeTarget.mAttrs.surfaceInsets.left,
                        mImeTarget.mAttrs.surfaceInsets.top);
                t.setPosition(imeSurface, surfacePosition.x, surfacePosition.y);
            }
            return imeSurface;
        }

@@ -4195,7 +4221,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
    /** Removes the IME screenshot immediately. */
    void removeImeSurfaceImmediately() {
        if (mImeScreenshot != null) {
            if (DEBUG_INPUT_METHOD) Slog.d(TAG, "remove IME snapshot");
            mImeScreenshot.detach(getSyncTransaction());
            mImeScreenshot = null;
        }
@@ -4509,7 +4534,9 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
     * hierarchy.
     */
    void onWindowAnimationFinished(@NonNull WindowContainer wc, int type) {
        if (type == ANIMATION_TYPE_APP_TRANSITION || type == ANIMATION_TYPE_RECENTS) {
        if (mImeScreenshot != null && (wc == mImeScreenshot.getImeTarget()
                || wc.getWindow(w -> w == mImeScreenshot.getImeTarget()) != null)
                && (type & WindowState.EXIT_ANIMATING_TYPES) != 0) {
            removeImeSurfaceImmediately();
        }
    }
+1 −0
Original line number Diff line number Diff line
@@ -1968,6 +1968,7 @@ public class DisplayContentTests extends WindowTestsBase {
        final WindowState appWin2 = createWindow(null, TYPE_BASE_APPLICATION, act2, "appWin2");
        appWin2.setHasSurface(true);
        assertTrue(appWin2.canBeImeTarget());
        doReturn(true).when(appWin1).isClosing();
        doReturn(true).when(appWin1).inAppOrRecentsTransition();

        // Test step 3: Verify appWin2 will be the next IME target and the IME snapshot surface will