diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 44b92e18144e3..2ce43c824e894 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -549,8 +549,7 @@ public final class ViewRootImpl implements ViewParent, // Compute surface insets required to draw at specified Z value. // TODO: Use real shadow insets for a constant max Z. if (!attrs.hasManualSurfaceInsets) { - final int surfaceInset = (int) Math.ceil(view.getZ() * 2); - attrs.surfaceInsets.set(surfaceInset, surfaceInset, surfaceInset, surfaceInset); + attrs.setSurfaceInsets(view, false /*manual*/, true /*preservePrevious*/); } CompatibilityInfo compatibilityInfo = mDisplayAdjustments.getCompatibilityInfo(); @@ -883,10 +882,12 @@ public final class ViewRootImpl implements ViewParent, } mWindowAttributes.privateFlags |= compatibleWindowFlag; - // Restore old surface insets. - mWindowAttributes.surfaceInsets.set( - oldInsetLeft, oldInsetTop, oldInsetRight, oldInsetBottom); - mWindowAttributes.hasManualSurfaceInsets = oldHasManualSurfaceInsets; + if (mWindowAttributes.preservePreviousSurfaceInsets) { + // Restore old surface insets. + mWindowAttributes.surfaceInsets.set( + oldInsetLeft, oldInsetTop, oldInsetRight, oldInsetBottom); + mWindowAttributes.hasManualSurfaceInsets = oldHasManualSurfaceInsets; + } applyKeepScreenOnFlag(mWindowAttributes); diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index 584233c434f13..e3de8106fb1bf 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -1481,6 +1481,16 @@ public interface WindowManager extends ViewManager { */ public boolean hasManualSurfaceInsets; + /** + * Whether the previous surface insets should be used vs. what is currently set. When set + * to {@code true}, the view root will ignore surfaces insets in this object and use what + * it currently has. + * + * @see #surfaceInsets + * @hide + */ + public boolean preservePreviousSurfaceInsets = true; + /** * The desired bitmap format. May be one of the constants in * {@link android.graphics.PixelFormat}. Default is OPAQUE. @@ -1771,6 +1781,17 @@ public interface WindowManager extends ViewManager { return mTitle != null ? mTitle : ""; } + /** + * Sets the surface insets based on the elevation (visual z position) of the input view. + * @hide + */ + public final void setSurfaceInsets(View view, boolean manual, boolean preservePrevious) { + final int surfaceInset = (int) Math.ceil(view.getZ() * 2); + surfaceInsets.set(surfaceInset, surfaceInset, surfaceInset, surfaceInset); + hasManualSurfaceInsets = manual; + preservePreviousSurfaceInsets = preservePrevious; + } + /** @hide */ @SystemApi public final void setUserActivityTimeout(long timeout) { @@ -1822,6 +1843,7 @@ public interface WindowManager extends ViewManager { out.writeInt(surfaceInsets.right); out.writeInt(surfaceInsets.bottom); out.writeInt(hasManualSurfaceInsets ? 1 : 0); + out.writeInt(preservePreviousSurfaceInsets ? 1 : 0); out.writeInt(needsMenuKey); out.writeInt(accessibilityIdOfAnchor); TextUtils.writeToParcel(accessibilityTitle, out, parcelableFlags); @@ -1874,6 +1896,7 @@ public interface WindowManager extends ViewManager { surfaceInsets.right = in.readInt(); surfaceInsets.bottom = in.readInt(); hasManualSurfaceInsets = in.readInt() != 0; + preservePreviousSurfaceInsets = in.readInt() != 0; needsMenuKey = in.readInt(); accessibilityIdOfAnchor = in.readInt(); accessibilityTitle = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in); @@ -2075,6 +2098,11 @@ public interface WindowManager extends ViewManager { changes |= SURFACE_INSETS_CHANGED; } + if (preservePreviousSurfaceInsets != o.preservePreviousSurfaceInsets) { + preservePreviousSurfaceInsets = o.preservePreviousSurfaceInsets; + changes |= SURFACE_INSETS_CHANGED; + } + if (needsMenuKey != o.needsMenuKey) { needsMenuKey = o.needsMenuKey; changes |= NEEDS_MENU_KEY_CHANGED; @@ -2200,11 +2228,15 @@ public interface WindowManager extends ViewManager { sb.append(" userActivityTimeout=").append(userActivityTimeout); } if (surfaceInsets.left != 0 || surfaceInsets.top != 0 || surfaceInsets.right != 0 || - surfaceInsets.bottom != 0 || hasManualSurfaceInsets) { + surfaceInsets.bottom != 0 || hasManualSurfaceInsets + || !preservePreviousSurfaceInsets) { sb.append(" surfaceInsets=").append(surfaceInsets); if (hasManualSurfaceInsets) { sb.append(" (manual)"); } + if (!preservePreviousSurfaceInsets) { + sb.append(" (!preservePreviousSurfaceInsets)"); + } } if (needsMenuKey != NEEDS_MENU_UNSET) { sb.append(" needsMenuKey="); diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java index 0d8d8ed17b654..12f2e20151ee9 100644 --- a/core/java/android/widget/PopupWindow.java +++ b/core/java/android/widget/PopupWindow.java @@ -1290,9 +1290,7 @@ public class PopupWindow { // We may wrap that in another view, so we'll need to manually specify // the surface insets. - final int surfaceInset = (int) Math.ceil(mBackgroundView.getZ() * 2); - p.surfaceInsets.set(surfaceInset, surfaceInset, surfaceInset, surfaceInset); - p.hasManualSurfaceInsets = true; + p.setSurfaceInsets(mBackgroundView, true /*manual*/, true /*preservePrevious*/); mPopupViewInitialLayoutDirectionInherited = (mContentView.getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT); diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java index d2ff9bc4c7d44..fe632678713d9 100644 --- a/core/java/com/android/internal/policy/PhoneWindow.java +++ b/core/java/com/android/internal/policy/PhoneWindow.java @@ -1403,10 +1403,12 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { @Override public final void setElevation(float elevation) { mElevation = elevation; + final WindowManager.LayoutParams attrs = getAttributes(); if (mDecor != null) { mDecor.setElevation(elevation); + attrs.setSurfaceInsets(mDecor, true /*manual*/, false /*preservePrevious*/); } - dispatchWindowAttributesChanged(getAttributes()); + dispatchWindowAttributesChanged(attrs); } @Override diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index c48d7d11692ee..8371cfe7a2ddb 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -2410,8 +2410,8 @@ final class WindowState implements WindowManagerPolicy.WindowState { pw.print(prefix); pw.print("mToken="); pw.println(mToken); pw.print(prefix); pw.print("mRootToken="); pw.println(mRootToken); if (mAppToken != null) { - pw.print(prefix); pw.print("mAppToken="); pw.print(mAppToken); - pw.print(" isAnimatingWithSavedSurface()="); + pw.print(prefix); pw.print("mAppToken="); pw.println(mAppToken); + pw.print(prefix); pw.print(" isAnimatingWithSavedSurface()="); pw.print(isAnimatingWithSavedSurface()); pw.print(" mAppDied=");pw.println(mAppDied); } @@ -2496,6 +2496,7 @@ final class WindowState implements WindowManagerPolicy.WindowState { pw.print(" content="); mContentInsets.printShortString(pw); pw.print(" visible="); mVisibleInsets.printShortString(pw); pw.print(" stable="); mStableInsets.printShortString(pw); + pw.print(" surface="); mAttrs.surfaceInsets.printShortString(pw); pw.print(" outsets="); mOutsets.printShortString(pw); pw.println(); pw.print(prefix); pw.print("Lst insets: overscan="); diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java index 140f3811ef537..0245513401667 100644 --- a/services/core/java/com/android/server/wm/WindowStateAnimator.java +++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java @@ -16,6 +16,7 @@ package com.android.server.wm; +import static android.app.ActivityManager.StackId; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED; import static android.view.WindowManager.LayoutParams.FLAG_SCALED; @@ -1032,7 +1033,7 @@ class WindowStateAnimator { // relative to their containing frame. We need to offset the difference // between the containing frame as used to calculate the crop and our // bounds to compensate for this. - if (mWin.isChildWindow() && mWin.layoutInParentFrame()) { + if (mWin.layoutInParentFrame()) { mClipRect.offset( (mWin.mContainingFrame.left - mWin.mFrame.left), mWin.mContainingFrame.top - mWin.mFrame.top ); } @@ -1164,8 +1165,8 @@ class WindowStateAnimator { final float scale = w.mInvGlobalScale; mSystemDecorRect.left = (int) (mSystemDecorRect.left * scale - 0.5f); mSystemDecorRect.top = (int) (mSystemDecorRect.top * scale - 0.5f); - mSystemDecorRect.right = (int) ((mSystemDecorRect.right+1) * scale - 0.5f); - mSystemDecorRect.bottom = (int) ((mSystemDecorRect.bottom+1) * scale - 0.5f); + mSystemDecorRect.right = (int) ((mSystemDecorRect.right + 1) * scale - 0.5f); + mSystemDecorRect.bottom = (int) ((mSystemDecorRect.bottom + 1) * scale - 0.5f); } } @@ -1178,8 +1179,8 @@ class WindowStateAnimator { return; } final DisplayInfo displayInfo = displayContent.getDisplayInfo(); - if (DEBUG_WINDOW_CROP) Slog.d(TAG, "Updating crop for window: " + w + ", " + "mLastCrop=" + - mLastClipRect); + if (DEBUG_WINDOW_CROP) Slog.d(TAG, + "Updating crop win=" + w + " mLastCrop=" + mLastClipRect); // Need to recompute a new system decor rect each time. if (!w.isDefaultDisplay()) { @@ -1204,8 +1205,8 @@ class WindowStateAnimator { } else { // Crop to the system decor specified by policy. calculateSystemDecorRect(); - if (DEBUG_WINDOW_CROP) Slog.d(TAG, "Applying decor to crop for " + w + ", mDecorFrame=" - + w.mDecorFrame + ", mSystemDecorRect=" + mSystemDecorRect); + if (DEBUG_WINDOW_CROP) Slog.d(TAG, "Applying decor to crop win=" + w + " mDecorFrame=" + + w.mDecorFrame + " mSystemDecorRect=" + mSystemDecorRect); } final boolean fullscreen = w.isFrameFullscreen(displayInfo); @@ -1215,8 +1216,8 @@ class WindowStateAnimator { // We use the clip rect as provided by the tranformation for non-fullscreen windows to // avoid premature clipping with the system decor rect. clipRect.set((mHasClipRect && !fullscreen) ? mClipRect : mSystemDecorRect); - if (DEBUG_WINDOW_CROP) Slog.d(TAG, "Initial clip rect: " + clipRect + ", mHasClipRect=" - + mHasClipRect + ", fullscreen=" + fullscreen); + if (DEBUG_WINDOW_CROP) Slog.d(TAG, "win=" + w + " Initial clip rect: " + clipRect + + " mHasClipRect=" + mHasClipRect + " fullscreen=" + fullscreen); if (isFreeformResizing && !w.isChildWindow()) { // For freeform resizing non child windows, we are using the big surface positioned @@ -1243,7 +1244,8 @@ class WindowStateAnimator { finalClipRect.setEmpty(); adjustCropToStackBounds(w, clipRect, finalClipRect, isFreeformResizing); - if (DEBUG_WINDOW_CROP) Slog.d(TAG, "Clip rect after stack adjustment=" + clipRect); + if (DEBUG_WINDOW_CROP) Slog.d(TAG, + "win=" + w + " Clip rect after stack adjustment=" + clipRect); w.transformFromScreenToSurfaceSpace(clipRect); @@ -1254,6 +1256,8 @@ class WindowStateAnimator { } void updateSurfaceWindowCrop(Rect clipRect, Rect finalClipRect, boolean recoveringMemory) { + if (DEBUG_WINDOW_CROP) Slog.d(TAG, "updateSurfaceWindowCrop: win=" + mWin + + " clipRect=" + clipRect + " finalClipRect=" + finalClipRect); if (!clipRect.equals(mLastClipRect)) { mLastClipRect.set(clipRect); mSurfaceController.setCropInTransaction(clipRect, recoveringMemory); @@ -1294,13 +1298,14 @@ class WindowStateAnimator { final TaskStack stack = task.mStack; stack.getDimBounds(mTmpStackBounds); + final Rect surfaceInsets = w.getAttrs().surfaceInsets; // When we resize we use the big surface approach, which means we can't trust the // window frame bounds anymore. Instead, the window will be placed at 0, 0, but to avoid // hardcoding it, we use surface coordinates. final int frameX = isFreeformResizing ? (int) mSurfaceController.getX() : - w.mFrame.left + mWin.mXOffset - w.getAttrs().surfaceInsets.left; + w.mFrame.left + mWin.mXOffset - surfaceInsets.left; final int frameY = isFreeformResizing ? (int) mSurfaceController.getY() : - w.mFrame.top + mWin.mYOffset - w.getAttrs().surfaceInsets.top; + w.mFrame.top + mWin.mYOffset - surfaceInsets.top; // If we are animating, we either apply the clip before applying all the animation // transformation or after all the transformation. @@ -1311,6 +1316,15 @@ class WindowStateAnimator { if (useFinalClipRect) { finalClipRect.set(mTmpStackBounds); } else { + if (StackId.hasWindowShadow(stack.mStackId) + && !StackId.isTaskResizeAllowed(stack.mStackId)) { + // The windows in this stack display drop shadows and the fill the entire stack + // area. Adjust the stack bounds we will use to cropping take into account the + // offsets we use to display the drop shadow so it doesn't get cropped. + mTmpStackBounds.inset(-surfaceInsets.left, -surfaceInsets.top, + -surfaceInsets.right, -surfaceInsets.bottom); + } + clipRect.left = Math.max(0, Math.max(mTmpStackBounds.left, frameX + clipRect.left) - frameX); clipRect.top = Math.max(0, @@ -1356,21 +1370,19 @@ class WindowStateAnimator { // past where the system would have cropped us mTmpClipRect.set(0, 0, mTmpSize.width(), mTmpSize.height()); mTmpFinalClipRect.setEmpty(); - updateSurfaceWindowCrop(mTmpClipRect, mTmpFinalClipRect, recoveringMemory); } else { mSurfaceController.setPositionInTransaction(mTmpSize.left, mTmpSize.top, recoveringMemory); - updateSurfaceWindowCrop(mTmpClipRect, mTmpFinalClipRect, recoveringMemory); } + updateSurfaceWindowCrop(mTmpClipRect, mTmpFinalClipRect, recoveringMemory); mSurfaceController.setMatrixInTransaction(mDsDx * w.mHScale * extraHScale, mDtDx * w.mVScale * extraVScale, mDsDy * w.mHScale * extraHScale, mDtDy * w.mVScale * extraVScale, recoveringMemory); mSurfaceResized = mSurfaceController.setSizeInTransaction( - mTmpSize.width(), mTmpSize.height(), - recoveringMemory); + mTmpSize.width(), mTmpSize.height(), recoveringMemory); if (mSurfaceResized) { mReportSurfaceResized = true; @@ -1775,7 +1787,7 @@ class WindowStateAnimator { pw.print(prefix); pw.print("mAnimating="); pw.print(mAnimating); pw.print(" mLocalAnimating="); pw.print(mLocalAnimating); pw.print(" mAnimationIsEntrance="); pw.print(mAnimationIsEntrance); - pw.print(" mAnimation="); pw.println(mAnimation); + pw.print(" mAnimation="); pw.print(mAnimation); pw.print(" mStackClip="); pw.println(mStackClip); } if (mHasTransformation || mHasLocalTransformation) { @@ -1793,9 +1805,9 @@ class WindowStateAnimator { pw.print(prefix); pw.print(" mLastHidden="); pw.println(mLastHidden); pw.print(prefix); pw.print("mSystemDecorRect="); mSystemDecorRect.printShortString(pw); pw.print(" last="); mLastSystemDecorRect.printShortString(pw); - if (mHasClipRect) { - pw.print(" mLastClipRect="); mLastClipRect.printShortString(pw); - } + pw.print(" mHasClipRect="); pw.print(mHasClipRect); + pw.print(" mLastClipRect="); mLastClipRect.printShortString(pw); + if (!mLastFinalClipRect.isEmpty()) { pw.print(" mLastFinalClipRect="); mLastFinalClipRect.printShortString(pw); }