Merge "Move logic about computing window frames to the client side"
This commit is contained in:
@@ -317,6 +317,26 @@ public class InsetsState implements Parcelable {
|
||||
return insets;
|
||||
}
|
||||
|
||||
public Insets calculateInsets(Rect frame, @InsetsType int types,
|
||||
InsetsVisibilities overrideVisibilities) {
|
||||
Insets insets = Insets.NONE;
|
||||
for (int type = FIRST_TYPE; type <= LAST_TYPE; type++) {
|
||||
InsetsSource source = mSources[type];
|
||||
if (source == null) {
|
||||
continue;
|
||||
}
|
||||
int publicType = InsetsState.toPublicType(type);
|
||||
if ((publicType & types) == 0) {
|
||||
continue;
|
||||
}
|
||||
if (!overrideVisibilities.getVisibility(type)) {
|
||||
continue;
|
||||
}
|
||||
insets = Insets.max(source.calculateInsets(frame, true), insets);
|
||||
}
|
||||
return insets;
|
||||
}
|
||||
|
||||
public Insets calculateVisibleInsets(Rect frame, @SoftInputModeFlags int softInputMode) {
|
||||
Insets insets = Insets.NONE;
|
||||
for (int type = FIRST_TYPE; type <= LAST_TYPE; type++) {
|
||||
@@ -482,6 +502,26 @@ public class InsetsState implements Parcelable {
|
||||
return mDisplayCutout.get();
|
||||
}
|
||||
|
||||
public void getDisplayCutoutSafe(Rect outBounds) {
|
||||
outBounds.set(Integer.MIN_VALUE, Integer.MIN_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE);
|
||||
final DisplayCutout cutout = mDisplayCutout.get();
|
||||
final Rect displayFrame = mDisplayFrame;
|
||||
if (!cutout.isEmpty()) {
|
||||
if (cutout.getSafeInsetLeft() > 0) {
|
||||
outBounds.left = displayFrame.left + cutout.getSafeInsetLeft();
|
||||
}
|
||||
if (cutout.getSafeInsetTop() > 0) {
|
||||
outBounds.top = displayFrame.top + cutout.getSafeInsetTop();
|
||||
}
|
||||
if (cutout.getSafeInsetRight() > 0) {
|
||||
outBounds.right = displayFrame.right - cutout.getSafeInsetRight();
|
||||
}
|
||||
if (cutout.getSafeInsetBottom() > 0) {
|
||||
outBounds.bottom = displayFrame.bottom - cutout.getSafeInsetBottom();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setRoundedCorners(RoundedCorners roundedCorners) {
|
||||
mRoundedCorners = roundedCorners;
|
||||
}
|
||||
|
||||
@@ -140,7 +140,6 @@ import android.os.Trace;
|
||||
import android.os.UserHandle;
|
||||
import android.sysprop.DisplayProperties;
|
||||
import android.util.AndroidRuntimeException;
|
||||
import android.util.ArraySet;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.EventLog;
|
||||
import android.util.IndentingPrintWriter;
|
||||
@@ -160,7 +159,6 @@ import android.view.View.AttachInfo;
|
||||
import android.view.View.FocusDirection;
|
||||
import android.view.View.MeasureSpec;
|
||||
import android.view.Window.OnContentApplyWindowInsetsListener;
|
||||
import android.view.WindowInsets.Side.InsetsSide;
|
||||
import android.view.WindowInsets.Type;
|
||||
import android.view.WindowInsets.Type.InsetsType;
|
||||
import android.view.WindowManager.LayoutParams.SoftInputModeFlags;
|
||||
@@ -511,9 +509,11 @@ public final class ViewRootImpl implements ViewParent,
|
||||
private final Point mSurfaceSize = new Point();
|
||||
private final Point mLastSurfaceSize = new Point();
|
||||
|
||||
final Rect mTempRect; // used in the transaction to not thrash the heap.
|
||||
final Rect mVisRect; // used to retrieve visible rect of focused view.
|
||||
private final Rect mTempBoundsRect = new Rect(); // used to set the size of the bounds surface.
|
||||
private final Rect mVisRect = new Rect(); // used to retrieve visible rect of focused view.
|
||||
private final Rect mTempRect = new Rect();
|
||||
private final Rect mTempRect2 = new Rect();
|
||||
|
||||
private final WindowLayout mWindowLayout = new WindowLayout();
|
||||
|
||||
// This is used to reduce the race between window focus changes being dispatched from
|
||||
// the window manager and input events coming through the input system.
|
||||
@@ -809,8 +809,6 @@ public final class ViewRootImpl implements ViewParent,
|
||||
mWidth = -1;
|
||||
mHeight = -1;
|
||||
mDirty = new Rect();
|
||||
mTempRect = new Rect();
|
||||
mVisRect = new Rect();
|
||||
mWinFrame = new Rect();
|
||||
mWindow = new W(this);
|
||||
mLeashToken = new Binder();
|
||||
@@ -985,29 +983,6 @@ public final class ViewRootImpl implements ViewParent,
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(b/161810301): Make this private after window layout is moved to the client side.
|
||||
public static void computeWindowBounds(WindowManager.LayoutParams attrs, InsetsState state,
|
||||
Rect displayFrame, Rect outBounds) {
|
||||
final @InsetsType int typesToFit = attrs.getFitInsetsTypes();
|
||||
final @InsetsSide int sidesToFit = attrs.getFitInsetsSides();
|
||||
final ArraySet<Integer> types = InsetsState.toInternalType(typesToFit);
|
||||
final Rect df = displayFrame;
|
||||
Insets insets = Insets.of(0, 0, 0, 0);
|
||||
for (int i = types.size() - 1; i >= 0; i--) {
|
||||
final InsetsSource source = state.peekSource(types.valueAt(i));
|
||||
if (source == null) {
|
||||
continue;
|
||||
}
|
||||
insets = Insets.max(insets, source.calculateInsets(
|
||||
df, attrs.isFitInsetsIgnoringVisibility()));
|
||||
}
|
||||
final int left = (sidesToFit & WindowInsets.Side.LEFT) != 0 ? insets.left : 0;
|
||||
final int top = (sidesToFit & WindowInsets.Side.TOP) != 0 ? insets.top : 0;
|
||||
final int right = (sidesToFit & WindowInsets.Side.RIGHT) != 0 ? insets.right : 0;
|
||||
final int bottom = (sidesToFit & WindowInsets.Side.BOTTOM) != 0 ? insets.bottom : 0;
|
||||
outBounds.set(df.left + left, df.top + top, df.right - right, df.bottom - bottom);
|
||||
}
|
||||
|
||||
private Configuration getConfiguration() {
|
||||
return mContext.getResources().getConfiguration();
|
||||
}
|
||||
@@ -1168,8 +1143,13 @@ public final class ViewRootImpl implements ViewParent,
|
||||
mPendingAlwaysConsumeSystemBars = mAttachInfo.mAlwaysConsumeSystemBars;
|
||||
mInsetsController.onStateChanged(mTempInsets);
|
||||
mInsetsController.onControlsChanged(mTempControls);
|
||||
computeWindowBounds(mWindowAttributes, mInsetsController.getState(),
|
||||
getConfiguration().windowConfiguration.getBounds(), mTmpFrames.frame);
|
||||
final InsetsState state = mInsetsController.getState();
|
||||
final Rect displayCutoutSafe = mTempRect;
|
||||
state.getDisplayCutoutSafe(displayCutoutSafe);
|
||||
mWindowLayout.computeWindowFrames(mWindowAttributes, state,
|
||||
displayCutoutSafe, getConfiguration().windowConfiguration.getBounds(),
|
||||
mInsetsController.getRequestedVisibilities(),
|
||||
null /* attachedWindowFrame */, mTmpFrames.frame, mTempRect2);
|
||||
setFrame(mTmpFrames.frame);
|
||||
if (DEBUG_LAYOUT) Log.v(mTag, "Added window " + mWindow);
|
||||
if (res < WindowManagerGlobal.ADD_OKAY) {
|
||||
@@ -1966,11 +1946,11 @@ public final class ViewRootImpl implements ViewParent,
|
||||
private void setBoundsLayerCrop(Transaction t) {
|
||||
// Adjust of insets and update the bounds layer so child surfaces do not draw into
|
||||
// the surface inset region.
|
||||
mTempBoundsRect.set(0, 0, mSurfaceSize.x, mSurfaceSize.y);
|
||||
mTempBoundsRect.inset(mWindowAttributes.surfaceInsets.left,
|
||||
mTempRect.set(0, 0, mSurfaceSize.x, mSurfaceSize.y);
|
||||
mTempRect.inset(mWindowAttributes.surfaceInsets.left,
|
||||
mWindowAttributes.surfaceInsets.top,
|
||||
mWindowAttributes.surfaceInsets.right, mWindowAttributes.surfaceInsets.bottom);
|
||||
t.setWindowCrop(mBoundsLayer, mTempBoundsRect);
|
||||
t.setWindowCrop(mBoundsLayer, mTempRect);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
152
core/java/android/view/WindowLayout.java
Normal file
152
core/java/android/view/WindowLayout.java
Normal file
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.view;
|
||||
|
||||
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.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
|
||||
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
|
||||
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
|
||||
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT;
|
||||
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
|
||||
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_INSET_PARENT_FRAME_BY_IME;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
|
||||
|
||||
import android.graphics.Insets;
|
||||
import android.graphics.Rect;
|
||||
|
||||
/**
|
||||
* Computes window frames.
|
||||
* @hide
|
||||
*/
|
||||
public class WindowLayout {
|
||||
private final Rect mTempDisplayCutoutSafeExceptMaybeBarsRect = new Rect();
|
||||
private final Rect mTempRect = new Rect();
|
||||
|
||||
public boolean computeWindowFrames(WindowManager.LayoutParams attrs, InsetsState state,
|
||||
Rect displayCutoutSafe, Rect windowBounds, InsetsVisibilities requestedVisibilities,
|
||||
Rect attachedWindowFrame, Rect outDisplayFrame, Rect outParentFrame) {
|
||||
final int type = attrs.type;
|
||||
final int fl = attrs.flags;
|
||||
final int pfl = attrs.privateFlags;
|
||||
final boolean layoutInScreen = (fl & FLAG_LAYOUT_IN_SCREEN) == FLAG_LAYOUT_IN_SCREEN;
|
||||
|
||||
// Compute bounds restricted by insets
|
||||
final Insets insets = state.calculateInsets(windowBounds, attrs.getFitInsetsTypes(),
|
||||
attrs.isFitInsetsIgnoringVisibility());
|
||||
final @WindowInsets.Side.InsetsSide int sides = attrs.getFitInsetsSides();
|
||||
final int left = (sides & WindowInsets.Side.LEFT) != 0 ? insets.left : 0;
|
||||
final int top = (sides & WindowInsets.Side.TOP) != 0 ? insets.top : 0;
|
||||
final int right = (sides & WindowInsets.Side.RIGHT) != 0 ? insets.right : 0;
|
||||
final int bottom = (sides & WindowInsets.Side.BOTTOM) != 0 ? insets.bottom : 0;
|
||||
outDisplayFrame.set(windowBounds.left + left, windowBounds.top + top,
|
||||
windowBounds.right - right, windowBounds.bottom - bottom);
|
||||
|
||||
if (attachedWindowFrame == null) {
|
||||
outParentFrame.set(outDisplayFrame);
|
||||
if ((pfl & PRIVATE_FLAG_INSET_PARENT_FRAME_BY_IME) != 0) {
|
||||
final InsetsSource source = state.peekSource(ITYPE_IME);
|
||||
if (source != null) {
|
||||
outParentFrame.inset(source.calculateInsets(
|
||||
outParentFrame, false /* ignoreVisibility */));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
outParentFrame.set(!layoutInScreen ? attachedWindowFrame : outDisplayFrame);
|
||||
}
|
||||
|
||||
// Compute bounds restricted by display cutout
|
||||
final DisplayCutout cutout = state.getDisplayCutout();
|
||||
if (cutout.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
boolean clippedByDisplayCutout = false;
|
||||
final Rect displayCutoutSafeExceptMaybeBars = mTempDisplayCutoutSafeExceptMaybeBarsRect;
|
||||
displayCutoutSafeExceptMaybeBars.set(displayCutoutSafe);
|
||||
|
||||
// Ensure that windows with a non-ALWAYS display cutout mode are laid out in
|
||||
// the cutout safe zone.
|
||||
final int cutoutMode = attrs.layoutInDisplayCutoutMode;
|
||||
if (cutoutMode != LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS) {
|
||||
final Rect displayFrame = state.getDisplayFrame();
|
||||
final InsetsSource statusBarSource = state.peekSource(ITYPE_STATUS_BAR);
|
||||
if (statusBarSource != null && displayCutoutSafe.top > displayFrame.top) {
|
||||
// Make sure that the zone we're avoiding for the cutout is at least as tall as the
|
||||
// status bar; otherwise fullscreen apps will end up cutting halfway into the status
|
||||
// bar.
|
||||
displayCutoutSafeExceptMaybeBars.top =
|
||||
Math.max(statusBarSource.getFrame().bottom, displayCutoutSafe.top);
|
||||
}
|
||||
if (cutoutMode == LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES) {
|
||||
if (displayFrame.width() < displayFrame.height()) {
|
||||
displayCutoutSafeExceptMaybeBars.top = Integer.MIN_VALUE;
|
||||
displayCutoutSafeExceptMaybeBars.bottom = Integer.MAX_VALUE;
|
||||
} else {
|
||||
displayCutoutSafeExceptMaybeBars.left = Integer.MIN_VALUE;
|
||||
displayCutoutSafeExceptMaybeBars.right = Integer.MAX_VALUE;
|
||||
}
|
||||
}
|
||||
final boolean layoutInsetDecor = (attrs.flags & FLAG_LAYOUT_INSET_DECOR) != 0;
|
||||
if (layoutInScreen && layoutInsetDecor
|
||||
&& (cutoutMode == LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT
|
||||
|| cutoutMode == LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES)) {
|
||||
final Insets systemBarsInsets = state.calculateInsets(
|
||||
displayFrame, WindowInsets.Type.systemBars(), requestedVisibilities);
|
||||
if (systemBarsInsets.left > 0) {
|
||||
displayCutoutSafeExceptMaybeBars.left = Integer.MIN_VALUE;
|
||||
}
|
||||
if (systemBarsInsets.top > 0) {
|
||||
displayCutoutSafeExceptMaybeBars.top = Integer.MIN_VALUE;
|
||||
}
|
||||
if (systemBarsInsets.right > 0) {
|
||||
displayCutoutSafeExceptMaybeBars.right = Integer.MAX_VALUE;
|
||||
}
|
||||
if (systemBarsInsets.bottom > 0) {
|
||||
displayCutoutSafeExceptMaybeBars.bottom = Integer.MAX_VALUE;
|
||||
}
|
||||
}
|
||||
if (type == TYPE_INPUT_METHOD) {
|
||||
final InsetsSource navSource = state.peekSource(ITYPE_NAVIGATION_BAR);
|
||||
if (navSource != null && navSource.calculateInsets(displayFrame, true).bottom > 0) {
|
||||
// The IME can always extend under the bottom cutout if the navbar is there.
|
||||
displayCutoutSafeExceptMaybeBars.bottom = Integer.MAX_VALUE;
|
||||
}
|
||||
}
|
||||
final boolean attachedInParent = attachedWindowFrame != null && !layoutInScreen;
|
||||
|
||||
// TYPE_BASE_APPLICATION windows are never considered floating here because they don't
|
||||
// get cropped / shifted to the displayFrame in WindowState.
|
||||
final boolean floatingInScreenWindow = !attrs.isFullscreen() && layoutInScreen
|
||||
&& type != TYPE_BASE_APPLICATION;
|
||||
|
||||
// Windows that are attached to a parent and laid out in said parent already avoid
|
||||
// the cutout according to that parent and don't need to be further constrained.
|
||||
// Floating IN_SCREEN windows get what they ask for and lay out in the full screen.
|
||||
// They will later be cropped or shifted using the displayFrame in WindowState,
|
||||
// which prevents overlap with the DisplayCutout.
|
||||
if (!attachedInParent && !floatingInScreenWindow) {
|
||||
mTempRect.set(outParentFrame);
|
||||
outParentFrame.intersectUnchecked(displayCutoutSafeExceptMaybeBars);
|
||||
clippedByDisplayCutout = !mTempRect.equals(outParentFrame);
|
||||
}
|
||||
outDisplayFrame.intersectUnchecked(displayCutoutSafeExceptMaybeBars);
|
||||
}
|
||||
return clippedByDisplayCutout;
|
||||
}
|
||||
}
|
||||
@@ -84,7 +84,7 @@ public class DisplayFrames {
|
||||
final Rect safe = mDisplayCutoutSafe;
|
||||
final DisplayCutout cutout = displayCutout.getDisplayCutout();
|
||||
if (mDisplayWidth == info.logicalWidth && mDisplayHeight == info.logicalHeight
|
||||
&& state.getDisplayCutout().equals(cutout)
|
||||
&& state.getDisplayCutout().equals(cutout)
|
||||
&& state.getRoundedCorners().equals(roundedCorners)
|
||||
&& state.getPrivacyIndicatorBounds().equals(indicatorBounds)) {
|
||||
return false;
|
||||
@@ -93,24 +93,12 @@ public class DisplayFrames {
|
||||
mDisplayHeight = info.logicalHeight;
|
||||
final Rect unrestricted = mUnrestricted;
|
||||
unrestricted.set(0, 0, mDisplayWidth, mDisplayHeight);
|
||||
safe.set(Integer.MIN_VALUE, Integer.MIN_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE);
|
||||
state.setDisplayFrame(unrestricted);
|
||||
state.setDisplayCutout(cutout);
|
||||
state.setRoundedCorners(roundedCorners);
|
||||
state.setPrivacyIndicatorBounds(indicatorBounds);
|
||||
state.getDisplayCutoutSafe(safe);
|
||||
if (!cutout.isEmpty()) {
|
||||
if (cutout.getSafeInsetLeft() > 0) {
|
||||
safe.left = unrestricted.left + cutout.getSafeInsetLeft();
|
||||
}
|
||||
if (cutout.getSafeInsetTop() > 0) {
|
||||
safe.top = unrestricted.top + cutout.getSafeInsetTop();
|
||||
}
|
||||
if (cutout.getSafeInsetRight() > 0) {
|
||||
safe.right = unrestricted.right - cutout.getSafeInsetRight();
|
||||
}
|
||||
if (cutout.getSafeInsetBottom() > 0) {
|
||||
safe.bottom = unrestricted.bottom - cutout.getSafeInsetBottom();
|
||||
}
|
||||
state.getSource(ITYPE_LEFT_DISPLAY_CUTOUT).setFrame(
|
||||
unrestricted.left, unrestricted.top, safe.left, unrestricted.bottom);
|
||||
state.getSource(ITYPE_TOP_DISPLAY_CUTOUT).setFrame(
|
||||
|
||||
@@ -29,7 +29,6 @@ import static android.view.InsetsState.ITYPE_BOTTOM_TAPPABLE_ELEMENT;
|
||||
import static android.view.InsetsState.ITYPE_CAPTION_BAR;
|
||||
import static android.view.InsetsState.ITYPE_CLIMATE_BAR;
|
||||
import static android.view.InsetsState.ITYPE_EXTRA_NAVIGATION_BAR;
|
||||
import static android.view.InsetsState.ITYPE_IME;
|
||||
import static android.view.InsetsState.ITYPE_LEFT_GESTURES;
|
||||
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
|
||||
import static android.view.InsetsState.ITYPE_RIGHT_GESTURES;
|
||||
@@ -37,7 +36,6 @@ import static android.view.InsetsState.ITYPE_STATUS_BAR;
|
||||
import static android.view.InsetsState.ITYPE_TOP_MANDATORY_GESTURES;
|
||||
import static android.view.InsetsState.ITYPE_TOP_TAPPABLE_ELEMENT;
|
||||
import static android.view.ViewRootImpl.INSETS_LAYOUT_GENERALIZATION;
|
||||
import static android.view.ViewRootImpl.computeWindowBounds;
|
||||
import static android.view.WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS;
|
||||
import static android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS;
|
||||
import static android.view.WindowInsetsController.APPEARANCE_LOW_PROFILE_BARS;
|
||||
@@ -50,21 +48,15 @@ import static android.view.WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW;
|
||||
import static android.view.WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON;
|
||||
import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
|
||||
import static android.view.WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN;
|
||||
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
|
||||
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
|
||||
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
|
||||
import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
|
||||
import static android.view.WindowManager.LayoutParams.FLAG_SLIPPERY;
|
||||
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
|
||||
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT;
|
||||
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
|
||||
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS;
|
||||
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR;
|
||||
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_INSET_PARENT_FRAME_BY_IME;
|
||||
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_INTERCEPT_GLOBAL_DRAG_AND_DROP;
|
||||
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE;
|
||||
@@ -147,6 +139,7 @@ import android.view.View;
|
||||
import android.view.ViewDebug;
|
||||
import android.view.WindowInsets.Type;
|
||||
import android.view.WindowInsets.Type.InsetsType;
|
||||
import android.view.WindowLayout;
|
||||
import android.view.WindowManager;
|
||||
import android.view.WindowManager.LayoutParams;
|
||||
import android.view.WindowManagerGlobal;
|
||||
@@ -356,15 +349,15 @@ public class DisplayPolicy {
|
||||
// If nonzero, a panic gesture was performed at that time in uptime millis and is still pending.
|
||||
private long mPendingPanicGestureUptime;
|
||||
|
||||
private static final Rect sTmpDisplayCutoutSafeExceptMaybeBarsRect = new Rect();
|
||||
private static final Rect sTmpRect = new Rect();
|
||||
private static final Rect sTmpNavFrame = new Rect();
|
||||
private static final Rect sTmpStatusFrame = new Rect();
|
||||
private static final Rect sTmpDecorFrame = new Rect();
|
||||
private static final Rect sTmpScreenDecorFrame = new Rect();
|
||||
private static final Rect sTmpLastParentFrame = new Rect();
|
||||
private static final Rect sTmpDisplayFrameBounds = new Rect();
|
||||
|
||||
private final WindowLayout mWindowLayout = new WindowLayout();
|
||||
|
||||
private WindowState mTopFullscreenOpaqueWindowState;
|
||||
private boolean mTopIsFullscreen;
|
||||
private boolean mForceStatusBar;
|
||||
@@ -1484,7 +1477,7 @@ public class DisplayPolicy {
|
||||
* @param outInsetsState The insets state of this display from the client's perspective.
|
||||
* @param localClient Whether the client is from the our process.
|
||||
* @return Whether to always consume the system bars.
|
||||
* See {@link #areSystemBarsForcedShownLw(WindowState)}.
|
||||
* See {@link #areSystemBarsForcedShownLw()}.
|
||||
*/
|
||||
boolean getLayoutHint(LayoutParams attrs, WindowToken windowToken, InsetsState outInsetsState,
|
||||
boolean localClient) {
|
||||
@@ -1721,108 +1714,24 @@ public class DisplayPolicy {
|
||||
|
||||
final int type = attrs.type;
|
||||
final int fl = attrs.flags;
|
||||
final int pfl = attrs.privateFlags;
|
||||
final int sim = attrs.softInputMode;
|
||||
|
||||
displayFrames = win.getDisplayFrames(displayFrames);
|
||||
final WindowFrames windowFrames = win.getLayoutingWindowFrames();
|
||||
|
||||
sTmpLastParentFrame.set(windowFrames.mParentFrame);
|
||||
final Rect pf = windowFrames.mParentFrame;
|
||||
final Rect df = windowFrames.mDisplayFrame;
|
||||
windowFrames.setParentFrameWasClippedByDisplayCutout(false);
|
||||
final Rect attachedWindowFrame = attached != null ? attached.getFrame() : null;
|
||||
sTmpLastParentFrame.set(pf);
|
||||
|
||||
final boolean layoutInScreen = (fl & FLAG_LAYOUT_IN_SCREEN) == FLAG_LAYOUT_IN_SCREEN;
|
||||
final boolean layoutInsetDecor = (fl & FLAG_LAYOUT_INSET_DECOR) == FLAG_LAYOUT_INSET_DECOR;
|
||||
// Override the bounds in window token has many side effects. Directly use the display
|
||||
// frame set for the simulated layout for this case.
|
||||
final Rect winBounds = windowFrames.mIsSimulatingDecorWindow ? df : win.getBounds();
|
||||
|
||||
final InsetsState state = win.getInsetsState();
|
||||
if (windowFrames.mIsSimulatingDecorWindow && INSETS_LAYOUT_GENERALIZATION) {
|
||||
// Override the bounds in window token has many side effects. Directly use the display
|
||||
// frame set for the simulated layout for this case.
|
||||
computeWindowBounds(attrs, state, df, df);
|
||||
} else {
|
||||
computeWindowBounds(attrs, state, win.getBounds(), df);
|
||||
}
|
||||
if (attached == null) {
|
||||
pf.set(df);
|
||||
if ((pfl & PRIVATE_FLAG_INSET_PARENT_FRAME_BY_IME) != 0) {
|
||||
final InsetsSource source = state.peekSource(ITYPE_IME);
|
||||
if (source != null) {
|
||||
pf.inset(source.calculateInsets(pf, false /* ignoreVisibility */));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
pf.set((fl & FLAG_LAYOUT_IN_SCREEN) == 0 ? attached.getFrame() : df);
|
||||
}
|
||||
|
||||
final int cutoutMode = attrs.layoutInDisplayCutoutMode;
|
||||
// Ensure that windows with a DEFAULT or NEVER display cutout mode are laid out in
|
||||
// the cutout safe zone.
|
||||
if (cutoutMode != LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS) {
|
||||
final boolean attachedInParent = attached != null && !layoutInScreen;
|
||||
final boolean requestedFullscreen = !win.getRequestedVisibility(ITYPE_STATUS_BAR);
|
||||
final boolean requestedHideNavigation =
|
||||
!win.getRequestedVisibility(ITYPE_NAVIGATION_BAR);
|
||||
|
||||
// TYPE_BASE_APPLICATION windows are never considered floating here because they don't
|
||||
// get cropped / shifted to the displayFrame in WindowState.
|
||||
final boolean floatingInScreenWindow = !attrs.isFullscreen() && layoutInScreen
|
||||
&& type != TYPE_BASE_APPLICATION;
|
||||
final Rect displayCutoutSafeExceptMaybeBars = sTmpDisplayCutoutSafeExceptMaybeBarsRect;
|
||||
displayCutoutSafeExceptMaybeBars.set(displayFrames.mDisplayCutoutSafe);
|
||||
if (cutoutMode == LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES) {
|
||||
if (displayFrames.mDisplayWidth < displayFrames.mDisplayHeight) {
|
||||
displayCutoutSafeExceptMaybeBars.top = Integer.MIN_VALUE;
|
||||
displayCutoutSafeExceptMaybeBars.bottom = Integer.MAX_VALUE;
|
||||
} else {
|
||||
displayCutoutSafeExceptMaybeBars.left = Integer.MIN_VALUE;
|
||||
displayCutoutSafeExceptMaybeBars.right = Integer.MAX_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (layoutInScreen && layoutInsetDecor && !requestedFullscreen
|
||||
&& (cutoutMode == LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT
|
||||
|| cutoutMode == LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES)) {
|
||||
// At the top we have the status bar, so apps that are
|
||||
// LAYOUT_IN_SCREEN | LAYOUT_INSET_DECOR but not FULLSCREEN
|
||||
// already expect that there's an inset there and we don't need to exclude
|
||||
// the window from that area.
|
||||
displayCutoutSafeExceptMaybeBars.top = Integer.MIN_VALUE;
|
||||
}
|
||||
if (layoutInScreen && layoutInsetDecor && !requestedHideNavigation
|
||||
&& (cutoutMode == LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT
|
||||
|| cutoutMode == LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES)) {
|
||||
// Same for the navigation bar.
|
||||
switch (mNavigationBarPosition) {
|
||||
case NAV_BAR_BOTTOM:
|
||||
displayCutoutSafeExceptMaybeBars.bottom = Integer.MAX_VALUE;
|
||||
break;
|
||||
case NAV_BAR_RIGHT:
|
||||
displayCutoutSafeExceptMaybeBars.right = Integer.MAX_VALUE;
|
||||
break;
|
||||
case NAV_BAR_LEFT:
|
||||
displayCutoutSafeExceptMaybeBars.left = Integer.MIN_VALUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (type == TYPE_INPUT_METHOD && mNavigationBarPosition == NAV_BAR_BOTTOM) {
|
||||
// The IME can always extend under the bottom cutout if the navbar is there.
|
||||
displayCutoutSafeExceptMaybeBars.bottom = Integer.MAX_VALUE;
|
||||
}
|
||||
// Windows that are attached to a parent and laid out in said parent already avoid
|
||||
// the cutout according to that parent and don't need to be further constrained.
|
||||
// Floating IN_SCREEN windows get what they ask for and lay out in the full screen.
|
||||
// They will later be cropped or shifted using the displayFrame in WindowState,
|
||||
// which prevents overlap with the DisplayCutout.
|
||||
if (!attachedInParent && !floatingInScreenWindow) {
|
||||
sTmpRect.set(pf);
|
||||
pf.intersectUnchecked(displayCutoutSafeExceptMaybeBars);
|
||||
windowFrames.setParentFrameWasClippedByDisplayCutout(!sTmpRect.equals(pf));
|
||||
}
|
||||
// Make sure that NO_LIMITS windows clipped to the display don't extend under the
|
||||
// cutout.
|
||||
df.intersectUnchecked(displayCutoutSafeExceptMaybeBars);
|
||||
}
|
||||
final boolean clippedByDisplayCutout = mWindowLayout.computeWindowFrames(attrs,
|
||||
win.getInsetsState(), displayFrames.mDisplayCutoutSafe, winBounds,
|
||||
win.getRequestedVisibilities(), attachedWindowFrame, df, pf);
|
||||
windowFrames.setParentFrameWasClippedByDisplayCutout(clippedByDisplayCutout);
|
||||
|
||||
// TYPE_SYSTEM_ERROR is above the NavigationBar so it can't be allowed to extend over it.
|
||||
// Also, we don't allow windows in multi-window mode to extend out of the screen.
|
||||
@@ -1843,16 +1752,6 @@ public class DisplayPolicy {
|
||||
}
|
||||
|
||||
win.computeFrameAndUpdateSourceFrame(displayFrames);
|
||||
if (INSETS_LAYOUT_GENERALIZATION && attrs.type == TYPE_STATUS_BAR) {
|
||||
if (displayFrames.mDisplayCutoutSafe.top > displayFrames.mUnrestricted.top) {
|
||||
// Make sure that the zone we're avoiding for the cutout is at least as tall as the
|
||||
// status bar; otherwise fullscreen apps will end up cutting halfway into the status
|
||||
// bar.
|
||||
displayFrames.mDisplayCutoutSafe.top = Math.max(
|
||||
displayFrames.mDisplayCutoutSafe.top,
|
||||
windowFrames.mFrame.bottom);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WindowState getTopFullscreenOpaqueWindow() {
|
||||
|
||||
Reference in New Issue
Block a user