summaryrefslogtreecommitdiff
path: root/core/java/android/view/WindowInsets.java
diff options
context:
space:
mode:
authorAdrian Roos <roosa@google.com>2018-08-24 16:29:06 +0200
committerAdrian Roos <roosa@google.com>2018-10-30 19:09:03 +0100
commit60f59298c77dc0a662a2523fcbd5c866ed648518 (patch)
treecec09ce20f0ac2ffe2c484e62f50b2ced54a426d /core/java/android/view/WindowInsets.java
parentb57bfe04b435ca44d5f9c07fa8e7c7d2b0abd5d4 (diff)
WindowInsets: reimplement WindowInsets on top of Insets
Bug: 111829774 Test: atest WindowInsetsTest Change-Id: Ic01c6cd46981af2e457c740c35b17c8cc9c8d25a
Diffstat (limited to 'core/java/android/view/WindowInsets.java')
-rw-r--r--core/java/android/view/WindowInsets.java268
1 files changed, 147 insertions, 121 deletions
diff --git a/core/java/android/view/WindowInsets.java b/core/java/android/view/WindowInsets.java
index 0a0ef985e80f..411be5b45488 100644
--- a/core/java/android/view/WindowInsets.java
+++ b/core/java/android/view/WindowInsets.java
@@ -17,8 +17,10 @@
package android.view;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UnsupportedAppUsage;
+import android.graphics.Insets;
import android.graphics.Rect;
import com.android.internal.util.Preconditions;
@@ -43,26 +45,24 @@ import java.util.Objects;
*/
public final class WindowInsets {
- private Rect mSystemWindowInsets;
- private Rect mWindowDecorInsets;
- private Rect mStableInsets;
- private Rect mTempRect;
- private boolean mIsRound;
- private DisplayCutout mDisplayCutout;
+ @NonNull private final Insets mSystemWindowInsets;
+ @NonNull private final Insets mWindowDecorInsets;
+ @NonNull private final Insets mStableInsets;
+ @Nullable private Rect mTempRect;
+ private final boolean mIsRound;
+ @Nullable private final DisplayCutout mDisplayCutout;
/**
* In multi-window we force show the navigation bar. Because we don't want that the surface size
* changes in this mode, we instead have a flag whether the navigation bar size should always
* be consumed, so the app is treated like there is no virtual navigation bar at all.
*/
- private boolean mAlwaysConsumeNavBar;
+ private final boolean mAlwaysConsumeNavBar;
- private boolean mSystemWindowInsetsConsumed = false;
- private boolean mWindowDecorInsetsConsumed = false;
- private boolean mStableInsetsConsumed = false;
- private boolean mDisplayCutoutConsumed = false;
-
- private static final Rect EMPTY_RECT = new Rect(0, 0, 0, 0);
+ private final boolean mSystemWindowInsetsConsumed;
+ private final boolean mWindowDecorInsetsConsumed;
+ private final boolean mStableInsetsConsumed;
+ private final boolean mDisplayCutoutConsumed;
/**
* Since new insets may be added in the future that existing apps couldn't
@@ -74,21 +74,27 @@ public final class WindowInsets {
public static final WindowInsets CONSUMED;
static {
- CONSUMED = new WindowInsets(null, null, null, false, false, null);
+ CONSUMED = new WindowInsets((Insets) null, null, null, false, false, null);
}
/** @hide */
public WindowInsets(Rect systemWindowInsets, Rect windowDecorInsets, Rect stableInsets,
boolean isRound, boolean alwaysConsumeNavBar, DisplayCutout displayCutout) {
+ this(Insets.of(systemWindowInsets), Insets.of(windowDecorInsets), Insets.of(stableInsets),
+ isRound, alwaysConsumeNavBar, displayCutout);
+ }
+
+ private WindowInsets(Insets systemWindowInsets, Insets windowDecorInsets,
+ Insets stableInsets, boolean isRound, boolean alwaysConsumeNavBar,
+ DisplayCutout displayCutout) {
mSystemWindowInsetsConsumed = systemWindowInsets == null;
- mSystemWindowInsets = mSystemWindowInsetsConsumed
- ? EMPTY_RECT : new Rect(systemWindowInsets);
+ mSystemWindowInsets = mSystemWindowInsetsConsumed ? Insets.NONE : systemWindowInsets;
mWindowDecorInsetsConsumed = windowDecorInsets == null;
- mWindowDecorInsets = mWindowDecorInsetsConsumed ? EMPTY_RECT : new Rect(windowDecorInsets);
+ mWindowDecorInsets = mWindowDecorInsetsConsumed ? Insets.NONE : windowDecorInsets;
mStableInsetsConsumed = stableInsets == null;
- mStableInsets = mStableInsetsConsumed ? EMPTY_RECT : new Rect(stableInsets);
+ mStableInsets = mStableInsetsConsumed ? Insets.NONE : stableInsets;
mIsRound = isRound;
mAlwaysConsumeNavBar = alwaysConsumeNavBar;
@@ -104,16 +110,21 @@ public final class WindowInsets {
* @param src Source to copy insets from
*/
public WindowInsets(WindowInsets src) {
- mSystemWindowInsets = src.mSystemWindowInsets;
- mWindowDecorInsets = src.mWindowDecorInsets;
- mStableInsets = src.mStableInsets;
- mSystemWindowInsetsConsumed = src.mSystemWindowInsetsConsumed;
- mWindowDecorInsetsConsumed = src.mWindowDecorInsetsConsumed;
- mStableInsetsConsumed = src.mStableInsetsConsumed;
- mIsRound = src.mIsRound;
- mAlwaysConsumeNavBar = src.mAlwaysConsumeNavBar;
- mDisplayCutout = src.mDisplayCutout;
- mDisplayCutoutConsumed = src.mDisplayCutoutConsumed;
+ this(src.mSystemWindowInsetsConsumed ? null : src.mSystemWindowInsets,
+ src.mWindowDecorInsetsConsumed ? null : src.mWindowDecorInsets,
+ src.mStableInsetsConsumed ? null : src.mStableInsets,
+ src.mIsRound, src.mAlwaysConsumeNavBar,
+ displayCutoutCopyConstructorArgument(src));
+ }
+
+ private static DisplayCutout displayCutoutCopyConstructorArgument(WindowInsets w) {
+ if (w.mDisplayCutoutConsumed) {
+ return null;
+ } else if (w.mDisplayCutout == null) {
+ return DisplayCutout.NO_CUTOUT;
+ } else {
+ return w.mDisplayCutout;
+ }
}
/** @hide */
@@ -126,14 +137,17 @@ public final class WindowInsets {
* Used to provide a safe copy of the system window insets to pass through
* to the existing fitSystemWindows method and other similar internals.
* @hide
+ *
+ * @deprecated use {@link #getSystemWindowInsets()} instead.
*/
- @UnsupportedAppUsage
- public Rect getSystemWindowInsets() {
+ @Deprecated
+ public Rect getSystemWindowInsetsAsRect() {
if (mTempRect == null) {
mTempRect = new Rect();
}
if (mSystemWindowInsets != null) {
- mTempRect.set(mSystemWindowInsets);
+ mTempRect.set(mSystemWindowInsets.left, mSystemWindowInsets.top,
+ mSystemWindowInsets.right, mSystemWindowInsets.bottom);
} else {
// If there were no system window insets, this is just empty.
mTempRect.setEmpty();
@@ -142,6 +156,20 @@ public final class WindowInsets {
}
/**
+ * Returns the system window insets in pixels.
+ *
+ * <p>The system window inset represents the area of a full-screen window that is
+ * partially or fully obscured by the status bar, navigation bar, IME or other system windows.
+ * </p>
+ *
+ * @return The system window insets
+ */
+ @NonNull
+ public Insets getSystemWindowInsets() {
+ return mSystemWindowInsets;
+ }
+
+ /**
* Returns the left system window inset in pixels.
*
* <p>The system window inset represents the area of a full-screen window that is
@@ -305,10 +333,11 @@ public final class WindowInsets {
* @return A modified copy of this WindowInsets
*/
public WindowInsets consumeDisplayCutout() {
- final WindowInsets result = new WindowInsets(this);
- result.mDisplayCutout = null;
- result.mDisplayCutoutConsumed = true;
- return result;
+ return new WindowInsets(mSystemWindowInsetsConsumed ? null : mSystemWindowInsets,
+ mWindowDecorInsetsConsumed ? null : mWindowDecorInsets,
+ mStableInsetsConsumed ? null : mStableInsets,
+ mIsRound, mAlwaysConsumeNavBar,
+ null /* displayCutout */);
}
@@ -350,100 +379,90 @@ public final class WindowInsets {
* @return A modified copy of this WindowInsets
*/
public WindowInsets consumeSystemWindowInsets() {
- final WindowInsets result = new WindowInsets(this);
- result.mSystemWindowInsets = EMPTY_RECT;
- result.mSystemWindowInsetsConsumed = true;
- return result;
- }
-
- /**
- * Returns a copy of this WindowInsets with selected system window insets fully consumed.
- *
- * @param left true to consume the left system window inset
- * @param top true to consume the top system window inset
- * @param right true to consume the right system window inset
- * @param bottom true to consume the bottom system window inset
- * @return A modified copy of this WindowInsets
- * @hide pending API
- */
- public WindowInsets consumeSystemWindowInsets(boolean left, boolean top,
- boolean right, boolean bottom) {
- if (left || top || right || bottom) {
- final WindowInsets result = new WindowInsets(this);
- result.mSystemWindowInsets = new Rect(
- left ? 0 : mSystemWindowInsets.left,
- top ? 0 : mSystemWindowInsets.top,
- right ? 0 : mSystemWindowInsets.right,
- bottom ? 0 : mSystemWindowInsets.bottom);
- return result;
- }
- return this;
+ return new WindowInsets(null /* systemWindowInsets */,
+ mWindowDecorInsetsConsumed ? null : mWindowDecorInsets,
+ mStableInsetsConsumed ? null : mStableInsets,
+ mIsRound, mAlwaysConsumeNavBar,
+ displayCutoutCopyConstructorArgument(this));
}
/**
* Returns a copy of this WindowInsets with selected system window insets replaced
* with new values.
*
+ * <p>Note: If the system window insets are already consumed, this method will return them
+ * unchanged on {@link android.os.Build.VERSION_CODES#Q Q} and later. Prior to
+ * {@link android.os.Build.VERSION_CODES#Q Q}, the new values were applied regardless of
+ * whether they were consumed, and this method returns invalid non-zero consumed insets.
+ *
* @param left New left inset in pixels
* @param top New top inset in pixels
* @param right New right inset in pixels
* @param bottom New bottom inset in pixels
* @return A modified copy of this WindowInsets
*/
- public WindowInsets replaceSystemWindowInsets(int left, int top,
- int right, int bottom) {
- final WindowInsets result = new WindowInsets(this);
- result.mSystemWindowInsets = new Rect(left, top, right, bottom);
- return result;
+ public WindowInsets replaceSystemWindowInsets(int left, int top, int right, int bottom) {
+ // TODO(roosa): deprecate in follow-up CL, once we have a builder for WindowInsets.
+
+ // Compat edge case: what should this do if the insets have already been consumed?
+ // On platforms prior to Q, the behavior was to override the insets with non-zero values,
+ // but leave them consumed, which is invalid (consumed insets must be zero).
+ // The behavior is now keeping them consumed and discarding the new insets.
+ if (mSystemWindowInsetsConsumed) {
+ return this;
+ }
+
+ return new WindowInsets(Insets.of(left, top, right, bottom),
+ mWindowDecorInsetsConsumed ? null : mWindowDecorInsets,
+ mStableInsetsConsumed ? null : mStableInsets,
+ mIsRound, mAlwaysConsumeNavBar,
+ displayCutoutCopyConstructorArgument(this));
}
/**
* Returns a copy of this WindowInsets with selected system window insets replaced
* with new values.
*
+ * <p>Note: If the system window insets are already consumed, this method will return them
+ * unchanged on {@link android.os.Build.VERSION_CODES#Q Q} and later. Prior to
+ * {@link android.os.Build.VERSION_CODES#Q Q}, the new values were applied regardless of
+ * whether they were consumed, and this method returns invalid non-zero consumed insets.
+ *
* @param systemWindowInsets New system window insets. Each field is the inset in pixels
* for that edge
* @return A modified copy of this WindowInsets
*/
public WindowInsets replaceSystemWindowInsets(Rect systemWindowInsets) {
- final WindowInsets result = new WindowInsets(this);
- result.mSystemWindowInsets = new Rect(systemWindowInsets);
- return result;
+ // TODO(roosa): deprecate in follow-up CL, once we have a builder for WindowInsets.
+ return replaceSystemWindowInsets(systemWindowInsets.left, systemWindowInsets.top,
+ systemWindowInsets.right, systemWindowInsets.bottom);
}
/**
* @hide
*/
public WindowInsets consumeWindowDecorInsets() {
- final WindowInsets result = new WindowInsets(this);
- result.mWindowDecorInsets.set(0, 0, 0, 0);
- result.mWindowDecorInsetsConsumed = true;
- return result;
- }
-
- /**
- * @hide
- */
- public WindowInsets consumeWindowDecorInsets(boolean left, boolean top,
- boolean right, boolean bottom) {
- if (left || top || right || bottom) {
- final WindowInsets result = new WindowInsets(this);
- result.mWindowDecorInsets = new Rect(left ? 0 : mWindowDecorInsets.left,
- top ? 0 : mWindowDecorInsets.top,
- right ? 0 : mWindowDecorInsets.right,
- bottom ? 0 : mWindowDecorInsets.bottom);
- return result;
- }
- return this;
+ return new WindowInsets(mSystemWindowInsetsConsumed ? null : mSystemWindowInsets,
+ null /* windowDecorInsets */,
+ mStableInsetsConsumed ? null : mStableInsets,
+ mIsRound, mAlwaysConsumeNavBar,
+ displayCutoutCopyConstructorArgument(this));
}
/**
- * @hide
+ * Returns the stable insets in pixels.
+ *
+ * <p>The stable inset represents the area of a full-screen window that <b>may</b> be
+ * partially or fully obscured by the system UI elements. This value does not change
+ * based on the visibility state of those elements; for example, if the status bar is
+ * normally shown, but temporarily hidden, the stable inset will still provide the inset
+ * associated with the status bar being shown.</p>
+ *
+ * @return The stable insets
*/
- public WindowInsets replaceWindowDecorInsets(int left, int top, int right, int bottom) {
- final WindowInsets result = new WindowInsets(this);
- result.mWindowDecorInsets = new Rect(left, top, right, bottom);
- return result;
+ @NonNull
+ public Insets getStableInsets() {
+ return mStableInsets;
}
/**
@@ -528,10 +547,11 @@ public final class WindowInsets {
* @return A modified copy of this WindowInsets
*/
public WindowInsets consumeStableInsets() {
- final WindowInsets result = new WindowInsets(this);
- result.mStableInsets = EMPTY_RECT;
- result.mStableInsetsConsumed = true;
- return result;
+ return new WindowInsets(mSystemWindowInsetsConsumed ? null : mSystemWindowInsets,
+ mWindowDecorInsetsConsumed ? null : mWindowDecorInsets,
+ null /* stableInsets */,
+ mIsRound, mAlwaysConsumeNavBar,
+ displayCutoutCopyConstructorArgument(this));
}
/**
@@ -555,8 +575,10 @@ public final class WindowInsets {
* Returns a copy of this instance inset in the given directions.
*
* @see #inset(int, int, int, int)
+ * @deprecated use {@link #inset(Insets)}
* @hide
*/
+ @Deprecated
public WindowInsets inset(Rect r) {
return inset(r.left, r.top, r.right, r.bottom);
}
@@ -564,6 +586,16 @@ public final class WindowInsets {
/**
* Returns a copy of this instance inset in the given directions.
*
+ * @see #inset(int, int, int, int)
+ * @hide
+ */
+ public WindowInsets inset(Insets insets) {
+ return inset(insets.left, insets.top, insets.right, insets.bottom);
+ }
+
+ /**
+ * Returns a copy of this instance inset in the given directions.
+ *
* This is intended for dispatching insets to areas of the window that are smaller than the
* current area.
*
@@ -587,25 +619,19 @@ public final class WindowInsets {
Preconditions.checkArgumentNonnegative(right);
Preconditions.checkArgumentNonnegative(bottom);
- WindowInsets result = new WindowInsets(this);
- if (!result.mSystemWindowInsetsConsumed) {
- result.mSystemWindowInsets =
- insetInsets(result.mSystemWindowInsets, left, top, right, bottom);
- }
- if (!result.mWindowDecorInsetsConsumed) {
- result.mWindowDecorInsets =
- insetInsets(result.mWindowDecorInsets, left, top, right, bottom);
- }
- if (!result.mStableInsetsConsumed) {
- result.mStableInsets = insetInsets(result.mStableInsets, left, top, right, bottom);
- }
- if (mDisplayCutout != null) {
- result.mDisplayCutout = result.mDisplayCutout.inset(left, top, right, bottom);
- if (result.mDisplayCutout.isEmpty()) {
- result.mDisplayCutout = null;
- }
- }
- return result;
+ return new WindowInsets(
+ mSystemWindowInsetsConsumed ? null :
+ insetInsets(mSystemWindowInsets, left, top, right, bottom),
+ mWindowDecorInsetsConsumed ? null :
+ insetInsets(mWindowDecorInsets, left, top, right, bottom),
+ mStableInsetsConsumed ? null :
+ insetInsets(mStableInsets, left, top, right, bottom),
+ mIsRound, mAlwaysConsumeNavBar,
+ mDisplayCutoutConsumed
+ ? null :
+ mDisplayCutout == null
+ ? DisplayCutout.NO_CUTOUT
+ : mDisplayCutout.inset(left, top, right, bottom));
}
@Override
@@ -632,7 +658,7 @@ public final class WindowInsets {
mWindowDecorInsetsConsumed, mStableInsetsConsumed, mDisplayCutoutConsumed);
}
- private static Rect insetInsets(Rect insets, int left, int top, int right, int bottom) {
+ private static Insets insetInsets(Insets insets, int left, int top, int right, int bottom) {
int newLeft = Math.max(0, insets.left - left);
int newTop = Math.max(0, insets.top - top);
int newRight = Math.max(0, insets.right - right);
@@ -640,7 +666,7 @@ public final class WindowInsets {
if (newLeft == left && newTop == top && newRight == right && newBottom == bottom) {
return insets;
}
- return new Rect(newLeft, newTop, newRight, newBottom);
+ return Insets.of(newLeft, newTop, newRight, newBottom);
}
/**