am eea0aa25: Support primitive ALT-TAB style navigation using Recent Apps. (DO NOT MERGE)
* commit 'eea0aa25870d49e381567f09abbfb41de52a5a32':
Support primitive ALT-TAB style navigation using Recent Apps. (DO NOT MERGE)
diff --git a/data/keyboards/Generic.kcm b/data/keyboards/Generic.kcm
index 51a8b27..ef0a4e6 100644
--- a/data/keyboards/Generic.kcm
+++ b/data/keyboards/Generic.kcm
@@ -287,8 +287,8 @@
key SPACE {
label: ' '
base: ' '
- ctrl, alt: none
- meta: fallback SEARCH
+ ctrl: none
+ alt, meta: fallback SEARCH
}
key ENTER {
@@ -300,8 +300,8 @@
key TAB {
label: '\t'
base: '\t'
- ctrl, alt: none
- meta: fallback APP_SWITCH
+ ctrl: none
+ alt, meta: fallback APP_SWITCH
}
key COMMA {
@@ -542,8 +542,8 @@
key ESCAPE {
base: fallback BACK
- meta: fallback HOME
- alt: fallback MENU
+ alt, meta: fallback HOME
+ ctrl: fallback MENU
}
### Gamepad buttons ###
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 1d406beb..298c587 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -623,7 +623,7 @@
}
if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_DIALOG) {
- showRecentAppsDialog();
+ showRecentAppsDialog(0);
} else if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_ACTIVITY) {
try {
Intent intent = new Intent();
@@ -642,12 +642,12 @@
/**
* Create (if necessary) and launch the recent apps dialog
*/
- void showRecentAppsDialog() {
+ void showRecentAppsDialog(final int initialModifiers) {
mHandler.post(new Runnable() {
@Override
public void run() {
if (mRecentAppsDialog == null) {
- mRecentAppsDialog = new RecentApplicationsDialog(mContext);
+ mRecentAppsDialog = new RecentApplicationsDialog(mContext, initialModifiers);
}
mRecentAppsDialog.show();
}
@@ -1433,7 +1433,7 @@
return false;
} else if (keyCode == KeyEvent.KEYCODE_APP_SWITCH) {
if (down && repeatCount == 0) {
- showRecentAppsDialog();
+ showRecentAppsDialog(event.getMetaState() & KeyEvent.getModifierMetaStateMask());
}
return true;
}
diff --git a/policy/src/com/android/internal/policy/impl/RecentApplicationsDialog.java b/policy/src/com/android/internal/policy/impl/RecentApplicationsDialog.java
index db66346..c4b7822 100644
--- a/policy/src/com/android/internal/policy/impl/RecentApplicationsDialog.java
+++ b/policy/src/com/android/internal/policy/impl/RecentApplicationsDialog.java
@@ -17,16 +17,13 @@
package com.android.internal.policy.impl;
import android.app.ActivityManager;
-import android.app.ActivityManagerNative;
import android.app.Dialog;
-import android.app.IActivityManager;
import android.app.StatusBarManager;
import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.content.res.Resources;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
@@ -34,6 +31,8 @@
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
+import android.view.KeyEvent;
+import android.view.SoundEffectConstants;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
@@ -72,13 +71,12 @@
}
};
- private int mIconSize;
+ private int mInitialModifiers;
- public RecentApplicationsDialog(Context context) {
+ public RecentApplicationsDialog(Context context, int initialModifiers) {
super(context, com.android.internal.R.style.Theme_Dialog_RecentApplications);
- final Resources resources = context.getResources();
- mIconSize = (int) resources.getDimension(android.R.dimen.app_icon_size);
+ mInitialModifiers = initialModifiers;
}
/**
@@ -127,34 +125,102 @@
}
}
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ if (keyCode == KeyEvent.KEYCODE_APP_SWITCH || keyCode == KeyEvent.KEYCODE_TAB) {
+ // 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.
+ // DPad navigation is handled by the ViewRoot elsewhere.
+ final boolean backward = event.isShiftPressed();
+ final int numIcons = mIcons.length;
+ int numButtons = 0;
+ while (numButtons < numIcons && mIcons[numButtons].getVisibility() == View.VISIBLE) {
+ numButtons += 1;
+ }
+ if (numButtons != 0) {
+ int nextFocus = backward ? numButtons - 1 : 0;
+ for (int i = 0; i < numButtons; i++) {
+ if (mIcons[i].hasFocus()) {
+ if (backward) {
+ nextFocus = (i + numButtons - 1) % numButtons;
+ } else {
+ nextFocus = (i + 1) % numButtons;
+ }
+ break;
+ }
+ }
+ final int direction = backward ? View.FOCUS_BACKWARD : View.FOCUS_FORWARD;
+ if (mIcons[nextFocus].requestFocus(direction)) {
+ mIcons[nextFocus].playSoundEffect(
+ SoundEffectConstants.getContantForFocusDirection(direction));
+ }
+ }
+
+ // The dialog always handles the key to prevent the ViewRoot from
+ // performing the default navigation itself.
+ return true;
+ }
+
+ return super.onKeyDown(keyCode, event);
+ }
+
+ @Override
+ public boolean onKeyUp(int keyCode, KeyEvent event) {
+ if (mInitialModifiers != 0 && event.hasNoModifiers()) {
+ 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 (tag != null) {
+ switchTo(tag);
+ }
+ dismiss();
+ return true;
+ }
+
+ return super.onKeyUp(keyCode, event);
+ }
+
/**
* Handler for user clicks. If a button was clicked, launch the corresponding activity.
*/
public void onClick(View v) {
-
for (TextView b: mIcons) {
if (b == v) {
RecentTag tag = (RecentTag)b.getTag();
- if (tag.info.id >= 0) {
- // This is an active task; it should just go to the foreground.
- final ActivityManager am = (ActivityManager)
- getContext().getSystemService(Context.ACTIVITY_SERVICE);
- am.moveTaskToFront(tag.info.id, ActivityManager.MOVE_TASK_WITH_HOME);
- } else if (tag.intent != null) {
- tag.intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY
- | Intent.FLAG_ACTIVITY_TASK_ON_HOME);
- try {
- getContext().startActivity(tag.intent);
- } catch (ActivityNotFoundException e) {
- Log.w("Recent", "Unable to launch recent task", e);
- }
- }
+ switchTo(tag);
break;
}
}
dismiss();
}
+ private void switchTo(RecentTag tag) {
+ if (tag.info.id >= 0) {
+ // This is an active task; it should just go to the foreground.
+ final ActivityManager am = (ActivityManager)
+ getContext().getSystemService(Context.ACTIVITY_SERVICE);
+ am.moveTaskToFront(tag.info.id, ActivityManager.MOVE_TASK_WITH_HOME);
+ } else if (tag.intent != null) {
+ tag.intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY
+ | Intent.FLAG_ACTIVITY_TASK_ON_HOME);
+ try {
+ getContext().startActivity(tag.intent);
+ } catch (ActivityNotFoundException e) {
+ Log.w("Recent", "Unable to launch recent task", e);
+ }
+ }
+ }
+
/**
* Set up and show the recent activities dialog.
*/