From 6bab4cf52d53074b7d353738ebd014c72366774d Mon Sep 17 00:00:00 2001 From: Wale Ogunwale Date: Thu, 7 Apr 2016 12:23:08 -0700 Subject: [PATCH 1/2] Fixed bug with cropping out drop shadow for pinned stack. The surface crop we apply to windows in the pinned stack was based on the stack bounds. However, the windows in the pinned stack have a drop shadow that extends outside the stack bounds to make them appear floating so they were out displayed. We now extand the crop for windows in stacks that have shadows and occupy the entire stack space to that their drop shadows are visible. Bug: 27364161 Change-Id: Ic2a94b091a93e7145a5455b494f0b689118eb5e3 --- .../com/android/server/wm/WindowState.java | 5 +- .../server/wm/WindowStateAnimator.java | 50 ++++++++++++------- 2 files changed, 34 insertions(+), 21 deletions(-) diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index ddfc022aeb3f3..62776a4e75add 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -2397,8 +2397,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); } @@ -2483,6 +2483,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 34452ee1eefa4..e753ed7c15153 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; @@ -1156,8 +1157,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); } } @@ -1170,8 +1171,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()) { @@ -1196,8 +1197,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); @@ -1207,8 +1208,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 @@ -1235,7 +1236,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); @@ -1246,6 +1248,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); @@ -1286,13 +1290,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. @@ -1303,6 +1308,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, @@ -1348,21 +1362,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; @@ -1772,7 +1784,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) { @@ -1790,9 +1802,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); } From 246c209e4fe704c0745224be0ab05225e8431d11 Mon Sep 17 00:00:00 2001 From: Wale Ogunwale Date: Thu, 7 Apr 2016 14:12:44 -0700 Subject: [PATCH 2/2] Update surface insets on window elevation changes. Window manager factors in the surface insets when calculating the right crop for a window surface. Without the surface insets been updated and new param forwarded to window manager, the window crop will not be the right size and the window drop shadow might not show. Bug: 27364161 Change-Id: Ieefeb8435543f3137672a065269cdeefca371111 --- core/java/android/view/ViewRootImpl.java | 13 +++---- core/java/android/view/WindowManager.java | 34 ++++++++++++++++++- core/java/android/widget/PopupWindow.java | 4 +-- .../android/internal/policy/PhoneWindow.java | 4 ++- .../server/wm/WindowStateAnimator.java | 2 +- 5 files changed, 45 insertions(+), 12 deletions(-) diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 5b2877faef021..42c78f8bc045b 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 c372c30915f2f..33bd752f36423 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -1474,6 +1474,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. @@ -1755,6 +1765,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) { @@ -1806,6 +1827,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); } @@ -1857,6 +1879,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(); } @@ -2055,6 +2078,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; @@ -2173,11 +2201,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 0f257d78d5f54..2b18831dd6215 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/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java index e753ed7c15153..cd7974b9839df 100644 --- a/services/core/java/com/android/server/wm/WindowStateAnimator.java +++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java @@ -1033,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 ); }