Adjust split layout with IME animation in split (5/N)

Adjust split bounds to match the IME animation.

Fix: 179262787
Test: atest WMShellUnitTests
Test: observed split bounds been offset properly when rotating devices
or changing focus while IME showing.

Change-Id: I70d8cdf5a019f77873a75bc0881b1c100b372664
This commit is contained in:
Jerry Chang
2021-02-26 20:53:06 +08:00
parent 64049c4e00
commit aebdc015e0

View File

@@ -119,17 +119,17 @@ public final class SplitLayout {
/** Gets bounds of the primary split. */
public Rect getBounds1() {
return mBounds1;
return new Rect(mBounds1);
}
/** Gets bounds of the secondary split. */
public Rect getBounds2() {
return mBounds2;
return new Rect(mBounds2);
}
/** Gets bounds of divider window. */
public Rect getDividerBounds() {
return mDividerBounds;
return new Rect(mDividerBounds);
}
/** Returns leash of the current divider bar. */
@@ -308,18 +308,21 @@ public final class SplitLayout {
/** Apply recorded surface layout to the {@link SurfaceControl.Transaction}. */
public void applySurfaceChanges(SurfaceControl.Transaction t, SurfaceControl leash1,
SurfaceControl leash2, SurfaceControl dimLayer1, SurfaceControl dimLayer2) {
final Rect dividerBounds = mImePositionProcessor.adjustForIme(mDividerBounds);
final Rect bounds1 = mImePositionProcessor.adjustForIme(mBounds1);
final Rect bounds2 = mImePositionProcessor.adjustForIme(mBounds2);
final SurfaceControl dividerLeash = getDividerLeash();
if (dividerLeash != null) {
t.setPosition(dividerLeash, mDividerBounds.left, mDividerBounds.top)
t.setPosition(dividerLeash, dividerBounds.left, dividerBounds.top)
// Resets layer of divider bar to make sure it is always on top.
.setLayer(dividerLeash, Integer.MAX_VALUE);
}
t.setPosition(leash1, mBounds1.left, mBounds1.top)
.setWindowCrop(leash1, mBounds1.width(), mBounds1.height());
t.setPosition(leash1, bounds1.left, bounds1.top)
.setWindowCrop(leash1, bounds1.width(), bounds1.height());
t.setPosition(leash2, mBounds2.left, mBounds2.top)
.setWindowCrop(leash2, mBounds2.width(), mBounds2.height());
t.setPosition(leash2, bounds2.left, bounds2.top)
.setWindowCrop(leash2, bounds2.width(), bounds2.height());
mImePositionProcessor.applySurfaceDimValues(t, dimLayer1, dimLayer2);
}
@@ -327,8 +330,8 @@ public final class SplitLayout {
/** Apply recorded task layout to the {@link WindowContainerTransaction}. */
public void applyTaskChanges(WindowContainerTransaction wct,
ActivityManager.RunningTaskInfo task1, ActivityManager.RunningTaskInfo task2) {
wct.setBounds(task1.token, mBounds1)
.setBounds(task2.token, mBounds2);
wct.setBounds(task1.token, mImePositionProcessor.adjustForIme(mBounds1))
.setBounds(task2.token, mImePositionProcessor.adjustForIme(mBounds2));
}
/** Handles layout change event. */
@@ -363,12 +366,15 @@ public final class SplitLayout {
private final int mDisplayId;
private int mYOffsetForIme;
private float mDimValue1;
private float mDimValue2;
private int mStartImeTop;
private int mEndImeTop;
private int mTargetYOffset;
private int mLastYOffset;
private float mTargetDim1;
private float mTargetDim2;
private float mLastDim1;
@@ -395,6 +401,12 @@ public final class SplitLayout {
mTargetDim2 = imeTargetPosition == SPLIT_POSITION_TOP_OR_LEFT && showing
? ADJUSTED_NONFOCUS_DIM : 0.0f;
// Calculate target bounds offset for IME
mLastYOffset = mYOffsetForIme;
final boolean needOffset = imeTargetPosition == SPLIT_POSITION_BOTTOM_OR_RIGHT
&& !isFloating && !isLandscape(mRootBounds) && showing;
mTargetYOffset = needOffset ? getTargetYOffset() : 0;
// Make {@link DividerView} non-interactive while IME showing in split mode. Listen to
// ImePositionProcessor#onImeVisibilityChanged directly in DividerView is not enough
// because DividerView won't receive onImeVisibilityChanged callback after it being
@@ -420,6 +432,13 @@ public final class SplitLayout {
mSplitLayoutHandler.onBoundsChanging(SplitLayout.this);
}
private int getTargetYOffset() {
final int desireOffset = Math.abs(mEndImeTop - mStartImeTop);
// Make sure to keep at least 30% visible for the top split.
final int maxOffset = (int) (mBounds1.height() * ADJUSTED_SPLIT_FRACTION_MAX);
return -Math.min(desireOffset, maxOffset);
}
@SplitPosition
private int getImeTargetPosition() {
final WindowContainerToken token = mTaskOrganizer.getImeTarget(mDisplayId);
@@ -433,6 +452,8 @@ public final class SplitLayout {
private void onProgress(float progress) {
mDimValue1 = getProgressValue(mLastDim1, mTargetDim1, progress);
mDimValue2 = getProgressValue(mLastDim2, mTargetDim2, progress);
mYOffsetForIme =
(int) getProgressValue((float) mLastYOffset, (float) mTargetYOffset, progress);
}
private float getProgressValue(float start, float end, float progress) {
@@ -440,9 +461,17 @@ public final class SplitLayout {
}
private void reset() {
mYOffsetForIme = 0;
mDimValue1 = mDimValue2 = 0.0f;
}
/* Adjust bounds with IME offset. */
private Rect adjustForIme(Rect bounds) {
final Rect temp = new Rect(bounds);
if (mYOffsetForIme != 0) temp.offset(0, mYOffsetForIme);
return temp;
}
private void applySurfaceDimValues(SurfaceControl.Transaction t, SurfaceControl dimLayer1,
SurfaceControl dimLayer2) {
t.setAlpha(dimLayer1, mDimValue1).setVisibility(dimLayer1, mDimValue1 > 0.001f);