Merge "Minor Alt-TAB / Recent Apps Dialog improvements."
diff --git a/api/current.xml b/api/current.xml
index 22d82ce..6749a564a 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -213125,6 +213125,17 @@
visibility="public"
>
</method>
+<method name="getModifiers"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="getNumber"
return="char"
abstract="false"
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index 4320160..c282e4b 100755
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -1807,12 +1807,33 @@
* @see #META_CAPS_LOCK_ON
* @see #META_NUM_LOCK_ON
* @see #META_SCROLL_LOCK_ON
+ * @see #getModifiers
*/
public final int getMetaState() {
return mMetaState;
}
/**
+ * Returns the state of the modifier keys.
+ * <p>
+ * For the purposes of this function, {@link #KEYCODE_CAPS_LOCK},
+ * {@link #KEYCODE_SCROLL_LOCK}, and {@link #KEYCODE_NUM_LOCK} are
+ * not considered modifier keys. Consequently, this function specifically masks out
+ * {@link #META_CAPS_LOCK_ON}, {@link #META_SCROLL_LOCK_ON} and {@link #META_NUM_LOCK_ON}.
+ * </p><p>
+ * The value returned consists of the meta state (from {@link #getMetaState})
+ * normalized using {@link #normalizeMetaState(int)} and then masked with
+ * {@link #getModifierMetaStateMask} so that only valid modifier bits are retained.
+ * </p>
+ *
+ * @return An integer in which each bit set to 1 represents a pressed modifier key.
+ * @see #getMetaState
+ */
+ public final int getModifiers() {
+ return normalizeMetaState(mMetaState) & META_MODIFIER_MASK;
+ }
+
+ /**
* Returns the flags for this key event.
*
* @see #FLAG_WOKE_HERE
diff --git a/data/keyboards/Generic.kcm b/data/keyboards/Generic.kcm
index ef0a4e6..b5f6897 100644
--- a/data/keyboards/Generic.kcm
+++ b/data/keyboards/Generic.kcm
@@ -300,8 +300,7 @@
key TAB {
label: '\t'
base: '\t'
- ctrl: none
- alt, meta: fallback APP_SWITCH
+ ctrl, alt, meta: none
}
key COMMA {
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 768c0cd..5f84547 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -626,7 +626,7 @@
}
if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_DIALOG) {
- showRecentAppsDialog(0);
+ showOrHideRecentAppsDialog(0, true /*dismissIfShown*/);
} else if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_ACTIVITY) {
try {
Intent intent = new Intent();
@@ -643,16 +643,24 @@
}
/**
- * Create (if necessary) and launch the recent apps dialog
+ * Create (if necessary) and launch the recent apps dialog, or hide it if it is
+ * already shown.
*/
- void showRecentAppsDialog(final int initialModifiers) {
+ void showOrHideRecentAppsDialog(final int heldModifiers, final boolean dismissIfShown) {
mHandler.post(new Runnable() {
@Override
public void run() {
if (mRecentAppsDialog == null) {
- mRecentAppsDialog = new RecentApplicationsDialog(mContext, initialModifiers);
+ mRecentAppsDialog = new RecentApplicationsDialog(mContext);
}
- mRecentAppsDialog.show();
+ if (mRecentAppsDialog.isShowing()) {
+ if (dismissIfShown) {
+ mRecentAppsDialog.dismiss();
+ }
+ } else {
+ mRecentAppsDialog.setHeldModifiers(heldModifiers);
+ mRecentAppsDialog.show();
+ }
}
});
}
@@ -1388,7 +1396,7 @@
return false;
} else if (keyCode == KeyEvent.KEYCODE_APP_SWITCH) {
if (down && repeatCount == 0) {
- showRecentAppsDialog(event.getMetaState() & KeyEvent.getModifierMetaStateMask());
+ showOrHideRecentAppsDialog(0, true /*dismissIfShown*/);
}
return true;
}
@@ -1430,6 +1438,7 @@
/** {@inheritDoc} */
@Override
public KeyEvent dispatchUnhandledKey(WindowState win, KeyEvent event, int policyFlags) {
+ // Note: This method is only called if the initial down was unhandled.
if (DEBUG_FALLBACK) {
Slog.d(TAG, "Unhandled key: win=" + win + ", action=" + event.getAction()
+ ", flags=" + event.getFlags()
@@ -1441,28 +1450,44 @@
}
if ((event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
- // Invoke shortcuts using Meta as a fallback.
final KeyCharacterMap kcm = event.getKeyCharacterMap();
final int keyCode = event.getKeyCode();
final int metaState = event.getMetaState();
- if ((metaState & KeyEvent.META_META_ON) != 0) {
- Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode,
- metaState & ~(KeyEvent.META_META_ON
- | KeyEvent.META_META_LEFT_ON | KeyEvent.META_META_RIGHT_ON));
- if (shortcutIntent != null) {
- shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- try {
- mContext.startActivity(shortcutIntent);
- } catch (ActivityNotFoundException ex) {
- Slog.w(TAG, "Dropping shortcut key combination because "
- + "the activity to which it is registered was not found: "
- + "META+" + KeyEvent.keyCodeToString(keyCode), ex);
+ final boolean initialDown = event.getAction() == KeyEvent.ACTION_DOWN
+ && event.getRepeatCount() == 0;
+
+ if (initialDown) {
+ // Invoke shortcuts using Meta as a fallback.
+ if ((metaState & KeyEvent.META_META_ON) != 0) {
+ Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode,
+ metaState & ~(KeyEvent.META_META_ON
+ | KeyEvent.META_META_LEFT_ON | KeyEvent.META_META_RIGHT_ON));
+ if (shortcutIntent != null) {
+ shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ try {
+ mContext.startActivity(shortcutIntent);
+ } catch (ActivityNotFoundException ex) {
+ Slog.w(TAG, "Dropping shortcut key combination because "
+ + "the activity to which it is registered was not found: "
+ + "META+" + KeyEvent.keyCodeToString(keyCode), ex);
+ }
+ return null;
}
- return null;
+ }
+
+ // Display task switcher for ALT-TAB or Meta-TAB.
+ if (keyCode == KeyEvent.KEYCODE_TAB) {
+ final int shiftlessModifiers = event.getModifiers() & ~KeyEvent.META_SHIFT_MASK;
+ if (KeyEvent.metaStateHasModifiers(shiftlessModifiers, KeyEvent.META_ALT_ON)
+ || KeyEvent.metaStateHasModifiers(
+ shiftlessModifiers, KeyEvent.META_META_ON)) {
+ showOrHideRecentAppsDialog(shiftlessModifiers, false /*dismissIfShown*/);
+ return null;
+ }
}
}
- // Check for fallback actions.
+ // Check for fallback actions specified by the key character map.
if (getFallbackAction(kcm, keyCode, metaState, mFallbackAction)) {
if (DEBUG_FALLBACK) {
Slog.d(TAG, "Fallback: keyCode=" + mFallbackAction.keyCode
diff --git a/policy/src/com/android/internal/policy/impl/RecentApplicationsDialog.java b/policy/src/com/android/internal/policy/impl/RecentApplicationsDialog.java
index c4b7822..aa00fbdd 100644
--- a/policy/src/com/android/internal/policy/impl/RecentApplicationsDialog.java
+++ b/policy/src/com/android/internal/policy/impl/RecentApplicationsDialog.java
@@ -71,12 +71,11 @@
}
};
- private int mInitialModifiers;
+ private int mHeldModifiers;
- public RecentApplicationsDialog(Context context, int initialModifiers) {
+ public RecentApplicationsDialog(Context context) {
super(context, com.android.internal.R.style.Theme_Dialog_RecentApplications);
- mInitialModifiers = initialModifiers;
}
/**
@@ -125,9 +124,20 @@
}
}
+ /**
+ * Sets the modifier keys that are being held to keep the dialog open, or 0 if none.
+ * Used to make the recent apps dialog automatically dismiss itself when the modifiers
+ * all go up.
+ * @param heldModifiers The held key modifiers, such as {@link KeyEvent#META_ALT_ON}.
+ * Should exclude shift.
+ */
+ public void setHeldModifiers(int heldModifiers) {
+ mHeldModifiers = heldModifiers;
+ }
+
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
- if (keyCode == KeyEvent.KEYCODE_APP_SWITCH || keyCode == KeyEvent.KEYCODE_TAB) {
+ if (keyCode == KeyEvent.KEYCODE_TAB) {
// Ignore all meta keys other than SHIFT. The app switch key could be a
// fallback action chorded with ALT, META or even CTRL depending on the key map.
// DPad navigation is handled by the ViewRoot elsewhere.
@@ -166,7 +176,7 @@
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
- if (mInitialModifiers != 0 && event.hasNoModifiers()) {
+ if (mHeldModifiers != 0 && (event.getModifiers() & mHeldModifiers) == 0) {
final int numIcons = mIcons.length;
RecentTag tag = null;
for (int i = 0; i < numIcons; i++) {