diff options
3 files changed, 98 insertions, 32 deletions
diff --git a/data/keyboards/Generic.kcm b/data/keyboards/Generic.kcm index 51a8b27bc877..ef0a4e624bfe 100644 --- a/data/keyboards/Generic.kcm +++ b/data/keyboards/Generic.kcm @@ -287,8 +287,8 @@ key 9 { key SPACE { label: ' ' base: ' ' - ctrl, alt: none - meta: fallback SEARCH + ctrl: none + alt, meta: fallback SEARCH } key ENTER { @@ -300,8 +300,8 @@ key ENTER { 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 PLUS { 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 4fa5bcbd1570..44f55b3296c7 100755 --- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java @@ -626,7 +626,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { } if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_DIALOG) { - showRecentAppsDialog(); + showRecentAppsDialog(0); } else if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_ACTIVITY) { try { Intent intent = new Intent(); @@ -645,12 +645,12 @@ public class PhoneWindowManager implements WindowManagerPolicy { /** * 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(); } @@ -1392,7 +1392,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { 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 db66346ff57d..c4b78222746d 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.graphics.drawable.Drawable; 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 @@ public class RecentApplicationsDialog extends Dialog implements OnClickListener } }; - 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 @@ public class RecentApplicationsDialog extends Dialog implements OnClickListener } } + @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. */ |