diff options
| author | Daniel Sandler <dsandler@google.com> | 2010-10-08 15:13:22 -0400 |
|---|---|---|
| committer | Daniel Sandler <dsandler@google.com> | 2010-10-13 16:25:43 -0400 |
| commit | e02d808abf370965c3c4e4d38af11bc69110fde2 (patch) | |
| tree | 78e681d5f884ee5fd9a75f297b6c0384e6542a2c | |
| parent | 3f703de0fbc4a626eacc2973926a99bb8e4fe8e2 (diff) | |
| download | frameworks_base-e02d808abf370965c3c4e4d38af11bc69110fde2.zip frameworks_base-e02d808abf370965c3c4e4d38af11bc69110fde2.tar.gz frameworks_base-e02d808abf370965c3c4e4d38af11bc69110fde2.tar.bz2 | |
Dynamically show the menu button on the system bar.
Windows with FLAG_NEEDS_MENU_KEY (or windowNeedsMenuKey=true
in their theme) will cause the system bar to show a menu
icon. (Note that the phone's status bar currently ignores
this, but phones tend to have hardware menu keys anyway.)
Additionally, all windows whose package's SDK version is
pre-Honeycomb will have FLAG_NEEDS_MENU_KEY set by default.
Bug: 3003728
Change-Id: I2d983763a726ea4f32cd1af9b0390e30478b11d1
11 files changed, 120 insertions, 12 deletions
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index eddd04e..7cb4671 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -611,6 +611,19 @@ public interface WindowManager extends ViewManager { * {@hide} */ public static final int FLAG_SPLIT_TOUCH = 0x00800000; + /** + * Flag for a window belonging to an activity that responds to {@link KeyEvent#KEYCODE_MENU} + * and therefore needs a Menu key. For devices where Menu is a physical button this flag is + * ignored, but on devices where the Menu key is drawn in software it may be hidden unless + * this flag is set. + * + * (Note that Action Bars, when available, are the preferred way to offer additional + * functions otherwise accessed via an options menu.) + * + * {@hide} + */ + public static final int FLAG_NEEDS_MENU_KEY = 0x01000000; + /** Window flag: *sigh* The lock screen wants to continue running its * animation while it is fading. A kind-of hack to allow this. Maybe * in the future we just make this the default behavior. diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl index e884af8..34a5b11 100644 --- a/core/java/com/android/internal/statusbar/IStatusBar.aidl +++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl @@ -31,5 +31,6 @@ oneway interface IStatusBar void animateExpand(); void animateCollapse(); void setLightsOn(boolean on); + void setMenuKeyVisible(boolean visible); } diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl index 0763f5e..90f4d48 100644 --- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl +++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl @@ -31,12 +31,13 @@ interface IStatusBarService void setIconVisibility(String slot, boolean visible); void removeIcon(String slot); void setActiveWindowIsFullscreen(boolean fullscreen); + void setMenuKeyVisible(boolean visible); // ---- Methods below are for use by the status bar policy services ---- // You need the STATUS_BAR_SERVICE permission void registerStatusBar(IStatusBar callbacks, out StatusBarIconList iconList, out List<IBinder> notificationKeys, out List<StatusBarNotification> notifications, - out boolean[] lightsOn); + out boolean[] switches); void onPanelRevealed(); void onNotificationClick(String pkg, String tag, int id); void onNotificationError(String pkg, String tag, int id, diff --git a/packages/SystemUI/res/layout-xlarge/status_bar.xml b/packages/SystemUI/res/layout-xlarge/status_bar.xml index 494dfa8..295c79b 100644 --- a/packages/SystemUI/res/layout-xlarge/status_bar.xml +++ b/packages/SystemUI/res/layout-xlarge/status_bar.xml @@ -144,6 +144,7 @@ android:paddingLeft="4dip" android:paddingRight="4dip" systemui:keyCode="82" + android:visibility="invisible" /> <ImageButton android:id="@+id/recent" android:layout_width="wrap_content" diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java index 81091e3..c164eb4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java @@ -54,6 +54,8 @@ public class CommandQueue extends IStatusBar.Stub { private static final int MSG_SET_LIGHTS_ON = 0x00070000; + private static final int MSG_SHOW_MENU = 0x00080000; + private StatusBarIconList mList; private Callbacks mCallbacks; private Handler mHandler = new H(); @@ -78,6 +80,7 @@ public class CommandQueue extends IStatusBar.Stub { public void animateExpand(); public void animateCollapse(); public void setLightsOn(boolean on); + public void setMenuKeyVisible(boolean visible); } public CommandQueue(Callbacks callbacks, StatusBarIconList list) { @@ -153,6 +156,13 @@ public class CommandQueue extends IStatusBar.Stub { } } + public void setMenuKeyVisible(boolean visible) { + synchronized (mList) { + mHandler.removeMessages(MSG_SHOW_MENU); + mHandler.obtainMessage(MSG_SHOW_MENU, visible ? 1 : 0, 0, null).sendToTarget(); + } + } + private final class H extends Handler { public void handleMessage(Message msg) { final int what = msg.what & MSG_MASK; @@ -210,6 +220,9 @@ public class CommandQueue extends IStatusBar.Stub { case MSG_SET_LIGHTS_ON: mCallbacks.setLightsOn(msg.arg1 != 0); break; + case MSG_SHOW_MENU: + mCallbacks.setMenuKeyVisible(msg.arg1 != 0); + break; } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/PhoneStatusBarService.java b/packages/SystemUI/src/com/android/systemui/statusbar/PhoneStatusBarService.java index 57ebd27..9fbfc64 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/PhoneStatusBarService.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/PhoneStatusBarService.java @@ -1013,6 +1013,9 @@ public class PhoneStatusBarService extends StatusBarService { } } + // Not supported + public void setMenuKeyVisible(boolean visible) { } + private class Launcher implements View.OnClickListener { private PendingIntent mIntent; private String mPkg; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarService.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarService.java index 695fdba..5594a47 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarService.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarService.java @@ -72,15 +72,16 @@ public abstract class StatusBarService extends Service implements CommandQueue.C mCommandQueue = new CommandQueue(this, iconList); mBarService = IStatusBarService.Stub.asInterface( ServiceManager.getService(Context.STATUS_BAR_SERVICE)); - boolean[] lightsOn = new boolean[1]; + boolean[] switches = new boolean[2]; try { mBarService.registerStatusBar(mCommandQueue, iconList, notificationKeys, notifications, - lightsOn); + switches); } catch (RemoteException ex) { // If the system process isn't there we're doomed anyway. } - setLightsOn(lightsOn[0]); + setLightsOn(switches[0]); + setMenuKeyVisible(switches[1]); // Set up the initial icon state int N = iconList.size(); @@ -120,7 +121,11 @@ public abstract class StatusBarService extends Service implements CommandQueue.C // TODO lp.windowAnimations = R.style.Animation_StatusBar; WindowManagerImpl.getDefault().addView(sb, lp); - Slog.d(TAG, "Added status bar view w/ gravity 0x" + Integer.toHexString(lp.gravity)); + Slog.d(TAG, "Added status bar view: gravity=0x" + Integer.toHexString(lp.gravity) + + " icons=" + iconList.size() + + " lights=" + (switches[0]?"on":"off") + + " menu=" + (switches[1]?"visible":"invisible") + ); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarService.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarService.java index 0e26f52..69e9a94 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarService.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarService.java @@ -79,6 +79,7 @@ public class TabletStatusBarService extends StatusBarService { View mNotificationButtons; View mSystemInfo; View mNavigationArea; + View mMenuButton; NotificationPanel mNotificationPanel; SystemPanel mSystemPanel; @@ -205,6 +206,7 @@ public class TabletStatusBarService extends StatusBarService { // The navigation buttons mNavigationArea = sb.findViewById(R.id.navigationArea); + mMenuButton = mNavigationArea.findViewById(R.id.menu); // set the initial view visibility setAreThereNotifications(); @@ -503,6 +505,15 @@ public class TabletStatusBarService extends StatusBarService { } } + public void setMenuKeyVisible(boolean visible) { + if (DEBUG) { + Slog.d(TAG, (visible?"showing":"hiding") + " the MENU button"); + } + setViewVisibility(mMenuButton, + visible ? View.VISIBLE : View.INVISIBLE, + visible ? R.anim.navigation_in : R.anim.navigation_out); + } + private void setAreThereNotifications() { final boolean hasClearable = mNotns.hasClearableItems(); diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java index 24c9443..db5f6c1 100644 --- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java @@ -21,6 +21,7 @@ import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN; import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR; import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; +import static android.view.WindowManager.LayoutParams.FLAG_NEEDS_MENU_KEY; import com.android.internal.view.BaseSurfaceHolder; import com.android.internal.view.RootViewSurfaceTaker; @@ -2324,6 +2325,11 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { setFlags(FLAG_SHOW_WALLPAPER, FLAG_SHOW_WALLPAPER&(~getForcedWindowFlags())); } + if (getContext().getApplicationInfo().targetSdkVersion + < android.os.Build.VERSION_CODES.HONEYCOMB) { + addFlags(WindowManager.LayoutParams.FLAG_NEEDS_MENU_KEY); + } + WindowManager.LayoutParams params = getAttributes(); if (!hasSoftInputMode()) { diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java index 449bd4c..ec5b098 100755 --- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java @@ -287,6 +287,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { Intent mDeskDockIntent; boolean mSearchKeyPressed; boolean mConsumeSearchKeyUp; + boolean mShowMenuKey = false; // track FLAG_NEEDS_MENU_KEY on frontmost window // support for activating the lock screen while the screen is on boolean mAllowLockscreenWhenOn; @@ -1603,8 +1604,12 @@ public class PhoneWindowManager implements WindowManagerPolicy { /** {@inheritDoc} */ public int finishAnimationLw() { int changes = 0; - boolean topIsFullscreen = false; + + final WindowManager.LayoutParams lp = (mTopFullscreenOpaqueWindowState != null) + ? mTopFullscreenOpaqueWindowState.getAttrs() + : null; + if (mStatusBar != null) { if (localLOGV) Log.i(TAG, "force=" + mForceStatusBar + " top=" + mTopFullscreenOpaqueWindowState); @@ -1612,7 +1617,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (DEBUG_LAYOUT) Log.v(TAG, "Showing status bar"); if (mStatusBar.showLw(true)) changes |= FINISH_LAYOUT_REDO_LAYOUT; } else if (mTopFullscreenOpaqueWindowState != null) { - final WindowManager.LayoutParams lp = mTopFullscreenOpaqueWindowState.getAttrs(); if (localLOGV) { Log.d(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrameLw() + " shown frame: " + mTopFullscreenOpaqueWindowState.getShownFrameLw()); @@ -1637,10 +1641,26 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } } - - if (topIsFullscreen != mTopIsFullscreen) { + + boolean topNeedsMenu = mShowMenuKey; + if (lp != null) { + topNeedsMenu = (lp.flags & WindowManager.LayoutParams.FLAG_NEEDS_MENU_KEY) != 0; + } + + if (DEBUG_LAYOUT) Log.v(TAG, "Top window " + + (topNeedsMenu ? "needs" : "does not need") + + " the MENU key"); + + final boolean changedFullscreen = (mTopIsFullscreen != topIsFullscreen); + final boolean changedMenu = (topNeedsMenu != mShowMenuKey); + + if (changedFullscreen || changedMenu) { final boolean topIsFullscreenF = topIsFullscreen; + final boolean topNeedsMenuF = topNeedsMenu; + mTopIsFullscreen = topIsFullscreen; + mShowMenuKey = topNeedsMenu; + mHandler.post(new Runnable() { public void run() { if (mStatusBarService == null) { @@ -1654,7 +1674,12 @@ public class PhoneWindowManager implements WindowManagerPolicy { final IStatusBarService sbs = mStatusBarService; if (mStatusBarService != null) { try { - sbs.setActiveWindowIsFullscreen(topIsFullscreenF); + if (changedFullscreen) { + sbs.setActiveWindowIsFullscreen(topIsFullscreenF); + } + if (changedMenu) { + sbs.setMenuKeyVisible(topNeedsMenuF); + } } catch (RemoteException e) { // This should be impossible because we're in the same process. mStatusBarService = null; diff --git a/services/java/com/android/server/StatusBarManagerService.java b/services/java/com/android/server/StatusBarManagerService.java index b1baec5..66e0214 100644 --- a/services/java/com/android/server/StatusBarManagerService.java +++ b/services/java/com/android/server/StatusBarManagerService.java @@ -72,6 +72,8 @@ public class StatusBarManagerService extends IStatusBarService.Stub // We usually call it lights out mode, but double negatives are annoying boolean mLightsOn = true; + boolean mMenuVisible = false; + private class DisableRecord implements IBinder.DeathRecipient { String pkg; int what; @@ -246,6 +248,32 @@ public class StatusBarManagerService extends IStatusBarService.Stub } } + /** + * Hide or show the on-screen Menu key. Only call this from the window manager, typically in + * response to a window with FLAG_NEEDS_MENU_KEY set. + */ + public void setMenuKeyVisible(final boolean visible) { + enforceStatusBar(); + + if (SPEW) Slog.d(TAG, (visible?"showing":"hiding") + " MENU key"); + + synchronized(mLock) { + if (mMenuVisible != visible) { + mMenuVisible = visible; + mHandler.post(new Runnable() { + public void run() { + if (mBar != null) { + try { + mBar.setMenuKeyVisible(visible); + } catch (RemoteException ex) { + } + } + } + }); + } + } + } + /** * This is used for the automatic version of lights-out mode. Only call this from * the window manager. @@ -317,7 +345,7 @@ public class StatusBarManagerService extends IStatusBarService.Stub // ================================================================================ public void registerStatusBar(IStatusBar bar, StatusBarIconList iconList, List<IBinder> notificationKeys, List<StatusBarNotification> notifications, - boolean lightsOn[]) { + boolean switches[]) { enforceStatusBarService(); Slog.i(TAG, "registerStatusBar bar=" + bar); @@ -332,7 +360,8 @@ public class StatusBarManagerService extends IStatusBarService.Stub } } synchronized (mLock) { - lightsOn[0] = mLightsOn; + switches[0] = mLightsOn; + switches[1] = mMenuVisible; } } |
