Skip to content

Commit e0e9fd9

Browse files
Jeff BrownAndroid (Google) Code Review
authored andcommitted
Merge "Fix system hotkey handling." into ics-mr1
2 parents ef8913c + 68b909d commit e0e9fd9

File tree

5 files changed

+114
-79
lines changed

5 files changed

+114
-79
lines changed

core/res/res/values/themes.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -810,7 +810,7 @@ please see themes_device_defaults.xml.
810810

811811
<!-- Special theme for the recent apps dialog, to allow customization
812812
with overlays. -->
813-
<style name="Theme.Dialog.RecentApplications">
813+
<style name="Theme.Dialog.RecentApplications" parent="Theme.DeviceDefault.Dialog">
814814
<item name="windowFrame">@null</item>
815815
<item name="windowBackground">@android:color/transparent</item>
816816
<item name="android:windowAnimationStyle">@android:style/Animation.RecentApplications</item>

policy/src/com/android/internal/policy/impl/IconUtilities.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@
3838
import android.text.TextPaint;
3939
import android.util.DisplayMetrics;
4040
import android.util.Log;
41+
import android.util.TypedValue;
42+
import android.view.ContextThemeWrapper;
4143
import android.content.res.Resources;
4244
import android.content.Context;
4345

@@ -74,9 +76,13 @@ public IconUtilities(Context context) {
7476
mIconTextureWidth = mIconTextureHeight = mIconWidth + (int)(blurPx*2);
7577

7678
mBlurPaint.setMaskFilter(new BlurMaskFilter(blurPx, BlurMaskFilter.Blur.NORMAL));
77-
mGlowColorPressedPaint.setColor(0xffffc300);
79+
80+
TypedValue value = new TypedValue();
81+
mGlowColorPressedPaint.setColor(context.getTheme().resolveAttribute(
82+
android.R.attr.colorPressedHighlight, value, true) ? value.data : 0xffffc300);
7883
mGlowColorPressedPaint.setMaskFilter(TableMaskFilter.CreateClipTable(0, 30));
79-
mGlowColorFocusedPaint.setColor(0xffff8e00);
84+
mGlowColorFocusedPaint.setColor(context.getTheme().resolveAttribute(
85+
android.R.attr.colorFocusedHighlight, value, true) ? value.data : 0xffff8e00);
8086
mGlowColorFocusedPaint.setMaskFilter(TableMaskFilter.CreateClipTable(0, 30));
8187

8288
ColorMatrix cm = new ColorMatrix();

policy/src/com/android/internal/policy/impl/PhoneWindowManager.java

Lines changed: 77 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -298,9 +298,15 @@ public class PhoneWindowManager implements WindowManagerPolicy {
298298
GlobalActions mGlobalActions;
299299
volatile boolean mPowerKeyHandled; // accessed from input reader and handler thread
300300
boolean mPendingPowerKeyUpCanceled;
301-
RecentApplicationsDialog mRecentAppsDialog;
302301
Handler mHandler;
303302

303+
static final int RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS = 0;
304+
static final int RECENT_APPS_BEHAVIOR_EXIT_TOUCH_MODE_AND_SHOW = 1;
305+
static final int RECENT_APPS_BEHAVIOR_DISMISS_AND_SWITCH = 2;
306+
307+
RecentApplicationsDialog mRecentAppsDialog;
308+
int mRecentAppsDialogHeldModifiers;
309+
304310
private static final int LID_ABSENT = -1;
305311
private static final int LID_CLOSED = 0;
306312
private static final int LID_OPEN = 1;
@@ -693,7 +699,7 @@ private void handleLongPressOnHome() {
693699
}
694700

695701
if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_DIALOG) {
696-
showOrHideRecentAppsDialog(0, true /*dismissIfShown*/);
702+
showOrHideRecentAppsDialog(RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS);
697703
} else if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_SYSTEM_UI) {
698704
try {
699705
mStatusBarService.toggleRecentApps();
@@ -704,23 +710,44 @@ private void handleLongPressOnHome() {
704710
}
705711

706712
/**
707-
* Create (if necessary) and launch the recent apps dialog, or hide it if it is
708-
* already shown.
713+
* Create (if necessary) and show or dismiss the recent apps dialog according
714+
* according to the requested behavior.
709715
*/
710-
void showOrHideRecentAppsDialog(final int heldModifiers, final boolean dismissIfShown) {
716+
void showOrHideRecentAppsDialog(final int behavior) {
711717
mHandler.post(new Runnable() {
712718
@Override
713719
public void run() {
714720
if (mRecentAppsDialog == null) {
715721
mRecentAppsDialog = new RecentApplicationsDialog(mContext);
716722
}
717723
if (mRecentAppsDialog.isShowing()) {
718-
if (dismissIfShown) {
719-
mRecentAppsDialog.dismiss();
724+
switch (behavior) {
725+
case RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS:
726+
mRecentAppsDialog.dismiss();
727+
break;
728+
case RECENT_APPS_BEHAVIOR_DISMISS_AND_SWITCH:
729+
mRecentAppsDialog.dismissAndSwitch();
730+
break;
731+
case RECENT_APPS_BEHAVIOR_EXIT_TOUCH_MODE_AND_SHOW:
732+
default:
733+
break;
720734
}
721735
} else {
722-
mRecentAppsDialog.setHeldModifiers(heldModifiers);
723-
mRecentAppsDialog.show();
736+
switch (behavior) {
737+
case RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS:
738+
mRecentAppsDialog.show();
739+
break;
740+
case RECENT_APPS_BEHAVIOR_EXIT_TOUCH_MODE_AND_SHOW:
741+
try {
742+
mWindowManager.setInTouchMode(false);
743+
} catch (RemoteException e) {
744+
}
745+
mRecentAppsDialog.show();
746+
break;
747+
case RECENT_APPS_BEHAVIOR_DISMISS_AND_SWITCH:
748+
default:
749+
break;
750+
}
724751
}
725752
}
726753
});
@@ -1598,7 +1625,7 @@ public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int p
15981625
return 0;
15991626
} else if (keyCode == KeyEvent.KEYCODE_APP_SWITCH) {
16001627
if (down && repeatCount == 0) {
1601-
showOrHideRecentAppsDialog(0, true /*dismissIfShown*/);
1628+
showOrHideRecentAppsDialog(RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS);
16021629
}
16031630
return -1;
16041631
}
@@ -1634,6 +1661,26 @@ public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int p
16341661
}
16351662
}
16361663

1664+
// Invoke shortcuts using Meta.
1665+
if (down && repeatCount == 0
1666+
&& (metaState & KeyEvent.META_META_ON) != 0) {
1667+
final KeyCharacterMap kcm = event.getKeyCharacterMap();
1668+
Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode,
1669+
metaState & ~(KeyEvent.META_META_ON
1670+
| KeyEvent.META_META_LEFT_ON | KeyEvent.META_META_RIGHT_ON));
1671+
if (shortcutIntent != null) {
1672+
shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1673+
try {
1674+
mContext.startActivity(shortcutIntent);
1675+
} catch (ActivityNotFoundException ex) {
1676+
Slog.w(TAG, "Dropping shortcut key combination because "
1677+
+ "the activity to which it is registered was not found: "
1678+
+ "META+" + KeyEvent.keyCodeToString(keyCode), ex);
1679+
}
1680+
return -1;
1681+
}
1682+
}
1683+
16371684
// Handle application launch keys.
16381685
if (down && repeatCount == 0) {
16391686
String category = sApplicationLaunchKeyCategories.get(keyCode);
@@ -1647,9 +1694,29 @@ public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int p
16471694
+ "the activity to which it is registered was not found: "
16481695
+ "keyCode=" + keyCode + ", category=" + category, ex);
16491696
}
1697+
return -1;
16501698
}
16511699
}
16521700

1701+
// Display task switcher for ALT-TAB or Meta-TAB.
1702+
if (down && repeatCount == 0 && keyCode == KeyEvent.KEYCODE_TAB) {
1703+
if (mRecentAppsDialogHeldModifiers == 0) {
1704+
final int shiftlessModifiers = event.getModifiers() & ~KeyEvent.META_SHIFT_MASK;
1705+
if (KeyEvent.metaStateHasModifiers(shiftlessModifiers, KeyEvent.META_ALT_ON)
1706+
|| KeyEvent.metaStateHasModifiers(
1707+
shiftlessModifiers, KeyEvent.META_META_ON)) {
1708+
mRecentAppsDialogHeldModifiers = shiftlessModifiers;
1709+
showOrHideRecentAppsDialog(RECENT_APPS_BEHAVIOR_EXIT_TOUCH_MODE_AND_SHOW);
1710+
return -1;
1711+
}
1712+
}
1713+
} else if (!down && mRecentAppsDialogHeldModifiers != 0
1714+
&& (metaState & mRecentAppsDialogHeldModifiers) == 0) {
1715+
mRecentAppsDialogHeldModifiers = 0;
1716+
showOrHideRecentAppsDialog(RECENT_APPS_BEHAVIOR_DISMISS_AND_SWITCH);
1717+
}
1718+
1719+
// Let the application handle the key.
16531720
return 0;
16541721
}
16551722

@@ -1671,39 +1738,6 @@ public KeyEvent dispatchUnhandledKey(WindowState win, KeyEvent event, int policy
16711738
final KeyCharacterMap kcm = event.getKeyCharacterMap();
16721739
final int keyCode = event.getKeyCode();
16731740
final int metaState = event.getMetaState();
1674-
final boolean initialDown = event.getAction() == KeyEvent.ACTION_DOWN
1675-
&& event.getRepeatCount() == 0;
1676-
1677-
if (initialDown) {
1678-
// Invoke shortcuts using Meta as a fallback.
1679-
if ((metaState & KeyEvent.META_META_ON) != 0) {
1680-
Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode,
1681-
metaState & ~(KeyEvent.META_META_ON
1682-
| KeyEvent.META_META_LEFT_ON | KeyEvent.META_META_RIGHT_ON));
1683-
if (shortcutIntent != null) {
1684-
shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1685-
try {
1686-
mContext.startActivity(shortcutIntent);
1687-
} catch (ActivityNotFoundException ex) {
1688-
Slog.w(TAG, "Dropping shortcut key combination because "
1689-
+ "the activity to which it is registered was not found: "
1690-
+ "META+" + KeyEvent.keyCodeToString(keyCode), ex);
1691-
}
1692-
return null;
1693-
}
1694-
}
1695-
1696-
// Display task switcher for ALT-TAB or Meta-TAB.
1697-
if (keyCode == KeyEvent.KEYCODE_TAB) {
1698-
final int shiftlessModifiers = event.getModifiers() & ~KeyEvent.META_SHIFT_MASK;
1699-
if (KeyEvent.metaStateHasModifiers(shiftlessModifiers, KeyEvent.META_ALT_ON)
1700-
|| KeyEvent.metaStateHasModifiers(
1701-
shiftlessModifiers, KeyEvent.META_META_ON)) {
1702-
showOrHideRecentAppsDialog(shiftlessModifiers, false /*dismissIfShown*/);
1703-
return null;
1704-
}
1705-
}
1706-
}
17071741

17081742
// Check for fallback actions specified by the key character map.
17091743
if (getFallbackAction(kcm, keyCode, metaState, mFallbackAction)) {

policy/src/com/android/internal/policy/impl/RecentApplicationsDialog.java

Lines changed: 17 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,6 @@ public void run() {
7171
}
7272
};
7373

74-
private int mHeldModifiers;
75-
7674
public RecentApplicationsDialog(Context context) {
7775
super(context, com.android.internal.R.style.Theme_Dialog_RecentApplications);
7876

@@ -124,17 +122,6 @@ protected void onCreate(Bundle savedInstanceState) {
124122
}
125123
}
126124

127-
/**
128-
* Sets the modifier keys that are being held to keep the dialog open, or 0 if none.
129-
* Used to make the recent apps dialog automatically dismiss itself when the modifiers
130-
* all go up.
131-
* @param heldModifiers The held key modifiers, such as {@link KeyEvent#META_ALT_ON}.
132-
* Should exclude shift.
133-
*/
134-
public void setHeldModifiers(int heldModifiers) {
135-
mHeldModifiers = heldModifiers;
136-
}
137-
138125
@Override
139126
public boolean onKeyDown(int keyCode, KeyEvent event) {
140127
if (keyCode == KeyEvent.KEYCODE_TAB) {
@@ -174,30 +161,27 @@ public boolean onKeyDown(int keyCode, KeyEvent event) {
174161
return super.onKeyDown(keyCode, event);
175162
}
176163

177-
@Override
178-
public boolean onKeyUp(int keyCode, KeyEvent event) {
179-
if (mHeldModifiers != 0 && (event.getModifiers() & mHeldModifiers) == 0) {
180-
final int numIcons = mIcons.length;
181-
RecentTag tag = null;
182-
for (int i = 0; i < numIcons; i++) {
183-
if (mIcons[i].getVisibility() != View.VISIBLE) {
164+
/**
165+
* Dismiss the dialog and switch to the selected application.
166+
*/
167+
public void dismissAndSwitch() {
168+
final int numIcons = mIcons.length;
169+
RecentTag tag = null;
170+
for (int i = 0; i < numIcons; i++) {
171+
if (mIcons[i].getVisibility() != View.VISIBLE) {
172+
break;
173+
}
174+
if (i == 0 || mIcons[i].hasFocus()) {
175+
tag = (RecentTag) mIcons[i].getTag();
176+
if (mIcons[i].hasFocus()) {
184177
break;
185178
}
186-
if (i == 0 || mIcons[i].hasFocus()) {
187-
tag = (RecentTag) mIcons[i].getTag();
188-
if (mIcons[i].hasFocus()) {
189-
break;
190-
}
191-
}
192-
}
193-
if (tag != null) {
194-
switchTo(tag);
195179
}
196-
dismiss();
197-
return true;
198180
}
199-
200-
return super.onKeyUp(keyCode, event);
181+
if (tag != null) {
182+
switchTo(tag);
183+
}
184+
dismiss();
201185
}
202186

203187
/**

services/input/InputDispatcher.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4320,12 +4320,23 @@ bool InputDispatcher::InputState::trackKey(const KeyEntry* entry,
43204320
mKeyMementos.removeAt(index);
43214321
return true;
43224322
}
4323+
/* FIXME: We can't just drop the key up event because that prevents creating
4324+
* popup windows that are automatically shown when a key is held and then
4325+
* dismissed when the key is released. The problem is that the popup will
4326+
* not have received the original key down, so the key up will be considered
4327+
* to be inconsistent with its observed state. We could perhaps handle this
4328+
* by synthesizing a key down but that will cause other problems.
4329+
*
4330+
* So for now, allow inconsistent key up events to be dispatched.
4331+
*
43234332
#if DEBUG_OUTBOUND_EVENT_DETAILS
43244333
LOGD("Dropping inconsistent key up event: deviceId=%d, source=%08x, "
43254334
"keyCode=%d, scanCode=%d",
43264335
entry->deviceId, entry->source, entry->keyCode, entry->scanCode);
43274336
#endif
43284337
return false;
4338+
*/
4339+
return true;
43294340
}
43304341

43314342
case AKEY_EVENT_ACTION_DOWN: {

0 commit comments

Comments
 (0)