Minor Alt-TAB / Recent Apps Dialog improvements. (DO NOT MERGE)
Alt-TAB should have different semantics from the APP_SWITCH key or long-press on HOME. Accordingly, remove the fallback action for Alt-TAB and initiate the task switching behavior directly in the policy. Modified RecentApplicationsDialog to be more precise about the initial modifiers that it considers to be holding the dialog. The dialog is now dismissed by a second press on the APP_SWITCH key or by a second long press on HOME. Change-Id: I07e72dc4e1f3cd8edaf357c1d49e79f60d6d1604
This commit is contained in:
@ -212956,6 +212956,17 @@
|
|||||||
visibility="public"
|
visibility="public"
|
||||||
>
|
>
|
||||||
</method>
|
</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"
|
<method name="getNumber"
|
||||||
return="char"
|
return="char"
|
||||||
abstract="false"
|
abstract="false"
|
||||||
|
@ -1741,11 +1741,32 @@ public class KeyEvent extends InputEvent implements Parcelable {
|
|||||||
* @see #META_CAPS_LOCK_ON
|
* @see #META_CAPS_LOCK_ON
|
||||||
* @see #META_NUM_LOCK_ON
|
* @see #META_NUM_LOCK_ON
|
||||||
* @see #META_SCROLL_LOCK_ON
|
* @see #META_SCROLL_LOCK_ON
|
||||||
|
* @see #getModifiers
|
||||||
*/
|
*/
|
||||||
public final int getMetaState() {
|
public final int getMetaState() {
|
||||||
return mMetaState;
|
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.
|
* Returns the flags for this key event.
|
||||||
*
|
*
|
||||||
|
@ -300,8 +300,7 @@ key ENTER {
|
|||||||
key TAB {
|
key TAB {
|
||||||
label: '\t'
|
label: '\t'
|
||||||
base: '\t'
|
base: '\t'
|
||||||
ctrl: none
|
ctrl, alt, meta: none
|
||||||
alt, meta: fallback APP_SWITCH
|
|
||||||
}
|
}
|
||||||
|
|
||||||
key COMMA {
|
key COMMA {
|
||||||
|
@ -623,7 +623,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_DIALOG) {
|
if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_DIALOG) {
|
||||||
showRecentAppsDialog(0);
|
showOrHideRecentAppsDialog(0, true /*dismissIfShown*/);
|
||||||
} else if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_ACTIVITY) {
|
} else if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_ACTIVITY) {
|
||||||
try {
|
try {
|
||||||
Intent intent = new Intent();
|
Intent intent = new Intent();
|
||||||
@ -640,16 +640,24 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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() {
|
mHandler.post(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if (mRecentAppsDialog == null) {
|
if (mRecentAppsDialog == null) {
|
||||||
mRecentAppsDialog = new RecentApplicationsDialog(mContext, initialModifiers);
|
mRecentAppsDialog = new RecentApplicationsDialog(mContext);
|
||||||
|
}
|
||||||
|
if (mRecentAppsDialog.isShowing()) {
|
||||||
|
if (dismissIfShown) {
|
||||||
|
mRecentAppsDialog.dismiss();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
mRecentAppsDialog.setHeldModifiers(heldModifiers);
|
||||||
|
mRecentAppsDialog.show();
|
||||||
}
|
}
|
||||||
mRecentAppsDialog.show();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -1433,7 +1441,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
|||||||
return false;
|
return false;
|
||||||
} else if (keyCode == KeyEvent.KEYCODE_APP_SWITCH) {
|
} else if (keyCode == KeyEvent.KEYCODE_APP_SWITCH) {
|
||||||
if (down && repeatCount == 0) {
|
if (down && repeatCount == 0) {
|
||||||
showRecentAppsDialog(event.getMetaState() & KeyEvent.getModifierMetaStateMask());
|
showOrHideRecentAppsDialog(0, true /*dismissIfShown*/);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1475,6 +1483,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
|||||||
/** {@inheritDoc} */
|
/** {@inheritDoc} */
|
||||||
@Override
|
@Override
|
||||||
public KeyEvent dispatchUnhandledKey(WindowState win, KeyEvent event, int policyFlags) {
|
public KeyEvent dispatchUnhandledKey(WindowState win, KeyEvent event, int policyFlags) {
|
||||||
|
// Note: This method is only called if the initial down was unhandled.
|
||||||
if (DEBUG_FALLBACK) {
|
if (DEBUG_FALLBACK) {
|
||||||
Slog.d(TAG, "Unhandled key: win=" + win + ", action=" + event.getAction()
|
Slog.d(TAG, "Unhandled key: win=" + win + ", action=" + event.getAction()
|
||||||
+ ", flags=" + event.getFlags()
|
+ ", flags=" + event.getFlags()
|
||||||
@ -1486,28 +1495,44 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
|
if ((event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
|
||||||
// Invoke shortcuts using Meta as a fallback.
|
|
||||||
final KeyCharacterMap kcm = event.getKeyCharacterMap();
|
final KeyCharacterMap kcm = event.getKeyCharacterMap();
|
||||||
final int keyCode = event.getKeyCode();
|
final int keyCode = event.getKeyCode();
|
||||||
final int metaState = event.getMetaState();
|
final int metaState = event.getMetaState();
|
||||||
if ((metaState & KeyEvent.META_META_ON) != 0) {
|
final boolean initialDown = event.getAction() == KeyEvent.ACTION_DOWN
|
||||||
Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode,
|
&& event.getRepeatCount() == 0;
|
||||||
metaState & ~(KeyEvent.META_META_ON
|
|
||||||
| KeyEvent.META_META_LEFT_ON | KeyEvent.META_META_RIGHT_ON));
|
if (initialDown) {
|
||||||
if (shortcutIntent != null) {
|
// Invoke shortcuts using Meta as a fallback.
|
||||||
shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
if ((metaState & KeyEvent.META_META_ON) != 0) {
|
||||||
try {
|
Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode,
|
||||||
mContext.startActivity(shortcutIntent);
|
metaState & ~(KeyEvent.META_META_ON
|
||||||
} catch (ActivityNotFoundException ex) {
|
| KeyEvent.META_META_LEFT_ON | KeyEvent.META_META_RIGHT_ON));
|
||||||
Slog.w(TAG, "Dropping shortcut key combination because "
|
if (shortcutIntent != null) {
|
||||||
+ "the activity to which it is registered was not found: "
|
shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
+ "META+" + KeyEvent.keyCodeToString(keyCode), ex);
|
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;
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for fallback actions.
|
// Check for fallback actions specified by the key character map.
|
||||||
if (getFallbackAction(kcm, keyCode, metaState, mFallbackAction)) {
|
if (getFallbackAction(kcm, keyCode, metaState, mFallbackAction)) {
|
||||||
if (DEBUG_FALLBACK) {
|
if (DEBUG_FALLBACK) {
|
||||||
Slog.d(TAG, "Fallback: keyCode=" + mFallbackAction.keyCode
|
Slog.d(TAG, "Fallback: keyCode=" + mFallbackAction.keyCode
|
||||||
|
@ -71,12 +71,11 @@ public class RecentApplicationsDialog extends Dialog implements OnClickListener
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
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);
|
super(context, com.android.internal.R.style.Theme_Dialog_RecentApplications);
|
||||||
|
|
||||||
mInitialModifiers = initialModifiers;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -125,9 +124,20 @@ 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
|
@Override
|
||||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
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
|
// 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.
|
// fallback action chorded with ALT, META or even CTRL depending on the key map.
|
||||||
// DPad navigation is handled by the ViewRoot elsewhere.
|
// DPad navigation is handled by the ViewRoot elsewhere.
|
||||||
@ -166,7 +176,7 @@ public class RecentApplicationsDialog extends Dialog implements OnClickListener
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onKeyUp(int keyCode, KeyEvent event) {
|
public boolean onKeyUp(int keyCode, KeyEvent event) {
|
||||||
if (mInitialModifiers != 0 && event.hasNoModifiers()) {
|
if (mHeldModifiers != 0 && (event.getModifiers() & mHeldModifiers) == 0) {
|
||||||
final int numIcons = mIcons.length;
|
final int numIcons = mIcons.length;
|
||||||
RecentTag tag = null;
|
RecentTag tag = null;
|
||||||
for (int i = 0; i < numIcons; i++) {
|
for (int i = 0; i < numIcons; i++) {
|
||||||
|
Reference in New Issue
Block a user