Don't extend alert windows onto status bar/nav bar.
This requires preserving information about the status bar/nav bar insets
and using it to reduce the available space when measuring wrap_content
windows.
Also remove the hack that was introduced for round devices and should be
handled instead by the round qualifier and theming.
Bug: 26014496
Change-Id: I5688c50153047dcabc197adab8fec141630a2b51
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index 36009dc..1a20e5c 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -205,6 +205,9 @@
private float mAvailableWidth;
String mLogTag = TAG;
+ private final Rect mFloatingInsets = new Rect();
+ private boolean mApplyFloatingVerticalInsets = false;
+ private boolean mApplyFloatingHorizontalInsets = false;
DecorView(Context context, int featureId, PhoneWindow window,
WindowManager.LayoutParams params) {
@@ -567,6 +570,7 @@
final int heightMode = getMode(heightMeasureSpec);
boolean fixedWidth = false;
+ mApplyFloatingHorizontalInsets = false;
if (widthMode == AT_MOST) {
final TypedValue tvw = isPortrait ? mWindow.mFixedWidthMinor : mWindow.mFixedWidthMajor;
if (tvw != null && tvw.type != TypedValue.TYPE_NULL) {
@@ -584,10 +588,16 @@
widthMeasureSpec = MeasureSpec.makeMeasureSpec(
Math.min(w, widthSize), EXACTLY);
fixedWidth = true;
+ } else {
+ widthMeasureSpec = MeasureSpec.makeMeasureSpec(
+ widthMeasureSpec - mFloatingInsets.left - mFloatingInsets.right,
+ AT_MOST);
+ mApplyFloatingHorizontalInsets = true;
}
}
}
+ mApplyFloatingVerticalInsets = false;
if (heightMode == AT_MOST) {
final TypedValue tvh = isPortrait ? mWindow.mFixedHeightMajor
: mWindow.mFixedHeightMinor;
@@ -601,10 +611,14 @@
h = 0;
}
if (DEBUG_MEASURE) Log.d(mLogTag, "Fixed height: " + h);
+ final int heightSize = MeasureSpec.getSize(heightMeasureSpec);
if (h > 0) {
- final int heightSize = MeasureSpec.getSize(heightMeasureSpec);
heightMeasureSpec = MeasureSpec.makeMeasureSpec(
Math.min(h, heightSize), EXACTLY);
+ } else if ((mWindow.getAttributes().flags & FLAG_FULLSCREEN) == 0) {
+ heightMeasureSpec = MeasureSpec.makeMeasureSpec(
+ heightSize - mFloatingInsets.top - mFloatingInsets.bottom, AT_MOST);
+ mApplyFloatingVerticalInsets = true;
}
}
}
@@ -672,6 +686,12 @@
if (mOutsets.top > 0) {
offsetTopAndBottom(-mOutsets.top);
}
+ if (mApplyFloatingVerticalInsets) {
+ offsetTopAndBottom(mFloatingInsets.top);
+ }
+ if (mApplyFloatingHorizontalInsets) {
+ offsetLeftAndRight(mFloatingInsets.left);
+ }
// If the application changed its SystemUI metrics, we might also have to adapt
// our shadow elevation.
@@ -868,6 +888,25 @@
@Override
public WindowInsets onApplyWindowInsets(WindowInsets insets) {
+ final WindowManager.LayoutParams attrs = mWindow.getAttributes();
+ mFloatingInsets.setEmpty();
+ if ((attrs.flags & FLAG_FULLSCREEN) == 0) {
+ // For dialog windows we want to make sure they don't go over the status bar or nav bar.
+ // We consume the system insets and we will reuse them later during the measure phase.
+ // We allow the app to ignore this and handle insets itself by using FLAG_FULLSCREEN.
+ if (attrs.height == WindowManager.LayoutParams.WRAP_CONTENT) {
+ mFloatingInsets.top = insets.getSystemWindowInsetTop();
+ mFloatingInsets.bottom = insets.getSystemWindowInsetBottom();
+ insets = insets.replaceSystemWindowInsets(insets.getSystemWindowInsetLeft(), 0,
+ insets.getSystemWindowInsetRight(), 0);
+ }
+ if (mWindow.getAttributes().width == WindowManager.LayoutParams.WRAP_CONTENT) {
+ mFloatingInsets.left = insets.getSystemWindowInsetTop();
+ mFloatingInsets.right = insets.getSystemWindowInsetBottom();
+ insets = insets.replaceSystemWindowInsets(0, insets.getSystemWindowInsetTop(),
+ 0, insets.getSystemWindowInsetBottom());
+ }
+ }
mFrameOffsets.set(insets.getSystemWindowInsets());
insets = updateColorViews(insets, true /* animate */);
insets = updateStatusGuard(insets);