summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDianne Hackborn <hackbod@google.com>2012-03-30 17:36:32 -0700
committerAndroid (Google) Code Review <android-gerrit@google.com>2012-03-30 17:36:32 -0700
commit61d6c8ca49d4a3d5bf4c961878a3f71145d75058 (patch)
treedac339e3067c6e8cd20e759f1d1e5b0d402d05e4
parent96695f9ba04f85b24f906c59673e92f00f89adbe (diff)
parent3a3a6cfd8ec12208ca75c0d0d871d19d76c34194 (diff)
downloadframeworks_base-61d6c8ca49d4a3d5bf4c961878a3f71145d75058.zip
frameworks_base-61d6c8ca49d4a3d5bf4c961878a3f71145d75058.tar.gz
frameworks_base-61d6c8ca49d4a3d5bf4c961878a3f71145d75058.tar.bz2
Merge "Add new feature to let apps layout over status bar / system bar."
-rw-r--r--api/current.txt10
-rw-r--r--core/java/android/app/ActionBar.java10
-rw-r--r--core/java/android/view/View.java242
-rw-r--r--core/java/android/view/ViewGroup.java50
-rw-r--r--core/java/android/view/ViewParent.java6
-rw-r--r--core/java/android/view/ViewRootImpl.java255
-rw-r--r--core/java/android/view/Window.java10
-rw-r--r--core/java/com/android/internal/app/ActionBarImpl.java107
-rw-r--r--core/java/com/android/internal/statusbar/IStatusBar.aidl2
-rw-r--r--core/java/com/android/internal/statusbar/IStatusBarService.aidl2
-rw-r--r--core/java/com/android/internal/widget/ActionBarOverlayLayout.java193
-rw-r--r--core/res/res/layout-xlarge/screen_action_bar_overlay.xml54
-rw-r--r--core/res/res/layout/screen_action_bar_overlay.xml15
-rw-r--r--core/res/res/values/public.xml2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java28
-rw-r--r--policy/src/com/android/internal/policy/impl/PhoneWindow.java3
-rwxr-xr-xpolicy/src/com/android/internal/policy/impl/PhoneWindowManager.java147
-rw-r--r--services/java/com/android/server/StatusBarManagerService.java8
-rw-r--r--services/java/com/android/server/wm/WindowManagerService.java3
23 files changed, 907 insertions, 265 deletions
diff --git a/api/current.txt b/api/current.txt
index 233938b5..483283d 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -23240,6 +23240,7 @@ package android.view {
method public boolean dispatchUnhandledMove(android.view.View, int);
method protected void dispatchVisibilityChanged(android.view.View, int);
method public void dispatchWindowFocusChanged(boolean);
+ method public void dispatchWindowSystemUiVisiblityChanged(int);
method public void dispatchWindowVisibilityChanged(int);
method public void draw(android.graphics.Canvas);
method protected void drawableStateChanged();
@@ -23353,6 +23354,7 @@ package android.view {
method public int getVisibility();
method public final int getWidth();
method protected int getWindowAttachCount();
+ method public int getWindowSystemUiVisibility();
method public android.os.IBinder getWindowToken();
method public int getWindowVisibility();
method public void getWindowVisibleDisplayFrame(android.graphics.Rect);
@@ -23456,6 +23458,7 @@ package android.view {
method public boolean onTrackballEvent(android.view.MotionEvent);
method protected void onVisibilityChanged(android.view.View, int);
method public void onWindowFocusChanged(boolean);
+ method public void onWindowSystemUiVisibilityChanged(int);
method protected void onWindowVisibilityChanged(int);
method protected boolean overScrollBy(int, int, int, int, int, int, int, int, boolean);
method public boolean performClick();
@@ -23473,6 +23476,7 @@ package android.view {
method public boolean removeCallbacks(java.lang.Runnable);
method public void removeOnAttachStateChangeListener(android.view.View.OnAttachStateChangeListener);
method public void removeOnLayoutChangeListener(android.view.View.OnLayoutChangeListener);
+ method public void requestFitSystemWindows();
method public final boolean requestFocus();
method public final boolean requestFocus(int);
method public boolean requestFocus(int, android.graphics.Rect);
@@ -23671,9 +23675,14 @@ package android.view {
field public static final int SOUND_EFFECTS_ENABLED = 134217728; // 0x8000000
field public static final deprecated int STATUS_BAR_HIDDEN = 1; // 0x1
field public static final deprecated int STATUS_BAR_VISIBLE = 0; // 0x0
+ field public static final int SYSTEM_UI_FLAG_FULLSCREEN = 4; // 0x4
field public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 2; // 0x2
+ field public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 1024; // 0x400
+ field public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 512; // 0x200
+ field public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 256; // 0x100
field public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 1; // 0x1
field public static final int SYSTEM_UI_FLAG_VISIBLE = 0; // 0x0
+ field public static final int SYSTEM_UI_LAYOUT_FLAGS = 1536; // 0x600
field public static final int TEXT_DIRECTION_ANY_RTL = 2; // 0x2
field protected static int TEXT_DIRECTION_DEFAULT;
field public static final int TEXT_DIRECTION_FIRST_STRONG = 1; // 0x1
@@ -24037,6 +24046,7 @@ package android.view {
method public abstract void requestChildFocus(android.view.View, android.view.View);
method public abstract boolean requestChildRectangleOnScreen(android.view.View, android.graphics.Rect, boolean);
method public abstract void requestDisallowInterceptTouchEvent(boolean);
+ method public abstract void requestFitSystemWindows();
method public abstract void requestLayout();
method public abstract boolean requestSendAccessibilityEvent(android.view.View, android.view.accessibility.AccessibilityEvent);
method public abstract void requestTransparentRegion(android.view.View);
diff --git a/core/java/android/app/ActionBar.java b/core/java/android/app/ActionBar.java
index 24d3a6b..cff16ff 100644
--- a/core/java/android/app/ActionBar.java
+++ b/core/java/android/app/ActionBar.java
@@ -611,6 +611,10 @@ public abstract class ActionBar {
* If the window hosting the ActionBar does not have the feature
* {@link Window#FEATURE_ACTION_BAR_OVERLAY} it will resize application
* content to fit the new space available.
+ *
+ * <p>If you are hiding the ActionBar through
+ * {@link View#SYSTEM_UI_FLAG_FULLSCREEN View.SYSTEM_UI_FLAG_FULLSCREEN},
+ * you should not call this function directly.
*/
public abstract void show();
@@ -619,6 +623,12 @@ public abstract class ActionBar {
* If the window hosting the ActionBar does not have the feature
* {@link Window#FEATURE_ACTION_BAR_OVERLAY} it will resize application
* content to fit the new space available.
+ *
+ * <p>Instead of calling this function directly, you can also cause an
+ * ActionBar using the overlay feature to hide through
+ * {@link View#SYSTEM_UI_FLAG_FULLSCREEN View.SYSTEM_UI_FLAG_FULLSCREEN}.
+ * Hiding the ActionBar through this system UI flag allows you to more
+ * seamlessly hide it in conjunction with other screen decorations.
*/
public abstract void hide();
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 6c964b0..81f3f6a 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -765,7 +765,12 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
*/
static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
- // note flag value 0x00000800 is now available for next flags...
+ /**
+ * Set for framework elements that use FITS_SYSTEM_WINDOWS, to indicate
+ * that they are optional and should be skipped if the window has
+ * requested system UI flags that ignore those insets for layout.
+ */
+ static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800;
/**
* <p>This view doesn't show fading edges.</p>
@@ -1909,28 +1914,31 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
public static final int OVER_SCROLL_NEVER = 2;
/**
- * View has requested the system UI (status bar) to be visible (the default).
+ * Special constant for {@link #setSystemUiVisibility(int)}: View has
+ * requested the system UI (status bar) to be visible (the default).
*
* @see #setSystemUiVisibility(int)
*/
public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
/**
- * View has requested the system UI to enter an unobtrusive "low profile" mode.
+ * Flag for {@link #setSystemUiVisibility(int)}: View has requested the
+ * system UI to enter an unobtrusive "low profile" mode.
*
- * This is for use in games, book readers, video players, or any other "immersive" application
- * where the usual system chrome is deemed too distracting.
+ * <p>This is for use in games, book readers, video players, or any other
+ * "immersive" application where the usual system chrome is deemed too distracting.
*
- * In low profile mode, the status bar and/or navigation icons may dim.
+ * <p>In low profile mode, the status bar and/or navigation icons may dim.
*
* @see #setSystemUiVisibility(int)
*/
public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
/**
- * View has requested that the system navigation be temporarily hidden.
+ * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the
+ * system navigation be temporarily hidden.
*
- * This is an even less obtrusive state than that called for by
+ * <p>This is an even less obtrusive state than that called for by
* {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
* (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
* those to disappear. This is useful (in conjunction with the
@@ -1938,14 +1946,92 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
* window flags) for displaying content using every last pixel on the display.
*
- * There is a limitation: because navigation controls are so important, the least user
- * interaction will cause them to reappear immediately.
+ * <p>There is a limitation: because navigation controls are so important, the least user
+ * interaction will cause them to reappear immediately. When this happens, both
+ * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically,
+ * so that both elements reappear at the same time.
*
* @see #setSystemUiVisibility(int)
*/
public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
/**
+ * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go
+ * into the normal fullscreen mode so that its content can take over the screen
+ * while still allowing the user to interact with the application.
+ *
+ * <p>This has the same visual effect as
+ * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
+ * WindowManager.LayoutParams.FLAG_FULLSCREEN},
+ * meaning that non-critical screen decorations (such as the status bar) will be
+ * hidden while the user is in the View's window, focusing the experience on
+ * that content. Unlike the window flag, if you are using ActionBar in
+ * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
+ * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also
+ * hide the action bar.
+ *
+ * <p>This approach to going fullscreen is best used over the window flag when
+ * it is a transient state -- that is, the application does this at certain
+ * points in its user interaction where it wants to allow the user to focus
+ * on content, but not as a continuous state. For situations where the application
+ * would like to simply stay full screen the entire time (such as a game that
+ * wants to take over the screen), the
+ * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag}
+ * is usually a better approach. The state set here will be removed by the system
+ * in various situations (such as the user moving to another application) like
+ * the other system UI states.
+ *
+ * <p>When using this flag, the application should provide some easy facility
+ * for the user to go out of it. A common example would be in an e-book
+ * reader, where tapping on the screen brings back whatever screen and UI
+ * decorations that had been hidden while the user was immersed in reading
+ * the book.
+ *
+ * @see #setSystemUiVisibility(int)
+ */
+ public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
+
+ /**
+ * Flag for {@link #setSystemUiVisibility(int)}: When using other layout
+ * flags, we would like a stable view of the content insets given to
+ * {@link #fitSystemWindows(Rect)}. This means that the insets seen there
+ * will always represent the worst case that the application can expect
+ * as a continue state. In practice this means with any of system bar,
+ * nav bar, and status bar shown, but not the space that would be needed
+ * for an input method.
+ *
+ * <p>If you are using ActionBar in
+ * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
+ * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the
+ * insets it adds to those given to the application.
+ */
+ public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
+
+ /**
+ * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
+ * to be layed out as if it has requested
+ * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't. This
+ * allows it to avoid artifacts when switching in and out of that mode, at
+ * the expense that some of its user interface may be covered by screen
+ * decorations when they are shown. You can perform layout of your inner
+ * UI elements to account for the navagation system UI through the
+ * {@link #fitSystemWindows(Rect)} method.
+ */
+ public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
+
+ /**
+ * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
+ * to be layed out as if it has requested
+ * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't. This
+ * allows it to avoid artifacts when switching in and out of that mode, at
+ * the expense that some of its user interface may be covered by screen
+ * decorations when they are shown. You can perform layout of your inner
+ * UI elements to account for non-fullscreen system UI through the
+ * {@link #fitSystemWindows(Rect)} method.
+ */
+ public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
+
+ /**
* @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
*/
public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
@@ -2055,17 +2141,6 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
/**
* @hide
- *
- * NOTE: This flag may only be used in subtreeSystemUiVisibility, etc. etc.
- *
- * This hides HOME and RECENT and is provided for compatibility with interim implementations.
- */
- @Deprecated
- public static final int STATUS_BAR_DISABLE_NAVIGATION =
- STATUS_BAR_DISABLE_HOME | STATUS_BAR_DISABLE_RECENT;
-
- /**
- * @hide
*/
public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x0000FFFF;
@@ -2076,7 +2151,15 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* @hide
*/
public static final int SYSTEM_UI_CLEARABLE_FLAGS =
- SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION;
+ SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION
+ | SYSTEM_UI_FLAG_FULLSCREEN;
+
+ /**
+ * Flags that can impact the layout in relation to system UI.
+ */
+ public static final int SYSTEM_UI_LAYOUT_FLAGS =
+ SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
+ | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
/**
* Find views that render the specified text.
@@ -4692,21 +4775,54 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
}
/**
- * Apply the insets for system windows to this view, if the FITS_SYSTEM_WINDOWS flag
- * is set
+ * Called by the view hierarchy when the content insets for a window have
+ * changed, to allow it to adjust its content to fit within those windows.
+ * The content insets tell you the space that the status bar, input method,
+ * and other system windows infringe on the application's window.
+ *
+ * <p>You do not normally need to deal with this function, since the default
+ * window decoration given to applications takes care of applying it to the
+ * content of the window. If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
+ * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case,
+ * and your content can be placed under those system elements. You can then
+ * use this method within your view hierarchy if you have parts of your UI
+ * which you would like to ensure are not being covered.
*
- * @param insets Insets for system windows
+ * <p>The default implementation of this method simply applies the content
+ * inset's to the view's padding. This can be enabled through
+ * {@link #setFitsSystemWindows(boolean)}. Alternatively, you can override
+ * the method and handle the insets however you would like. Note that the
+ * insets provided by the framework are always relative to the far edges
+ * of the window, not accounting for the location of the called view within
+ * that window. (In fact when this method is called you do not yet know
+ * where the layout will place the view, as it is done before layout happens.)
*
- * @return True if this view applied the insets, false otherwise
+ * <p>Note: unlike many View methods, there is no dispatch phase to this
+ * call. If you are overriding it in a ViewGroup and want to allow the
+ * call to continue to your children, you must be sure to call the super
+ * implementation.
+ *
+ * @param insets Current content insets of the window. Prior to
+ * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
+ * the insets or else you and Android will be unhappy.
+ *
+ * @return Return true if this view applied the insets and it should not
+ * continue propagating further down the hierarchy, false otherwise.
*/
protected boolean fitSystemWindows(Rect insets) {
if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
- mPaddingLeft = insets.left;
- mPaddingTop = insets.top;
- mPaddingRight = insets.right;
- mPaddingBottom = insets.bottom;
- requestLayout();
- return true;
+ mUserPaddingStart = -1;
+ mUserPaddingEnd = -1;
+ mUserPaddingRelative = false;
+ if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
+ || mAttachInfo == null
+ || (mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0) {
+ internalSetPadding(insets.left, insets.top, insets.right, insets.bottom);
+ return true;
+ } else {
+ internalSetPadding(0, 0, 0, 0);
+ return false;
+ }
}
return false;
}
@@ -4742,6 +4858,23 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
}
/**
+ * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
+ */
+ public void requestFitSystemWindows() {
+ if (mParent != null) {
+ mParent.requestFitSystemWindows();
+ }
+ }
+
+ /**
+ * For use by PhoneWindow to make its own system window fitting optional.
+ * @hide
+ */
+ public void makeOptionalFitsSystemWindows() {
+ setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
+ }
+
+ /**
* Returns the visibility status for this view.
*
* @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
@@ -6118,19 +6251,19 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* Private function to aggregate all per-view attributes in to the view
* root.
*/
- void dispatchCollectViewAttributes(int visibility) {
- performCollectViewAttributes(visibility);
+ void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
+ performCollectViewAttributes(attachInfo, visibility);
}
- void performCollectViewAttributes(int visibility) {
- if ((visibility & VISIBILITY_MASK) == VISIBLE && mAttachInfo != null) {
+ void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
+ if ((visibility & VISIBILITY_MASK) == VISIBLE) {
if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
- mAttachInfo.mKeepScreenOn = true;
+ attachInfo.mKeepScreenOn = true;
}
- mAttachInfo.mSystemUiVisibility |= mSystemUiVisibility;
+ attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
ListenerInfo li = mListenerInfo;
if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
- mAttachInfo.mHasSystemUiListeners = true;
+ attachInfo.mHasSystemUiListeners = true;
}
}
}
@@ -10126,7 +10259,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
mAttachInfo.mScrollContainers.add(this);
mPrivateFlags |= SCROLL_CONTAINER_ADDED;
}
- performCollectViewAttributes(visibility);
+ performCollectViewAttributes(mAttachInfo, visibility);
onAttachedToWindow();
ListenerInfo li = mListenerInfo;
@@ -13982,6 +14115,35 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
}
/**
+ * Returns the current system UI visibility that is currently set for
+ * the entire window. This is the combination of the
+ * {@link #setSystemUiVisibility(int)} values supplied by all of the
+ * views in the window.
+ */
+ public int getWindowSystemUiVisibility() {
+ return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
+ }
+
+ /**
+ * Override to find out when the window's requested system UI visibility
+ * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}.
+ * This is different from the callbacks recieved through
+ * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
+ * in that this is only telling you about the local request of the window,
+ * not the actual values applied by the system.
+ */
+ public void onWindowSystemUiVisibilityChanged(int visible) {
+ }
+
+ /**
+ * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
+ * the view hierarchy.
+ */
+ public void dispatchWindowSystemUiVisiblityChanged(int visible) {
+ onWindowSystemUiVisibilityChanged(visible);
+ }
+
+ /**
* Set a listener to receive callbacks when the visibility of the system bar changes.
* @param l The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
*/
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 30d6ec7..d5c783f 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -918,7 +918,20 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
}
}
}
-
+
+ /**
+ * @hide
+ */
+ @Override
+ public void makeOptionalFitsSystemWindows() {
+ super.makeOptionalFitsSystemWindows();
+ final int count = mChildrenCount;
+ final View[] children = mChildren;
+ for (int i = 0; i < count; i++) {
+ children[i].makeOptionalFitsSystemWindows();
+ }
+ }
+
/**
* {@inheritDoc}
*/
@@ -1017,13 +1030,16 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
}
@Override
- void dispatchCollectViewAttributes(int visibility) {
- visibility |= mViewFlags&VISIBILITY_MASK;
- super.dispatchCollectViewAttributes(visibility);
- final int count = mChildrenCount;
- final View[] children = mChildren;
- for (int i = 0; i < count; i++) {
- children[i].dispatchCollectViewAttributes(visibility);
+ void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
+ if ((visibility & VISIBILITY_MASK) == VISIBLE) {
+ super.dispatchCollectViewAttributes(attachInfo, visibility);
+ final int count = mChildrenCount;
+ final View[] children = mChildren;
+ for (int i = 0; i < count; i++) {
+ final View child = children[i];
+ child.dispatchCollectViewAttributes(attachInfo,
+ visibility | (child.mViewFlags&VISIBILITY_MASK));
+ }
}
}
@@ -1239,6 +1255,18 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
}
@Override
+ public void dispatchWindowSystemUiVisiblityChanged(int visible) {
+ super.dispatchWindowSystemUiVisiblityChanged(visible);
+
+ final int count = mChildrenCount;
+ final View[] children = mChildren;
+ for (int i=0; i <count; i++) {
+ final View child = children[i];
+ child.dispatchWindowSystemUiVisiblityChanged(visible);
+ }
+ }
+
+ @Override
public void dispatchSystemUiVisibilityChanged(int visible) {
super.dispatchSystemUiVisibilityChanged(visible);
@@ -2244,12 +2272,12 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
super.dispatchAttachedToWindow(info, visibility);
mGroupFlags &= ~FLAG_PREVENT_DISPATCH_ATTACHED_TO_WINDOW;
- visibility |= mViewFlags & VISIBILITY_MASK;
-
final int count = mChildrenCount;
final View[] children = mChildren;
for (int i = 0; i < count; i++) {
- children[i].dispatchAttachedToWindow(info, visibility);
+ final View child = children[i];
+ child.dispatchAttachedToWindow(info,
+ visibility | (child.mViewFlags&VISIBILITY_MASK));
}
}
diff --git a/core/java/android/view/ViewParent.java b/core/java/android/view/ViewParent.java
index 8395f1b..75e9151 100644
--- a/core/java/android/view/ViewParent.java
+++ b/core/java/android/view/ViewParent.java
@@ -271,4 +271,10 @@ public interface ViewParent {
* @hide
*/
public void childHasTransientStateChanged(View child, boolean hasTransientState);
+
+ /**
+ * Ask that a new dispatch of {@link View#fitSystemWindows(Rect)
+ * View.fitSystemWindows(Rect)} be performed.
+ */
+ public void requestFitSystemWindows();
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 4d589d7..d72f3b7 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -223,6 +223,7 @@ public final class ViewRootImpl implements ViewParent,
long mLastTraversalFinishedTimeNanos;
long mLastDrawFinishedTimeNanos;
boolean mWillDrawSoon;
+ boolean mFitSystemWindowsRequested;
boolean mLayoutRequested;
boolean mFirst;
boolean mReportNextDraw;
@@ -230,6 +231,7 @@ public final class ViewRootImpl implements ViewParent,
boolean mNewSurfaceNeeded;
boolean mHasHadWindowFocus;
boolean mLastWasImTarget;
+ int mLastSystemUiVisibility;
// Pool of queued input events.
private static final int MAX_QUEUED_INPUT_EVENT_POOL_SIZE = 10;
@@ -263,6 +265,8 @@ public final class ViewRootImpl implements ViewParent,
final ViewTreeObserver.InternalInsetsInfo mLastGivenInsets
= new ViewTreeObserver.InternalInsetsInfo();
+ final Rect mFitSystemWindowsInsets = new Rect();
+
final Configuration mLastConfiguration = new Configuration();
final Configuration mPendingConfiguration = new Configuration();
@@ -539,6 +543,8 @@ public final class ViewRootImpl implements ViewParent,
}
try {
mOrigWindowType = mWindowAttributes.type;
+ mAttachInfo.mRecomputeGlobalAttributes = true;
+ collectViewAttributes();
res = sWindowSession.add(mWindow, mSeq, mWindowAttributes,
getHostVisibility(), mAttachInfo.mContentInsets,
mInputChannel);
@@ -786,6 +792,15 @@ public final class ViewRootImpl implements ViewParent,
/**
* {@inheritDoc}
*/
+ public void requestFitSystemWindows() {
+ checkThread();
+ mFitSystemWindowsRequested = true;
+ scheduleTraversals();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
public void requestLayout() {
checkThread();
mLayoutRequested = true;
@@ -974,6 +989,100 @@ public final class ViewRootImpl implements ViewParent,
}
}
+ private boolean collectViewAttributes() {
+ final View.AttachInfo attachInfo = mAttachInfo;
+ if (attachInfo.mRecomputeGlobalAttributes) {
+ //Log.i(TAG, "Computing view hierarchy attributes!");
+ attachInfo.mRecomputeGlobalAttributes = false;
+ boolean oldScreenOn = attachInfo.mKeepScreenOn;
+ int oldVis = attachInfo.mSystemUiVisibility;
+ boolean oldHasSystemUiListeners = attachInfo.mHasSystemUiListeners;
+ attachInfo.mKeepScreenOn = false;
+ attachInfo.mSystemUiVisibility = 0;
+ attachInfo.mHasSystemUiListeners = false;
+ mView.dispatchCollectViewAttributes(attachInfo, 0);
+ if (attachInfo.mKeepScreenOn != oldScreenOn
+ || attachInfo.mSystemUiVisibility != oldVis
+ || attachInfo.mHasSystemUiListeners != oldHasSystemUiListeners) {
+ WindowManager.LayoutParams params = mWindowAttributes;
+ if (attachInfo.mKeepScreenOn) {
+ params.flags |= WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
+ }
+ params.subtreeSystemUiVisibility = attachInfo.mSystemUiVisibility;
+ params.hasSystemUiListeners = attachInfo.mHasSystemUiListeners;
+ mView.dispatchWindowSystemUiVisiblityChanged(attachInfo.mSystemUiVisibility);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean measureHierarchy(final View host, final WindowManager.LayoutParams lp,
+ final Resources res, final int desiredWindowWidth, final int desiredWindowHeight) {
+ int childWidthMeasureSpec;
+ int childHeightMeasureSpec;
+ boolean windowSizeMayChange = false;
+
+ if (DEBUG_ORIENTATION || DEBUG_LAYOUT) Log.v(TAG,
+ "Measuring " + host + " in display " + desiredWindowWidth
+ + "x" + desiredWindowHeight + "...");
+
+ boolean goodMeasure = false;
+ if (lp.width == ViewGroup.LayoutParams.WRAP_CONTENT) {
+ // On large screens, we don't want to allow dialogs to just
+ // stretch to fill the entire width of the screen to display
+ // one line of text. First try doing the layout at a smaller
+ // size to see if it will fit.
+ final DisplayMetrics packageMetrics = res.getDisplayMetrics();
+ res.getValue(com.android.internal.R.dimen.config_prefDialogWidth, mTmpValue, true);
+ int baseSize = 0;
+ if (mTmpValue.type == TypedValue.TYPE_DIMENSION) {
+ baseSize = (int)mTmpValue.getDimension(packageMetrics);
+ }
+ if (DEBUG_DIALOG) Log.v(TAG, "Window " + mView + ": baseSize=" + baseSize);
+ if (baseSize != 0 && desiredWindowWidth > baseSize) {
+ childWidthMeasureSpec = getRootMeasureSpec(baseSize, lp.width);
+ childHeightMeasureSpec = getRootMeasureSpec(desiredWindowHeight, lp.height);
+ host.measure(childWidthMeasureSpec, childHeightMeasureSpec);
+ if (DEBUG_DIALOG) Log.v(TAG, "Window " + mView + ": measured ("
+ + host.getMeasuredWidth() + "," + host.getMeasuredHeight() + ")");
+ if ((host.getMeasuredWidthAndState()&View.MEASURED_STATE_TOO_SMALL) == 0) {
+ goodMeasure = true;
+ } else {
+ // Didn't fit in that size... try expanding a bit.
+ baseSize = (baseSize+desiredWindowWidth)/2;
+ if (DEBUG_DIALOG) Log.v(TAG, "Window " + mView + ": next baseSize="
+ + baseSize);
+ childWidthMeasureSpec = getRootMeasureSpec(baseSize, lp.width);
+ host.measure(childWidthMeasureSpec, childHeightMeasureSpec);
+ if (DEBUG_DIALOG) Log.v(TAG, "Window " + mView + ": measured ("
+ + host.getMeasuredWidth() + "," + host.getMeasuredHeight() + ")");
+ if ((host.getMeasuredWidthAndState()&View.MEASURED_STATE_TOO_SMALL) == 0) {
+ if (DEBUG_DIALOG) Log.v(TAG, "Good!");
+ goodMeasure = true;
+ }
+ }
+ }
+ }
+
+ if (!goodMeasure) {
+ childWidthMeasureSpec = getRootMeasureSpec(desiredWindowWidth, lp.width);
+ childHeightMeasureSpec = getRootMeasureSpec(desiredWindowHeight, lp.height);
+ host.measure(childWidthMeasureSpec, childHeightMeasureSpec);
+ if (mWidth != host.getMeasuredWidth() || mHeight != host.getMeasuredHeight()) {
+ windowSizeMayChange = true;
+ }
+ }
+
+ if (DBG) {
+ System.out.println("======================================");
+ System.out.println("performTraversals -- after measure");
+ host.debug();
+ }
+
+ return windowSizeMayChange;
+ }
+
private void performTraversals() {
// cache mView since it is used so much below...
final View host = mView;
@@ -995,8 +1104,6 @@ public final class ViewRootImpl implements ViewParent,
int desiredWindowWidth;
int desiredWindowHeight;
- int childWidthMeasureSpec;
- int childHeightMeasureSpec;
final View.AttachInfo attachInfo = mAttachInfo;
@@ -1057,15 +1164,14 @@ public final class ViewRootImpl implements ViewParent,
attachInfo.mHasWindowFocus = false;
attachInfo.mWindowVisibility = viewVisibility;
attachInfo.mRecomputeGlobalAttributes = false;
- attachInfo.mKeepScreenOn = false;
- attachInfo.mSystemUiVisibility = 0;
viewVisibilityChanged = false;
mLastConfiguration.setTo(host.getResources().getConfiguration());
+ mLastSystemUiVisibility = mAttachInfo.mSystemUiVisibility;
host.dispatchAttachedToWindow(attachInfo, 0);
+ mFitSystemWindowsInsets.set(mAttachInfo.mContentInsets);
+ host.fitSystemWindows(mFitSystemWindowsInsets);
//Log.i(TAG, "Screen on initialized: " + attachInfo.mKeepScreenOn);
- host.fitSystemWindows(mAttachInfo.mContentInsets);
-
} else {
desiredWindowWidth = frame.width();
desiredWindowHeight = frame.height();
@@ -1093,7 +1199,8 @@ public final class ViewRootImpl implements ViewParent,
boolean insetsChanged = false;
- if (mLayoutRequested && !mStopped) {
+ boolean layoutRequested = mLayoutRequested && !mStopped;
+ if (layoutRequested) {
// Execute enqueued actions on every layout in case a view that was detached
// enqueued an action after being detached
getRunQueue().executeActions(attachInfo.mHandler);
@@ -1134,79 +1241,12 @@ public final class ViewRootImpl implements ViewParent,
}
// Ask host how big it wants to be
- if (DEBUG_ORIENTATION || DEBUG_LAYOUT) Log.v(TAG,
- "Measuring " + host + " in display " + desiredWindowWidth
- + "x" + desiredWindowHeight + "...");
-
- boolean goodMeasure = false;
- if (lp.width == ViewGroup.LayoutParams.WRAP_CONTENT) {
- // On large screens, we don't want to allow dialogs to just
- // stretch to fill the entire width of the screen to display
- // one line of text. First try doing the layout at a smaller
- // size to see if it will fit.
- final DisplayMetrics packageMetrics = res.getDisplayMetrics();
- res.getValue(com.android.internal.R.dimen.config_prefDialogWidth, mTmpValue, true);
- int baseSize = 0;
- if (mTmpValue.type == TypedValue.TYPE_DIMENSION) {
- baseSize = (int)mTmpValue.getDimension(packageMetrics);
- }
- if (DEBUG_DIALOG) Log.v(TAG, "Window " + mView + ": baseSize=" + baseSize);
- if (baseSize != 0 && desiredWindowWidth > baseSize) {
- childWidthMeasureSpec = getRootMeasureSpec(baseSize, lp.width);
- childHeightMeasureSpec = getRootMeasureSpec(desiredWindowHeight, lp.height);
- host.measure(childWidthMeasureSpec, childHeightMeasureSpec);
- if (DEBUG_DIALOG) Log.v(TAG, "Window " + mView + ": measured ("
- + host.getMeasuredWidth() + "," + host.getMeasuredHeight() + ")");
- if ((host.getMeasuredWidthAndState()&View.MEASURED_STATE_TOO_SMALL) == 0) {
- goodMeasure = true;
- } else {
- // Didn't fit in that size... try expanding a bit.
- baseSize = (baseSize+desiredWindowWidth)/2;
- if (DEBUG_DIALOG) Log.v(TAG, "Window " + mView + ": next baseSize="
- + baseSize);
- childWidthMeasureSpec = getRootMeasureSpec(baseSize, lp.width);
- host.measure(childWidthMeasureSpec, childHeightMeasureSpec);
- if (DEBUG_DIALOG) Log.v(TAG, "Window " + mView + ": measured ("
- + host.getMeasuredWidth() + "," + host.getMeasuredHeight() + ")");
- if ((host.getMeasuredWidthAndState()&View.MEASURED_STATE_TOO_SMALL) == 0) {
- if (DEBUG_DIALOG) Log.v(TAG, "Good!");
- goodMeasure = true;
- }
- }
- }
- }
-
- if (!goodMeasure) {
- childWidthMeasureSpec = getRootMeasureSpec(desiredWindowWidth, lp.width);
- childHeightMeasureSpec = getRootMeasureSpec(desiredWindowHeight, lp.height);
- host.measure(childWidthMeasureSpec, childHeightMeasureSpec);
- if (mWidth != host.getMeasuredWidth() || mHeight != host.getMeasuredHeight()) {
- windowSizeMayChange = true;
- }
- }
-
- if (DBG) {
- System.out.println("======================================");
- System.out.println("performTraversals -- after measure");
- host.debug();
- }
+ windowSizeMayChange |= measureHierarchy(host, lp, res,
+ desiredWindowWidth, desiredWindowHeight);
}
- if (attachInfo.mRecomputeGlobalAttributes && host.mAttachInfo != null) {
- //Log.i(TAG, "Computing view hierarchy attributes!");
- attachInfo.mRecomputeGlobalAttributes = false;
- boolean oldScreenOn = attachInfo.mKeepScreenOn;
- int oldVis = attachInfo.mSystemUiVisibility;
- boolean oldHasSystemUiListeners = attachInfo.mHasSystemUiListeners;
- attachInfo.mKeepScreenOn = false;
- attachInfo.mSystemUiVisibility = 0;
- attachInfo.mHasSystemUiListeners = false;
- host.dispatchCollectViewAttributes(0);
- if (attachInfo.mKeepScreenOn != oldScreenOn
- || attachInfo.mSystemUiVisibility != oldVis
- || attachInfo.mHasSystemUiListeners != oldHasSystemUiListeners) {
- params = lp;
- }
+ if (collectViewAttributes()) {
+ params = lp;
}
if (attachInfo.mForceReportNewAttributes) {
attachInfo.mForceReportNewAttributes = false;
@@ -1245,7 +1285,28 @@ public final class ViewRootImpl implements ViewParent,
}
}
- boolean windowShouldResize = mLayoutRequested && windowSizeMayChange
+ if (mFitSystemWindowsRequested) {
+ mFitSystemWindowsRequested = false;
+ mFitSystemWindowsInsets.set(mAttachInfo.mContentInsets);
+ host.fitSystemWindows(mFitSystemWindowsInsets);
+ if (mLayoutRequested) {
+ // Short-circuit catching a new layout request here, so
+ // we don't need to go through two layout passes when things
+ // change due to fitting system windows, which can happen a lot.
+ windowSizeMayChange |= measureHierarchy(host, lp,
+ mView.getContext().getResources(),
+ desiredWindowWidth, desiredWindowHeight);
+ }
+ }
+
+ if (layoutRequested) {
+ // Clear this now, so that if anything requests a layout in the
+ // rest of this function we will catch it and re-run a full
+ // layout pass.
+ mLayoutRequested = false;
+ }
+
+ boolean windowShouldResize = layoutRequested && windowSizeMayChange
&& ((mWidth != host.getMeasuredWidth() || mHeight != host.getMeasuredHeight())
|| (lp.width == ViewGroup.LayoutParams.WRAP_CONTENT &&
frame.width() < desiredWindowWidth && frame.width() != mWidth)
@@ -1285,15 +1346,6 @@ public final class ViewRootImpl implements ViewParent,
boolean hadSurface = mSurface.isValid();
try {
- int fl = 0;
- if (params != null) {
- fl = params.flags;
- if (attachInfo.mKeepScreenOn) {
- params.flags |= WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
- }
- params.subtreeSystemUiVisibility = attachInfo.mSystemUiVisibility;
- params.hasSystemUiListeners = attachInfo.mHasSystemUiListeners;
- }
if (DEBUG_LAYOUT) {
Log.i(TAG, "host=w:" + host.getMeasuredWidth() + ", h:" +
host.getMeasuredHeight() + ", params=" + params);
@@ -1302,10 +1354,6 @@ public final class ViewRootImpl implements ViewParent,
final int surfaceGenerationId = mSurface.getGenerationId();
relayoutResult = relayoutWindow(params, viewVisibility, insetsPending);
- if (params != null) {
- params.flags = fl;
- }
-
if (DEBUG_LAYOUT) Log.v(TAG, "relayout: frame=" + frame.toShortString()
+ " content=" + mPendingContentInsets.toShortString()
+ " visible=" + mPendingVisibleInsets.toShortString()
@@ -1323,7 +1371,9 @@ public final class ViewRootImpl implements ViewParent,
visibleInsetsChanged = !mPendingVisibleInsets.equals(
mAttachInfo.mVisibleInsets);
if (contentInsetsChanged) {
- if (mWidth > 0 && mHeight > 0 &&
+ if (mWidth > 0 && mHeight > 0 && lp != null &&
+ ((lp.systemUiVisibility|lp.subtreeSystemUiVisibility)
+ & View.SYSTEM_UI_LAYOUT_FLAGS) == 0 &&
mSurface != null && mSurface.isValid() &&
!mAttachInfo.mTurnOffWindowResizeAnim &&
mAttachInfo.mHardwareRenderer != null &&
@@ -1390,10 +1440,16 @@ public final class ViewRootImpl implements ViewParent,
}
}
mAttachInfo.mContentInsets.set(mPendingContentInsets);
- host.fitSystemWindows(mAttachInfo.mContentInsets);
if (DEBUG_LAYOUT) Log.v(TAG, "Content insets changing to: "
+ mAttachInfo.mContentInsets);
}
+ if (contentInsetsChanged || mLastSystemUiVisibility !=
+ mAttachInfo.mSystemUiVisibility || mFitSystemWindowsRequested) {
+ mLastSystemUiVisibility = mAttachInfo.mSystemUiVisibility;
+ mFitSystemWindowsRequested = false;
+ mFitSystemWindowsInsets.set(mAttachInfo.mContentInsets);
+ host.fitSystemWindows(mFitSystemWindowsInsets);
+ }
if (visibleInsetsChanged) {
mAttachInfo.mVisibleInsets.set(mPendingVisibleInsets);
if (DEBUG_LAYOUT) Log.v(TAG, "Visible insets changing to: "
@@ -1547,8 +1603,8 @@ public final class ViewRootImpl implements ViewParent,
(relayoutResult&WindowManagerImpl.RELAYOUT_RES_IN_TOUCH_MODE) != 0);
if (focusChangedDueToTouchMode || mWidth != host.getMeasuredWidth()
|| mHeight != host.getMeasuredHeight() || contentInsetsChanged) {
- childWidthMeasureSpec = getRootMeasureSpec(mWidth, lp.width);
- childHeightMeasureSpec = getRootMeasureSpec(mHeight, lp.height);
+ int childWidthMeasureSpec = getRootMeasureSpec(mWidth, lp.width);
+ int childHeightMeasureSpec = getRootMeasureSpec(mHeight, lp.height);
if (DEBUG_LAYOUT) Log.v(TAG, "Ooops, something changed! mWidth="
+ mWidth + " measuredWidth=" + host.getMeasuredWidth()
@@ -1586,12 +1642,12 @@ public final class ViewRootImpl implements ViewParent,
host.measure(childWidthMeasureSpec, childHeightMeasureSpec);
}
- mLayoutRequested = true;
+ layoutRequested = true;
}
}
}
- final boolean didLayout = mLayoutRequested && !mStopped;
+ final boolean didLayout = layoutRequested && !mStopped;
boolean triggerGlobalLayoutListener = didLayout
|| attachInfo.mRecomputeGlobalAttributes;
if (didLayout) {
@@ -3579,9 +3635,6 @@ public final class ViewRootImpl implements ViewParent,
if (mView == null) return;
if (args.localChanges != 0) {
if (mAttachInfo != null) {
- mAttachInfo.mSystemUiVisibility =
- (mAttachInfo.mSystemUiVisibility & ~args.localChanges) |
- (args.localValue & args.localChanges);
mAttachInfo.mRecomputeGlobalAttributes = true;
}
mView.updateLocalSystemUiVisibility(args.localValue, args.localChanges);
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index a99ac03..b0e90db 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -75,6 +75,16 @@ public abstract class Window {
* over how the Action Bar is displayed, such as letting application content scroll beneath
* an Action Bar with a transparent background or otherwise displaying a transparent/translucent
* Action Bar over application content.
+ *
+ * <p>This mode is especially useful with {@link View#SYSTEM_UI_FLAG_FULLSCREEN
+ * View.SYSTEM_UI_FLAG_FULLSCREEN}, which allows you to seamlessly hide the
+ * action bar in conjunction with other screen decorations.
+ *
+ * <p>As of {@link android.os.Build.VERSION_CODES#JELLY_BEAN}, when an
+ * ActionBar is in this mode it will adjust the insets provided to
+ * {@link View#fitSystemWindows(android.graphics.Rect) View.fitSystemWindows(Rect)}
+ * to include the content covered by the action bar, so you can do layout within
+ * that space.
*/
public static final int FEATURE_ACTION_BAR_OVERLAY = 9;
/**
diff --git a/core/java/com/android/internal/app/ActionBarImpl.java b/core/java/com/android/internal/app/ActionBarImpl.java
index f3486bd..3115eff 100644
--- a/core/java/com/android/internal/app/ActionBarImpl.java
+++ b/core/java/com/android/internal/app/ActionBarImpl.java
@@ -21,6 +21,7 @@ import com.android.internal.view.menu.MenuPopupHelper;
import com.android.internal.view.menu.SubMenuBuilder;
import com.android.internal.widget.ActionBarContainer;
import com.android.internal.widget.ActionBarContextView;
+import com.android.internal.widget.ActionBarOverlayLayout;
import com.android.internal.widget.ActionBarView;
import com.android.internal.widget.ScrollingTabContainerView;
@@ -47,6 +48,7 @@ import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
+import android.view.ViewGroup;
import android.view.Window;
import android.view.accessibility.AccessibilityEvent;
import android.widget.SpinnerAdapter;
@@ -69,7 +71,9 @@ public class ActionBarImpl extends ActionBar {
private Activity mActivity;
private Dialog mDialog;
+ private ActionBarOverlayLayout mOverlayLayout;
private ActionBarContainer mContainerView;
+ private ViewGroup mTopVisibilityView;
private ActionBarView mActionView;
private ActionBarContextView mContextView;
private ActionBarContainer mSplitView;
@@ -100,6 +104,8 @@ public class ActionBarImpl extends ActionBar {
final Handler mHandler = new Handler();
Runnable mTabSelector;
+ private int mCurWindowVisibility = View.VISIBLE;
+
private Animator mCurrentShowAnim;
private Animator mCurrentModeAnim;
private boolean mShowHideAnimationEnabled;
@@ -110,12 +116,12 @@ public class ActionBarImpl extends ActionBar {
public void onAnimationEnd(Animator animation) {
if (mContentView != null) {
mContentView.setTranslationY(0);
- mContainerView.setTranslationY(0);
+ mTopVisibilityView.setTranslationY(0);
}
if (mSplitView != null && mContextDisplayMode == CONTEXT_DISPLAY_SPLIT) {
mSplitView.setVisibility(View.GONE);
}
- mContainerView.setVisibility(View.GONE);
+ mTopVisibilityView.setVisibility(View.GONE);
mContainerView.setTransitioning(false);
mCurrentShowAnim = null;
completeDeferredDestroyActionMode();
@@ -126,7 +132,7 @@ public class ActionBarImpl extends ActionBar {
@Override
public void onAnimationEnd(Animator animation) {
mCurrentShowAnim = null;
- mContainerView.requestLayout();
+ mTopVisibilityView.requestLayout();
}
};
@@ -147,11 +153,21 @@ public class ActionBarImpl extends ActionBar {
private void init(View decor) {
mContext = decor.getContext();
+ mOverlayLayout = (ActionBarOverlayLayout) decor.findViewById(
+ com.android.internal.R.id.action_bar_overlay_layout);
+ if (mOverlayLayout != null) {
+ mOverlayLayout.setActionBar(this);
+ }
mActionView = (ActionBarView) decor.findViewById(com.android.internal.R.id.action_bar);
mContextView = (ActionBarContextView) decor.findViewById(
com.android.internal.R.id.action_context_bar);
mContainerView = (ActionBarContainer) decor.findViewById(
com.android.internal.R.id.action_bar_container);
+ mTopVisibilityView = (ViewGroup)decor.findViewById(
+ com.android.internal.R.id.top_action_bar);
+ if (mTopVisibilityView == null) {
+ mTopVisibilityView = mContainerView;
+ }
mSplitView = (ActionBarContainer) decor.findViewById(
com.android.internal.R.id.split_action_bar);
@@ -190,11 +206,22 @@ public class ActionBarImpl extends ActionBar {
}
final boolean isInTabMode = getNavigationMode() == NAVIGATION_MODE_TABS;
if (mTabScrollView != null) {
- mTabScrollView.setVisibility(isInTabMode ? View.VISIBLE : View.GONE);
+ if (isInTabMode) {
+ mTabScrollView.setVisibility(View.VISIBLE);
+ if (mOverlayLayout != null) {
+ mOverlayLayout.requestFitSystemWindows();
+ }
+ } else {
+ mTabScrollView.setVisibility(View.GONE);
+ }
}
mActionView.setCollapsable(!mHasEmbeddedTabs && isInTabMode);
}
+ public boolean hasNonEmbeddedTabs() {
+ return !mHasEmbeddedTabs && getNavigationMode() == NAVIGATION_MODE_TABS;
+ }
+
private void ensureTabsExist() {
if (mTabScrollView != null) {
return;
@@ -206,8 +233,14 @@ public class ActionBarImpl extends ActionBar {
tabScroller.setVisibility(View.VISIBLE);
mActionView.setEmbeddedTabView(tabScroller);
} else {
- tabScroller.setVisibility(getNavigationMode() == NAVIGATION_MODE_TABS ?
- View.VISIBLE : View.GONE);
+ if (getNavigationMode() == NAVIGATION_MODE_TABS) {
+ tabScroller.setVisibility(View.VISIBLE);
+ if (mOverlayLayout != null) {
+ mOverlayLayout.requestFitSystemWindows();
+ }
+ } else {
+ tabScroller.setVisibility(View.GONE);
+ }
mContainerView.setTabContainer(tabScroller);
}
mTabScrollView = tabScroller;
@@ -221,6 +254,10 @@ public class ActionBarImpl extends ActionBar {
}
}
+ public void setWindowVisibility(int visibility) {
+ mCurWindowVisibility = visibility;
+ }
+
/**
* Enables or disables animation between show/hide states.
* If animation is disabled using this method, animations in progress
@@ -396,7 +433,12 @@ public class ActionBarImpl extends ActionBar {
animateToMode(true);
if (mSplitView != null && mContextDisplayMode == CONTEXT_DISPLAY_SPLIT) {
// TODO animate this
- mSplitView.setVisibility(View.VISIBLE);
+ if (mSplitView.getVisibility() != View.VISIBLE) {
+ mSplitView.setVisibility(View.VISIBLE);
+ if (mOverlayLayout != null) {
+ mOverlayLayout.requestFitSystemWindows();
+ }
+ }
}
mContextView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
mActionMode = mode;
@@ -530,28 +572,29 @@ public class ActionBarImpl extends ActionBar {
@Override
public void show() {
- show(true);
+ show(true, false);
}
- void show(boolean markHiddenBeforeMode) {
+ public void show(boolean markHiddenBeforeMode, boolean alwaysAnimate) {
if (mCurrentShowAnim != null) {
mCurrentShowAnim.end();
}
- if (mContainerView.getVisibility() == View.VISIBLE) {
+ if (mTopVisibilityView.getVisibility() == View.VISIBLE) {
if (markHiddenBeforeMode) mWasHiddenBeforeMode = false;
return;
}
- mContainerView.setVisibility(View.VISIBLE);
+ mTopVisibilityView.setVisibility(View.VISIBLE);
- if (mShowHideAnimationEnabled) {
- mContainerView.setAlpha(0);
+ if (mCurWindowVisibility == View.VISIBLE && (mShowHideAnimationEnabled
+ || alwaysAnimate)) {
+ mTopVisibilityView.setAlpha(0);
AnimatorSet anim = new AnimatorSet();
- AnimatorSet.Builder b = anim.play(ObjectAnimator.ofFloat(mContainerView, "alpha", 1));
+ AnimatorSet.Builder b = anim.play(ObjectAnimator.ofFloat(mTopVisibilityView, "alpha", 1));
if (mContentView != null) {
b.with(ObjectAnimator.ofFloat(mContentView, "translationY",
- -mContainerView.getHeight(), 0));
- mContainerView.setTranslationY(-mContainerView.getHeight());
- b.with(ObjectAnimator.ofFloat(mContainerView, "translationY", 0));
+ -mTopVisibilityView.getHeight(), 0));
+ mTopVisibilityView.setTranslationY(-mTopVisibilityView.getHeight());
+ b.with(ObjectAnimator.ofFloat(mTopVisibilityView, "translationY", 0));
}
if (mSplitView != null && mContextDisplayMode == CONTEXT_DISPLAY_SPLIT) {
mSplitView.setAlpha(0);
@@ -562,7 +605,7 @@ public class ActionBarImpl extends ActionBar {
mCurrentShowAnim = anim;
anim.start();
} else {
- mContainerView.setAlpha(1);
+ mTopVisibilityView.setAlpha(1);
mContainerView.setTranslationY(0);
mShowListener.onAnimationEnd(null);
}
@@ -570,23 +613,28 @@ public class ActionBarImpl extends ActionBar {
@Override
public void hide() {
+ hide(false);
+ }
+
+ public void hide(boolean alwaysAnimate) {
if (mCurrentShowAnim != null) {
mCurrentShowAnim.end();
}
- if (mContainerView.getVisibility() == View.GONE) {
+ if (mTopVisibilityView.getVisibility() == View.GONE) {
return;
}
- if (mShowHideAnimationEnabled) {
- mContainerView.setAlpha(1);
+ if (mCurWindowVisibility == View.VISIBLE && (mShowHideAnimationEnabled
+ || alwaysAnimate)) {
+ mTopVisibilityView.setAlpha(1);
mContainerView.setTransitioning(true);
AnimatorSet anim = new AnimatorSet();
- AnimatorSet.Builder b = anim.play(ObjectAnimator.ofFloat(mContainerView, "alpha", 0));
+ AnimatorSet.Builder b = anim.play(ObjectAnimator.ofFloat(mTopVisibilityView, "alpha", 0));
if (mContentView != null) {
b.with(ObjectAnimator.ofFloat(mContentView, "translationY",
- 0, -mContainerView.getHeight()));
- b.with(ObjectAnimator.ofFloat(mContainerView, "translationY",
- -mContainerView.getHeight()));
+ 0, -mTopVisibilityView.getHeight()));
+ b.with(ObjectAnimator.ofFloat(mTopVisibilityView, "translationY",
+ -mTopVisibilityView.getHeight()));
}
if (mSplitView != null && mSplitView.getVisibility() == View.VISIBLE) {
mSplitView.setAlpha(1);
@@ -601,12 +649,12 @@ public class ActionBarImpl extends ActionBar {
}
public boolean isShowing() {
- return mContainerView.getVisibility() == View.VISIBLE;
+ return mTopVisibilityView.getVisibility() == View.VISIBLE;
}
void animateToMode(boolean toActionMode) {
if (toActionMode) {
- show(false);
+ show(false, false);
}
if (mCurrentModeAnim != null) {
mCurrentModeAnim.end();
@@ -980,6 +1028,11 @@ public class ActionBarImpl extends ActionBar {
mTabScrollView.setVisibility(View.GONE);
break;
}
+ if (oldMode != mode && !mHasEmbeddedTabs) {
+ if (mOverlayLayout != null) {
+ mOverlayLayout.requestFitSystemWindows();
+ }
+ }
mActionView.setNavigationMode(mode);
switch (mode) {
case NAVIGATION_MODE_TABS:
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index 6e36fdb..294d4c4 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -30,7 +30,7 @@ oneway interface IStatusBar
void disable(int state);
void animateExpand();
void animateCollapse();
- void setSystemUiVisibility(int vis);
+ void setSystemUiVisibility(int vis, int mask);
void topAppWindowChanged(boolean menuVisible);
void setImeWindowStatus(in IBinder token, int vis, int backDisposition);
void setHardKeyboardStatus(boolean available, boolean enabled);
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index 118e541..c64f170 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -44,7 +44,7 @@ interface IStatusBarService
int uid, int initialPid, String message);
void onClearAllNotifications();
void onNotificationClear(String pkg, String tag, int id);
- void setSystemUiVisibility(int vis);
+ void setSystemUiVisibility(int vis, int mask);
void setHardKeyboardEnabled(boolean enabled);
void toggleRecentApps();
void preloadRecentApps();
diff --git a/core/java/com/android/internal/widget/ActionBarOverlayLayout.java b/core/java/com/android/internal/widget/ActionBarOverlayLayout.java
new file mode 100644
index 0000000..5f36bb6
--- /dev/null
+++ b/core/java/com/android/internal/widget/ActionBarOverlayLayout.java
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 2012 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 com.android.internal.widget;
+
+import com.android.internal.app.ActionBarImpl;
+
+import android.animation.LayoutTransition;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Rect;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewTreeObserver;
+import android.widget.FrameLayout;
+
+/**
+ * Special layout for the containing of an overlay action bar (and its
+ * content) to correctly handle fitting system windows when the content
+ * has request that its layout ignore them.
+ */
+public class ActionBarOverlayLayout extends FrameLayout {
+ private int mActionBarHeight;
+ private ActionBarImpl mActionBar;
+ private int mWindowVisibility = View.VISIBLE;
+ private View mContent;
+ private View mActionBarTop;
+ private ActionBarContainer mContainerView;
+ private ActionBarView mActionView;
+ private View mActionBarBottom;
+ private int mLastSystemUiVisibility;
+ private final Rect mZeroRect = new Rect(0, 0, 0, 0);
+
+ static final int[] mActionBarSizeAttr = new int [] {
+ com.android.internal.R.attr.actionBarSize
+ };
+
+ public ActionBarOverlayLayout(Context context) {
+ super(context);
+ init(context);
+ }
+
+ public ActionBarOverlayLayout(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init(context);
+ }
+
+ private void init(Context context) {
+ TypedArray ta = getContext().getTheme().obtainStyledAttributes(mActionBarSizeAttr);
+ mActionBarHeight = ta.getDimensionPixelSize(0, 0);
+ ta.recycle();
+ }
+
+ public void setActionBar(ActionBarImpl impl) {
+ mActionBar = impl;
+ if (getWindowToken() != null) {
+ // This is being initialized after being added to a window;
+ // make sure to update all state now.
+ mActionBar.setWindowVisibility(mWindowVisibility);
+ if (mLastSystemUiVisibility != 0) {
+ int newVis = mLastSystemUiVisibility;
+ onWindowSystemUiVisibilityChanged(newVis);
+ requestFitSystemWindows();
+ }
+ }
+ }
+
+ @Override
+ public void onWindowSystemUiVisibilityChanged(int visible) {
+ super.onWindowSystemUiVisibilityChanged(visible);
+ pullChildren();
+ final int diff = mLastSystemUiVisibility ^ visible;
+ mLastSystemUiVisibility = visible;
+ final boolean barVisible = (visible&SYSTEM_UI_FLAG_FULLSCREEN) == 0;
+ final boolean wasVisible = mActionBar != null ? mActionBar.isShowing() : true;
+ if (barVisible != wasVisible || (diff&SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) {
+ if (mActionBar != null) {
+ if (barVisible) mActionBar.show(true, true);
+ else mActionBar.hide(true);
+ requestFitSystemWindows();
+ }
+ }
+ }
+
+ @Override
+ protected void onWindowVisibilityChanged(int visibility) {
+ super.onWindowVisibilityChanged(visibility);
+ mWindowVisibility = visibility;
+ if (mActionBar != null) {
+ mActionBar.setWindowVisibility(visibility);
+ }
+ }
+
+ private boolean applyInsets(View view, Rect insets, boolean left, boolean top,
+ boolean bottom, boolean right) {
+ boolean changed = false;
+ FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams)view.getLayoutParams();
+ if (left && lp.leftMargin != insets.left) {
+ changed = true;
+ lp.leftMargin = insets.left;
+ }
+ if (top && lp.topMargin != insets.top) {
+ changed = true;
+ lp.topMargin = insets.top;
+ }
+ if (right && lp.rightMargin != insets.right) {
+ changed = true;
+ lp.rightMargin = insets.right;
+ }
+ if (bottom && lp.bottomMargin != insets.bottom) {
+ changed = true;
+ lp.bottomMargin = insets.bottom;
+ }
+ return changed;
+ }
+
+ @Override
+ protected boolean fitSystemWindows(Rect insets) {
+ pullChildren();
+
+ final int vis = getWindowSystemUiVisibility();
+ final boolean stable = (vis & SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0;
+
+ // The top and bottom action bars are always within the content area.
+ boolean changed = applyInsets(mActionBarTop, insets, true, true, false, true);
+ changed |= applyInsets(mActionBarBottom, insets, true, false, true, true);
+
+ // If the window has not requested system UI layout flags, we need to
+ // make sure its content is not being covered by system UI... though it
+ // will still be covered by the action bar since they have requested it to
+ // overlay.
+ if ((vis & SYSTEM_UI_LAYOUT_FLAGS) == 0) {
+ changed |= applyInsets(mContent, insets, true, true, true, true);
+ // The insets are now consumed.
+ insets.set(0, 0, 0, 0);
+ } else {
+ changed |= applyInsets(mContent, mZeroRect, true, true, true, true);
+ }
+
+
+ if (stable || mActionBarTop.getVisibility() == VISIBLE) {
+ // The action bar creates additional insets for its content to use.
+ insets.top += mActionBarHeight;
+ }
+
+ if (mActionBar != null && mActionBar.hasNonEmbeddedTabs()) {
+ View tabs = mContainerView.getTabContainer();
+ if (stable || (tabs != null && tabs.getVisibility() == VISIBLE)) {
+ // If tabs are not embedded, adjust insets to account for them.
+ insets.top += mActionBarHeight;
+ }
+ }
+
+ if (mActionView.isSplitActionBar()) {
+ if (stable || (mActionBarBottom != null
+ && mActionBarBottom.getVisibility() == VISIBLE)) {
+ // If action bar is split, adjust buttom insets for it.
+ insets.bottom += mActionBarHeight;
+ }
+ }
+
+ if (changed) {
+ requestLayout();
+ }
+
+ return super.fitSystemWindows(insets);
+ }
+
+ void pullChildren() {
+ if (mContent == null) {
+ mContent = findViewById(com.android.internal.R.id.content);
+ mActionBarTop = findViewById(com.android.internal.R.id.top_action_bar);
+ mContainerView = (ActionBarContainer)findViewById(
+ com.android.internal.R.id.action_bar_container);
+ mActionView = (ActionBarView) findViewById(com.android.internal.R.id.action_bar);
+ mActionBarBottom = findViewById(com.android.internal.R.id.split_action_bar);
+ }
+ }
+}
diff --git a/core/res/res/layout-xlarge/screen_action_bar_overlay.xml b/core/res/res/layout-xlarge/screen_action_bar_overlay.xml
index 89f0d89..f2a1ea1 100644
--- a/core/res/res/layout-xlarge/screen_action_bar_overlay.xml
+++ b/core/res/res/layout-xlarge/screen_action_bar_overlay.xml
@@ -19,31 +19,39 @@ This is an optimized layout for a screen with
the Action Bar enabled overlaying application content.
-->
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:fitsSystemWindows="true">
+<com.android.internal.widget.ActionBarOverlayLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/action_bar_overlay_layout"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
<FrameLayout android:id="@android:id/content"
android:layout_width="match_parent"
android:layout_height="match_parent" />
- <com.android.internal.widget.ActionBarContainer android:id="@+id/action_bar_container"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- style="?android:attr/actionBarStyle"
- android:gravity="top">
- <com.android.internal.widget.ActionBarView
- android:id="@+id/action_bar"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- style="?android:attr/actionBarStyle" />
- <com.android.internal.widget.ActionBarContextView
- android:id="@+id/action_context_bar"
+ <LinearLayout android:id="@+id/top_action_bar"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="top">
+ <com.android.internal.widget.ActionBarContainer android:id="@+id/action_bar_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:visibility="gone"
- style="?android:attr/actionModeStyle" />
- </com.android.internal.widget.ActionBarContainer>
- <ImageView android:src="?android:attr/windowContentOverlay"
- android:scaleType="fitXY"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_below="@id/action_bar_container" />
-</RelativeLayout>
+ android:layout_alignParentTop="true"
+ style="?android:attr/actionBarStyle"
+ android:gravity="top">
+ <com.android.internal.widget.ActionBarView
+ android:id="@+id/action_bar"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ style="?android:attr/actionBarStyle" />
+ <com.android.internal.widget.ActionBarContextView
+ android:id="@+id/action_context_bar"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:visibility="gone"
+ style="?android:attr/actionModeStyle" />
+ </com.android.internal.widget.ActionBarContainer>
+ <ImageView android:src="?android:attr/windowContentOverlay"
+ android:scaleType="fitXY"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
+ </LinearLayout>
+</com.android.internal.widget.ActionBarOverlayLayout>
diff --git a/core/res/res/layout/screen_action_bar_overlay.xml b/core/res/res/layout/screen_action_bar_overlay.xml
index 2a8c7c3..20a7db1 100644
--- a/core/res/res/layout/screen_action_bar_overlay.xml
+++ b/core/res/res/layout/screen_action_bar_overlay.xml
@@ -19,14 +19,16 @@ This is an optimized layout for a screen with
the Action Bar enabled overlaying application content.
-->
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<com.android.internal.widget.ActionBarOverlayLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/action_bar_overlay_layout"
android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:fitsSystemWindows="true">
+ android:layout_height="match_parent">
<FrameLayout android:id="@android:id/content"
android:layout_width="match_parent"
android:layout_height="match_parent" />
- <LinearLayout android:layout_width="match_parent"
+ <LinearLayout android:id="@+id/top_action_bar"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top">
<com.android.internal.widget.ActionBarContainer android:id="@+id/action_bar_container"
@@ -50,8 +52,7 @@ the Action Bar enabled overlaying application content.
<ImageView android:src="?android:attr/windowContentOverlay"
android:scaleType="fitXY"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_below="@id/action_bar_container" />
+ android:layout_height="wrap_content" />
</LinearLayout>
<com.android.internal.widget.ActionBarContainer android:id="@+id/split_action_bar"
android:layout_width="match_parent"
@@ -60,4 +61,4 @@ the Action Bar enabled overlaying application content.
style="?android:attr/actionBarSplitStyle"
android:visibility="gone"
android:gravity="center"/>
-</FrameLayout>
+</com.android.internal.widget.ActionBarOverlayLayout>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 7b4f50b..5af4f72 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -34,6 +34,7 @@
<java-symbol type="id" name="account_type" />
<java-symbol type="id" name="action_bar" />
<java-symbol type="id" name="action_bar_container" />
+ <java-symbol type="id" name="action_bar_overlay_layout" />
<java-symbol type="id" name="action_bar_title" />
<java-symbol type="id" name="action_bar_subtitle" />
<java-symbol type="id" name="action_context_bar" />
@@ -183,6 +184,7 @@
<java-symbol type="id" name="to_common" />
<java-symbol type="id" name="to_org" />
<java-symbol type="id" name="to_org_unit" />
+ <java-symbol type="id" name="top_action_bar" />
<java-symbol type="id" name="topPanel" />
<java-symbol type="id" name="up" />
<java-symbol type="id" name="value" />
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 23222f2..2fb61b9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -119,7 +119,7 @@ public abstract class BaseStatusBar extends SystemUI implements
createAndAddWindows();
disable(switches[0]);
- setSystemUiVisibility(switches[1]);
+ setSystemUiVisibility(switches[1], 0xffffffff);
topAppWindowChanged(switches[2] != 0);
// StatusBarManagerService has a back up of IME token and it's restored here.
setImeWindowStatus(binders.get(0), switches[3], switches[4]);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 37ab58a..f88a3cc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -89,7 +89,7 @@ public class CommandQueue extends IStatusBar.Stub {
public void disable(int state);
public void animateExpand();
public void animateCollapse();
- public void setSystemUiVisibility(int vis);
+ public void setSystemUiVisibility(int vis, int mask);
public void topAppWindowChanged(boolean visible);
public void setImeWindowStatus(IBinder token, int vis, int backDisposition);
public void setHardKeyboardStatus(boolean available, boolean enabled);
@@ -165,10 +165,10 @@ public class CommandQueue extends IStatusBar.Stub {
}
}
- public void setSystemUiVisibility(int vis) {
+ public void setSystemUiVisibility(int vis, int mask) {
synchronized (mList) {
mHandler.removeMessages(MSG_SET_SYSTEMUI_VISIBILITY);
- mHandler.obtainMessage(MSG_SET_SYSTEMUI_VISIBILITY, vis, 0, null).sendToTarget();
+ mHandler.obtainMessage(MSG_SET_SYSTEMUI_VISIBILITY, vis, mask, null).sendToTarget();
}
}
@@ -279,7 +279,7 @@ public class CommandQueue extends IStatusBar.Stub {
}
break;
case MSG_SET_SYSTEMUI_VISIBILITY:
- mCallbacks.setSystemUiVisibility(msg.arg1);
+ mCallbacks.setSystemUiVisibility(msg.arg1, msg.arg2);
break;
case MSG_TOP_APP_WINDOW_CHANGED:
mCallbacks.topAppWindowChanged(msg.arg1 != 0);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 6574c7d..5582b0f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -139,7 +139,7 @@ public class NavigationBarView extends LinearLayout {
setLowProfile(false, false, false);
try {
- mBarService.setSystemUiVisibility(0);
+ mBarService.setSystemUiVisibility(0, View.SYSTEM_UI_FLAG_LOW_PROFILE);
} catch (android.os.RemoteException ex) {
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 7c679b2..dc2953e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -1471,12 +1471,13 @@ public class PhoneStatusBar extends BaseStatusBar {
}
@Override // CommandQueue
- public void setSystemUiVisibility(int vis) {
- final int old = mSystemUiVisibility;
- final int diff = vis ^ old;
+ public void setSystemUiVisibility(int vis, int mask) {
+ final int oldVal = mSystemUiVisibility;
+ final int newVal = (oldVal&~mask) | (vis&mask);
+ final int diff = newVal ^ oldVal;
if (diff != 0) {
- mSystemUiVisibility = vis;
+ mSystemUiVisibility = newVal;
if (0 != (diff & View.SYSTEM_UI_FLAG_LOW_PROFILE)) {
final boolean lightsOut = (0 != (vis & View.SYSTEM_UI_FLAG_LOW_PROFILE));
@@ -1495,9 +1496,9 @@ public class PhoneStatusBar extends BaseStatusBar {
public void setLightsOn(boolean on) {
Log.v(TAG, "setLightsOn(" + on + ")");
if (on) {
- setSystemUiVisibility(mSystemUiVisibility & ~View.SYSTEM_UI_FLAG_LOW_PROFILE);
+ setSystemUiVisibility(0, View.SYSTEM_UI_FLAG_LOW_PROFILE);
} else {
- setSystemUiVisibility(mSystemUiVisibility | View.SYSTEM_UI_FLAG_LOW_PROFILE);
+ setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE, View.SYSTEM_UI_FLAG_LOW_PROFILE);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
index 2491d18..27bc972 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
@@ -594,7 +594,7 @@ public class TabletStatusBar extends BaseStatusBar implements
mBarContents.setVisibility(View.VISIBLE);
try {
- mBarService.setSystemUiVisibility(View.STATUS_BAR_VISIBLE);
+ mBarService.setSystemUiVisibility(0, View.SYSTEM_UI_FLAG_LOW_PROFILE);
} catch (RemoteException ex) {
// system process dead
}
@@ -1165,14 +1165,20 @@ public class TabletStatusBar extends BaseStatusBar implements
}
@Override // CommandQueue
- public void setSystemUiVisibility(int vis) {
- if (vis != mSystemUiVisibility) {
- mSystemUiVisibility = vis;
-
- mHandler.removeMessages(MSG_HIDE_CHROME);
- mHandler.removeMessages(MSG_SHOW_CHROME);
- mHandler.sendEmptyMessage(0 == (vis & View.SYSTEM_UI_FLAG_LOW_PROFILE)
- ? MSG_SHOW_CHROME : MSG_HIDE_CHROME);
+ public void setSystemUiVisibility(int vis, int mask) {
+ final int oldVal = mSystemUiVisibility;
+ final int newVal = (oldVal&~mask) | (vis&mask);
+ final int diff = newVal ^ oldVal;
+
+ if (diff != 0) {
+ mSystemUiVisibility = newVal;
+
+ if (0 != (diff & View.SYSTEM_UI_FLAG_LOW_PROFILE)) {
+ mHandler.removeMessages(MSG_HIDE_CHROME);
+ mHandler.removeMessages(MSG_SHOW_CHROME);
+ mHandler.sendEmptyMessage(0 == (vis & View.SYSTEM_UI_FLAG_LOW_PROFILE)
+ ? MSG_SHOW_CHROME : MSG_HIDE_CHROME);
+ }
notifyUiVisibilityChanged();
}
@@ -1187,9 +1193,9 @@ public class TabletStatusBar extends BaseStatusBar implements
Slog.v(TAG, "setLightsOn(" + on + ")");
if (on) {
- setSystemUiVisibility(mSystemUiVisibility & ~View.SYSTEM_UI_FLAG_LOW_PROFILE);
+ setSystemUiVisibility(0, View.SYSTEM_UI_FLAG_LOW_PROFILE);
} else {
- setSystemUiVisibility(mSystemUiVisibility | View.SYSTEM_UI_FLAG_LOW_PROFILE);
+ setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE, View.SYSTEM_UI_FLAG_LOW_PROFILE);
}
}
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index 301dbf5..c3c49b0 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -2829,6 +2829,9 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
if (mContentParent == null) {
mContentParent = generateLayout(mDecor);
+ // Set up decor part of UI to ignore fitsSystemWindows if appropriate.
+ mDecor.makeOptionalFitsSystemWindows();
+
mTitleView = (TextView)findViewById(com.android.internal.R.id.title);
if (mTitleView != null) {
if ((getLocalFeatures() & (1 << FEATURE_NO_TITLE)) != 0) {
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 6214086..fb1e106 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -230,6 +230,13 @@ public class PhoneWindowManager implements WindowManagerPolicy {
static public final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";
static public final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey";
+ /**
+ * These are the system UI flags that, when changing, can cause the layout
+ * of the screen to change.
+ */
+ static final int SYSTEM_UI_CHANGING_LAYOUT =
+ View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN;
+
// Useful scan codes.
private static final int SW_LID = 0x00;
private static final int BTN_MOUSE = 0x110;
@@ -391,6 +398,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// that area of the display from all other windows.
int mRestrictedScreenLeft, mRestrictedScreenTop;
int mRestrictedScreenWidth, mRestrictedScreenHeight;
+ // For applications requesting stable content insets, these are them.
+ int mStableLeft, mStableTop, mStableRight, mStableBottom;
// During layout, the current screen borders with all outer decoration
// (status bar, input method dock) accounted for.
int mCurLeft, mCurTop, mCurRight, mCurBottom;
@@ -1958,10 +1967,15 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// When the user taps down, we re-show the nav bar.
boolean changed = false;
synchronized (mLock) {
- // Any user activity always causes us to show the navigation controls,
- // if they had been hidden.
- int newVal = mResettingSystemUiFlags
- | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
+ // Any user activity always causes us to show the
+ // navigation controls, if they had been hidden.
+ // We also clear the low profile and only content
+ // flags so that tapping on the screen will atomically
+ // restore all currently hidden screen decorations.
+ int newVal = mResettingSystemUiFlags |
+ View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
+ View.SYSTEM_UI_FLAG_LOW_PROFILE |
+ View.SYSTEM_UI_FLAG_FULLSCREEN;
if (mResettingSystemUiFlags != newVal) {
mResettingSystemUiFlags = newVal;
changed = true;
@@ -1969,14 +1983,15 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// We don't allow the system's nav bar to be hidden
// again for 1 second, to prevent applications from
// spamming us and keeping it from being shown.
- newVal = mForceClearedSystemUiFlags
- | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
+ newVal = mForceClearedSystemUiFlags |
+ View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
if (mForceClearedSystemUiFlags != newVal) {
mForceClearedSystemUiFlags = newVal;
changed = true;
mHandler.postDelayed(new Runnable() {
@Override public void run() {
synchronized (mLock) {
+ // Clear flags.
mForceClearedSystemUiFlags &=
~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
}
@@ -2017,17 +2032,33 @@ public class PhoneWindowManager implements WindowManagerPolicy {
public void getContentInsetHintLw(WindowManager.LayoutParams attrs, Rect contentInset) {
final int fl = attrs.flags;
-
+
if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_FULLSCREEN | FLAG_LAYOUT_INSET_DECOR))
== (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) {
- contentInset.set(mCurLeft, mCurTop,
- (mRestrictedScreenLeft+mRestrictedScreenWidth) - mCurRight,
- (mRestrictedScreenTop+mRestrictedScreenHeight) - mCurBottom);
- } else {
- contentInset.setEmpty();
+ int availRight, availBottom;
+ if ((attrs.systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0) {
+ availRight = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
+ availBottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
+ } else {
+ availRight = mRestrictedScreenLeft + mRestrictedScreenWidth;
+ availBottom = mRestrictedScreenTop + mRestrictedScreenHeight;
+ }
+ if ((attrs.systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) {
+ contentInset.set(mStableLeft, mStableTop,
+ availRight - mStableRight, availBottom - mStableBottom);
+ } else if ((attrs.systemUiVisibility & (View.SYSTEM_UI_FLAG_FULLSCREEN
+ | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)) == 0) {
+ contentInset.set(mCurLeft, mCurTop,
+ availRight - mCurRight, availBottom - mCurBottom);
+ } else {
+ contentInset.set(mCurLeft, mCurTop,
+ availRight - mCurRight, availBottom - mCurBottom);
+ }
+ return;
}
+ contentInset.setEmpty();
}
-
+
/** {@inheritDoc} */
public void beginLayoutLw(int displayWidth, int displayHeight, int displayRotation) {
mUnrestrictedScreenLeft = mUnrestrictedScreenTop = 0;
@@ -2036,10 +2067,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mRestrictedScreenLeft = mRestrictedScreenTop = 0;
mRestrictedScreenWidth = displayWidth;
mRestrictedScreenHeight = displayHeight;
- mDockLeft = mContentLeft = mCurLeft = 0;
- mDockTop = mContentTop = mCurTop = 0;
- mDockRight = mContentRight = mCurRight = displayWidth;
- mDockBottom = mContentBottom = mCurBottom = displayHeight;
+ mDockLeft = mContentLeft = mStableLeft = mCurLeft = 0;
+ mDockTop = mContentTop = mStableTop = mCurTop = 0;
+ mDockRight = mContentRight = mStableRight = mCurRight = displayWidth;
+ mDockBottom = mContentBottom = mStableBottom = mCurBottom = displayHeight;
mDockLayer = 0x10000000;
// start with the current dock rect, which will be (0,0,displayWidth,displayHeight)
@@ -2081,6 +2112,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// Portrait screen; nav bar goes on bottom.
mTmpNavigationFrame.set(0, displayHeight-mNavigationBarHeight,
displayWidth, displayHeight);
+ mStableBottom = mTmpNavigationFrame.top;
if (navVisible) {
mDockBottom = mTmpNavigationFrame.top;
mRestrictedScreenHeight = mDockBottom - mDockTop;
@@ -2094,6 +2126,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// Landscape screen; nav bar goes to the right.
mTmpNavigationFrame.set(displayWidth-mNavigationBarWidth, 0,
displayWidth, displayHeight);
+ mStableRight = mTmpNavigationFrame.left;
if (navVisible) {
mDockRight = mTmpNavigationFrame.left;
mRestrictedScreenWidth = mDockRight - mDockLeft;
@@ -2125,11 +2158,23 @@ public class PhoneWindowManager implements WindowManagerPolicy {
pf.bottom = df.bottom = vf.bottom = mDockBottom;
mStatusBar.computeFrameLw(pf, df, vf, vf);
+ final Rect r = mStatusBar.getFrameLw();
+
+ // Compute the stable dimensions whether or not the status bar is hidden.
+ if (mStatusBarCanHide) {
+ if (mDockTop == r.top) mStableTop = r.bottom;
+ else if (mDockBottom == r.bottom) mStableBottom = r.top;
+ } else {
+ if (mStableTop == r.top) {
+ mStableTop = r.bottom;
+ } else if (mStableBottom == r.bottom) {
+ mStableBottom = r.top;
+ }
+ }
if (mStatusBar.isVisibleLw()) {
// If the status bar is hidden, we don't want to cause
// windows behind it to scroll.
- final Rect r = mStatusBar.getFrameLw();
if (mStatusBarCanHide) {
// Status bar may go away, so the screen area it occupies
// is available to apps but just covering them when the
@@ -2229,7 +2274,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
final int fl = attrs.flags;
final int sim = attrs.softInputMode;
-
+ final int sysUiFl = win.getSystemUiVisibility();
+
final Rect pf = mTmpParentFrame;
final Rect df = mTmpDisplayFrame;
final Rect cf = mTmpContentFrame;
@@ -2250,7 +2296,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
final int adjust = sim & SOFT_INPUT_MASK_ADJUST;
if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_FULLSCREEN | FLAG_LAYOUT_INSET_DECOR))
- == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) {
+ == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)
+ && (sysUiFl & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) {
if (DEBUG_LAYOUT)
Log.v(TAG, "layoutWindowLw(" + attrs.getTitle()
+ "): IN_SCREEN, INSET_DECOR, !FULLSCREEN");
@@ -2286,6 +2333,17 @@ public class PhoneWindowManager implements WindowManagerPolicy {
"Laying out status bar window: (%d,%d - %d,%d)",
pf.left, pf.top, pf.right, pf.bottom));
}
+ } else if ((sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
+ && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
+ && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
+ // Asking for layout as if the nav bar is hidden, lets the
+ // application extend into the unrestricted screen area. We
+ // only do this for application windows to ensure no window that
+ // can be above the nav bar can do this.
+ pf.left = df.left = mUnrestrictedScreenLeft;
+ pf.top = df.top = mUnrestrictedScreenTop;
+ pf.right = df.right = mUnrestrictedScreenLeft+mUnrestrictedScreenWidth;
+ pf.bottom = df.bottom = mUnrestrictedScreenTop+mUnrestrictedScreenHeight;
} else {
pf.left = df.left = mRestrictedScreenLeft;
pf.top = df.top = mRestrictedScreenTop;
@@ -2303,6 +2361,14 @@ public class PhoneWindowManager implements WindowManagerPolicy {
cf.right = mContentRight;
cf.bottom = mContentBottom;
}
+ if ((sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) {
+ // If app is requesting a stable layout, don't let the
+ // content insets go below the stable values.
+ if (cf.left < mStableLeft) cf.left = mStableLeft;
+ if (cf.top < mStableTop) cf.top = mStableTop;
+ if (cf.right > mStableRight) cf.right = mStableRight;
+ if (cf.bottom > mStableBottom) cf.bottom = mStableBottom;
+ }
if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
vf.left = mCurLeft;
vf.top = mCurTop;
@@ -2312,7 +2378,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
vf.set(cf);
}
}
- } else if ((fl & FLAG_LAYOUT_IN_SCREEN) != 0) {
+ } else if ((fl & FLAG_LAYOUT_IN_SCREEN) != 0 || (sysUiFl
+ & (View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
+ | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION)) != 0) {
if (DEBUG_LAYOUT)
Log.v(TAG, "layoutWindowLw(" + attrs.getTitle() + "): IN_SCREEN");
// A window that has requested to fill the entire screen just
@@ -2327,7 +2395,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
pf.bottom = df.bottom = cf.bottom = hasNavBar
? mRestrictedScreenTop+mRestrictedScreenHeight
: mUnrestrictedScreenTop+mUnrestrictedScreenHeight;
-
if (DEBUG_LAYOUT) {
Log.v(TAG, String.format(
"Laying out IN_SCREEN status bar window: (%d,%d - %d,%d)",
@@ -2359,6 +2426,21 @@ public class PhoneWindowManager implements WindowManagerPolicy {
pf.right = df.right = cf.right = mUnrestrictedScreenLeft+mUnrestrictedScreenWidth;
pf.bottom = df.bottom = cf.bottom
= mUnrestrictedScreenTop+mUnrestrictedScreenHeight;
+ } else if ((sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
+ && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
+ && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
+ // Asking for layout as if the nav bar is hidden, lets the
+ // application extend into the unrestricted screen area. We
+ // only do this for application windows to ensure no window that
+ // can be above the nav bar can do this.
+ // XXX This assumes that an app asking for this will also
+ // ask for layout in only content. We can't currently figure out
+ // what the screen would be if only laying out to hide the nav bar.
+ pf.left = df.left = cf.left = mUnrestrictedScreenLeft;
+ pf.top = df.top = cf.top = mUnrestrictedScreenTop;
+ pf.right = df.right = cf.right = mUnrestrictedScreenLeft+mUnrestrictedScreenWidth;
+ pf.bottom = df.bottom = cf.bottom
+ = mUnrestrictedScreenTop+mUnrestrictedScreenHeight;
} else {
pf.left = df.left = cf.left = mRestrictedScreenLeft;
pf.top = df.top = cf.top = mRestrictedScreenTop;
@@ -2366,6 +2448,14 @@ public class PhoneWindowManager implements WindowManagerPolicy {
pf.bottom = df.bottom = cf.bottom
= mRestrictedScreenTop+mRestrictedScreenHeight;
}
+ if ((sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) {
+ // If app is requesting a stable layout, don't let the
+ // content insets go below the stable values.
+ if (cf.left < mStableLeft) cf.left = mStableLeft;
+ if (cf.top < mStableTop) cf.top = mStableTop;
+ if (cf.right > mStableRight) cf.right = mStableRight;
+ if (cf.bottom > mStableBottom) cf.bottom = mStableBottom;
+ }
if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
vf.left = mCurLeft;
vf.top = mCurTop;
@@ -2526,7 +2616,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
Log.d(TAG, "attr: " + mTopFullscreenOpaqueWindowState.getAttrs()
+ " lp.flags=0x" + Integer.toHexString(lp.flags));
}
- topIsFullscreen = (lp.flags & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0;
+ topIsFullscreen = (lp.flags & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0
+ || (mLastSystemUiFlags & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;
// The subtle difference between the window for mTopFullscreenOpaqueWindowState
// and mTopIsFullscreen is that that mTopIsFullscreen is set only if the window
// has the FLAG_FULLSCREEN set. Not sure if there is another way that to be the
@@ -2591,7 +2682,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
}
- if ((updateSystemUiVisibilityLw()&View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0) {
+ if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) {
// If the navigation bar has been hidden or shown, we need to do another
// layout pass to update that window.
changes |= FINISH_LAYOUT_REDO_LAYOUT;
@@ -2638,7 +2729,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
public int focusChangedLw(WindowState lastFocus, WindowState newFocus) {
mFocusedWindow = newFocus;
- if ((updateSystemUiVisibilityLw()&View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0) {
+ if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) {
// If the navigation bar has been hidden or shown, we need to do another
// layout pass to update that window.
return FINISH_LAYOUT_REDO_LAYOUT;
@@ -3998,7 +4089,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
if (mStatusBarService != null) {
try {
- mStatusBarService.setSystemUiVisibility(visibility);
+ mStatusBarService.setSystemUiVisibility(visibility, 0xffffffff);
mStatusBarService.topAppWindowChanged(needsMenu);
} catch (RemoteException e) {
// not much to be done
@@ -4065,6 +4156,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
pw.print(","); pw.print(mRestrictedScreenTop);
pw.print(") "); pw.print(mRestrictedScreenWidth);
pw.print("x"); pw.println(mRestrictedScreenHeight);
+ pw.print(prefix); pw.print("mStable=("); pw.print(mStableLeft);
+ pw.print(","); pw.print(mStableTop);
+ pw.print(")-("); pw.print(mStableRight);
+ pw.print(","); pw.print(mStableBottom); pw.println(")");
pw.print(prefix); pw.print("mCur=("); pw.print(mCurLeft);
pw.print(","); pw.print(mCurTop);
pw.print(")-("); pw.print(mCurRight);
diff --git a/services/java/com/android/server/StatusBarManagerService.java b/services/java/com/android/server/StatusBarManagerService.java
index 6452be7..8429086 100644
--- a/services/java/com/android/server/StatusBarManagerService.java
+++ b/services/java/com/android/server/StatusBarManagerService.java
@@ -292,27 +292,27 @@ public class StatusBarManagerService extends IStatusBarService.Stub
}
}
- public void setSystemUiVisibility(int vis) {
+ public void setSystemUiVisibility(int vis, int mask) {
// also allows calls from window manager which is in this process.
enforceStatusBarService();
if (SPEW) Slog.d(TAG, "setSystemUiVisibility(0x" + Integer.toHexString(vis) + ")");
synchronized (mLock) {
- updateUiVisibilityLocked(vis);
+ updateUiVisibilityLocked(vis, mask);
disableLocked(vis & StatusBarManager.DISABLE_MASK, mSysUiVisToken,
"WindowManager.LayoutParams");
}
}
- private void updateUiVisibilityLocked(final int vis) {
+ private void updateUiVisibilityLocked(final int vis, final int mask) {
if (mSystemUiVisibility != vis) {
mSystemUiVisibility = vis;
mHandler.post(new Runnable() {
public void run() {
if (mBar != null) {
try {
- mBar.setSystemUiVisibility(vis);
+ mBar.setSystemUiVisibility(vis, mask);
} catch (RemoteException ex) {
}
}
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index a91e716..a2dfd91 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -2648,7 +2648,8 @@ public class WindowManagerService extends IWindowManager.Stub
}
flagChanges = win.mAttrs.flags ^= attrs.flags;
attrChanges = win.mAttrs.copyFrom(attrs);
- if ((attrChanges&WindowManager.LayoutParams.LAYOUT_CHANGED) != 0) {
+ if ((attrChanges & (WindowManager.LayoutParams.LAYOUT_CHANGED
+ | WindowManager.LayoutParams.SYSTEM_UI_VISIBILITY_CHANGED)) != 0) {
win.mLayoutNeeded = true;
}
}