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

Commit 46e68011 authored by Evan Rosky's avatar Evan Rosky
Browse files

Finish supporting floating-IME alpha in split-screen

There are a couple situations that cause floating IME:
zero-sized frame due to fullscreenIme and the IME itself
providing a frame that doesn't generate insets.

This CL adds detection for an IME frame that doesn't provide
insets and it also allows the subsidiary IME processers (like
divider) to disable alpha animation. This is necessary because
when divider adjust for ime, there is no content behind the
ime, so we can't have it fade in/out; however, if the divider
doesn't adjust, we want the fade in/out so it matches the
ime behavior when not in split.

Bug: 160915523
Test: Use fullscreen IME as well as making gboard floating.
      Open ime in either top or bottom for both cases.
Change-Id: If6fd192c6e7f843a958d98bf40c4d0866d818394
parent c2322518
Loading
Loading
Loading
Loading
+8 −5
Original line number Original line Diff line number Diff line
@@ -126,18 +126,20 @@ class DividerImeController implements DisplayImeController.ImePositionProcessor
    }
    }


    @Override
    @Override
    public void onImeStartPositioning(int displayId, int hiddenTop, int shownTop,
    @ImeAnimationFlags
            boolean imeShouldShow, SurfaceControl.Transaction t) {
    public int onImeStartPositioning(int displayId, int hiddenTop, int shownTop,
            boolean imeShouldShow, boolean imeIsFloating, SurfaceControl.Transaction t) {
        mHiddenTop = hiddenTop;
        mHiddenTop = hiddenTop;
        mShownTop = shownTop;
        mShownTop = shownTop;
        mTargetShown = imeShouldShow;
        mTargetShown = imeShouldShow;
        if (!isDividerVisible()) {
        if (!isDividerVisible()) {
            return;
            return 0;
        }
        }
        final boolean splitIsVisible = !getView().isHidden();
        final boolean splitIsVisible = !getView().isHidden();
        mSecondaryHasFocus = getSecondaryHasFocus(displayId);
        mSecondaryHasFocus = getSecondaryHasFocus(displayId);
        final boolean targetAdjusted = splitIsVisible && imeShouldShow && mSecondaryHasFocus
        final boolean targetAdjusted = splitIsVisible && imeShouldShow && mSecondaryHasFocus
                && !getLayout().mDisplayLayout.isLandscape() && !mSplits.mDivider.isMinimized();
                && !imeIsFloating && !getLayout().mDisplayLayout.isLandscape()
                && !mSplits.mDivider.isMinimized();
        if (mLastAdjustTop < 0) {
        if (mLastAdjustTop < 0) {
            mLastAdjustTop = imeShouldShow ? hiddenTop : shownTop;
            mLastAdjustTop = imeShouldShow ? hiddenTop : shownTop;
        } else if (mLastAdjustTop != (imeShouldShow ? mShownTop : mHiddenTop)) {
        } else if (mLastAdjustTop != (imeShouldShow ? mShownTop : mHiddenTop)) {
@@ -155,7 +157,7 @@ class DividerImeController implements DisplayImeController.ImePositionProcessor
        if (mPaused) {
        if (mPaused) {
            mPausedTargetAdjusted = targetAdjusted;
            mPausedTargetAdjusted = targetAdjusted;
            if (DEBUG) Slog.d(TAG, " ime starting but paused " + dumpState());
            if (DEBUG) Slog.d(TAG, " ime starting but paused " + dumpState());
            return;
            return (targetAdjusted || mAdjusted) ? IME_ANIMATION_NO_ALPHA : 0;
        }
        }
        mTargetAdjusted = targetAdjusted;
        mTargetAdjusted = targetAdjusted;
        updateDimTargets();
        updateDimTargets();
@@ -174,6 +176,7 @@ class DividerImeController implements DisplayImeController.ImePositionProcessor
        } else {
        } else {
            mAdjustedWhileHidden = true;
            mAdjustedWhileHidden = true;
        }
        }
        return (mTargetAdjusted || mAdjusted) ? IME_ANIMATION_NO_ALPHA : 0;
    }
    }


    private void updateImeAdjustState() {
    private void updateImeAdjustState() {
+54 −13
Original line number Original line Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.systemui.wm;
import android.animation.Animator;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator;
import android.annotation.IntDef;
import android.content.Context;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Configuration;
import android.graphics.Point;
import android.graphics.Point;
@@ -136,12 +137,16 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged
        }
        }
    }
    }


    private void dispatchStartPositioning(int displayId, int hiddenTop, int shownTop,
    @ImePositionProcessor.ImeAnimationFlags
            boolean show, SurfaceControl.Transaction t) {
    private int dispatchStartPositioning(int displayId, int hiddenTop, int shownTop,
            boolean show, boolean isFloating, SurfaceControl.Transaction t) {
        synchronized (mPositionProcessors) {
        synchronized (mPositionProcessors) {
            int flags = 0;
            for (ImePositionProcessor pp : mPositionProcessors) {
            for (ImePositionProcessor pp : mPositionProcessors) {
                pp.onImeStartPositioning(displayId, hiddenTop, shownTop, show, t);
                flags |= pp.onImeStartPositioning(
                        displayId, hiddenTop, shownTop, show, isFloating, t);
            }
            }
            return flags;
        }
        }
    }
    }


@@ -184,6 +189,7 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged
        int mRotation = Surface.ROTATION_0;
        int mRotation = Surface.ROTATION_0;
        boolean mImeShowing = false;
        boolean mImeShowing = false;
        final Rect mImeFrame = new Rect();
        final Rect mImeFrame = new Rect();
        boolean mAnimateAlpha = true;


        PerDisplay(int displayId, int initialRotation) {
        PerDisplay(int displayId, int initialRotation) {
            mDisplayId = displayId;
            mDisplayId = displayId;
@@ -268,15 +274,29 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged
            return mImeFrame.top + (int) surfaceOffset;
            return mImeFrame.top + (int) surfaceOffset;
        }
        }


        private boolean calcIsFloating(InsetsSource imeSource) {
            final Rect frame = imeSource.getFrame();
            if (frame.height() == 0) {
                return true;
            }
            // Some Floating Input Methods will still report a frame, but the frame is actually
            // a nav-bar inset created by WM and not part of the IME (despite being reported as
            // an IME inset). For now, we assume that no non-floating IME will be <= this nav bar
            // frame height so any reported frame that is <= nav-bar frame height is assumed to
            // be floating.
            return frame.height() <= mSystemWindows.mDisplayController.getDisplayLayout(mDisplayId)
                    .navBarFrameHeight();
        }

        private void startAnimation(final boolean show, final boolean forceRestart) {
        private void startAnimation(final boolean show, final boolean forceRestart) {
            final InsetsSource imeSource = mInsetsState.getSource(InsetsState.ITYPE_IME);
            final InsetsSource imeSource = mInsetsState.getSource(InsetsState.ITYPE_IME);
            if (imeSource == null || mImeSourceControl == null) {
            if (imeSource == null || mImeSourceControl == null) {
                return;
                return;
            }
            }
            final Rect newFrame = imeSource.getFrame();
            final Rect newFrame = imeSource.getFrame();
            final boolean isFloating = newFrame.height() == 0 && show;
            final boolean isFloating = calcIsFloating(imeSource) && show;
            if (isFloating) {
            if (isFloating) {
                // This is likely a "floating" or "expanded" IME, so to get animations, just
                // This is a "floating" or "expanded" IME, so to get animations, just
                // pretend the ime has some size just below the screen.
                // pretend the ime has some size just below the screen.
                mImeFrame.set(newFrame);
                mImeFrame.set(newFrame);
                final int floatingInset = (int) (
                final int floatingInset = (int) (
@@ -329,7 +349,8 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged
                SurfaceControl.Transaction t = mTransactionPool.acquire();
                SurfaceControl.Transaction t = mTransactionPool.acquire();
                float value = (float) animation.getAnimatedValue();
                float value = (float) animation.getAnimatedValue();
                t.setPosition(mImeSourceControl.getLeash(), x, value);
                t.setPosition(mImeSourceControl.getLeash(), x, value);
                final float alpha = isFloating ? (value - hiddenY) / (shownY - hiddenY) : 1.f;
                final float alpha = (mAnimateAlpha || isFloating)
                        ? (value - hiddenY) / (shownY - hiddenY) : 1.f;
                t.setAlpha(mImeSourceControl.getLeash(), alpha);
                t.setAlpha(mImeSourceControl.getLeash(), alpha);
                dispatchPositionChanged(mDisplayId, imeTop(value), t);
                dispatchPositionChanged(mDisplayId, imeTop(value), t);
                t.apply();
                t.apply();
@@ -342,16 +363,18 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged
                public void onAnimationStart(Animator animation) {
                public void onAnimationStart(Animator animation) {
                    SurfaceControl.Transaction t = mTransactionPool.acquire();
                    SurfaceControl.Transaction t = mTransactionPool.acquire();
                    t.setPosition(mImeSourceControl.getLeash(), x, startY);
                    t.setPosition(mImeSourceControl.getLeash(), x, startY);
                    final float alpha = isFloating ? (startY - hiddenY) / (shownY - hiddenY) : 1.f;
                    t.setAlpha(mImeSourceControl.getLeash(), alpha);
                    if (DEBUG) {
                    if (DEBUG) {
                        Slog.d(TAG, "onAnimationStart d:" + mDisplayId + " top:"
                        Slog.d(TAG, "onAnimationStart d:" + mDisplayId + " top:"
                                + imeTop(hiddenY) + "->" + imeTop(shownY)
                                + imeTop(hiddenY) + "->" + imeTop(shownY)
                                + " showing:" + (mAnimationDirection == DIRECTION_SHOW));
                                + " showing:" + (mAnimationDirection == DIRECTION_SHOW));
                    }
                    }
                    dispatchStartPositioning(mDisplayId, imeTop(hiddenY),
                    int flags = dispatchStartPositioning(mDisplayId, imeTop(hiddenY),
                            imeTop(shownY), mAnimationDirection == DIRECTION_SHOW,
                            imeTop(shownY), mAnimationDirection == DIRECTION_SHOW, isFloating, t);
                            t);
                    mAnimateAlpha = (flags & ImePositionProcessor.IME_ANIMATION_NO_ALPHA) == 0;
                    final float alpha = (mAnimateAlpha || isFloating)
                            ? (startY - hiddenY) / (shownY - hiddenY)
                            : 1.f;
                    t.setAlpha(mImeSourceControl.getLeash(), alpha);
                    if (mAnimationDirection == DIRECTION_SHOW) {
                    if (mAnimationDirection == DIRECTION_SHOW) {
                        t.show(mImeSourceControl.getLeash());
                        t.show(mImeSourceControl.getLeash());
                    }
                    }
@@ -413,6 +436,19 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged
     * Allows other things to synchronize with the ime position
     * Allows other things to synchronize with the ime position
     */
     */
    public interface ImePositionProcessor {
    public interface ImePositionProcessor {
        /**
         * Indicates that ime shouldn't animate alpha. It will always be opaque. Used when stuff
         * behind the IME shouldn't be visible (for example during split-screen adjustment where
         * there is nothing behind the ime).
         */
        int IME_ANIMATION_NO_ALPHA = 1;

        /** @hide */
        @IntDef(prefix = { "IME_ANIMATION_" }, value = {
                IME_ANIMATION_NO_ALPHA,
        })
        @interface ImeAnimationFlags {}

        /**
        /**
         * Called when the IME position is starting to animate.
         * Called when the IME position is starting to animate.
         *
         *
@@ -420,9 +456,14 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged
         * @param shownTop  The y position of the top of the IME surface when it is shown.
         * @param shownTop  The y position of the top of the IME surface when it is shown.
         * @param showing   {@code true} when we are animating from hidden to shown, {@code false}
         * @param showing   {@code true} when we are animating from hidden to shown, {@code false}
         *                  when animating from shown to hidden.
         *                  when animating from shown to hidden.
         * @param isFloating {@code true} when the ime is a floating ime (doesn't inset).
         * @return flags that may alter how ime itself is animated (eg. no-alpha).
         */
         */
        default void onImeStartPositioning(int displayId, int hiddenTop, int shownTop,
        @ImeAnimationFlags
                boolean showing, SurfaceControl.Transaction t) {}
        default int onImeStartPositioning(int displayId, int hiddenTop, int shownTop,
                boolean showing, boolean isFloating, SurfaceControl.Transaction t) {
            return 0;
        }


        /**
        /**
         * Called when the ime position changed. This is expected to be a synchronous call on the
         * Called when the ime position changed. This is expected to be a synchronous call on the
+15 −0
Original line number Original line Diff line number Diff line
@@ -79,6 +79,7 @@ public class DisplayLayout {
    private final Rect mStableInsets = new Rect();
    private final Rect mStableInsets = new Rect();
    private boolean mHasNavigationBar = false;
    private boolean mHasNavigationBar = false;
    private boolean mHasStatusBar = false;
    private boolean mHasStatusBar = false;
    private int mNavBarFrameHeight = 0;


    /**
    /**
     * Create empty layout.
     * Create empty layout.
@@ -146,6 +147,7 @@ public class DisplayLayout {
        if (mHasStatusBar) {
        if (mHasStatusBar) {
            convertNonDecorInsetsToStableInsets(res, mStableInsets, mWidth, mHeight, mHasStatusBar);
            convertNonDecorInsetsToStableInsets(res, mStableInsets, mWidth, mHeight, mHasStatusBar);
        }
        }
        mNavBarFrameHeight = getNavigationBarFrameHeight(res, mWidth > mHeight);
    }
    }


    /**
    /**
@@ -214,6 +216,11 @@ public class DisplayLayout {
        return mWidth > mHeight;
        return mWidth > mHeight;
    }
    }


    /** Get the navbar frame height (used by ime). */
    public int navBarFrameHeight() {
        return mNavBarFrameHeight;
    }

    /** Gets the orientation of this layout */
    /** Gets the orientation of this layout */
    public int getOrientation() {
    public int getOrientation() {
        return (mWidth > mHeight) ? ORIENTATION_LANDSCAPE : ORIENTATION_PORTRAIT;
        return (mWidth > mHeight) ? ORIENTATION_LANDSCAPE : ORIENTATION_PORTRAIT;
@@ -483,6 +490,7 @@ public class DisplayLayout {
            } else {
            } else {
                return res.getDimensionPixelSize(R.dimen.navigation_bar_width_car_mode);
                return res.getDimensionPixelSize(R.dimen.navigation_bar_width_car_mode);
            }
            }

        } else {
        } else {
            if (navBarSide == NAV_BAR_BOTTOM) {
            if (navBarSide == NAV_BAR_BOTTOM) {
                return res.getDimensionPixelSize(landscape
                return res.getDimensionPixelSize(landscape
@@ -493,4 +501,11 @@ public class DisplayLayout {
            }
            }
        }
        }
    }
    }

    /** @see com.android.server.wm.DisplayPolicy#getNavigationBarFrameHeight */
    public static int getNavigationBarFrameHeight(Resources res, boolean landscape) {
        return res.getDimensionPixelSize(landscape
                ? R.dimen.navigation_bar_frame_height_landscape
                : R.dimen.navigation_bar_frame_height);
    }
}
}