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
This commit is contained in:
Chong Zhang
2016-03-24 10:21:26 -07:00
parent a17893b009
commit baba78319b
4 changed files with 112 additions and 28 deletions

View File

@@ -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<TaskStack> 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;

View File

@@ -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;

View File

@@ -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<TaskStack> stacks = displayContent.getStacks();
@@ -7391,12 +7392,14 @@ public class WindowManagerService extends IWindowManager.Stub
stack.setAdjustedForIme(imeWin);
}
}
displayContent.mDividerControllerLocked.setAdjustedForIme(true, true);
} else {
final ArrayList<TaskStack> 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);
}
}

View File

@@ -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,