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:
@@ -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.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user