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/app/AlertController.java b/core/java/com/android/internal/app/AlertController.java
index 27c3b72..f13373e 100644
--- a/core/java/com/android/internal/app/AlertController.java
+++ b/core/java/com/android/internal/app/AlertController.java
@@ -232,7 +232,6 @@
int contentView = selectContentView();
mWindow.setContentView(contentView);
setupView();
- setupDecor();
}
private int selectContentView() {
@@ -429,27 +428,6 @@
return mScrollView != null && mScrollView.executeKeyEvent(event);
}
- private void setupDecor() {
- final View decor = mWindow.getDecorView();
- final View parent = mWindow.findViewById(R.id.parentPanel);
- if (parent != null && decor != null) {
- decor.setOnApplyWindowInsetsListener(new View.OnApplyWindowInsetsListener() {
- @Override
- public WindowInsets onApplyWindowInsets(View view, WindowInsets insets) {
- if (insets.isRound()) {
- // TODO: Get the padding as a function of the window size.
- int roundOffset = mContext.getResources().getDimensionPixelOffset(
- R.dimen.alert_dialog_round_padding);
- parent.setPadding(roundOffset, roundOffset, roundOffset, roundOffset);
- }
- return insets.consumeSystemWindowInsets();
- }
- });
- decor.setFitsSystemWindows(true);
- decor.requestApplyInsets();
- }
- }
-
/**
* Resolves whether a custom or default panel should be used. Removes the
* default panel if a custom panel should be used. If the resolved panel is
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);