summaryrefslogtreecommitdiffstats
path: root/policy/src
diff options
context:
space:
mode:
authorDaniel Sandler <dsandler@android.com>2011-05-04 11:26:38 -0700
committerAndroid (Google) Code Review <android-gerrit@google.com>2011-05-04 11:26:38 -0700
commit0c19aaaebb5baf78857e2e18ebe7fb37b7e1cf8e (patch)
tree23a20876a43b62c67c94d7e7b579201a0671f894 /policy/src
parent65b96059766a12454236712931d66bffb311729c (diff)
parent8956dbbc5f292d8b79072ae73b25f2114c8c7479 (diff)
downloadframeworks_base-0c19aaaebb5baf78857e2e18ebe7fb37b7e1cf8e.zip
frameworks_base-0c19aaaebb5baf78857e2e18ebe7fb37b7e1cf8e.tar.gz
frameworks_base-0c19aaaebb5baf78857e2e18ebe7fb37b7e1cf8e.tar.bz2
Merge "On-screen navigation bar (separate from the status bar)."
Diffstat (limited to 'policy/src')
-rwxr-xr-xpolicy/src/com/android/internal/policy/impl/PhoneWindowManager.java164
1 files changed, 131 insertions, 33 deletions
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index a37ccc7..8a29419 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -111,6 +111,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import static android.view.WindowManager.LayoutParams.TYPE_POINTER;
+import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
import android.view.WindowManagerImpl;
import android.view.WindowManagerPolicy;
import android.view.KeyCharacterMap.FallbackAction;
@@ -175,14 +176,16 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// responsible for power management when displayed.
static final int KEYGUARD_LAYER = 15;
static final int KEYGUARD_DIALOG_LAYER = 16;
+ // the navigation bar, if available, shows atop most things
+ static final int NAVIGATION_BAR_LAYER = 17;
// the drag layer: input for drag-and-drop is associated with this window,
// which sits above all other focusable windows
- static final int DRAG_LAYER = 17;
+ static final int DRAG_LAYER = 18;
// things in here CAN NOT take focus, but are shown on top of everything else.
- static final int SYSTEM_OVERLAY_LAYER = 18;
- static final int SECURE_SYSTEM_OVERLAY_LAYER = 19;
+ static final int SYSTEM_OVERLAY_LAYER = 19;
+ static final int SECURE_SYSTEM_OVERLAY_LAYER = 20;
// the (mouse) pointer layer
- static final int POINTER_LAYER = 20;
+ static final int POINTER_LAYER = 21;
static final int APPLICATION_MEDIA_SUBLAYER = -2;
static final int APPLICATION_MEDIA_OVERLAY_SUBLAYER = -1;
@@ -228,6 +231,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
WindowState mStatusBar = null;
boolean mStatusBarCanHide;
final ArrayList<WindowState> mStatusBarPanels = new ArrayList<WindowState>();
+ WindowState mNavigationBar = null;
+
WindowState mKeyguard = null;
KeyguardViewMediator mKeyguardMediator;
GlobalActions mGlobalActions;
@@ -1037,6 +1042,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
return DRAG_LAYER;
case TYPE_POINTER:
return POINTER_LAYER;
+ case TYPE_NAVIGATION_BAR:
+ return NAVIGATION_BAR_LAYER;
}
Log.e(TAG, "Unknown window type: " + type);
return APPLICATION_LAYER;
@@ -1214,6 +1221,13 @@ public class PhoneWindowManager implements WindowManagerPolicy {
com.android.internal.R.bool.config_statusBarCanHide);
break;
+ case TYPE_NAVIGATION_BAR:
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.STATUS_BAR_SERVICE,
+ "PhoneWindowManager");
+ mNavigationBar = win;
+ if (DEBUG_LAYOUT) Log.i(TAG, "NAVIGATION BAR: " + mNavigationBar);
+ break;
case TYPE_STATUS_BAR_PANEL:
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.STATUS_BAR_SERVICE,
@@ -1240,9 +1254,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
public void removeWindowLw(WindowState win) {
if (mStatusBar == win) {
mStatusBar = null;
- }
- else if (mKeyguard == win) {
+ } else if (mKeyguard == win) {
mKeyguard = null;
+ } else if (mNavigationBar == win) {
+ mNavigationBar = null;
} else {
mStatusBarPanels.remove(win);
}
@@ -1609,17 +1624,48 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mDockBottom = mContentBottom = mCurBottom = displayHeight;
mDockLayer = 0x10000000;
+ // start with the current dock rect, which will be (0,0,displayWidth,displayHeight)
+ final Rect pf = mTmpParentFrame;
+ final Rect df = mTmpDisplayFrame;
+ final Rect vf = mTmpVisibleFrame;
+ pf.left = df.left = vf.left = mDockLeft;
+ pf.top = df.top = vf.top = mDockTop;
+ pf.right = df.right = vf.right = mDockRight;
+ pf.bottom = df.bottom = vf.bottom = mDockBottom;
+
// decide where the status bar goes ahead of time
if (mStatusBar != null) {
- final Rect pf = mTmpParentFrame;
- final Rect df = mTmpDisplayFrame;
- final Rect vf = mTmpVisibleFrame;
- pf.left = df.left = vf.left = 0;
- pf.top = df.top = vf.top = 0;
- pf.right = df.right = vf.right = displayWidth;
- pf.bottom = df.bottom = vf.bottom = displayHeight;
-
+ Rect navr = null;
+ if (mNavigationBar != null) {
+ mNavigationBar.computeFrameLw(pf, df, vf, vf);
+ if (mNavigationBar.isVisibleLw()) {
+ navr = mNavigationBar.getFrameLw();
+
+ if (navr.top == 0) {
+ // Navigation bar is vertical
+ if (mDockLeft == navr.left) {
+ mDockLeft = navr.right;
+ } else if (mDockRight == navr.right) {
+ mDockRight = navr.left;
+ }
+ } else {
+ // Navigation bar horizontal, at bottom
+ if (mDockBottom == navr.bottom) {
+ mDockBottom = navr.top;
+ }
+ }
+ }
+ }
+ if (DEBUG_LAYOUT) Log.i(TAG, "mNavigationBar frame: " + navr);
+
+ // apply navigation bar insets
+ pf.left = df.left = vf.left = mDockLeft;
+ pf.top = df.top = vf.top = mDockTop;
+ pf.right = df.right = vf.right = mDockRight;
+ pf.bottom = df.bottom = vf.bottom = mDockBottom;
+
mStatusBar.computeFrameLw(pf, df, vf, vf);
+
if (mStatusBar.isVisibleLw()) {
// If the status bar is hidden, we don't want to cause
// windows behind it to scroll.
@@ -1630,14 +1676,18 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// status bar is visible.
if (mDockTop == r.top) mDockTop = r.bottom;
else if (mDockBottom == r.bottom) mDockBottom = r.top;
+
mContentTop = mCurTop = mDockTop;
mContentBottom = mCurBottom = mDockBottom;
- if (DEBUG_LAYOUT) Log.v(TAG, "Status bar: mDockTop=" + mDockTop
- + " mContentTop=" + mContentTop
- + " mCurTop=" + mCurTop
- + " mDockBottom=" + mDockBottom
- + " mContentBottom=" + mContentBottom
- + " mCurBottom=" + mCurBottom);
+ mContentLeft = mCurLeft = mDockLeft;
+ mContentRight = mCurRight = mDockRight;
+
+ if (DEBUG_LAYOUT) Log.v(TAG, "Status bar: " +
+ String.format(
+ "dock=[%d,%d][%d,%d] content=[%d,%d][%d,%d] cur=[%d,%d][%d,%d]",
+ mDockLeft, mDockTop, mDockRight, mDockBottom,
+ mContentLeft, mContentTop, mContentRight, mContentBottom,
+ mCurLeft, mCurTop, mCurRight, mCurBottom));
} else {
// Status bar can't go away; the part of the screen it
// covers does not exist for anything behind it.
@@ -1647,12 +1697,32 @@ public class PhoneWindowManager implements WindowManagerPolicy {
} else if ((mRestrictedScreenHeight-mRestrictedScreenTop) == r.bottom) {
mRestrictedScreenHeight -= (r.bottom-r.top);
}
+
+ if (navr != null) {
+ if (navr.top == 0) {
+ // Navigation bar is vertical
+ if (mRestrictedScreenLeft == navr.left) {
+ mRestrictedScreenLeft = navr.right;
+ mRestrictedScreenWidth -= (navr.right - navr.left);
+ } else if ((mRestrictedScreenLeft+mRestrictedScreenWidth) == navr.right) {
+ mRestrictedScreenWidth -= (navr.right - navr.left);
+ }
+ } else {
+ // Navigation bar horizontal, at bottom
+ if ((mRestrictedScreenHeight-mRestrictedScreenTop) == r.bottom) {
+ mRestrictedScreenHeight -= (navr.bottom-navr.top);
+ }
+ }
+ }
+
mContentTop = mCurTop = mDockTop = mRestrictedScreenTop;
mContentBottom = mCurBottom = mDockBottom
= mRestrictedScreenTop + mRestrictedScreenHeight;
- if (DEBUG_LAYOUT) Log.v(TAG, "Status bar: mRestrictedScreenTop="
- + mRestrictedScreenTop
- + " mRestrictedScreenHeight=" + mRestrictedScreenHeight);
+ if (DEBUG_LAYOUT) Log.v(TAG, "Status bar: restricted screen area: ("
+ + mRestrictedScreenLeft + ","
+ + mRestrictedScreenTop + ","
+ + (mRestrictedScreenLeft + mRestrictedScreenWidth) + ","
+ + (mRestrictedScreenTop + mRestrictedScreenHeight) + ")");
}
}
}
@@ -1722,6 +1792,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
final Rect cf = mTmpContentFrame;
final Rect vf = mTmpVisibleFrame;
+ final boolean hasNavBar = (mNavigationBar != null && mNavigationBar.isVisibleLw());
+
if (attrs.type == TYPE_INPUT_METHOD) {
pf.left = df.left = cf.left = vf.left = mDockLeft;
pf.top = df.top = cf.top = vf.top = mDockTop;
@@ -1735,6 +1807,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_FULLSCREEN | FLAG_LAYOUT_INSET_DECOR))
== (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) {
+ if (DEBUG_LAYOUT)
+ Log.v(TAG, "layoutWindowLw(" + attrs.getTitle()
+ + "): IN_SCREEN, INSET_DECOR, !FULLSCREEN");
// This is the case for a normal activity window: we want it
// to cover all of the screen space, and it can take care of
// moving its contents to account for screen decorations that
@@ -1744,15 +1819,26 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// frame is the same as the one we are attached to.
setAttachedWindowFrames(win, fl, sim, attached, true, pf, df, cf, vf);
} else {
- if (attrs.type == TYPE_STATUS_BAR_PANEL) {
+ if (attrs.type == TYPE_STATUS_BAR_PANEL
+ || attrs.type == TYPE_STATUS_BAR_SUB_PANEL) {
// Status bar panels are the only windows who can go on top of
// the status bar. They are protected by the STATUS_BAR_SERVICE
// permission, so they have the same privileges as the status
// bar itself.
- pf.left = df.left = mUnrestrictedScreenLeft;
+ //
+ // However, they should still dodge the navigation bar if it exists. A
+ // straightforward way to do this is to only allow the status bar panels to
+ // extend to the extrema of the allowable region for the IME dock.
+
+ pf.left = df.left = hasNavBar ? mDockLeft : mUnrestrictedScreenLeft;
pf.top = df.top = mUnrestrictedScreenTop;
- pf.right = df.right = mUnrestrictedScreenLeft+mUnrestrictedScreenWidth;
- pf.bottom = df.bottom = mUnrestrictedScreenTop+mUnrestrictedScreenHeight;
+ pf.right = df.right = hasNavBar
+ ? mDockRight
+ : mUnrestrictedScreenLeft+mUnrestrictedScreenWidth;
+ pf.bottom = df.bottom = hasNavBar
+ ? mDockBottom
+ : mUnrestrictedScreenTop+mUnrestrictedScreenHeight;
+
} else {
pf.left = df.left = mRestrictedScreenLeft;
pf.top = df.top = mRestrictedScreenTop;
@@ -1780,15 +1866,21 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
}
} else if ((fl & FLAG_LAYOUT_IN_SCREEN) != 0) {
+ if (DEBUG_LAYOUT)
+ Log.v(TAG, "layoutWindowLw(" + attrs.getTitle() + "): IN_SCREEN");
// A window that has requested to fill the entire screen just
// gets everything, period.
- if (attrs.type == TYPE_STATUS_BAR_PANEL) {
- pf.left = df.left = cf.left = mUnrestrictedScreenLeft;
+ if (attrs.type == TYPE_STATUS_BAR_PANEL
+ || attrs.type == TYPE_STATUS_BAR_SUB_PANEL) {
+ pf.left = df.left = cf.left = hasNavBar ? mDockLeft : mUnrestrictedScreenLeft;
pf.top = df.top = cf.top = mUnrestrictedScreenTop;
- pf.right = df.right = cf.right
- = mUnrestrictedScreenLeft+mUnrestrictedScreenWidth;
- pf.bottom = df.bottom = cf.bottom
- = mUnrestrictedScreenTop+mUnrestrictedScreenHeight;
+ pf.right = df.right = cf.right = hasNavBar
+ ? mDockRight
+ : mUnrestrictedScreenLeft+mUnrestrictedScreenWidth;
+ pf.bottom = df.bottom = cf.bottom = hasNavBar
+ ? mDockBottom
+ : mUnrestrictedScreenTop+mUnrestrictedScreenHeight;
+
} else {
pf.left = df.left = cf.left = mRestrictedScreenLeft;
pf.top = df.top = cf.top = mRestrictedScreenTop;
@@ -1805,10 +1897,14 @@ public class PhoneWindowManager implements WindowManagerPolicy {
vf.set(cf);
}
} else if (attached != null) {
+ if (DEBUG_LAYOUT)
+ Log.v(TAG, "layoutWindowLw(" + attrs.getTitle() + "): attached to " + attached);
// A child window should be placed inside of the same visible
// frame that its parent had.
setAttachedWindowFrames(win, fl, adjust, attached, false, pf, df, cf, vf);
} else {
+ if (DEBUG_LAYOUT)
+ Log.v(TAG, "layoutWindowLw(" + attrs.getTitle() + "): normal window");
// Otherwise, a normal window must be placed inside the content
// of all screen decorations.
pf.left = mContentLeft;
@@ -1844,6 +1940,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (DEBUG_LAYOUT) Log.v(TAG, "Compute frame " + attrs.getTitle()
+ ": sim=#" + Integer.toHexString(sim)
+ + " attach=" + attached + " type=" + attrs.type
+ + String.format(" flags=0x%08x", fl)
+ " pf=" + pf.toShortString() + " df=" + df.toShortString()
+ " cf=" + cf.toShortString() + " vf=" + vf.toShortString());