diff options
| author | 2020-01-10 17:17:42 +0000 | |
|---|---|---|
| committer | 2020-01-10 17:17:42 +0000 | |
| commit | fa833b69b4f0fe60ef0c5955acf1409bd816f603 (patch) | |
| tree | 9ec94a000d28f85673ebfc4c00d8564829f77b94 | |
| parent | bcc216f21251131e31edce8bbc3d1e01972e65f2 (diff) | |
| parent | 4e04eb24aeb921ab652367c5970a569fa8c498e1 (diff) | |
Merge "Move visible insets calculation to client"
10 files changed, 190 insertions, 6 deletions
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java index 0207abdda355..775490c757d4 100644 --- a/core/java/android/view/InsetsController.java +++ b/core/java/android/view/InsetsController.java @@ -42,6 +42,7 @@ import android.view.WindowInsets.Type; import android.view.WindowInsets.Type.InsetsType; import android.view.WindowInsetsAnimationCallback.AnimationBounds; import android.view.WindowInsetsAnimationCallback.InsetsAnimation; +import android.view.WindowManager.LayoutParams.SoftInputModeFlags; import android.view.animation.Interpolator; import android.view.animation.PathInterpolator; @@ -299,6 +300,14 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation } /** + * @see InsetsState#calculateVisibleInsets(Rect, Rect, int) + */ + public Rect calculateVisibleInsets(Rect legacyVisibleInsets, + @SoftInputModeFlags int softInputMode) { + return mState.calculateVisibleInsets(mFrame, legacyVisibleInsets, softInputMode); + } + + /** * Called when the server has dispatched us a new set of inset controls. */ public void onControlsChanged(InsetsSourceControl[] activeControls) { diff --git a/core/java/android/view/InsetsSource.java b/core/java/android/view/InsetsSource.java index 324d562bfcfb..67ccfd6707f4 100644 --- a/core/java/android/view/InsetsSource.java +++ b/core/java/android/view/InsetsSource.java @@ -16,6 +16,7 @@ package android.view; +import android.annotation.Nullable; import android.graphics.Insets; import android.graphics.Rect; import android.os.Parcel; @@ -23,6 +24,7 @@ import android.os.Parcelable; import android.view.InsetsState.InternalInsetsType; import java.io.PrintWriter; +import java.util.Objects; /** * Represents the state of a single window generating insets for clients. @@ -34,6 +36,7 @@ public class InsetsSource implements Parcelable { /** Frame of the source in screen coordinate space */ private final Rect mFrame; + private @Nullable Rect mVisibleFrame; private boolean mVisible; private final Rect mTmpFrame = new Rect(); @@ -54,6 +57,10 @@ public class InsetsSource implements Parcelable { mFrame.set(frame); } + public void setVisibleFrame(@Nullable Rect visibleFrame) { + mVisibleFrame = visibleFrame != null ? new Rect(visibleFrame) : visibleFrame; + } + public void setVisible(boolean visible) { mVisible = visible; } @@ -66,6 +73,10 @@ public class InsetsSource implements Parcelable { return mFrame; } + public @Nullable Rect getVisibleFrame() { + return mVisibleFrame; + } + public boolean isVisible() { return mVisible; } @@ -79,10 +90,22 @@ public class InsetsSource implements Parcelable { * source. */ public Insets calculateInsets(Rect relativeFrame, boolean ignoreVisibility) { + return calculateInsets(relativeFrame, mFrame, ignoreVisibility); + } + + /** + * Like {@link #calculateInsets(Rect, boolean)}, but will return visible insets. + */ + public Insets calculateVisibleInsets(Rect relativeFrame) { + return calculateInsets(relativeFrame, mVisibleFrame != null ? mVisibleFrame : mFrame, + false /* ignoreVisibility */); + } + + private Insets calculateInsets(Rect relativeFrame, Rect frame, boolean ignoreVisibility) { if (!ignoreVisibility && !mVisible) { return Insets.NONE; } - if (!mTmpFrame.setIntersect(mFrame, relativeFrame)) { + if (!mTmpFrame.setIntersect(frame, relativeFrame)) { return Insets.NONE; } @@ -110,6 +133,9 @@ public class InsetsSource implements Parcelable { pw.print(prefix); pw.print("InsetsSource type="); pw.print(InsetsState.typeToString(mType)); pw.print(" frame="); pw.print(mFrame.toShortString()); + if (mVisibleFrame != null) { + pw.print(" visibleFrmae="); pw.print(mVisibleFrame.toShortString()); + } pw.print(" visible="); pw.print(mVisible); pw.println(); } @@ -123,6 +149,7 @@ public class InsetsSource implements Parcelable { if (mType != that.mType) return false; if (mVisible != that.mVisible) return false; + if (!Objects.equals(mVisibleFrame, that.mVisibleFrame)) return false; return mFrame.equals(that.mFrame); } @@ -137,6 +164,7 @@ public class InsetsSource implements Parcelable { public InsetsSource(Parcel in) { mType = in.readInt(); mFrame = in.readParcelable(null /* loader */); + mVisibleFrame = in.readParcelable(null /* loader */); mVisible = in.readBoolean(); } @@ -149,6 +177,7 @@ public class InsetsSource implements Parcelable { public void writeToParcel(Parcel dest, int flags) { dest.writeInt(mType); dest.writeParcelable(mFrame, 0 /* flags*/); + dest.writeParcelable(mVisibleFrame, 0 /* flags */); dest.writeBoolean(mVisible); } diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java index ae1e579da8f6..e33ca70c222e 100644 --- a/core/java/android/view/InsetsState.java +++ b/core/java/android/view/InsetsState.java @@ -19,12 +19,14 @@ package android.view; import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL; import static android.view.ViewRootImpl.NEW_INSETS_MODE_IME; import static android.view.ViewRootImpl.NEW_INSETS_MODE_NONE; +import static android.view.ViewRootImpl.sNewInsetsMode; import static android.view.WindowInsets.Type.IME; import static android.view.WindowInsets.Type.MANDATORY_SYSTEM_GESTURES; import static android.view.WindowInsets.Type.SIZE; import static android.view.WindowInsets.Type.SYSTEM_GESTURES; import static android.view.WindowInsets.Type.ime; import static android.view.WindowInsets.Type.indexOf; +import static android.view.WindowInsets.Type.isVisibleInsetsType; import static android.view.WindowInsets.Type.systemBars; import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE; import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST; @@ -41,6 +43,7 @@ import android.util.SparseIntArray; import android.view.WindowInsets.Type; import android.view.WindowInsets.Type.InsetsType; import android.view.WindowManager.LayoutParams; +import android.view.WindowManager.LayoutParams.SoftInputModeFlags; import java.io.PrintWriter; import java.lang.annotation.Retention; @@ -186,6 +189,32 @@ public class InsetsState implements Parcelable { : systemBars()); } + public Rect calculateVisibleInsets(Rect frame, Rect legacyVisibleInsets, + @SoftInputModeFlags int softInputMode) { + if (sNewInsetsMode == NEW_INSETS_MODE_NONE) { + return legacyVisibleInsets; + } + + Insets insets = Insets.NONE; + for (int type = FIRST_TYPE; type <= LAST_TYPE; type++) { + InsetsSource source = mSources.get(type); + if (source == null) { + continue; + } + if (sNewInsetsMode != NEW_INSETS_MODE_FULL && type != ITYPE_IME) { + continue; + } + + // Ignore everything that's not a system bar or IME. + int publicType = InsetsState.toPublicType(type); + if (!isVisibleInsetsType(publicType, softInputMode)) { + continue; + } + insets = Insets.max(source.calculateVisibleInsets(frame), insets); + } + return insets.toRect(); + } + private void processSource(InsetsSource source, Rect relativeFrame, boolean ignoreVisibility, Insets[] typeInsetsMap, @Nullable @InternalInsetsSide SparseIntArray typeSideMap, @Nullable boolean[] typeVisibilityMap) { diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index ab89ef46e09e..ca8ba4ca1b8a 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -2103,6 +2103,12 @@ public final class ViewRootImpl implements ViewParent, Trace.traceEnd(Trace.TRACE_TAG_VIEW); } + private void updateVisibleInsets() { + Rect visibleInsets = mInsetsController.calculateVisibleInsets(mPendingVisibleInsets, + mWindowAttributes.softInputMode); + mAttachInfo.mVisibleInsets.set(visibleInsets); + } + InsetsController getInsetsController() { return mInsetsController; } @@ -2251,7 +2257,7 @@ public final class ViewRootImpl implements ViewParent, insetsChanged = true; } if (!mPendingVisibleInsets.equals(mAttachInfo.mVisibleInsets)) { - mAttachInfo.mVisibleInsets.set(mPendingVisibleInsets); + updateVisibleInsets(); if (DEBUG_LAYOUT) Log.v(mTag, "Visible insets changing to: " + mAttachInfo.mVisibleInsets); } @@ -2317,6 +2323,7 @@ public final class ViewRootImpl implements ViewParent, if (mApplyInsetsRequested) { mApplyInsetsRequested = false; + updateVisibleInsets(); dispatchApplyInsets(host); if (mLayoutRequested) { // Short-circuit catching a new layout request here, so @@ -2501,7 +2508,7 @@ public final class ViewRootImpl implements ViewParent, contentInsetsChanged = true; } if (visibleInsetsChanged) { - mAttachInfo.mVisibleInsets.set(mPendingVisibleInsets); + updateVisibleInsets(); if (DEBUG_LAYOUT) Log.v(mTag, "Visible insets changing to: " + mAttachInfo.mVisibleInsets); } diff --git a/core/java/android/view/WindowInsets.java b/core/java/android/view/WindowInsets.java index 9df131de6754..9291b5652425 100644 --- a/core/java/android/view/WindowInsets.java +++ b/core/java/android/view/WindowInsets.java @@ -29,6 +29,8 @@ import static android.view.WindowInsets.Type.TAPPABLE_ELEMENT; import static android.view.WindowInsets.Type.all; import static android.view.WindowInsets.Type.indexOf; import static android.view.WindowInsets.Type.systemBars; +import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING; +import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST; import android.annotation.IntDef; import android.annotation.IntRange; @@ -40,6 +42,7 @@ import android.graphics.Insets; import android.graphics.Rect; import android.util.SparseArray; import android.view.WindowInsets.Type.InsetsType; +import android.view.WindowManager.LayoutParams.SoftInputModeFlags; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputMethod; @@ -1289,6 +1292,17 @@ public final class WindowInsets { public static @InsetsType int all() { return 0xFFFFFFFF; } + + /** + * Checks whether the specified type is considered to be part of visible insets. + * @hide + */ + public static boolean isVisibleInsetsType(int type, + @SoftInputModeFlags int softInputModeFlags) { + int softInputMode = softInputModeFlags & SOFT_INPUT_MASK_ADJUST; + return (type & Type.systemBars()) != 0 + || (softInputMode != SOFT_INPUT_ADJUST_NOTHING && (type & Type.ime()) != 0); + } } /** diff --git a/core/tests/coretests/src/android/view/InsetsSourceTest.java b/core/tests/coretests/src/android/view/InsetsSourceTest.java index d7f50bafdc0a..e3b08bb14e46 100644 --- a/core/tests/coretests/src/android/view/InsetsSourceTest.java +++ b/core/tests/coretests/src/android/view/InsetsSourceTest.java @@ -108,5 +108,30 @@ public class InsetsSourceTest { assertEquals(Insets.of(0, 100, 0, 0), insets); } + @Test + public void testCalculateVisibleInsets_default() { + mSource.setFrame(new Rect(0, 0, 500, 100)); + Insets insets = mSource.calculateVisibleInsets(new Rect(100, 0, 500, 500)); + assertEquals(Insets.of(0, 100, 0, 0), insets); + } + + @Test + public void testCalculateVisibleInsets_override() { + mSource.setFrame(new Rect(0, 0, 500, 100)); + mSource.setVisibleFrame(new Rect(0, 0, 500, 200)); + Insets insets = mSource.calculateVisibleInsets(new Rect(100, 0, 500, 500)); + assertEquals(Insets.of(0, 200, 0, 0), insets); + } + + @Test + public void testCalculateVisibleInsets_invisible() { + mSource.setFrame(new Rect(0, 0, 500, 100)); + mSource.setVisibleFrame(new Rect(0, 0, 500, 200)); + mSource.setVisible(false); + Insets insets = mSource.calculateVisibleInsets(new Rect(100, 0, 500, 500)); + assertEquals(Insets.of(0, 0, 0, 0), insets); + } + + // Parcel and equals already tested via InsetsStateTest } diff --git a/core/tests/coretests/src/android/view/InsetsStateTest.java b/core/tests/coretests/src/android/view/InsetsStateTest.java index fa2ffccaaa63..4b76fee00496 100644 --- a/core/tests/coretests/src/android/view/InsetsStateTest.java +++ b/core/tests/coretests/src/android/view/InsetsStateTest.java @@ -18,12 +18,14 @@ package android.view; import static android.view.InsetsState.ISIDE_BOTTOM; import static android.view.InsetsState.ISIDE_TOP; +import static android.view.InsetsState.ITYPE_BOTTOM_GESTURES; import static android.view.InsetsState.ITYPE_CAPTION_BAR; import static android.view.InsetsState.ITYPE_IME; import static android.view.InsetsState.ITYPE_NAVIGATION_BAR; import static android.view.InsetsState.ITYPE_STATUS_BAR; import static android.view.WindowInsets.Type.ime; import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING; +import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN; import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE; import static org.junit.Assert.assertEquals; @@ -209,6 +211,42 @@ public class InsetsStateTest { assertFalse(InsetsState.getDefaultVisibility(ITYPE_IME)); } + @Test + public void testCalculateVisibleInsets() throws Exception { + try (final InsetsModeSession session = + new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_FULL)) { + mState.getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 100, 100)); + mState.getSource(ITYPE_STATUS_BAR).setVisible(true); + mState.getSource(ITYPE_IME).setFrame(new Rect(0, 200, 100, 300)); + mState.getSource(ITYPE_IME).setVisible(true); + + // Make sure bottom gestures are ignored + mState.getSource(ITYPE_BOTTOM_GESTURES).setFrame(new Rect(0, 100, 100, 300)); + mState.getSource(ITYPE_BOTTOM_GESTURES).setVisible(true); + Rect visibleInsets = mState.calculateVisibleInsets( + new Rect(0, 0, 100, 300), new Rect(), SOFT_INPUT_ADJUST_PAN); + assertEquals(new Rect(0, 100, 0, 100), visibleInsets); + } + } + + @Test + public void testCalculateVisibleInsets_adjustNothing() throws Exception { + try (final InsetsModeSession session = + new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_FULL)) { + mState.getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 100, 100)); + mState.getSource(ITYPE_STATUS_BAR).setVisible(true); + mState.getSource(ITYPE_IME).setFrame(new Rect(0, 200, 100, 300)); + mState.getSource(ITYPE_IME).setVisible(true); + + // Make sure bottom gestures are ignored + mState.getSource(ITYPE_BOTTOM_GESTURES).setFrame(new Rect(0, 100, 100, 300)); + mState.getSource(ITYPE_BOTTOM_GESTURES).setVisible(true); + Rect visibleInsets = mState.calculateVisibleInsets( + new Rect(0, 0, 100, 300), new Rect(), SOFT_INPUT_ADJUST_NOTHING); + assertEquals(new Rect(0, 100, 0, 0), visibleInsets); + } + } + private void assertEqualsAndHashCode() { assertEquals(mState, mState2); assertEquals(mState.hashCode(), mState2.hashCode()); diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java index f9ad03f40723..9c62e9970b48 100644 --- a/services/core/java/com/android/server/wm/DisplayPolicy.java +++ b/services/core/java/com/android/server/wm/DisplayPolicy.java @@ -2061,7 +2061,8 @@ public class DisplayPolicy { cf.set(displayFrames.mRestricted); } applyStableConstraints(sysUiFl, fl, cf, displayFrames); - if (adjust != SOFT_INPUT_ADJUST_NOTHING) { + if (ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_NONE + && adjust != SOFT_INPUT_ADJUST_NOTHING) { vf.set(displayFrames.mCurrent); } else { vf.set(cf); @@ -2138,7 +2139,8 @@ public class DisplayPolicy { applyStableConstraints(sysUiFl, fl, cf, displayFrames); - if (adjust != SOFT_INPUT_ADJUST_NOTHING) { + if (ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_NONE + && adjust != SOFT_INPUT_ADJUST_NOTHING) { vf.set(displayFrames.mCurrent); } else { vf.set(cf); @@ -2179,7 +2181,8 @@ public class DisplayPolicy { cf.set(displayFrames.mContent); df.set(displayFrames.mContent); } - if (adjust != SOFT_INPUT_ADJUST_NOTHING) { + if (ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_NONE + && adjust != SOFT_INPUT_ADJUST_NOTHING) { vf.set(displayFrames.mCurrent); } else { vf.set(cf); diff --git a/services/core/java/com/android/server/wm/InsetsSourceProvider.java b/services/core/java/com/android/server/wm/InsetsSourceProvider.java index a13383d3991e..5a591ecd4746 100644 --- a/services/core/java/com/android/server/wm/InsetsSourceProvider.java +++ b/services/core/java/com/android/server/wm/InsetsSourceProvider.java @@ -129,6 +129,7 @@ class InsetsSourceProvider { if (win == null) { setServerVisible(false); mSource.setFrame(new Rect()); + mSource.setVisibleFrame(null); } else if (mControllable) { mWin.setControllableInsetProvider(this); if (mControlTarget != null) { @@ -160,6 +161,15 @@ class InsetsSourceProvider { mTmpRect.inset(mWin.mGivenContentInsets); } mSource.setFrame(mTmpRect); + + if (mWin.mGivenVisibleInsets.left != 0 || mWin.mGivenVisibleInsets.top != 0 + || mWin.mGivenVisibleInsets.right != 0 || mWin.mGivenVisibleInsets.bottom != 0) { + mTmpRect.set(mWin.getFrameLw()); + mTmpRect.inset(mWin.mGivenVisibleInsets); + mSource.setVisibleFrame(mTmpRect); + } else { + mSource.setVisibleFrame(null); + } } /** diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsSourceProviderTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsSourceProviderTest.java index 09ac9ce381c0..d819b1ada659 100644 --- a/services/tests/wmtests/src/com/android/server/wm/InsetsSourceProviderTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/InsetsSourceProviderTest.java @@ -63,6 +63,26 @@ public class InsetsSourceProviderTest extends WindowTestsBase { assertEquals(Insets.of(0, 100, 0, 0), mProvider.getSource().calculateInsets(new Rect(0, 0, 500, 500), false /* ignoreVisibility */)); + assertEquals(Insets.of(0, 100, 0, 0), + mProvider.getSource().calculateVisibleInsets(new Rect(0, 0, 500, 500))); + } + + @Test + public void testPostLayout_givenInsets() { + final WindowState ime = createWindow(null, TYPE_APPLICATION, "ime"); + ime.getFrameLw().set(0, 0, 500, 100); + ime.getGivenContentInsetsLw().set(0, 0, 0, 60); + ime.getGivenVisibleInsetsLw().set(0, 0, 0, 75); + ime.mHasSurface = true; + mProvider.setWindow(ime, null); + mProvider.onPostLayout(); + assertEquals(new Rect(0, 0, 500, 40), mProvider.getSource().getFrame()); + assertEquals(new Rect(0, 0, 500, 25), mProvider.getSource().getVisibleFrame()); + assertEquals(Insets.of(0, 40, 0, 0), + mProvider.getSource().calculateInsets(new Rect(0, 0, 500, 500), + false /* ignoreVisibility */)); + assertEquals(Insets.of(0, 25, 0, 0), + mProvider.getSource().calculateVisibleInsets(new Rect(0, 0, 500, 500))); } @Test |