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

Commit 3966fb94 authored by Chong Zhang's avatar Chong Zhang Committed by Android (Google) Code Review
Browse files

Merge "Fix IME adjust when stack focus changes while IME is visible" into nyc-dev

parents a645c975 f347ab5e
Loading
Loading
Loading
Loading
+46 −13
Original line number Diff line number Diff line
@@ -116,6 +116,11 @@ public class DockedStackDividerController implements DimLayerUser {
    private boolean mAnimatingForIme;
    private boolean mAdjustedForIme;
    private WindowState mDelayedImeWin;
    private boolean mAdjustedForDivider;
    private float mDividerAnimationStart;
    private float mDividerAnimationTarget;
    private float mLastAnimationProgress;
    private float mLastDividerProgress;

    DockedStackDividerController(WindowManagerService service, DisplayContent displayContent) {
        mService = service;
@@ -208,16 +213,18 @@ public class DockedStackDividerController implements DimLayerUser {
        return mLastVisibility;
    }

    void setAdjustedForIme(boolean adjusted, boolean animate, WindowState imeWin) {
        if (mAdjustedForIme != adjusted) {
            mAdjustedForIme = adjusted;
    void setAdjustedForIme(
            boolean adjustedForIme, boolean adjustedForDivider,
            boolean animate, WindowState imeWin) {
        if (mAdjustedForIme != adjustedForIme || mAdjustedForDivider != adjustedForDivider) {
            if (animate) {
                startImeAdjustAnimation(adjusted, imeWin);
                startImeAdjustAnimation(adjustedForIme, adjustedForDivider, imeWin);
            } else {

                // Animation might be delayed, so only notify if we don't run an animation.
                notifyAdjustedForImeChanged(adjusted, 0 /* duration */);
                notifyAdjustedForImeChanged(adjustedForIme || adjustedForDivider, 0 /* duration */);
            }
            mAdjustedForIme = adjustedForIme;
            mAdjustedForDivider = adjustedForDivider;
        }
    }

@@ -457,11 +464,25 @@ public class DockedStackDividerController implements DimLayerUser {
        mAnimationTarget = to;
    }

    private void startImeAdjustAnimation(boolean adjusted, WindowState imeWin) {
    private void startImeAdjustAnimation(
            boolean adjustedForIme, boolean adjustedForDivider, WindowState imeWin) {
        mAnimatingForIme = true;
        mAnimationStarted = false;
        mAnimationStart = adjusted ? 0 : 1;
        mAnimationTarget = adjusted ? 1 : 0;

        // If we're not in an animation, the starting point depends on whether we're adjusted
        // or not. If we're already in an animation, we start from where the current animation
        // left off, so that the motion doesn't look discontinuous.
        if (!mAnimatingForIme) {
            mAnimationStart = mAdjustedForIme ? 1 : 0;
            mDividerAnimationStart = mAdjustedForDivider ? 1 : 0;
            mLastAnimationProgress = mAnimationStart;
            mLastDividerProgress = mDividerAnimationStart;
        } else {
            mAnimationStart = mLastAnimationProgress;
            mDividerAnimationStart = mLastDividerProgress;
        }
        mAnimationTarget = adjustedForIme ? 1 : 0;
        mDividerAnimationTarget = adjustedForDivider ? 1 : 0;

        final ArrayList<TaskStack> stacks = mDisplayContent.getStacks();
        for (int i = stacks.size() - 1; i >= 0; --i) {
@@ -492,10 +513,12 @@ public class DockedStackDividerController implements DimLayerUser {
                if (mDelayedImeWin != null) {
                    mDelayedImeWin.mWinAnimator.endDelayingAnimationStart();
                }
                notifyAdjustedForImeChanged(adjusted, IME_ADJUST_ANIM_DURATION);
                notifyAdjustedForImeChanged(
                        adjustedForIme || adjustedForDivider, IME_ADJUST_ANIM_DURATION);
            };
        } else {
            notifyAdjustedForImeChanged(adjusted, IME_ADJUST_ANIM_DURATION);
            notifyAdjustedForImeChanged(
                    adjustedForIme || adjustedForDivider, IME_ADJUST_ANIM_DURATION);
        }
    }

@@ -539,11 +562,15 @@ public class DockedStackDividerController implements DimLayerUser {
        for (int i = stacks.size() - 1; i >= 0; --i) {
            final TaskStack stack = stacks.get(i);
            if (stack != null && stack.isAdjustedForIme()) {
                if (t >= 1f && mAnimationTarget == 0f) {
                if (t >= 1f && mAnimationTarget == 0f && mDividerAnimationTarget == 0f) {
                    stack.resetAdjustedForIme(true /* adjustBoundsNow */);
                    updated = true;
                } else {
                    updated |= stack.updateAdjustForIme(getInterpolatedAnimationValue(t),
                    mLastAnimationProgress = getInterpolatedAnimationValue(t);
                    mLastDividerProgress = getInterpolatedDividerValue(t);
                    updated |= stack.updateAdjustForIme(
                            mLastAnimationProgress,
                            mLastDividerProgress,
                            false /* force */);
                }
                if (t >= 1f) {
@@ -555,6 +582,8 @@ public class DockedStackDividerController implements DimLayerUser {
            mService.mWindowPlacerLocked.performSurfacePlacement();
        }
        if (t >= 1.0f) {
            mLastAnimationProgress = mAnimationTarget;
            mLastDividerProgress = mDividerAnimationTarget;
            mAnimatingForIme = false;
            return false;
        } else {
@@ -596,6 +625,10 @@ public class DockedStackDividerController implements DimLayerUser {
        return t * mAnimationTarget + (1 - t) * mAnimationStart;
    }

    private float getInterpolatedDividerValue(float t) {
        return t * mDividerAnimationTarget + (1 - t) * mDividerAnimationStart;
    }

    /**
     * Gets the amount how much to minimize a stack depending on the interpolated fraction t.
     */
+31 −23
Original line number Diff line number Diff line
@@ -126,6 +126,7 @@ public class TaskStack implements DimLayer.DimLayerUser,
    private WindowState mImeWin;
    private float mMinimizeAmount;
    private float mAdjustImeAmount;
    private float mAdjustDividerAmount;
    private final int mDockedStackMinimizeThickness;

    // If this is true, we are in the bounds animating mode.
@@ -853,7 +854,8 @@ public class TaskStack implements DimLayer.DimLayerUser,
        if (!mAdjustedForIme) {
            mAdjustedForIme = true;
            mAdjustImeAmount = 0f;
            updateAdjustForIme(0f, true /* force */);
            mAdjustDividerAmount = 0f;
            updateAdjustForIme(0f, 0f, true /* force */);
        }
    }

@@ -873,9 +875,11 @@ public class TaskStack implements DimLayer.DimLayerUser,
     *
     * @return true if a traversal should be performed after the adjustment.
     */
    boolean updateAdjustForIme(float adjustAmount, boolean force) {
        if (adjustAmount != mAdjustImeAmount || force) {
    boolean updateAdjustForIme(float adjustAmount, float adjustDividerAmount, boolean force) {
        if (adjustAmount != mAdjustImeAmount
                || adjustDividerAmount != mAdjustDividerAmount || force) {
            mAdjustImeAmount = adjustAmount;
            mAdjustDividerAmount = adjustDividerAmount;
            updateAdjustedBounds();
            return isVisibleForUserLocked();
        } else {
@@ -895,6 +899,7 @@ public class TaskStack implements DimLayer.DimLayerUser,
            mAdjustedForIme = false;
            mImeGoingAway = false;
            mAdjustImeAmount = 0f;
            mAdjustDividerAmount = 0f;
            updateAdjustedBounds();
            mService.setResizeDimLayer(false, mStackId, 1.0f);
        } else {
@@ -992,25 +997,27 @@ public class TaskStack implements DimLayer.DimLayerUser,
                    (int) (mAdjustImeAmount * bottom + (1 - mAdjustImeAmount) * mBounds.bottom);
            mFullyAdjustedImeBounds.set(mBounds);
        } else {
            final int top;
            final boolean isFocusedStack = mService.getFocusedStackLocked() == this;
            if (isFocusedStack) {
                // If this stack is docked on bottom and has focus, we shift it up so that it's not
                // occluded by IME. We try to move it up by the height of the IME window, but only
                // to the extent that leaves at least 30% of the top stack visible.
            // When the stack is on bottom and has no focus, it's only adjusted for divider width.
            final int dividerWidthDelta = dividerWidthInactive - dividerWidth;

            // When the stack is on bottom and has focus, it needs to be moved up so as to
            // not occluded by IME, and at the same time adjusted for divider width.
            // We try to move it up by the height of the IME window, but only to the extent
            // that leaves at least 30% of the top stack visible.
            // 'top' is where the top of bottom stack will move to in this case.
            final int topBeforeImeAdjust = mBounds.top - dividerWidth + dividerWidthInactive;
            final int minTopStackBottom =
                    getMinTopStackBottom(displayContentRect, mBounds.top - dividerWidth);
                top = Math.max(
            final int top = Math.max(
                    mBounds.top - yOffset, minTopStackBottom + dividerWidthInactive);
            } else {
                // If this stack is docked on bottom but doesn't have focus, we don't need to adjust
                // for IME, but still need to apply a small adjustment due to the thinner divider.
                top = mBounds.top - dividerWidth + dividerWidthInactive;
            }

            mTmpAdjustedBounds.set(mBounds);
            mTmpAdjustedBounds.top =
                    (int) (mAdjustImeAmount * top + (1 - mAdjustImeAmount) * mBounds.top);
            // Account for the adjustment for IME and divider width separately.
            // (top - topBeforeImeAdjust) is the amount of movement due to IME only,
            // and dividerWidthDelta is due to divider width change only.
            mTmpAdjustedBounds.top = mBounds.top +
                    (int) (mAdjustImeAmount * (top - topBeforeImeAdjust) +
                            mAdjustDividerAmount * dividerWidthDelta);
            mFullyAdjustedImeBounds.set(mBounds);
            mFullyAdjustedImeBounds.top = top;
            mFullyAdjustedImeBounds.bottom = top + mBounds.height();
@@ -1082,9 +1089,10 @@ public class TaskStack implements DimLayer.DimLayerUser,
        }
        setAdjustedBounds(mTmpAdjustedBounds);

        final boolean isFocusedStack = mService.getFocusedStackLocked() == this;
        if (mAdjustedForIme && adjust && !isFocusedStack) {
            final float alpha = mAdjustImeAmount * IME_ADJUST_DIM_AMOUNT;
        final boolean isImeTarget = (mService.getImeTargetStackLocked() == this);
        if (mAdjustedForIme && adjust && !isImeTarget) {
            final float alpha = Math.max(mAdjustImeAmount, mAdjustDividerAmount)
                    * IME_ADJUST_DIM_AMOUNT;
            mService.setResizeDimLayer(true, mStackId, alpha);
        }
    }
+21 −22
Original line number Diff line number Diff line
@@ -7455,27 +7455,38 @@ public class WindowManagerService extends IWindowManager.Stub

    void adjustForImeIfNeeded(final DisplayContent displayContent) {
        final WindowState imeWin = mInputMethodWindow;
        final TaskStack focusedStack = getFocusedStackLocked();
        final boolean imeVisible = imeWin != null && imeWin.isVisibleLw() && imeWin.isDisplayedLw();
        final boolean dockVisible = isStackVisibleLocked(DOCKED_STACK_ID);
        if (imeWin != null && imeWin.isVisibleLw() && imeWin.isDisplayedLw()
                && dockVisible && focusedStack != null) {
            final boolean isFocusOnBottom = focusedStack.getDockSide() == DOCKED_BOTTOM;
        final TaskStack imeTargetStack = getImeTargetStackLocked();

        // The divider could be adjusted for IME position, or be thinner than usual,
        // or both. There are three possible cases:
        // - If IME is visible, and focus is on top, divider is not moved for IME but thinner.
        // - If IME is visible, and focus is on bottom, divider is moved for IME and thinner.
        // - If IME is not visible, divider is not moved and is normal width.

        if (imeVisible && dockVisible && imeTargetStack != null) {
            final boolean isFocusOnBottom = imeTargetStack.getDockSide() == DOCKED_BOTTOM;
            final ArrayList<TaskStack> stacks = displayContent.getStacks();
            for (int i = stacks.size() - 1; i >= 0; --i) {
                final TaskStack stack = stacks.get(i);
                final boolean isDockedOnBottom = stack.getDockSide() == DOCKED_BOTTOM;
                if (stack.isVisibleLocked() && (isFocusOnBottom || isDockedOnBottom)) {
                    stack.setAdjustedForIme(imeWin);
                } else {
                    stack.resetAdjustedForIme(false);
                }
            }
            displayContent.mDividerControllerLocked.setAdjustedForIme(true, true, imeWin);
            displayContent.mDividerControllerLocked.setAdjustedForIme(
                    isFocusOnBottom /*ime*/, true /*divider*/, true /*animate*/, imeWin);
        } else {
            final ArrayList<TaskStack> stacks = displayContent.getStacks();
            for (int i = stacks.size() - 1; i >= 0; --i) {
                final TaskStack stack = stacks.get(i);
                stack.resetAdjustedForIme(!dockVisible);
            }
            displayContent.mDividerControllerLocked.setAdjustedForIme(false, dockVisible, imeWin);
            displayContent.mDividerControllerLocked.setAdjustedForIme(
                    false /*ime*/, false /*divider*/, dockVisible /*animate*/, null);
        }
    }

@@ -7608,8 +7619,10 @@ public class WindowManagerService extends IWindowManager.Stub
        return mCurrentFocus;
    }

    TaskStack getFocusedStackLocked() {
        return mCurrentFocus != null ? mCurrentFocus.getStack() : null;
    TaskStack getImeTargetStackLocked() {
        // Don't use WindowState.getStack() because it returns home stack for system windows.
        Task imeTask = mInputMethodTarget != null ? mInputMethodTarget.getTask() : null;
        return imeTask != null ? imeTask.mStack : null;
    }

    private void showAuditSafeModeNotification() {
@@ -9354,7 +9367,6 @@ public class WindowManagerService extends IWindowManager.Stub
        WindowState newFocus = computeFocusedWindowLocked();
        if (mCurrentFocus != newFocus) {
            Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmUpdateFocus");
            TaskStack oldFocusedStack = getFocusedStackLocked();
            // This check makes sure that we don't already have the focus
            // change message pending.
            mH.removeMessages(H.REPORT_FOCUS_CHANGE);
@@ -9376,7 +9388,6 @@ public class WindowManagerService extends IWindowManager.Stub
            mLosingFocus.remove(newFocus);

            int focusChanged = mPolicy.focusChangedLw(oldFocus, newFocus);
            TaskStack newFocusedStack = getFocusedStackLocked();

            if (imWindowChanged && oldFocus != mInputMethodWindow) {
                // Focus of the input method window changed. Perform layout if needed.
@@ -9406,18 +9417,6 @@ public class WindowManagerService extends IWindowManager.Stub
                mInputMonitor.setInputFocusLw(mCurrentFocus, updateInputWindows);
            }

            // TODO: Reset and re-apply IME adjustment if needed when stack focus changed.
            // This makes sure divider starts an animation from pre-adjust position to final
            // position. Ideally we want to skip the reset and animation from current position
            // directly to final position.
            final WindowState imeWin = mInputMethodWindow;
            if (oldFocusedStack != null) {
                oldFocusedStack.resetAdjustedForIme(true);
            }
            if (newFocusedStack != null) {
                newFocusedStack.resetAdjustedForIme(true);
            }
            displayContent.mDividerControllerLocked.setAdjustedForIme(false, false, imeWin);
            adjustForImeIfNeeded(displayContent);

            Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);