am e0e9fd98
: Merge "Fix system hotkey handling." into ics-mr1
* commit 'e0e9fd981ca71aeaa45c888485c11788456bd838': Fix system hotkey handling.
This commit is contained in:
@ -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>
|
||||
|
@ -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();
|
||||
|
@ -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)) {
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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: {
|
||||
|
Reference in New Issue
Block a user