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

am: 3966fb9

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

Change-Id: I53a0d8101b13443c30182909d02d952fce2fede6
This commit is contained in:
Chong Zhang
2016-04-20 21:00:46 +00:00
committed by android-build-merger
3 changed files with 98 additions and 58 deletions

View File

@@ -116,6 +116,11 @@ public class DockedStackDividerController implements DimLayerUser {
private boolean mAnimatingForIme; private boolean mAnimatingForIme;
private boolean mAdjustedForIme; private boolean mAdjustedForIme;
private WindowState mDelayedImeWin; private WindowState mDelayedImeWin;
private boolean mAdjustedForDivider;
private float mDividerAnimationStart;
private float mDividerAnimationTarget;
private float mLastAnimationProgress;
private float mLastDividerProgress;
DockedStackDividerController(WindowManagerService service, DisplayContent displayContent) { DockedStackDividerController(WindowManagerService service, DisplayContent displayContent) {
mService = service; mService = service;
@@ -208,16 +213,18 @@ public class DockedStackDividerController implements DimLayerUser {
return mLastVisibility; return mLastVisibility;
} }
void setAdjustedForIme(boolean adjusted, boolean animate, WindowState imeWin) { void setAdjustedForIme(
if (mAdjustedForIme != adjusted) { boolean adjustedForIme, boolean adjustedForDivider,
mAdjustedForIme = adjusted; boolean animate, WindowState imeWin) {
if (mAdjustedForIme != adjustedForIme || mAdjustedForDivider != adjustedForDivider) {
if (animate) { if (animate) {
startImeAdjustAnimation(adjusted, imeWin); startImeAdjustAnimation(adjustedForIme, adjustedForDivider, imeWin);
} else { } else {
// Animation might be delayed, so only notify if we don't run an animation. // 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; mAnimationTarget = to;
} }
private void startImeAdjustAnimation(boolean adjusted, WindowState imeWin) { private void startImeAdjustAnimation(
boolean adjustedForIme, boolean adjustedForDivider, WindowState imeWin) {
mAnimatingForIme = true; mAnimatingForIme = true;
mAnimationStarted = false; 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(); final ArrayList<TaskStack> stacks = mDisplayContent.getStacks();
for (int i = stacks.size() - 1; i >= 0; --i) { for (int i = stacks.size() - 1; i >= 0; --i) {
@@ -492,10 +513,12 @@ public class DockedStackDividerController implements DimLayerUser {
if (mDelayedImeWin != null) { if (mDelayedImeWin != null) {
mDelayedImeWin.mWinAnimator.endDelayingAnimationStart(); mDelayedImeWin.mWinAnimator.endDelayingAnimationStart();
} }
notifyAdjustedForImeChanged(adjusted, IME_ADJUST_ANIM_DURATION); notifyAdjustedForImeChanged(
adjustedForIme || adjustedForDivider, IME_ADJUST_ANIM_DURATION);
}; };
} else { } 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) { for (int i = stacks.size() - 1; i >= 0; --i) {
final TaskStack stack = stacks.get(i); final TaskStack stack = stacks.get(i);
if (stack != null && stack.isAdjustedForIme()) { if (stack != null && stack.isAdjustedForIme()) {
if (t >= 1f && mAnimationTarget == 0f) { if (t >= 1f && mAnimationTarget == 0f && mDividerAnimationTarget == 0f) {
stack.resetAdjustedForIme(true /* adjustBoundsNow */); stack.resetAdjustedForIme(true /* adjustBoundsNow */);
updated = true; updated = true;
} else { } else {
updated |= stack.updateAdjustForIme(getInterpolatedAnimationValue(t), mLastAnimationProgress = getInterpolatedAnimationValue(t);
mLastDividerProgress = getInterpolatedDividerValue(t);
updated |= stack.updateAdjustForIme(
mLastAnimationProgress,
mLastDividerProgress,
false /* force */); false /* force */);
} }
if (t >= 1f) { if (t >= 1f) {
@@ -555,6 +582,8 @@ public class DockedStackDividerController implements DimLayerUser {
mService.mWindowPlacerLocked.performSurfacePlacement(); mService.mWindowPlacerLocked.performSurfacePlacement();
} }
if (t >= 1.0f) { if (t >= 1.0f) {
mLastAnimationProgress = mAnimationTarget;
mLastDividerProgress = mDividerAnimationTarget;
mAnimatingForIme = false; mAnimatingForIme = false;
return false; return false;
} else { } else {
@@ -596,6 +625,10 @@ public class DockedStackDividerController implements DimLayerUser {
return t * mAnimationTarget + (1 - t) * mAnimationStart; 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. * Gets the amount how much to minimize a stack depending on the interpolated fraction t.
*/ */

View File

@@ -126,6 +126,7 @@ public class TaskStack implements DimLayer.DimLayerUser,
private WindowState mImeWin; private WindowState mImeWin;
private float mMinimizeAmount; private float mMinimizeAmount;
private float mAdjustImeAmount; private float mAdjustImeAmount;
private float mAdjustDividerAmount;
private final int mDockedStackMinimizeThickness; private final int mDockedStackMinimizeThickness;
// If this is true, we are in the bounds animating mode. // If this is true, we are in the bounds animating mode.
@@ -853,7 +854,8 @@ public class TaskStack implements DimLayer.DimLayerUser,
if (!mAdjustedForIme) { if (!mAdjustedForIme) {
mAdjustedForIme = true; mAdjustedForIme = true;
mAdjustImeAmount = 0f; 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. * @return true if a traversal should be performed after the adjustment.
*/ */
boolean updateAdjustForIme(float adjustAmount, boolean force) { boolean updateAdjustForIme(float adjustAmount, float adjustDividerAmount, boolean force) {
if (adjustAmount != mAdjustImeAmount || force) { if (adjustAmount != mAdjustImeAmount
|| adjustDividerAmount != mAdjustDividerAmount || force) {
mAdjustImeAmount = adjustAmount; mAdjustImeAmount = adjustAmount;
mAdjustDividerAmount = adjustDividerAmount;
updateAdjustedBounds(); updateAdjustedBounds();
return isVisibleForUserLocked(); return isVisibleForUserLocked();
} else { } else {
@@ -895,6 +899,7 @@ public class TaskStack implements DimLayer.DimLayerUser,
mAdjustedForIme = false; mAdjustedForIme = false;
mImeGoingAway = false; mImeGoingAway = false;
mAdjustImeAmount = 0f; mAdjustImeAmount = 0f;
mAdjustDividerAmount = 0f;
updateAdjustedBounds(); updateAdjustedBounds();
mService.setResizeDimLayer(false, mStackId, 1.0f); mService.setResizeDimLayer(false, mStackId, 1.0f);
} else { } else {
@@ -992,25 +997,27 @@ public class TaskStack implements DimLayer.DimLayerUser,
(int) (mAdjustImeAmount * bottom + (1 - mAdjustImeAmount) * mBounds.bottom); (int) (mAdjustImeAmount * bottom + (1 - mAdjustImeAmount) * mBounds.bottom);
mFullyAdjustedImeBounds.set(mBounds); mFullyAdjustedImeBounds.set(mBounds);
} else { } else {
final int top; // When the stack is on bottom and has no focus, it's only adjusted for divider width.
final boolean isFocusedStack = mService.getFocusedStackLocked() == this; final int dividerWidthDelta = dividerWidthInactive - dividerWidth;
if (isFocusedStack) {
// If this stack is docked on bottom and has focus, we shift it up so that it's not // When the stack is on bottom and has focus, it needs to be moved up so as to
// occluded by IME. We try to move it up by the height of the IME window, but only // not occluded by IME, and at the same time adjusted for divider width.
// to the extent that leaves at least 30% of the top stack visible. // We try to move it up by the height of the IME window, but only to the extent
final int minTopStackBottom = // that leaves at least 30% of the top stack visible.
getMinTopStackBottom(displayContentRect, mBounds.top - dividerWidth); // 'top' is where the top of bottom stack will move to in this case.
top = Math.max( final int topBeforeImeAdjust = mBounds.top - dividerWidth + dividerWidthInactive;
mBounds.top - yOffset, minTopStackBottom + dividerWidthInactive); final int minTopStackBottom =
} else { getMinTopStackBottom(displayContentRect, mBounds.top - dividerWidth);
// If this stack is docked on bottom but doesn't have focus, we don't need to adjust final int top = Math.max(
// for IME, but still need to apply a small adjustment due to the thinner divider. mBounds.top - yOffset, minTopStackBottom + dividerWidthInactive);
top = mBounds.top - dividerWidth + dividerWidthInactive;
}
mTmpAdjustedBounds.set(mBounds); mTmpAdjustedBounds.set(mBounds);
mTmpAdjustedBounds.top = // Account for the adjustment for IME and divider width separately.
(int) (mAdjustImeAmount * top + (1 - mAdjustImeAmount) * mBounds.top); // (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.set(mBounds);
mFullyAdjustedImeBounds.top = top; mFullyAdjustedImeBounds.top = top;
mFullyAdjustedImeBounds.bottom = top + mBounds.height(); mFullyAdjustedImeBounds.bottom = top + mBounds.height();
@@ -1082,9 +1089,10 @@ public class TaskStack implements DimLayer.DimLayerUser,
} }
setAdjustedBounds(mTmpAdjustedBounds); setAdjustedBounds(mTmpAdjustedBounds);
final boolean isFocusedStack = mService.getFocusedStackLocked() == this; final boolean isImeTarget = (mService.getImeTargetStackLocked() == this);
if (mAdjustedForIme && adjust && !isFocusedStack) { if (mAdjustedForIme && adjust && !isImeTarget) {
final float alpha = mAdjustImeAmount * IME_ADJUST_DIM_AMOUNT; final float alpha = Math.max(mAdjustImeAmount, mAdjustDividerAmount)
* IME_ADJUST_DIM_AMOUNT;
mService.setResizeDimLayer(true, mStackId, alpha); mService.setResizeDimLayer(true, mStackId, alpha);
} }
} }

View File

@@ -7455,27 +7455,38 @@ public class WindowManagerService extends IWindowManager.Stub
void adjustForImeIfNeeded(final DisplayContent displayContent) { void adjustForImeIfNeeded(final DisplayContent displayContent) {
final WindowState imeWin = mInputMethodWindow; final WindowState imeWin = mInputMethodWindow;
final TaskStack focusedStack = getFocusedStackLocked(); final boolean imeVisible = imeWin != null && imeWin.isVisibleLw() && imeWin.isDisplayedLw();
final boolean dockVisible = isStackVisibleLocked(DOCKED_STACK_ID); final boolean dockVisible = isStackVisibleLocked(DOCKED_STACK_ID);
if (imeWin != null && imeWin.isVisibleLw() && imeWin.isDisplayedLw() final TaskStack imeTargetStack = getImeTargetStackLocked();
&& dockVisible && focusedStack != null) {
final boolean isFocusOnBottom = focusedStack.getDockSide() == DOCKED_BOTTOM; // 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(); final ArrayList<TaskStack> stacks = displayContent.getStacks();
for (int i = stacks.size() - 1; i >= 0; --i) { for (int i = stacks.size() - 1; i >= 0; --i) {
final TaskStack stack = stacks.get(i); final TaskStack stack = stacks.get(i);
final boolean isDockedOnBottom = stack.getDockSide() == DOCKED_BOTTOM; final boolean isDockedOnBottom = stack.getDockSide() == DOCKED_BOTTOM;
if (stack.isVisibleLocked() && (isFocusOnBottom || isDockedOnBottom)) { if (stack.isVisibleLocked() && (isFocusOnBottom || isDockedOnBottom)) {
stack.setAdjustedForIme(imeWin); stack.setAdjustedForIme(imeWin);
} else {
stack.resetAdjustedForIme(false);
} }
} }
displayContent.mDividerControllerLocked.setAdjustedForIme(true, true, imeWin); displayContent.mDividerControllerLocked.setAdjustedForIme(
isFocusOnBottom /*ime*/, true /*divider*/, true /*animate*/, imeWin);
} else { } else {
final ArrayList<TaskStack> stacks = displayContent.getStacks(); final ArrayList<TaskStack> stacks = displayContent.getStacks();
for (int i = stacks.size() - 1; i >= 0; --i) { for (int i = stacks.size() - 1; i >= 0; --i) {
final TaskStack stack = stacks.get(i); final TaskStack stack = stacks.get(i);
stack.resetAdjustedForIme(!dockVisible); 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; return mCurrentFocus;
} }
TaskStack getFocusedStackLocked() { TaskStack getImeTargetStackLocked() {
return mCurrentFocus != null ? mCurrentFocus.getStack() : null; // 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() { private void showAuditSafeModeNotification() {
@@ -9354,7 +9367,6 @@ public class WindowManagerService extends IWindowManager.Stub
WindowState newFocus = computeFocusedWindowLocked(); WindowState newFocus = computeFocusedWindowLocked();
if (mCurrentFocus != newFocus) { if (mCurrentFocus != newFocus) {
Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmUpdateFocus"); Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmUpdateFocus");
TaskStack oldFocusedStack = getFocusedStackLocked();
// This check makes sure that we don't already have the focus // This check makes sure that we don't already have the focus
// change message pending. // change message pending.
mH.removeMessages(H.REPORT_FOCUS_CHANGE); mH.removeMessages(H.REPORT_FOCUS_CHANGE);
@@ -9376,7 +9388,6 @@ public class WindowManagerService extends IWindowManager.Stub
mLosingFocus.remove(newFocus); mLosingFocus.remove(newFocus);
int focusChanged = mPolicy.focusChangedLw(oldFocus, newFocus); int focusChanged = mPolicy.focusChangedLw(oldFocus, newFocus);
TaskStack newFocusedStack = getFocusedStackLocked();
if (imWindowChanged && oldFocus != mInputMethodWindow) { if (imWindowChanged && oldFocus != mInputMethodWindow) {
// Focus of the input method window changed. Perform layout if needed. // 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); 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); adjustForImeIfNeeded(displayContent);
Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);