Merge "Various inset fixes" into rvc-dev

This commit is contained in:
Jorim Jaggi
2020-03-02 20:22:34 +00:00
committed by Android (Google) Code Review
7 changed files with 83 additions and 38 deletions

View File

@@ -76,8 +76,8 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll
private boolean mFinished;
private boolean mCancelled;
private boolean mShownOnFinish;
private float mCurrentAlpha;
private float mPendingAlpha;
private float mCurrentAlpha = 1.0f;
private float mPendingAlpha = 1.0f;
@VisibleForTesting
public InsetsAnimationControlImpl(SparseArray<InsetsSourceControl> controls, Rect frame,
@@ -153,7 +153,7 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll
}
mPendingFraction = sanitize(fraction);
mPendingInsets = sanitize(insets);
mPendingAlpha = 1 - sanitize(alpha);
mPendingAlpha = sanitize(alpha);
mController.scheduleApplyChangeInsets();
}
@@ -182,7 +182,8 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll
mController.applySurfaceParams(params.toArray(new SurfaceParams[params.size()]));
mCurrentInsets = mPendingInsets;
mAnimation.setFraction(mPendingFraction);
mCurrentAlpha = 1 - alphaOffset;
mCurrentAlpha = mPendingAlpha;
mAnimation.setAlpha(mPendingAlpha);
if (mFinished) {
mController.notifyFinished(this, mShownOnFinish);
}
@@ -238,7 +239,8 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll
private Insets getInsetsFromState(InsetsState state, Rect frame,
@Nullable @InternalInsetsSide SparseIntArray typeSideMap) {
return state.calculateInsets(frame, false /* isScreenRound */,
return state.calculateInsets(frame, null /* ignoringVisibilityState */,
false /* isScreenRound */,
false /* alwaysConsumeSystemBars */, null /* displayCutout */,
null /* legacyContentInsets */, null /* legacyStableInsets */,
LayoutParams.SOFT_INPUT_ADJUST_RESIZE /* legacySoftInputMode*/,
@@ -257,8 +259,8 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll
return alpha >= 1 ? 1 : (alpha <= 0 ? 0 : alpha);
}
private void updateLeashesForSide(@InternalInsetsSide int side, int offset, int inset,
int maxInset, ArrayList<SurfaceParams> surfaceParams, InsetsState state, Float alpha) {
private void updateLeashesForSide(@InternalInsetsSide int side, int offset, int maxInset,
int inset, ArrayList<SurfaceParams> surfaceParams, InsetsState state, Float alpha) {
ArraySet<InsetsSourceControl> items = mSideSourceMap.get(side);
if (items == null) {
return;
@@ -273,6 +275,7 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll
mTmpFrame.set(source.getFrame());
addTranslationToMatrix(side, offset, mTmpMatrix, mTmpFrame);
state.getSource(source.getType()).setVisible(side == ISIDE_FLOATING || inset != 0);
state.getSource(source.getType()).setFrame(mTmpFrame);
// If the system is controlling the insets source, the leash can be null.

View File

@@ -233,6 +233,12 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
final InsetsAnimationControlImpl control;
final @AnimationType int type;
/**
* Whether {@link WindowInsetsAnimation.Callback#onStart(WindowInsetsAnimation, Bounds)} has
* been dispatched already for this animation.
*/
boolean startDispatched;
}
/**
@@ -276,9 +282,9 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
private final SparseArray<InsetsSourceControl> mTmpControlArray = new SparseArray<>();
private final ArrayList<RunningAnimation> mRunningAnimations = new ArrayList<>();
private final ArrayList<WindowInsetsAnimation> mRunningInsetsAnimations = new ArrayList<>();
private final List<WindowInsetsAnimation> mUnmodifiableRunningInsetsAnimations =
Collections.unmodifiableList(mRunningInsetsAnimations);
private final ArrayList<WindowInsetsAnimation> mTmpRunningAnims = new ArrayList<>();
private final List<WindowInsetsAnimation> mUnmodifiableTmpRunningAnims =
Collections.unmodifiableList(mTmpRunningAnims);
private final ArrayList<InsetsAnimationControlImpl> mTmpFinishedControls = new ArrayList<>();
private WindowInsets mLastInsets;
@@ -294,6 +300,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
private int mLastLegacySoftInputMode;
private int mLastLegacySystemUiFlags;
private DisplayCutout mLastDisplayCutout;
private boolean mStartingAnimation;
private SyncRtSurfaceTransactionApplier mApplier;
@@ -329,20 +336,28 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
}
mTmpFinishedControls.clear();
mTmpRunningAnims.clear();
InsetsState state = new InsetsState(mState, true /* copySources */);
for (int i = mRunningAnimations.size() - 1; i >= 0; i--) {
InsetsAnimationControlImpl control = mRunningAnimations.get(i).control;
RunningAnimation runningAnimation = mRunningAnimations.get(i);
InsetsAnimationControlImpl control = runningAnimation.control;
// Keep track of running animation to be dispatched. Aggregate it here such that if
// it gets finished within applyChangeInsets we still dispatch it to onProgress.
if (runningAnimation.startDispatched) {
mTmpRunningAnims.add(control.getAnimation());
}
if (control.applyChangeInsets(state)) {
mTmpFinishedControls.add(control);
}
}
WindowInsets insets = state.calculateInsets(mFrame, mLastInsets.isRound(),
mLastInsets.shouldAlwaysConsumeSystemBars(), mLastInsets.getDisplayCutout(),
mLastLegacyContentInsets, mLastLegacyStableInsets, mLastLegacySoftInputMode,
mLastLegacySystemUiFlags, null /* typeSideMap */);
WindowInsets insets = state.calculateInsets(mFrame, mState /* ignoringVisibilityState*/,
mLastInsets.isRound(), mLastInsets.shouldAlwaysConsumeSystemBars(),
mLastDisplayCutout, mLastLegacyContentInsets, mLastLegacyStableInsets,
mLastLegacySoftInputMode, mLastLegacySystemUiFlags, null /* typeSideMap */);
mViewRoot.mView.dispatchWindowInsetsAnimationProgress(insets,
mUnmodifiableRunningInsetsAnimations);
mUnmodifiableTmpRunningAnims);
for (int i = mTmpFinishedControls.size() - 1; i >= 0; i--) {
dispatchAnimationEnd(mTmpFinishedControls.get(i).getAnimation());
@@ -394,8 +409,10 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
mLastLegacyStableInsets.set(legacyStableInsets);
mLastLegacySoftInputMode = legacySoftInputMode;
mLastLegacySystemUiFlags = legacySystemUiFlags;
mLastInsets = mState.calculateInsets(mFrame, isScreenRound, alwaysConsumeSystemBars, cutout,
legacyContentInsets, legacyStableInsets, legacySoftInputMode, legacySystemUiFlags,
mLastDisplayCutout = cutout;
mLastInsets = mState.calculateInsets(mFrame, null /* ignoringVisibilityState*/,
isScreenRound, alwaysConsumeSystemBars, cutout, legacyContentInsets,
legacyStableInsets, legacySoftInputMode, legacySystemUiFlags,
null /* typeSideMap */);
return mLastInsets;
}
@@ -584,7 +601,6 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
frame, mState, listener, typesReady, this, durationMs, interpolator, fade,
layoutInsetsDuringAnimation, animationType);
mRunningAnimations.add(new RunningAnimation(controller, animationType));
mRunningInsetsAnimations.add(controller.getAnimation());
cancellationSignal.setOnCancelListener(controller::onCancelled);
return cancellationSignal;
}
@@ -736,7 +752,6 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
for (int i = mRunningAnimations.size() - 1; i >= 0; i--) {
if (mRunningAnimations.get(i).control == control) {
mRunningAnimations.remove(i);
mRunningInsetsAnimations.remove(i);
break;
}
}
@@ -903,6 +918,12 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
if (controller.isCancelled()) {
return true;
}
for (int i = mRunningAnimations.size() - 1; i >= 0; i--) {
RunningAnimation runningAnimation = mRunningAnimations.get(i);
if (runningAnimation.control == controller) {
runningAnimation.startDispatched = true;
}
}
mViewRoot.mView.dispatchWindowInsetsAnimationStart(animation, bounds);
mStartingAnimation = true;
listener.onReady(controller, types);

View File

@@ -160,7 +160,8 @@ public class InsetsSourceConsumer {
}
boolean applyLocalVisibilityOverride() {
final boolean isVisible = mState.getSource(mType).isVisible();
InsetsSource source = mState.peekSource(mType);
final boolean isVisible = source != null && source.isVisible();
final boolean hasControl = mSourceControl != null;
// We still need to let the legacy app know the visibility change even if we don't have the

View File

@@ -147,10 +147,13 @@ public class InsetsState implements Parcelable {
* Calculates {@link WindowInsets} based on the current source configuration.
*
* @param frame The frame to calculate the insets relative to.
* @param ignoringVisibilityState {@link InsetsState} used to calculate
* {@link WindowInsets#getInsetsIgnoringVisibility(int)} information, or pass
* {@code null} to use this state to calculate that information.
* @return The calculated insets.
*/
public WindowInsets calculateInsets(Rect frame, boolean isScreenRound,
boolean alwaysConsumeSystemBars, DisplayCutout cutout,
public WindowInsets calculateInsets(Rect frame, @Nullable InsetsState ignoringVisibilityState,
boolean isScreenRound, boolean alwaysConsumeSystemBars, DisplayCutout cutout,
@Nullable Rect legacyContentInsets, @Nullable Rect legacyStableInsets,
int legacySoftInputMode, int legacySystemUiFlags,
@Nullable @InternalInsetsSide SparseIntArray typeSideMap) {
@@ -188,8 +191,15 @@ public class InsetsState implements Parcelable {
// IME won't be reported in max insets as the size depends on the EditorInfo of the IME
// target.
if (source.getType() != ITYPE_IME) {
processSource(source, relativeFrameMax, true /* ignoreVisibility */,
typeMaxInsetsMap, null /* typeSideMap */, null /* typeVisibilityMap */);
InsetsSource ignoringVisibilitySource = ignoringVisibilityState != null
? ignoringVisibilityState.getSource(type)
: source;
if (ignoringVisibilitySource == null) {
continue;
}
processSource(ignoringVisibilitySource, relativeFrameMax,
true /* ignoreVisibility */, typeMaxInsetsMap, null /* typeSideMap */,
null /* typeVisibilityMap */);
}
}
final int softInputAdjustMode = legacySoftInputMode & SOFT_INPUT_MASK_ADJUST;
@@ -297,6 +307,10 @@ public class InsetsState implements Parcelable {
return mSources.computeIfAbsent(type, InsetsSource::new);
}
public @Nullable InsetsSource peekSource(@InternalInsetsType int type) {
return mSources.get(type);
}
public void setDisplayFrame(Rect frame) {
mDisplayFrame.set(frame);
}

View File

@@ -264,6 +264,11 @@ public final class WindowInsetsAnimation {
WindowInsets.insetInsets(
mUpperBound, insets.left, insets.top, insets.right, insets.bottom));
}
@Override
public String toString() {
return "Bounds{lower=" + mLowerBound + " upper=" + mUpperBound + "}";
}
}
/**

View File

@@ -72,8 +72,8 @@ public class InsetsStateTest {
mState.getSource(ITYPE_IME).setFrame(new Rect(0, 200, 100, 300));
mState.getSource(ITYPE_IME).setVisible(true);
SparseIntArray typeSideMap = new SparseIntArray();
WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), false, false,
DisplayCutout.NO_CUTOUT, null, null, SOFT_INPUT_ADJUST_RESIZE, 0, typeSideMap);
WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
false, DisplayCutout.NO_CUTOUT, null, null, SOFT_INPUT_ADJUST_RESIZE, 0, typeSideMap);
assertEquals(Insets.of(0, 100, 0, 100), insets.getSystemWindowInsets());
assertEquals(Insets.of(0, 100, 0, 100), insets.getInsets(Type.all()));
assertEquals(ISIDE_TOP, typeSideMap.get(ITYPE_STATUS_BAR));
@@ -91,8 +91,8 @@ public class InsetsStateTest {
mState.getSource(ITYPE_NAVIGATION_BAR).setVisible(true);
mState.getSource(ITYPE_IME).setFrame(new Rect(0, 100, 100, 300));
mState.getSource(ITYPE_IME).setVisible(true);
WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), false, false,
DisplayCutout.NO_CUTOUT, null, null, SOFT_INPUT_ADJUST_RESIZE, 0, null);
WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
false, DisplayCutout.NO_CUTOUT, null, null, SOFT_INPUT_ADJUST_RESIZE, 0, null);
assertEquals(100, insets.getStableInsetBottom());
assertEquals(Insets.of(0, 0, 0, 100), insets.getInsetsIgnoringVisibility(Type.systemBars()));
assertEquals(Insets.of(0, 0, 0, 200), insets.getSystemWindowInsets());
@@ -110,8 +110,8 @@ public class InsetsStateTest {
mState.getSource(ITYPE_STATUS_BAR).setVisible(true);
mState.getSource(ITYPE_NAVIGATION_BAR).setFrame(new Rect(80, 0, 100, 300));
mState.getSource(ITYPE_NAVIGATION_BAR).setVisible(true);
WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), false, false,
DisplayCutout.NO_CUTOUT, null, null, 0, 0, null);
WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
false, DisplayCutout.NO_CUTOUT, null, null, 0, 0, null);
assertEquals(Insets.of(0, 100, 20, 0), insets.getSystemWindowInsets());
assertEquals(Insets.of(0, 100, 0, 0), insets.getInsets(Type.statusBars()));
assertEquals(Insets.of(0, 0, 20, 0), insets.getInsets(Type.navigationBars()));
@@ -126,8 +126,8 @@ public class InsetsStateTest {
mState.getSource(ITYPE_STATUS_BAR).setVisible(true);
mState.getSource(ITYPE_IME).setFrame(new Rect(0, 200, 100, 300));
mState.getSource(ITYPE_IME).setVisible(true);
WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), false, false,
DisplayCutout.NO_CUTOUT, null, null, SOFT_INPUT_ADJUST_NOTHING, 0, null);
WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
false, DisplayCutout.NO_CUTOUT, null, null, SOFT_INPUT_ADJUST_NOTHING, 0, null);
assertEquals(0, insets.getSystemWindowInsetBottom());
assertEquals(100, insets.getInsets(ime()).bottom);
assertTrue(insets.isVisible(ime()));
@@ -142,11 +142,11 @@ public class InsetsStateTest {
mState.getSource(ITYPE_STATUS_BAR).setVisible(false);
mState.getSource(ITYPE_IME).setFrame(new Rect(0, 200, 100, 300));
mState.getSource(ITYPE_IME).setVisible(true);
WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), false, false,
DisplayCutout.NO_CUTOUT, null, null, SOFT_INPUT_ADJUST_NOTHING,
WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
false, DisplayCutout.NO_CUTOUT, null, null, SOFT_INPUT_ADJUST_NOTHING,
SYSTEM_UI_FLAG_LAYOUT_STABLE, null);
assertEquals(100, insets.getSystemWindowInsetTop());
insets = mState.calculateInsets(new Rect(0, 0, 100, 300), false, false,
insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false, false,
DisplayCutout.NO_CUTOUT, null, null, SOFT_INPUT_ADJUST_NOTHING,
0 /* legacySystemUiFlags */, null);
assertEquals(0, insets.getSystemWindowInsetTop());
@@ -160,7 +160,7 @@ public class InsetsStateTest {
mState.getSource(ITYPE_IME).setFrame(new Rect(0, 200, 100, 300));
mState.getSource(ITYPE_IME).setVisible(true);
mState.removeSource(ITYPE_IME);
WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), false, false,
WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false, false,
DisplayCutout.NO_CUTOUT, null, null, SOFT_INPUT_ADJUST_RESIZE, 0, null);
assertEquals(0, insets.getSystemWindowInsetBottom());
}

View File

@@ -328,7 +328,8 @@ public class DividerView extends FrameLayout implements OnTouchListener,
// Our window doesn't cover entire display, so we use the display frame to re-calculate
// the insets.
final InsetsState state = getWindowInsetsController().getState();
insets = state.calculateInsets(state.getDisplayFrame(), insets.isRound(),
insets = state.calculateInsets(state.getDisplayFrame(),
null /* ignoringVisibilityState */, insets.isRound(),
insets.shouldAlwaysConsumeSystemBars(), insets.getDisplayCutout(),
null /* legacyContentInsets */, null /* legacyStableInsets */,
0 /* legacySystemUiFlags */,