From baba78319b954e8e42b8ecfc03b5fedc28a6168b Mon Sep 17 00:00:00 2001 From: Chong Zhang Date: Thu, 24 Mar 2016 10:21:26 -0700 Subject: [PATCH] Animate IME adjustment for docked stack through the divider This makes sure the top stack crop, divider position and bottom stack surface position moves together with the IME window. Currently the bottom stack and divider are moving together but top stack crop is changed immediately. bug: 27779495 Change-Id: I653ad9093621b218d9c11b0bb2efdddb1d33763e --- .../wm/DockedStackDividerController.java | 60 ++++++++++++++---- .../java/com/android/server/wm/TaskStack.java | 61 ++++++++++++++++--- .../server/wm/WindowManagerService.java | 7 ++- .../server/wm/WindowSurfacePlacer.java | 12 ++-- 4 files changed, 112 insertions(+), 28 deletions(-) diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java index 6741aba35f3c3..68ea4df0c0b0d 100644 --- a/services/core/java/com/android/server/wm/DockedStackDividerController.java +++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java @@ -41,6 +41,8 @@ import android.view.animation.Interpolator; import com.android.server.wm.DimLayer.DimLayerUser; +import java.util.ArrayList; + /** * Keeps information about the docked stack divider. */ @@ -87,7 +89,7 @@ public class DockedStackDividerController implements DimLayerUser { private final DimLayer mDimLayer; private boolean mMinimizedDock; - private boolean mAnimating; + private boolean mAnimatingForMinimizedDockedStack; private boolean mAnimationStarted; private long mAnimationStartTime; private float mAnimationStart; @@ -96,7 +98,8 @@ public class DockedStackDividerController implements DimLayerUser { private final Interpolator mMinimizedDockInterpolator; private float mMaximizeMeetFraction; private final Rect mTouchRegion = new Rect(); - private boolean mAdjustingForIme; + private boolean mAnimatingForIme; + private boolean mAdjustedForIme; DockedStackDividerController(WindowManagerService service, DisplayContent displayContent) { mService = service; @@ -174,12 +177,11 @@ public class DockedStackDividerController implements DimLayerUser { return mLastVisibility; } - void setAdjustingForIme(boolean adjusting) { - mAdjustingForIme = adjusting; - } - - boolean isAdjustingForIme() { - return mAdjustingForIme; + void setAdjustedForIme(boolean adjusted, boolean animate) { + if (mAdjustedForIme != adjusted) { + mAnimatingForIme = animate; + mAdjustedForIme = adjusted; + } } void positionDockedStackedDivider(Rect frame) { @@ -342,6 +344,7 @@ public class DockedStackDividerController implements DimLayerUser { } mMinimizedDock = minimizedDock; + mAnimatingForIme = false; if (minimizedDock) { if (animate) { startAdjustAnimation(0f, 1f); @@ -358,7 +361,7 @@ public class DockedStackDividerController implements DimLayerUser { } private void startAdjustAnimation(float from, float to) { - mAnimating = true; + mAnimatingForMinimizedDockedStack = true; mAnimationStarted = false; mAnimationStart = from; mAnimationTarget = to; @@ -380,10 +383,45 @@ public class DockedStackDividerController implements DimLayerUser { } public boolean animate(long now) { - if (!mAnimating) { + if (mAnimatingForMinimizedDockedStack) { + return animateForMinimizedDockedStack(now); + } else if (mAnimatingForIme) { + return animateForIme(); + } else { return false; } + } + private boolean animateForIme() { + boolean updated = false; + boolean animating = false; + + final ArrayList stacks = mDisplayContent.getStacks(); + for (int i = stacks.size() - 1; i >= 0; --i) { + final TaskStack stack = stacks.get(i); + if (stack != null && stack.isAdjustedForIme()) { + updated |= stack.updateAdjustForIme(); + animating |= stack.isAnimatingForIme(); + } + } + + if (updated) { + mService.mWindowPlacerLocked.performSurfacePlacement(); + } + + if (!animating) { + mAnimatingForIme = false; + for (int i = stacks.size() - 1; i >= 0; --i) { + final TaskStack stack = stacks.get(i); + if (stack != null) { + stack.clearImeGoingAway(); + } + } + } + return animating; + } + + private boolean animateForMinimizedDockedStack(long now) { final TaskStack stack = mDisplayContent.getDockedStackVisibleForUserLocked(); if (!mAnimationStarted) { mAnimationStarted = true; @@ -406,7 +444,7 @@ public class DockedStackDividerController implements DimLayerUser { } } if (t >= 1.0f) { - mAnimating = false; + mAnimatingForMinimizedDockedStack = false; return false; } else { return true; diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java index 8d67771e0bff1..0bf7102ddeb87 100644 --- a/services/core/java/com/android/server/wm/TaskStack.java +++ b/services/core/java/com/android/server/wm/TaskStack.java @@ -55,6 +55,11 @@ public class TaskStack implements DimLayer.DimLayerUser, // If the stack should be resized to fullscreen. private static final boolean FULLSCREEN = true; + // When we have a top-bottom split screen, we shift the bottom stack up to accommodate + // the IME window. The static flag below controls whether to run animation when the + // IME window goes away. + private static final boolean ANIMATE_IME_GOING_AWAY = false; + /** Unique identifier */ final int mStackId; @@ -107,6 +112,7 @@ public class TaskStack implements DimLayer.DimLayerUser, private final Rect mLastContentBounds = new Rect(); private final Rect mTmpAdjustedBounds = new Rect(); private boolean mAdjustedForIme; + private boolean mImeGoingAway; private WindowState mImeWin; private float mMinimizeAmount; private final int mDockedStackMinimizeThickness; @@ -796,19 +802,54 @@ public class TaskStack implements DimLayer.DimLayerUser, void setAdjustedForIme(WindowState imeWin) { mAdjustedForIme = true; mImeWin = imeWin; - if (updateAdjustedBounds()) { - getDisplayContent().mDividerControllerLocked.setAdjustingForIme(true); + mImeGoingAway = false; + } + + boolean isAdjustedForIme() { + return mAdjustedForIme || mImeGoingAway; + } + void clearImeGoingAway() { + mImeGoingAway = false; + } + + boolean isAnimatingForIme() { + return mImeWin != null && mImeWin.isAnimatingLw(); + } + + /** + * Update the stack's bounds (crop or position) according to the IME window's + * current position. When IME window is animated, the bottom stack is animated + * together to track the IME window's current position, and the top stack is + * cropped as necessary. + * + * @return true if a traversal should be performed after the adjustment. + */ + boolean updateAdjustForIme() { + boolean stopped = false; + if (mImeGoingAway && (!ANIMATE_IME_GOING_AWAY || !isAnimatingForIme())) { + mImeWin = null; + mAdjustedForIme = false; + stopped = true; } + // Make sure to run a traversal when the animation stops so that the stack + // is moved to its final position. + return updateAdjustedBounds() || stopped; } /** * Resets the adjustment after it got adjusted for the IME. + * @param adjustBoundsNow if true, reset and update the bounds immediately and forget about + * animations; otherwise, set flag and animates the window away together + * with IME window. */ - void resetAdjustedForIme() { - mAdjustedForIme = false; - mImeWin = null; - if (updateAdjustedBounds()) { - getDisplayContent().mDividerControllerLocked.setAdjustingForIme(true); + void resetAdjustedForIme(boolean adjustBoundsNow) { + if (adjustBoundsNow) { + mImeWin = null; + mAdjustedForIme = false; + mImeGoingAway = false; + updateAdjustedBounds(); + } else { + mImeGoingAway |= mAdjustedForIme; } } @@ -843,6 +884,12 @@ public class TaskStack implements DimLayer.DimLayerUser, getDisplayContent().getContentRect(displayContentRect); contentBounds.set(displayContentRect); int imeTop = Math.max(imeWin.getDisplayFrameLw().top, contentBounds.top); + + // if IME window is animating, get its actual vertical shown position (but no smaller than + // the final target vertical position) + if (imeWin.isAnimatingLw()) { + imeTop = Math.max(imeTop, imeWin.getShownPositionLw().y); + } imeTop += imeWin.getGivenContentInsetsLw().top; if (contentBounds.bottom > imeTop) { contentBounds.bottom = imeTop; diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 5771d691c6948..d55d3b89985d8 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -7380,8 +7380,9 @@ public class WindowManagerService extends IWindowManager.Stub final WindowState imeWin = mInputMethodWindow; final TaskStack focusedStack = mCurrentFocus != null ? mCurrentFocus.getStack() : null; + final boolean dockVisible = isStackVisibleLocked(DOCKED_STACK_ID); if (imeWin != null && imeWin.isVisibleLw() && imeWin.isDisplayedLw() - && isStackVisibleLocked(DOCKED_STACK_ID) + && dockVisible && focusedStack != null && focusedStack.getDockSide() == DOCKED_BOTTOM){ final ArrayList stacks = displayContent.getStacks(); @@ -7391,12 +7392,14 @@ public class WindowManagerService extends IWindowManager.Stub stack.setAdjustedForIme(imeWin); } } + displayContent.mDividerControllerLocked.setAdjustedForIme(true, true); } else { final ArrayList stacks = displayContent.getStacks(); for (int i = stacks.size() - 1; i >= 0; --i) { final TaskStack stack = stacks.get(i); - stack.resetAdjustedForIme(); + stack.resetAdjustedForIme(!dockVisible); } + displayContent.mDividerControllerLocked.setAdjustedForIme(false, dockVisible); } } diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java index 3b0081d6376f3..3e5ddbce5a7b3 100644 --- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java +++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java @@ -693,16 +693,14 @@ class WindowSurfacePlacer { // currently animating... let's do something. final int left = w.mFrame.left; final int top = w.mFrame.top; - final boolean adjustedForMinimizedDockedStack = w.getTask() != null && - w.getTask().mStack.isAdjustedForMinimizedDockedStack(); + final boolean adjustedForMinimizedDockOrIme = task != null + && (task.mStack.isAdjustedForMinimizedDockedStack() + || task.mStack.isAdjustedForIme()); if ((w.mAttrs.privateFlags & PRIVATE_FLAG_NO_MOVE_ANIMATION) == 0 - && !w.isDragResizing() && !adjustedForMinimizedDockedStack + && !w.isDragResizing() && !adjustedForMinimizedDockOrIme && (task == null || !w.getTask().mStack.getFreezeMovementAnimations()) && !w.mWinAnimator.mLastHidden) { winAnimator.setMoveAnimation(left, top); - } else if (w.mAttrs.type == TYPE_DOCK_DIVIDER && - displayContent.getDockedDividerController().isAdjustingForIme()) { - winAnimator.setMoveAnimation(left, top); } //TODO (multidisplay): Accessibility supported only for the default display. @@ -819,8 +817,6 @@ class WindowSurfacePlacer { mService.updateResizingWindows(w); } - displayContent.getDockedDividerController().setAdjustingForIme(false); - mService.mDisplayManagerInternal.setDisplayProperties(displayId, mDisplayHasContent, mPreferredRefreshRate,