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

* commit 'e0e9fd981ca71aeaa45c888485c11788456bd838':
  Fix system hotkey handling.
This commit is contained in:
Jeff Brown
2011-12-07 23:31:02 -08:00
committed by Android Git Automerger
5 changed files with 114 additions and 79 deletions

View File

@ -810,7 +810,7 @@ please see themes_device_defaults.xml.
<!-- 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>

View File

@ -38,6 +38,8 @@ import android.text.StaticLayout;
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 @@ final class IconUtilities {
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();

View File

@ -298,9 +298,15 @@ public class PhoneWindowManager implements WindowManagerPolicy {
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;
@ -693,7 +699,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
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();
@ -704,10 +710,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
/**
* 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() {
@ -715,12 +721,33 @@ public class PhoneWindowManager implements WindowManagerPolicy {
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;
}
}
}
});
@ -1598,7 +1625,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
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;
}
@ -1634,6 +1661,26 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
}
// 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);
@ -1647,9 +1694,29 @@ public class PhoneWindowManager implements WindowManagerPolicy {
+ "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;
}
@ -1671,39 +1738,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
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)) {

View File

@ -71,8 +71,6 @@ public class RecentApplicationsDialog extends Dialog implements OnClickListener
}
};
private int mHeldModifiers;
public RecentApplicationsDialog(Context context) {
super(context, com.android.internal.R.style.Theme_Dialog_RecentApplications);
@ -124,17 +122,6 @@ public class RecentApplicationsDialog extends Dialog implements OnClickListener
}
}
/**
* 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 @@ public class RecentApplicationsDialog extends Dialog implements OnClickListener
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();
}
/**

View File

@ -4320,12 +4320,23 @@ bool InputDispatcher::InputState::trackKey(const KeyEntry* entry,
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: {