From bf9eefc72f7da2048252d96175d04904a9503c57 Mon Sep 17 00:00:00 2001 From: Wale Ogunwale Date: Tue, 17 Nov 2015 14:47:52 -0800 Subject: [PATCH 1/2] Move management of BackdropFrameRenderer to DecorView Allows us to have the BackdropFrameRenderer independent of having a NonClientDecorView. Bug: 24810450 Change-Id: Ibcda3d722970536ee037b192e90e01da5650ac74 --- .../policy/BackdropFrameRenderer.java | 49 ++++--- .../android/internal/policy/DecorView.java | 128 ++++++++++++++++-- .../internal/widget/NonClientDecorView.java | 123 +---------------- 3 files changed, 148 insertions(+), 152 deletions(-) diff --git a/core/java/com/android/internal/policy/BackdropFrameRenderer.java b/core/java/com/android/internal/policy/BackdropFrameRenderer.java index 1eeb36310086d..f227bf35a4a08 100644 --- a/core/java/com/android/internal/policy/BackdropFrameRenderer.java +++ b/core/java/com/android/internal/policy/BackdropFrameRenderer.java @@ -16,8 +16,6 @@ package com.android.internal.policy; -import com.android.internal.widget.NonClientDecorView; - import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.os.Looper; @@ -37,7 +35,7 @@ import android.view.View; */ public class BackdropFrameRenderer extends Thread implements Choreographer.FrameCallback { - private NonClientDecorView mNonClientDecorView; + private DecorView mDecorView; // This is containing the last requested size by a resize command. Note that this size might // or might not have been applied to the output already. @@ -62,12 +60,15 @@ public class BackdropFrameRenderer extends Thread implements Choreographer.Frame // Whether to report when next frame is drawn or not. private boolean mReportNextDraw; - public BackdropFrameRenderer(NonClientDecorView nonClientDecorView, - ThreadedRenderer renderer, - Rect initialBounds) { - mNonClientDecorView = nonClientDecorView; + private Drawable mCaptionBackgroundDrawable; + private Drawable mResizingBackgroundDrawable; + + public BackdropFrameRenderer(DecorView decorView, ThreadedRenderer renderer, Rect initialBounds, + Drawable resizingBackgroundDrawable, Drawable captionBackgroundDrawable) { setName("ResizeFrame"); + mRenderer = renderer; + onResourcesLoaded(decorView, resizingBackgroundDrawable, captionBackgroundDrawable); // Create a render node for the content and frame backdrop // which can be resized independently from the content. @@ -85,6 +86,13 @@ public class BackdropFrameRenderer extends Thread implements Choreographer.Frame start(); } + void onResourcesLoaded(DecorView decorView, Drawable resizingBackgroundDrawable, + Drawable captionBackgroundDrawableDrawable) { + mDecorView = decorView; + mResizingBackgroundDrawable = resizingBackgroundDrawable; + mCaptionBackgroundDrawable = captionBackgroundDrawableDrawable; + } + /** * Call this function asynchronously when the window size has been changed. The change will * be picked up once per frame and the frame will be re-rendered accordingly. @@ -201,7 +209,8 @@ public class BackdropFrameRenderer extends Thread implements Choreographer.Frame mLastYOffset + mLastCaptionHeight + mLastContentHeight); // If this was the first call and changeWindowSizeLocked got already called prior // to us, we should re-issue a changeWindowSizeLocked now. - return firstCall && (mLastCaptionHeight != 0 || !mNonClientDecorView.mShowDecor); + return firstCall + && (mLastCaptionHeight != 0 || !mDecorView.mNonClientDecorView.mShowDecor); } } @@ -221,7 +230,7 @@ public class BackdropFrameRenderer extends Thread implements Choreographer.Frame // While a configuration change is taking place the view hierarchy might become // inaccessible. For that case we remember the previous metrics to avoid flashes. // Note that even when there is no visible caption, the caption child will exist. - View caption = mNonClientDecorView.getChildAt(0); + View caption = mDecorView.mNonClientDecorView.getChildAt(0); if (caption != null) { final int captionHeight = caption.getHeight(); // The caption height will probably never dynamically change while we are resizing. @@ -233,7 +242,7 @@ public class BackdropFrameRenderer extends Thread implements Choreographer.Frame } // Make sure that the other thread has already prepared the render draw calls for the // content. If any size is 0, we have to wait for it to be drawn first. - if ((mLastCaptionHeight == 0 && mNonClientDecorView.mShowDecor) || + if ((mLastCaptionHeight == 0 && mDecorView.mNonClientDecorView.mShowDecor) || mLastContentWidth == 0 || mLastContentHeight == 0) { return; } @@ -247,15 +256,13 @@ public class BackdropFrameRenderer extends Thread implements Choreographer.Frame mFrameAndBackdropNode.setLeftTopRightBottom(left, top, left + width, top + height); // Draw the caption and content backdrops in to our render node. - DisplayListCanvas canvas = mFrameAndBackdropNode.start(width, height); - mNonClientDecorView.mCaptionBackgroundDrawable.setBounds( - 0, 0, left + width, top + mLastCaptionHeight); - mNonClientDecorView.mCaptionBackgroundDrawable.draw(canvas); + final DisplayListCanvas canvas = mFrameAndBackdropNode.start(width, height); + mCaptionBackgroundDrawable.setBounds(0, 0, left + width, top + mLastCaptionHeight); + mCaptionBackgroundDrawable.draw(canvas); // The backdrop: clear everything with the background. Clipping is done elsewhere. - mNonClientDecorView.mResizingBackgroundDrawable.setBounds( - 0, mLastCaptionHeight, left + width, top + height); - mNonClientDecorView.mResizingBackgroundDrawable.draw(canvas); + mResizingBackgroundDrawable.setBounds(0, mLastCaptionHeight, left + width, top + height); + mResizingBackgroundDrawable.draw(canvas); mFrameAndBackdropNode.end(canvas); // We need to render the node explicitly @@ -264,13 +271,11 @@ public class BackdropFrameRenderer extends Thread implements Choreographer.Frame reportDrawIfNeeded(); } - /** - * Notify view root that a frame has been drawn by us, if it has requested so. - */ + /** Notify view root that a frame has been drawn by us, if it has requested so. */ private void reportDrawIfNeeded() { if (mReportNextDraw) { - if (mNonClientDecorView.isAttachedToWindow()) { - mNonClientDecorView.getViewRootImpl().reportDrawFinish(); + if (mDecorView.isAttachedToWindow()) { + mDecorView.getViewRootImpl().reportDrawFinish(); } mReportNextDraw = false; } diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java index 49ceced379cc0..b15ccb25d5b52 100644 --- a/core/java/com/android/internal/policy/DecorView.java +++ b/core/java/com/android/internal/policy/DecorView.java @@ -52,11 +52,13 @@ import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.MotionEvent; +import android.view.ThreadedRenderer; import android.view.View; import android.view.ViewGroup; import android.view.ViewStub; import android.view.ViewTreeObserver; import android.view.Window; +import android.view.WindowCallbacks; import android.view.WindowInsets; import android.view.WindowManager; import android.view.accessibility.AccessibilityEvent; @@ -80,7 +82,8 @@ import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; -class DecorView extends FrameLayout implements RootViewSurfaceTaker { +/** @hide */ +public class DecorView extends FrameLayout implements RootViewSurfaceTaker, WindowCallbacks { private static final String TAG = "DecorView"; private static final boolean SWEEP_OPEN_MENU = false; @@ -167,6 +170,12 @@ class DecorView extends FrameLayout implements RootViewSurfaceTaker { // workspace is expensive, this is the workspace value the window is currently set up for. int mWorkspaceId; + private boolean mWindowResizeCallbacksAdded = false; + + public BackdropFrameRenderer mBackdropFrameRenderer = null; + private Drawable mResizingBackgroundDrawable; + private Drawable mCaptionBackgroundDrawable; + DecorView(Context context, int featureId, PhoneWindow window) { super(context); mFeatureId = featureId; @@ -1225,6 +1234,17 @@ class DecorView extends FrameLayout implements RootViewSurfaceTaker { */ mWindow.openPanelsAfterRestore(); } + + if (!mWindowResizeCallbacksAdded) { + // If there is no window callback installed there was no window set before. Set it now. + // Note that our ViewRootImpl object will not change. + getViewRootImpl().addWindowCallbacks(this); + mWindowResizeCallbacksAdded = true; + } else if (mBackdropFrameRenderer != null) { + // We are resizing and this call happened due to a configuration change. Tell the + // renderer about it. + mBackdropFrameRenderer.onConfigurationChange(); + } } @Override @@ -1256,6 +1276,11 @@ class DecorView extends FrameLayout implements RootViewSurfaceTaker { if (st != null && st.menu != null && mFeatureId < 0) { st.menu.close(); } + + if (mWindowResizeCallbacksAdded) { + getViewRootImpl().removeWindowCallbacks(this); + mWindowResizeCallbacksAdded = false; + } } @Override @@ -1526,6 +1551,16 @@ class DecorView extends FrameLayout implements RootViewSurfaceTaker { } View onResourcesLoaded(LayoutInflater inflater, int layoutResource) { + mResizingBackgroundDrawable = getResizingBackgroundDrawable( + mWindow.mBackgroundResource, mWindow.mBackgroundFallbackResource); + mCaptionBackgroundDrawable = + getContext().getDrawable(R.drawable.non_client_decor_title_focused); + + if (mBackdropFrameRenderer != null) { + mBackdropFrameRenderer.onResourcesLoaded( + this, mResizingBackgroundDrawable, mCaptionBackgroundDrawable); + } + mNonClientDecorView = createNonClientDecorView(inflater); final View root = inflater.inflate(layoutResource, null); if (mNonClientDecorView != null) { @@ -1579,9 +1614,7 @@ class DecorView extends FrameLayout implements RootViewSurfaceTaker { } nonClientDecorView.setPhoneWindow(mWindow, ActivityManager.StackId.hasWindowDecor(mWorkspaceId), - ActivityManager.StackId.hasWindowShadow(mWorkspaceId), - getResizingBackgroundDrawable(), - getContext().getDrawable(R.drawable.non_client_decor_title_focused)); + ActivityManager.StackId.hasWindowShadow(mWorkspaceId)); } // Tell the decor if it has a visible non client decor. enableNonClientDecor( @@ -1591,22 +1624,21 @@ class DecorView extends FrameLayout implements RootViewSurfaceTaker { } /** - * Returns the color used to fill areas the app has not rendered content to yet when the user - * is resizing the window of an activity in multi-window mode. - * */ - private Drawable getResizingBackgroundDrawable() { + * Returns the color used to fill areas the app has not rendered content to yet when the + * user is resizing the window of an activity in multi-window mode. + */ + private Drawable getResizingBackgroundDrawable(int backgroundRes, int backgroundFallbackRes) { final Context context = getContext(); - if (mWindow.mBackgroundResource != 0) { - final Drawable drawable = context.getDrawable(mWindow.mBackgroundResource); + if (backgroundRes != 0) { + final Drawable drawable = context.getDrawable(backgroundRes); if (drawable != null) { return drawable; } } - if (mWindow.mBackgroundFallbackResource != 0) { - final Drawable fallbackDrawable = - context.getDrawable(mWindow.mBackgroundFallbackResource); + if (backgroundFallbackRes != 0) { + final Drawable fallbackDrawable = context.getDrawable(backgroundFallbackRes); if (fallbackDrawable != null) { return fallbackDrawable; } @@ -1652,6 +1684,76 @@ class DecorView extends FrameLayout implements RootViewSurfaceTaker { } } + @Override + public void onWindowSizeIsChanging(Rect newBounds) { + if (mBackdropFrameRenderer != null) { + mBackdropFrameRenderer.setTargetRect(newBounds); + } + } + + @Override + public void onWindowDragResizeStart(Rect initialBounds) { + if (mWindow.isDestroyed()) { + // If the owner's window is gone, we should not be able to come here anymore. + releaseThreadedRenderer(); + return; + } + if (mBackdropFrameRenderer != null) { + return; + } + final ThreadedRenderer renderer = (ThreadedRenderer) getHardwareRenderer(); + if (renderer != null) { + mBackdropFrameRenderer = new BackdropFrameRenderer(this, renderer, + initialBounds, mResizingBackgroundDrawable, mCaptionBackgroundDrawable); + + // Get rid of the shadow while we are resizing. Shadow drawing takes considerable time. + // If we want to get the shadow shown while resizing, we would need to elevate a new + // element which owns the caption and has the elevation. + updateElevation(); + } + } + + @Override + public void onWindowDragResizeEnd() { + releaseThreadedRenderer(); + } + + @Override + public boolean onContentDrawn(int offsetX, int offsetY, int sizeX, int sizeY) { + if (mBackdropFrameRenderer == null) { + return false; + } + return mBackdropFrameRenderer.onContentDrawn(offsetX, offsetY, sizeX, sizeY); + } + + @Override + public void onRequestDraw(boolean reportNextDraw) { + if (mBackdropFrameRenderer != null) { + mBackdropFrameRenderer.onRequestDraw(reportNextDraw); + } else if (reportNextDraw) { + // If render thread is gone, just report immediately. + if (isAttachedToWindow()) { + getViewRootImpl().reportDrawFinish(); + } + } + } + + /** Release the renderer thread which is usually done when the user stops resizing. */ + private void releaseThreadedRenderer() { + if (mBackdropFrameRenderer != null) { + mBackdropFrameRenderer.releaseRenderer(); + mBackdropFrameRenderer = null; + // Bring the shadow back. + updateElevation(); + } + } + + private void updateElevation() { + if (mNonClientDecorView != null) { + mNonClientDecorView.updateElevation(); + } + } + private static class ColorViewState { View view = null; int targetVisibility = View.INVISIBLE; diff --git a/core/java/com/android/internal/widget/NonClientDecorView.java b/core/java/com/android/internal/widget/NonClientDecorView.java index 48420dae22658..232e308a3c25f 100644 --- a/core/java/com/android/internal/widget/NonClientDecorView.java +++ b/core/java/com/android/internal/widget/NonClientDecorView.java @@ -19,23 +19,19 @@ package com.android.internal.widget; import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID; import android.content.Context; -import android.graphics.Rect; -import android.graphics.drawable.Drawable; import android.os.RemoteException; import android.util.AttributeSet; import android.view.MotionEvent; -import android.view.ThreadedRenderer; import android.view.View; import android.widget.LinearLayout; import android.view.ViewGroup; import android.view.ViewOutlineProvider; import android.view.Window; -import android.view.WindowCallbacks; import android.util.Log; import android.util.TypedValue; import com.android.internal.R; -import com.android.internal.policy.BackdropFrameRenderer; +import com.android.internal.policy.DecorView; import com.android.internal.policy.PhoneWindow; /** @@ -64,7 +60,7 @@ import com.android.internal.policy.PhoneWindow; * This will be mitigated once b/22527834 will be addressed. */ public class NonClientDecorView extends LinearLayout - implements View.OnClickListener, View.OnTouchListener, WindowCallbacks { + implements View.OnClickListener, View.OnTouchListener { private final static String TAG = "NonClientDecorView"; // The height of a window which has focus in DIP. private final int DECOR_SHADOW_FOCUSED_HEIGHT_IN_DIP = 20; @@ -73,8 +69,6 @@ public class NonClientDecorView extends LinearLayout private PhoneWindow mOwner = null; private boolean mWindowHasShadow = false; public boolean mShowDecor = false; - // True when this object is listening for window size changes. - private boolean mAttachedCallbacksToRootViewImpl = false; // True if the window is being dragged. private boolean mDragging = false; @@ -93,11 +87,6 @@ public class NonClientDecorView extends LinearLayout // to max until the first layout command has been executed. private boolean mAllowUpdateElevation = false; - private BackdropFrameRenderer mBackdropFrameRenderer = null; - - public Drawable mResizingBackgroundDrawable; - public Drawable mCaptionBackgroundDrawable; - public NonClientDecorView(Context context) { super(context); } @@ -110,37 +99,10 @@ public class NonClientDecorView extends LinearLayout super(context, attrs, defStyle); } - @Override - protected void onAttachedToWindow() { - super.onAttachedToWindow(); - if (!mAttachedCallbacksToRootViewImpl) { - // If there is no window callback installed there was no window set before. Set it now. - // Note that our ViewRootImpl object will not change. - getViewRootImpl().addWindowCallbacks(this); - mAttachedCallbacksToRootViewImpl = true; - } else if (mBackdropFrameRenderer != null) { - // We are resizing and this call happened due to a configuration change. Tell the - // renderer about it. - mBackdropFrameRenderer.onConfigurationChange(); - } - } - - @Override - protected void onDetachedFromWindow() { - super.onDetachedFromWindow(); - if (mAttachedCallbacksToRootViewImpl) { - getViewRootImpl().removeWindowCallbacks(this); - mAttachedCallbacksToRootViewImpl = false; - } - } - - public void setPhoneWindow(PhoneWindow owner, boolean showDecor, boolean windowHasShadow, - Drawable resizingBackgroundDrawable, Drawable captionBackgroundDrawableDrawable) { + public void setPhoneWindow(PhoneWindow owner, boolean showDecor, boolean windowHasShadow) { mOwner = owner; mWindowHasShadow = windowHasShadow; mShowDecor = showDecor; - mResizingBackgroundDrawable = resizingBackgroundDrawable; - mCaptionBackgroundDrawable = captionBackgroundDrawableDrawable; updateCaptionVisibility(); if (mWindowHasShadow) { initializeElevation(); @@ -290,11 +252,12 @@ public class NonClientDecorView extends LinearLayout * Note: Windows which have (temporarily) changed their attributes to cover the SystemUI * will get no shadow as they are expected to be "full screen". **/ - private void updateElevation() { + public void updateElevation() { float elevation = 0; // Do not use a shadow when we are in resizing mode (mRenderer not null) since the shadow // is bound to the content size and not the target size. - if (mWindowHasShadow && mBackdropFrameRenderer == null) { + if (mWindowHasShadow + && ((DecorView) mOwner.getDecorView()).mBackdropFrameRenderer == null) { boolean fill = isFillingScreen(); elevation = fill ? 0 : (mWindowHasFocus ? DECOR_SHADOW_FOCUSED_HEIGHT_IN_DIP : @@ -335,78 +298,4 @@ public class NonClientDecorView extends LinearLayout } } } - - @Override - public void onWindowDragResizeStart(Rect initialBounds) { - if (mOwner.isDestroyed()) { - // If the owner's window is gone, we should not be able to come here anymore. - releaseResources(); - return; - } - if (mBackdropFrameRenderer != null) { - return; - } - final ThreadedRenderer renderer = - (ThreadedRenderer) mOwner.getDecorView().getHardwareRenderer(); - if (renderer != null) { - mBackdropFrameRenderer = new BackdropFrameRenderer(this, renderer, initialBounds); - // Get rid of the shadow while we are resizing. Shadow drawing takes considerable time. - // If we want to get the shadow shown while resizing, we would need to elevate a new - // element which owns the caption and has the elevation. - updateElevation(); - } - } - - @Override - public boolean onContentDrawn(int xOffset, int yOffset, int xSize, int ySize) { - if (mBackdropFrameRenderer == null) { - return false; - } - return mBackdropFrameRenderer.onContentDrawn(xOffset, yOffset, xSize, ySize); - } - - @Override - public void onRequestDraw(boolean reportNextDraw) { - if (mBackdropFrameRenderer != null) { - mBackdropFrameRenderer.onRequestDraw(reportNextDraw); - } else if (reportNextDraw) { - // If render thread is gone, just report immediately. - if (isAttachedToWindow()) { - getViewRootImpl().reportDrawFinish(); - } - } - } - - @Override - public void onWindowDragResizeEnd() { - releaseThreadedRenderer(); - } - - @Override - public void onWindowSizeIsChanging(Rect newBounds) { - if (mBackdropFrameRenderer != null) { - mBackdropFrameRenderer.setTargetRect(newBounds); - } - } - - /** - * Release the renderer thread which is usually done when the user stops resizing. - */ - private void releaseThreadedRenderer() { - if (mBackdropFrameRenderer != null) { - mBackdropFrameRenderer.releaseRenderer(); - mBackdropFrameRenderer = null; - // Bring the shadow back. - updateElevation(); - } - } - - /** - * Called when the parent window is destroyed to release all resources. Note that this will also - * destroy the renderer thread. - */ - private void releaseResources() { - releaseThreadedRenderer(); - } - } From 8cc5a74c9049423260a14e0ebb44a052ef8f4e2a Mon Sep 17 00:00:00 2001 From: Wale Ogunwale Date: Tue, 17 Nov 2015 15:41:05 -0800 Subject: [PATCH 2/2] Only add NonClientDecorView when needed We were previously adding it to all decor views because it was required to be able to draw the resizing backdrop. We now manage the resizing backdrop independently of the NonClientDecorView. Bug: 25082500 Change-Id: Ib786d55eacd221e5d36a4afca9117d5409499674 --- .../policy/BackdropFrameRenderer.java | 22 +++++++++--------- .../android/internal/policy/DecorView.java | 23 +++++++++++++------ .../internal/widget/NonClientDecorView.java | 11 ++++++++- 3 files changed, 37 insertions(+), 19 deletions(-) diff --git a/core/java/com/android/internal/policy/BackdropFrameRenderer.java b/core/java/com/android/internal/policy/BackdropFrameRenderer.java index f227bf35a4a08..b101733a1a14a 100644 --- a/core/java/com/android/internal/policy/BackdropFrameRenderer.java +++ b/core/java/com/android/internal/policy/BackdropFrameRenderer.java @@ -210,7 +210,7 @@ public class BackdropFrameRenderer extends Thread implements Choreographer.Frame // If this was the first call and changeWindowSizeLocked got already called prior // to us, we should re-issue a changeWindowSizeLocked now. return firstCall - && (mLastCaptionHeight != 0 || !mDecorView.mNonClientDecorView.mShowDecor); + && (mLastCaptionHeight != 0 || !mDecorView.isShowingCaption()); } } @@ -227,25 +227,25 @@ public class BackdropFrameRenderer extends Thread implements Choreographer.Frame * @param newBounds The window bounds which needs to be drawn. */ private void changeWindowSizeLocked(Rect newBounds) { + // While a configuration change is taking place the view hierarchy might become // inaccessible. For that case we remember the previous metrics to avoid flashes. // Note that even when there is no visible caption, the caption child will exist. - View caption = mDecorView.mNonClientDecorView.getChildAt(0); - if (caption != null) { - final int captionHeight = caption.getHeight(); - // The caption height will probably never dynamically change while we are resizing. - // Once set to something other then 0 it should be kept that way. - if (captionHeight != 0) { - // Remember the height of the caption. - mLastCaptionHeight = captionHeight; - } + final int captionHeight = mDecorView.getCaptionHeight(); + // The caption height will probably never dynamically change while we are resizing. + // Once set to something other then 0 it should be kept that way. + if (captionHeight != 0) { + // Remember the height of the caption. + mLastCaptionHeight = captionHeight; } + // Make sure that the other thread has already prepared the render draw calls for the // content. If any size is 0, we have to wait for it to be drawn first. - if ((mLastCaptionHeight == 0 && mDecorView.mNonClientDecorView.mShowDecor) || + if ((mLastCaptionHeight == 0 && mDecorView.isShowingCaption()) || mLastContentWidth == 0 || mLastContentHeight == 0) { return; } + // Since the surface is spanning the entire screen, we have to add the start offset of // the bounds to get to the surface location. final int left = mLastXOffset + newBounds.left; diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java index b15ccb25d5b52..077cebc4ebf93 100644 --- a/core/java/com/android/internal/policy/DecorView.java +++ b/core/java/com/android/internal/policy/DecorView.java @@ -1551,6 +1551,8 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind } View onResourcesLoaded(LayoutInflater inflater, int layoutResource) { + mWorkspaceId = getWorkspaceId(); + mResizingBackgroundDrawable = getResizingBackgroundDrawable( mWindow.mBackgroundResource, mWindow.mBackgroundFallbackResource); mCaptionBackgroundDrawable = @@ -1591,12 +1593,10 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind final WindowManager.LayoutParams attrs = mWindow.getAttributes(); boolean isApplication = attrs.type == TYPE_BASE_APPLICATION || attrs.type == TYPE_APPLICATION; - mWorkspaceId = getWorkspaceId(); // Only a non floating application window on one of the allowed workspaces can get a non // client decor. - if (!mWindow.isFloating() - && isApplication - && ActivityManager.StackId.isStaticStack(mWorkspaceId)) { + final boolean hasNonClientDecor = ActivityManager.StackId.hasWindowDecor(mWorkspaceId); + if (!mWindow.isFloating() && isApplication && hasNonClientDecor) { // Dependent on the brightness of the used title we either use the // dark or the light button frame. if (nonClientDecorView == null) { @@ -1615,11 +1615,12 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind nonClientDecorView.setPhoneWindow(mWindow, ActivityManager.StackId.hasWindowDecor(mWorkspaceId), ActivityManager.StackId.hasWindowShadow(mWorkspaceId)); + } else { + nonClientDecorView = null; } - // Tell the decor if it has a visible non client decor. - enableNonClientDecor( - nonClientDecorView != null && ActivityManager.StackId.hasWindowDecor(mWorkspaceId)); + // Tell the decor if it has a visible non client decor. + enableNonClientDecor(nonClientDecorView != null && hasNonClientDecor); return nonClientDecorView; } @@ -1754,6 +1755,14 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind } } + boolean isShowingCaption() { + return mNonClientDecorView != null && mNonClientDecorView.isShowingDecor(); + } + + int getCaptionHeight() { + return isShowingCaption() ? mNonClientDecorView.getDecorCaptionHeight() : 0; + } + private static class ColorViewState { View view = null; int targetVisibility = View.INVISIBLE; diff --git a/core/java/com/android/internal/widget/NonClientDecorView.java b/core/java/com/android/internal/widget/NonClientDecorView.java index 232e308a3c25f..33b8e0515ab07 100644 --- a/core/java/com/android/internal/widget/NonClientDecorView.java +++ b/core/java/com/android/internal/widget/NonClientDecorView.java @@ -68,7 +68,7 @@ public class NonClientDecorView extends LinearLayout private final int DECOR_SHADOW_UNFOCUSED_HEIGHT_IN_DIP = 5; private PhoneWindow mOwner = null; private boolean mWindowHasShadow = false; - public boolean mShowDecor = false; + private boolean mShowDecor = false; // True if the window is being dragged. private boolean mDragging = false; @@ -298,4 +298,13 @@ public class NonClientDecorView extends LinearLayout } } } + + public boolean isShowingDecor() { + return mShowDecor; + } + + public int getDecorCaptionHeight() { + final View caption = getChildAt(0); + return (caption != null) ? caption.getHeight() : 0; + } }