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

Commit 35e13681 authored by Chong Zhang's avatar Chong Zhang Committed by android-build-merger
Browse files

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

am: 3966fb94

* commit '3966fb94':
  Fix IME adjust when stack focus changes while IME is visible

Change-Id: I53a0d8101b13443c30182909d02d952fce2fede6
parents b6060a3f 3966fb94
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);