am 944c985b: am e0e9fd98: Merge "Fix system hotkey handling." into ics-mr1

* commit '944c985b4199e6e029568ea87004c9727e469cc0':
  Fix system hotkey handling.
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index b18d88f..fe5388b 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -810,7 +810,7 @@
     
     <!-- Special theme for the recent apps dialog, to allow customization
          with overlays. -->
-    <style name="Theme.Dialog.RecentApplications">
+    <style name="Theme.Dialog.RecentApplications" parent="Theme.DeviceDefault.Dialog">
         <item name="windowFrame">@null</item>
         <item name="windowBackground">@android:color/transparent</item>
         <item name="android:windowAnimationStyle">@android:style/Animation.RecentApplications</item>
diff --git a/policy/src/com/android/internal/policy/impl/IconUtilities.java b/policy/src/com/android/internal/policy/impl/IconUtilities.java
index 4564f90..e997355 100644
--- a/policy/src/com/android/internal/policy/impl/IconUtilities.java
+++ b/policy/src/com/android/internal/policy/impl/IconUtilities.java
@@ -38,6 +38,8 @@
 import android.text.TextPaint;
 import android.util.DisplayMetrics;
 import android.util.Log;
+import android.util.TypedValue;
+import android.view.ContextThemeWrapper;
 import android.content.res.Resources;
 import android.content.Context;
 
@@ -74,9 +76,13 @@
         mIconTextureWidth = mIconTextureHeight = mIconWidth + (int)(blurPx*2);
 
         mBlurPaint.setMaskFilter(new BlurMaskFilter(blurPx, BlurMaskFilter.Blur.NORMAL));
-        mGlowColorPressedPaint.setColor(0xffffc300);
+
+        TypedValue value = new TypedValue();
+        mGlowColorPressedPaint.setColor(context.getTheme().resolveAttribute(
+                android.R.attr.colorPressedHighlight, value, true) ? value.data : 0xffffc300);
         mGlowColorPressedPaint.setMaskFilter(TableMaskFilter.CreateClipTable(0, 30));
-        mGlowColorFocusedPaint.setColor(0xffff8e00);
+        mGlowColorFocusedPaint.setColor(context.getTheme().resolveAttribute(
+                android.R.attr.colorFocusedHighlight, value, true) ? value.data : 0xffff8e00);
         mGlowColorFocusedPaint.setMaskFilter(TableMaskFilter.CreateClipTable(0, 30));
 
         ColorMatrix cm = new ColorMatrix();
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 92260d6..0a5a765 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -301,9 +301,15 @@
     GlobalActions mGlobalActions;
     volatile boolean mPowerKeyHandled; // accessed from input reader and handler thread
     boolean mPendingPowerKeyUpCanceled;
-    RecentApplicationsDialog mRecentAppsDialog;
     Handler mHandler;
 
+    static final int RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS = 0;
+    static final int RECENT_APPS_BEHAVIOR_EXIT_TOUCH_MODE_AND_SHOW = 1;
+    static final int RECENT_APPS_BEHAVIOR_DISMISS_AND_SWITCH = 2;
+
+    RecentApplicationsDialog mRecentAppsDialog;
+    int mRecentAppsDialogHeldModifiers;
+
     private static final int LID_ABSENT = -1;
     private static final int LID_CLOSED = 0;
     private static final int LID_OPEN = 1;
@@ -715,7 +721,7 @@
         }
 
         if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_DIALOG) {
-            showOrHideRecentAppsDialog(0, true /*dismissIfShown*/);
+            showOrHideRecentAppsDialog(RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS);
         } else if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_SYSTEM_UI) {
             try {
                 mStatusBarService.toggleRecentApps();
@@ -726,10 +732,10 @@
     }
 
     /**
-     * Create (if necessary) and launch the recent apps dialog, or hide it if it is
-     * already shown.
+     * Create (if necessary) and show or dismiss the recent apps dialog according
+     * according to the requested behavior.
      */
-    void showOrHideRecentAppsDialog(final int heldModifiers, final boolean dismissIfShown) {
+    void showOrHideRecentAppsDialog(final int behavior) {
         mHandler.post(new Runnable() {
             @Override
             public void run() {
@@ -737,12 +743,33 @@
                     mRecentAppsDialog = new RecentApplicationsDialog(mContext);
                 }
                 if (mRecentAppsDialog.isShowing()) {
-                    if (dismissIfShown) {
-                        mRecentAppsDialog.dismiss();
+                    switch (behavior) {
+                        case RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS:
+                            mRecentAppsDialog.dismiss();
+                            break;
+                        case RECENT_APPS_BEHAVIOR_DISMISS_AND_SWITCH:
+                            mRecentAppsDialog.dismissAndSwitch();
+                            break;
+                        case RECENT_APPS_BEHAVIOR_EXIT_TOUCH_MODE_AND_SHOW:
+                        default:
+                            break;
                     }
                 } else {
-                    mRecentAppsDialog.setHeldModifiers(heldModifiers);
-                    mRecentAppsDialog.show();
+                    switch (behavior) {
+                        case RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS:
+                            mRecentAppsDialog.show();
+                            break;
+                        case RECENT_APPS_BEHAVIOR_EXIT_TOUCH_MODE_AND_SHOW:
+                            try {
+                                mWindowManager.setInTouchMode(false);
+                            } catch (RemoteException e) {
+                            }
+                            mRecentAppsDialog.show();
+                            break;
+                        case RECENT_APPS_BEHAVIOR_DISMISS_AND_SWITCH:
+                        default:
+                            break;
+                    }
                 }
             }
         });
@@ -1649,7 +1676,7 @@
             return 0;
         } else if (keyCode == KeyEvent.KEYCODE_APP_SWITCH) {
             if (down && repeatCount == 0) {
-                showOrHideRecentAppsDialog(0, true /*dismissIfShown*/);
+                showOrHideRecentAppsDialog(RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS);
             }
             return -1;
         }
@@ -1685,6 +1712,26 @@
             }
         }
 
+        // Invoke shortcuts using Meta.
+        if (down && repeatCount == 0
+                && (metaState & KeyEvent.META_META_ON) != 0) {
+            final KeyCharacterMap kcm = event.getKeyCharacterMap();
+            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 -1;
+            }
+        }
+
         // Handle application launch keys.
         if (down && repeatCount == 0) {
             String category = sApplicationLaunchKeyCategories.get(keyCode);
@@ -1698,9 +1745,29 @@
                             + "the activity to which it is registered was not found: "
                             + "keyCode=" + keyCode + ", category=" + category, ex);
                 }
+                return -1;
             }
         }
 
+        // Display task switcher for ALT-TAB or Meta-TAB.
+        if (down && repeatCount == 0 && keyCode == KeyEvent.KEYCODE_TAB) {
+            if (mRecentAppsDialogHeldModifiers == 0) {
+                final int shiftlessModifiers = event.getModifiers() & ~KeyEvent.META_SHIFT_MASK;
+                if (KeyEvent.metaStateHasModifiers(shiftlessModifiers, KeyEvent.META_ALT_ON)
+                        || KeyEvent.metaStateHasModifiers(
+                                shiftlessModifiers, KeyEvent.META_META_ON)) {
+                    mRecentAppsDialogHeldModifiers = shiftlessModifiers;
+                    showOrHideRecentAppsDialog(RECENT_APPS_BEHAVIOR_EXIT_TOUCH_MODE_AND_SHOW);
+                    return -1;
+                }
+            }
+        } else if (!down && mRecentAppsDialogHeldModifiers != 0
+                && (metaState & mRecentAppsDialogHeldModifiers) == 0) {
+            mRecentAppsDialogHeldModifiers = 0;
+            showOrHideRecentAppsDialog(RECENT_APPS_BEHAVIOR_DISMISS_AND_SWITCH);
+        }
+
+        // Let the application handle the key.
         return 0;
     }
 
@@ -1722,39 +1789,6 @@
             final KeyCharacterMap kcm = event.getKeyCharacterMap();
             final int keyCode = event.getKeyCode();
             final int metaState = event.getMetaState();
-            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;
-                    }
-                }
-
-                // 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 specified by the key character map.
             if (getFallbackAction(kcm, keyCode, metaState, mFallbackAction)) {
diff --git a/policy/src/com/android/internal/policy/impl/RecentApplicationsDialog.java b/policy/src/com/android/internal/policy/impl/RecentApplicationsDialog.java
index aa00fbdd..b9903dd 100644
--- a/policy/src/com/android/internal/policy/impl/RecentApplicationsDialog.java
+++ b/policy/src/com/android/internal/policy/impl/RecentApplicationsDialog.java
@@ -71,8 +71,6 @@
         }
     };
 
-    private int mHeldModifiers;
-
     public RecentApplicationsDialog(Context context) {
         super(context, com.android.internal.R.style.Theme_Dialog_RecentApplications);
 
@@ -124,17 +122,6 @@
         }
     }
 
-    /**
-     * 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_TAB) {
@@ -174,30 +161,27 @@
         return super.onKeyDown(keyCode, event);
     }
 
-    @Override
-    public boolean onKeyUp(int keyCode, KeyEvent event) {
-        if (mHeldModifiers != 0 && (event.getModifiers() & mHeldModifiers) == 0) {
-            final int numIcons = mIcons.length;
-            RecentTag tag = null;
-            for (int i = 0; i < numIcons; i++) {
-                if (mIcons[i].getVisibility() != View.VISIBLE) {
+    /**
+     * Dismiss the dialog and switch to the selected application.
+     */
+    public void dismissAndSwitch() {
+        final int numIcons = mIcons.length;
+        RecentTag tag = null;
+        for (int i = 0; i < numIcons; i++) {
+            if (mIcons[i].getVisibility() != View.VISIBLE) {
+                break;
+            }
+            if (i == 0 || mIcons[i].hasFocus()) {
+                tag = (RecentTag) mIcons[i].getTag();
+                if (mIcons[i].hasFocus()) {
                     break;
                 }
-                if (i == 0 || mIcons[i].hasFocus()) {
-                    tag = (RecentTag) mIcons[i].getTag();
-                    if (mIcons[i].hasFocus()) {
-                        break;
-                    }
-                }
             }
-            if (tag != null) {
-                switchTo(tag);
-            }
-            dismiss();
-            return true;
         }
-
-        return super.onKeyUp(keyCode, event);
+        if (tag != null) {
+            switchTo(tag);
+        }
+        dismiss();
     }
 
     /**
diff --git a/services/input/InputDispatcher.cpp b/services/input/InputDispatcher.cpp
index 382f4d9..5f31f05 100644
--- a/services/input/InputDispatcher.cpp
+++ b/services/input/InputDispatcher.cpp
@@ -4312,12 +4312,23 @@
             mKeyMementos.removeAt(index);
             return true;
         }
+        /* FIXME: We can't just drop the key up event because that prevents creating
+         * popup windows that are automatically shown when a key is held and then
+         * dismissed when the key is released.  The problem is that the popup will
+         * not have received the original key down, so the key up will be considered
+         * to be inconsistent with its observed state.  We could perhaps handle this
+         * by synthesizing a key down but that will cause other problems.
+         *
+         * So for now, allow inconsistent key up events to be dispatched.
+         *
 #if DEBUG_OUTBOUND_EVENT_DETAILS
         LOGD("Dropping inconsistent key up event: deviceId=%d, source=%08x, "
                 "keyCode=%d, scanCode=%d",
                 entry->deviceId, entry->source, entry->keyCode, entry->scanCode);
 #endif
         return false;
+        */
+        return true;
     }
 
     case AKEY_EVENT_ACTION_DOWN: {