diff --git a/api/current.txt b/api/current.txt
index e91244074522e..bee446b157eaf 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -37441,6 +37441,8 @@ package android.view {
method public abstract void setContentView(int);
method public abstract void setContentView(android.view.View);
method public abstract void setContentView(android.view.View, android.view.ViewGroup.LayoutParams);
+ method public abstract void setDecorView(android.view.View);
+ method public abstract void setDecorView(int);
method protected void setDefaultWindowFormat(int);
method public void setDimAmount(float);
method public void setElevation(float);
diff --git a/api/system-current.txt b/api/system-current.txt
index b996af313a07c..4648672dc5a4c 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -39738,6 +39738,8 @@ package android.view {
method public abstract void setContentView(int);
method public abstract void setContentView(android.view.View);
method public abstract void setContentView(android.view.View, android.view.ViewGroup.LayoutParams);
+ method public abstract void setDecorView(android.view.View);
+ method public abstract void setDecorView(int);
method protected void setDefaultWindowFormat(int);
method public void setDimAmount(float);
method public void setDisableWallpaperTouchEvents(boolean);
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index d9ec866ffbabe..5d11c8b7d888e 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -1155,6 +1155,27 @@ public abstract class Window {
*/
public abstract void setContentView(View view);
+ /**
+ * Install a view in the decoration (title) area, to be shown when
+ * the window is in multi-window mode. This view will be placed
+ * next to the window controls.
+ *
+ * The view may be restored to defaults by passing null.
+ *
+ * @param view The desired view to display in window decorations.
+ */
+ public abstract void setDecorView(View view);
+
+ /**
+ * Convenience for
+ * {@link #setDecorView(View)}
+ * to set the custom window decoration from a layout resource. The layout will be inflated
+ * adding all top level views to the decoration
+ *
+ * @param layoutResID Resource ID to be inflated.
+ */
+ public abstract void setDecorView(@LayoutRes int layoutResID);
+
/**
* Set the screen content to an explicit view. This view is placed
* directly into the screen's view hierarchy. It can itself be a complex
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index afef7633bc69d..8a2621176f9ab 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -123,6 +123,7 @@ import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
import android.widget.FrameLayout;
+import android.widget.LinearLayout;
import android.widget.ImageView;
import android.widget.PopupWindow;
import android.widget.ProgressBar;
@@ -468,6 +469,30 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
}
}
+ @Override
+ public void setDecorView(int layoutResID) {
+ View v = mLayoutInflater.inflate(layoutResID, null);
+ setDecorView(v);
+ }
+
+ @Override
+ public void setDecorView(View view) {
+ if (mContentParent == null) {
+ installDecor();
+ }
+
+ LinearLayout clientDecorPlaceholder =
+ (LinearLayout) findViewById(R.id.client_decor_placeholder);
+
+ if (clientDecorPlaceholder != null) {
+ clientDecorPlaceholder.removeAllViews();
+
+ if (view != null) {
+ clientDecorPlaceholder.addView(view);
+ }
+ }
+ }
+
@Override
public void addContentView(View view, ViewGroup.LayoutParams params) {
if (mContentParent == null) {
diff --git a/core/java/com/android/internal/widget/NonClientDecorView.java b/core/java/com/android/internal/widget/NonClientDecorView.java
index 5d502c9dcca02..be9be11f9da6f 100644
--- a/core/java/com/android/internal/widget/NonClientDecorView.java
+++ b/core/java/com/android/internal/widget/NonClientDecorView.java
@@ -428,8 +428,7 @@ public class NonClientDecorView extends LinearLayout
// The render nodes for the multi threaded renderer.
private ThreadedRenderer mRenderer;
- private RenderNode mFrameNode;
- private RenderNode mBackdropNode;
+ private RenderNode mFrameAndBackdropNode;
private final Rect mOldTargetRect = new Rect();
private final Rect mNewTargetRect = new Rect();
@@ -450,13 +449,11 @@ public class NonClientDecorView extends LinearLayout
setName("ResizeFrame");
mRenderer = renderer;
- // Create the render nodes for our frame and backdrop which can be resized independently
- // from the content.
- mFrameNode = RenderNode.create("FrameNode", null);
- mBackdropNode = RenderNode.create("BackdropNode", null);
+ // Create a render node for the content and frame backdrop
+ // which can be resized independently from the content.
+ mFrameAndBackdropNode = RenderNode.create("FrameAndBackdropNode", null);
- mRenderer.addRenderNode(mFrameNode, false);
- mRenderer.addRenderNode(mBackdropNode, true);
+ mRenderer.addRenderNode(mFrameAndBackdropNode, true);
// Set the initial bounds and draw once so that we do not get a broken frame.
mTargetRect.set(initialBounds);
@@ -504,10 +501,9 @@ public class NonClientDecorView extends LinearLayout
// Invalidate the current content bounds.
mRenderer.setContentDrawBounds(0, 0, 0, 0);
- // Remove the render nodes again
+ // Remove the render node again
// (see comment above - better to do that only once).
- mRenderer.removeRenderNode(mFrameNode);
- mRenderer.removeRenderNode(mBackdropNode);
+ mRenderer.removeRenderNode(mFrameAndBackdropNode);
mRenderer = null;
@@ -575,7 +571,7 @@ public class NonClientDecorView extends LinearLayout
mRenderer.setContentDrawBounds(
mLastXOffset,
- mLastYOffset + mLastCaptionHeight,
+ mLastYOffset,
mLastXOffset + mLastContentWidth,
mLastYOffset + mLastCaptionHeight + mLastContentHeight);
// If this was the first call and changeWindowSizeLocked got already called prior
@@ -623,30 +619,20 @@ public class NonClientDecorView extends LinearLayout
final int width = newBounds.width();
final int height = newBounds.height();
- // Produce the draw calls.
- // TODO(skuhne): Create a separate caption view which draws this. If the shadow should
- // be resized while the window resizes, this hierarchy needs to have the elevation.
- // That said - it is probably no good idea to draw the shadow every time since it costs
- // a considerable time which we should rather spend for resizing the content and it does
- // barely show while the entire screen is moving.
- mFrameNode.setLeftTopRightBottom(left, top, left + width, top + mLastCaptionHeight);
- DisplayListCanvas canvas = mFrameNode.start(width, height);
+ 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);
mCaptionBackgroundDrawable.setBounds(0, 0, left + width, top + mLastCaptionHeight);
mCaptionBackgroundDrawable.draw(canvas);
- mFrameNode.end(canvas);
-
- mBackdropNode.setLeftTopRightBottom(left, top + mLastCaptionHeight, left + width,
- top + height);
// The backdrop: clear everything with the background. Clipping is done elsewhere.
- canvas = mBackdropNode.start(width, height - mLastCaptionHeight);
- mResizingBackgroundDrawable.setBounds(0, 0, left + width, top + height);
+ mResizingBackgroundDrawable.setBounds(0, mLastCaptionHeight, left + width, top + height);
mResizingBackgroundDrawable.draw(canvas);
- mBackdropNode.end(canvas);
+ mFrameAndBackdropNode.end(canvas);
- // We need to render both rendered nodes explicitly.
- mRenderer.drawRenderNode(mFrameNode);
- mRenderer.drawRenderNode(mBackdropNode);
+ // We need to render the node explicitly
+ mRenderer.drawRenderNode(mFrameAndBackdropNode);
reportDrawIfNeeded();
}
diff --git a/core/res/res/layout/non_client_decor_dark.xml b/core/res/res/layout/non_client_decor_dark.xml
index 112f4b7f74a90..40b8960a7ff96 100644
--- a/core/res/res/layout/non_client_decor_dark.xml
+++ b/core/res/res/layout/non_client_decor_dark.xml
@@ -29,10 +29,11 @@
android:background="@drawable/non_client_decor_title"
android:focusable="false"
android:descendantFocusability="blocksDescendants" >
-
+ android:layout_weight="1"/>