diff --git a/api/current.txt b/api/current.txt index 690fec7fdbb2b..f7651168205d7 100644 --- a/api/current.txt +++ b/api/current.txt @@ -41649,9 +41649,11 @@ package android.view { } public final class KeyboardShortcutInfo implements android.os.Parcelable { + ctor public KeyboardShortcutInfo(java.lang.CharSequence, int, int); ctor public KeyboardShortcutInfo(java.lang.CharSequence, char, int); method public int describeContents(); method public char getBaseCharacter(); + method public int getKeycode(); method public java.lang.CharSequence getLabel(); method public int getModifiers(); method public void writeToParcel(android.os.Parcel, int); diff --git a/api/system-current.txt b/api/system-current.txt index f06e545628679..96c4ba1148f3d 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -44375,9 +44375,11 @@ package android.view { } public final class KeyboardShortcutInfo implements android.os.Parcelable { + ctor public KeyboardShortcutInfo(java.lang.CharSequence, int, int); ctor public KeyboardShortcutInfo(java.lang.CharSequence, char, int); method public int describeContents(); method public char getBaseCharacter(); + method public int getKeycode(); method public java.lang.CharSequence getLabel(); method public int getModifiers(); method public void writeToParcel(android.os.Parcel, int); diff --git a/api/test-current.txt b/api/test-current.txt index 4afda9cfe65e2..6e8236002181d 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -41722,9 +41722,11 @@ package android.view { } public final class KeyboardShortcutInfo implements android.os.Parcelable { + ctor public KeyboardShortcutInfo(java.lang.CharSequence, int, int); ctor public KeyboardShortcutInfo(java.lang.CharSequence, char, int); method public int describeContents(); method public char getBaseCharacter(); + method public int getKeycode(); method public java.lang.CharSequence getLabel(); method public int getModifiers(); method public void writeToParcel(android.os.Parcel, int); diff --git a/core/java/android/view/KeyboardShortcutInfo.java b/core/java/android/view/KeyboardShortcutInfo.java index 2c9006deb1899..c2bd347687a6c 100644 --- a/core/java/android/view/KeyboardShortcutInfo.java +++ b/core/java/android/view/KeyboardShortcutInfo.java @@ -30,31 +30,46 @@ public final class KeyboardShortcutInfo implements Parcelable { private final CharSequence mLabel; private final Icon mIcon; private final char mBaseCharacter; + private final int mKeycode; private final int mModifiers; /** * @param label The label that identifies the action performed by this shortcut. * @param icon An icon that identifies the action performed by this shortcut. - * @param baseCharacter The character that triggers the shortcut. + * @param keycode The keycode that triggers the shortcut. This should be a valid constant + * defined in {@link KeyEvent}. * @param modifiers The set of modifiers that, combined with the key, trigger the shortcut. * These should be a combination of {@link KeyEvent#META_CTRL_ON}, - * {@link KeyEvent#META_SHIFT_ON}, {@link KeyEvent#META_META_ON} and - * {@link KeyEvent#META_ALT_ON}. + * {@link KeyEvent#META_SHIFT_ON}, {@link KeyEvent#META_META_ON}, + * {@link KeyEvent#META_ALT_ON}, {@link KeyEvent#META_FUNCTION_ON} and + * {@link KeyEvent#META_SYM_ON}. * * @hide */ public KeyboardShortcutInfo( - @Nullable CharSequence label, @Nullable Icon icon, char baseCharacter, int modifiers) { + @Nullable CharSequence label, @Nullable Icon icon, int keycode, int modifiers) { mLabel = label; mIcon = icon; - checkArgument(baseCharacter != MIN_VALUE); - mBaseCharacter = baseCharacter; + mBaseCharacter = MIN_VALUE; + checkArgument(keycode > KeyEvent.KEYCODE_UNKNOWN && keycode <= KeyEvent.getMaxKeyCode()); + mKeycode = keycode; mModifiers = modifiers; } /** - * Convenience constructor for shortcuts with a label and no icon. - * + * @param label The label that identifies the action performed by this shortcut. + * @param keycode The keycode that triggers the shortcut. This should be a valid constant + * defined in {@link KeyEvent}. + * @param modifiers The set of modifiers that, combined with the key, trigger the shortcut. + * These should be a combination of {@link KeyEvent#META_CTRL_ON}, + * {@link KeyEvent#META_SHIFT_ON}, {@link KeyEvent#META_META_ON} and + * {@link KeyEvent#META_ALT_ON}. + */ + public KeyboardShortcutInfo(CharSequence label, int keycode, int modifiers) { + this(label, null, keycode, modifiers); + } + + /** * @param label The label that identifies the action performed by this shortcut. * @param baseCharacter The character that triggers the shortcut. * @param modifiers The set of modifiers that, combined with the key, trigger the shortcut. @@ -66,14 +81,16 @@ public final class KeyboardShortcutInfo implements Parcelable { mLabel = label; checkArgument(baseCharacter != MIN_VALUE); mBaseCharacter = baseCharacter; + mKeycode = KeyEvent.KEYCODE_UNKNOWN; mModifiers = modifiers; mIcon = null; } private KeyboardShortcutInfo(Parcel source) { mLabel = source.readCharSequence(); - mIcon = (Icon) source.readParcelable(null); + mIcon = source.readParcelable(null); mBaseCharacter = (char) source.readInt(); + mKeycode = source.readInt(); mModifiers = source.readInt(); } @@ -96,7 +113,16 @@ public final class KeyboardShortcutInfo implements Parcelable { } /** - * Returns the base character that, combined with the modifiers, triggers this shortcut. + * Returns the base keycode that, combined with the modifiers, triggers this shortcut. If the + * base character was set instead, returns {@link KeyEvent#KEYCODE_UNKNOWN}. + */ + public int getKeycode() { + return mKeycode; + } + + /** + * Returns the base character that, combined with the modifiers, triggers this shortcut. If the + * keycode was set instead, returns {@link Character#MIN_VALUE}. */ public char getBaseCharacter() { return mBaseCharacter; @@ -119,6 +145,7 @@ public final class KeyboardShortcutInfo implements Parcelable { dest.writeCharSequence(mLabel); dest.writeParcelable(mIcon, 0); dest.writeInt(mBaseCharacter); + dest.writeInt(mKeycode); dest.writeInt(mModifiers); } diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl index 64c5b8de46a9c..b243cac291822 100644 --- a/core/java/com/android/internal/statusbar/IStatusBar.aidl +++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl @@ -65,7 +65,7 @@ oneway interface IStatusBar void cancelPreloadRecentApps(); void showScreenPinningRequest(); - void toggleKeyboardShortcutsMenu(); + void toggleKeyboardShortcutsMenu(int deviceId); /** * Notifies the status bar that an app transition is pending to delay applying some flags with diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl index 8acf5d3070d39..ee3f9379b03ef 100644 --- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl +++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl @@ -71,7 +71,7 @@ interface IStatusBarService void preloadRecentApps(); void cancelPreloadRecentApps(); - void toggleKeyboardShortcutsMenu(); + void toggleKeyboardShortcutsMenu(int deviceId); /** * Notifies the status bar that an app transition is pending to delay applying some flags with diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index c9aa714e1fe29..6f0f30d26f2e8 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -1327,6 +1327,59 @@ Reduces performance and background data + + Button %1$s + + Home + + Back + + Up + + Down + + Left + + Right + + Center + + Tab + + Space + + Enter + + Backspace + + Play/Pause + + Stop + + Next + + Previous + + Rewind + + Fast Forward + + Page Up + + Page Down + + Delete + + Home + + End + + Insert + + Num Lock + + Numpad %1$s + System diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java index ec56727bc040f..35f6db213adb3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java @@ -1210,10 +1210,10 @@ public abstract class BaseStatusBar extends SystemUI implements } @Override - public void toggleKeyboardShortcutsMenu() { + public void toggleKeyboardShortcutsMenu(int deviceId) { int msg = MSG_TOGGLE_KEYBOARD_SHORTCUTS_MENU; mHandler.removeMessages(msg); - mHandler.sendEmptyMessage(msg); + mHandler.obtainMessage(msg, deviceId, 0).sendToTarget(); } /** Jumps to the next affiliated task in the group. */ @@ -1299,8 +1299,8 @@ public abstract class BaseStatusBar extends SystemUI implements } } - protected void toggleKeyboardShortcuts() { - getKeyboardShortcuts().toggleKeyboardShortcuts(); + protected void toggleKeyboardShortcuts(int deviceId) { + getKeyboardShortcuts().toggleKeyboardShortcuts(deviceId); } protected void cancelPreloadingRecents() { @@ -1473,7 +1473,7 @@ public abstract class BaseStatusBar extends SystemUI implements showRecentsPreviousAffiliatedTask(); break; case MSG_TOGGLE_KEYBOARD_SHORTCUTS_MENU: - toggleKeyboardShortcuts(); + toggleKeyboardShortcuts(m.arg1); break; } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java index 6a984887931df..0ffab5b7a141e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java @@ -107,7 +107,7 @@ public class CommandQueue extends IStatusBar.Stub { public void toggleRecentApps(); public void toggleSplitScreen(); public void preloadRecentApps(); - public void toggleKeyboardShortcutsMenu(); + public void toggleKeyboardShortcutsMenu(int deviceId); public void cancelPreloadRecentApps(); public void setWindowState(int window, int state); public void buzzBeepBlinked(); @@ -254,10 +254,10 @@ public class CommandQueue extends IStatusBar.Stub { } @Override - public void toggleKeyboardShortcutsMenu() { + public void toggleKeyboardShortcutsMenu(int deviceId) { synchronized (mLock) { mHandler.removeMessages(MSG_TOGGLE_KEYBOARD_SHORTCUTS); - mHandler.obtainMessage(MSG_TOGGLE_KEYBOARD_SHORTCUTS).sendToTarget(); + mHandler.obtainMessage(MSG_TOGGLE_KEYBOARD_SHORTCUTS, deviceId, 0).sendToTarget(); } } @@ -425,7 +425,7 @@ public class CommandQueue extends IStatusBar.Stub { mCallbacks.cancelPreloadRecentApps(); break; case MSG_TOGGLE_KEYBOARD_SHORTCUTS: - mCallbacks.toggleKeyboardShortcutsMenu(); + mCallbacks.toggleKeyboardShortcutsMenu(msg.arg1); break; case MSG_SET_WINDOW_STATE: mCallbacks.setWindowState(msg.arg1, msg.arg2); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java index 60c2fa61830c4..dc015c69799ef 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java @@ -21,9 +21,14 @@ import android.app.Dialog; import android.content.Context; import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; +import android.hardware.input.InputManager; import android.os.Handler; import android.os.Looper; +import android.util.Log; +import android.util.SparseArray; import android.view.ContextThemeWrapper; +import android.view.InputDevice; +import android.view.KeyCharacterMap; import android.view.KeyEvent; import android.view.KeyboardShortcutGroup; import android.view.KeyboardShortcutInfo; @@ -42,16 +47,155 @@ import java.util.ArrayList; import java.util.List; import static android.content.Context.LAYOUT_INFLATER_SERVICE; -import static android.view.Gravity.TOP; import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG; /** * Contains functionality for handling keyboard shortcuts. */ public class KeyboardShortcuts { - private static final char SYSTEM_HOME_BASE_CHARACTER = '\u2386'; - private static final char SYSTEM_BACK_BASE_CHARACTER = '\u007F'; - private static final char SYSTEM_RECENTS_BASE_CHARACTER = '\u0009'; + private static final String TAG = KeyboardShortcuts.class.getSimpleName(); + + private static final SparseArray SPECIAL_CHARACTER_NAMES = new SparseArray<>(); + + private static void loadSpecialCharacterNames(Context context) { + SPECIAL_CHARACTER_NAMES.put( + KeyEvent.KEYCODE_HOME, context.getString(R.string.keyboard_key_home)); + SPECIAL_CHARACTER_NAMES.put( + KeyEvent.KEYCODE_BACK, context.getString(R.string.keyboard_key_back)); + SPECIAL_CHARACTER_NAMES.put( + KeyEvent.KEYCODE_DPAD_UP, context.getString(R.string.keyboard_key_dpad_up)); + SPECIAL_CHARACTER_NAMES.put( + KeyEvent.KEYCODE_DPAD_DOWN, context.getString(R.string.keyboard_key_dpad_down)); + SPECIAL_CHARACTER_NAMES.put( + KeyEvent.KEYCODE_DPAD_LEFT, context.getString(R.string.keyboard_key_dpad_left)); + SPECIAL_CHARACTER_NAMES.put( + KeyEvent.KEYCODE_DPAD_RIGHT, context.getString(R.string.keyboard_key_dpad_right)); + SPECIAL_CHARACTER_NAMES.put( + KeyEvent.KEYCODE_DPAD_CENTER, context.getString(R.string.keyboard_key_dpad_center)); + SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_PERIOD, "."); + SPECIAL_CHARACTER_NAMES.put( + KeyEvent.KEYCODE_TAB, context.getString(R.string.keyboard_key_tab)); + SPECIAL_CHARACTER_NAMES.put( + KeyEvent.KEYCODE_SPACE, context.getString(R.string.keyboard_key_space)); + SPECIAL_CHARACTER_NAMES.put( + KeyEvent.KEYCODE_ENTER, context.getString(R.string.keyboard_key_enter)); + SPECIAL_CHARACTER_NAMES.put( + KeyEvent.KEYCODE_DEL, context.getString(R.string.keyboard_key_backspace)); + SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, + context.getString(R.string.keyboard_key_media_play_pause)); + SPECIAL_CHARACTER_NAMES.put( + KeyEvent.KEYCODE_MEDIA_STOP, context.getString(R.string.keyboard_key_media_stop)); + SPECIAL_CHARACTER_NAMES.put( + KeyEvent.KEYCODE_MEDIA_NEXT, context.getString(R.string.keyboard_key_media_next)); + SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_MEDIA_PREVIOUS, + context.getString(R.string.keyboard_key_media_previous)); + SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_MEDIA_REWIND, + context.getString(R.string.keyboard_key_media_rewind)); + SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_MEDIA_FAST_FORWARD, + context.getString(R.string.keyboard_key_media_fast_forward)); + SPECIAL_CHARACTER_NAMES.put( + KeyEvent.KEYCODE_PAGE_UP, context.getString(R.string.keyboard_key_page_up)); + SPECIAL_CHARACTER_NAMES.put( + KeyEvent.KEYCODE_PAGE_DOWN, context.getString(R.string.keyboard_key_page_down)); + SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BUTTON_A, + context.getString(R.string.keyboard_key_button_template, "A")); + SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BUTTON_B, + context.getString(R.string.keyboard_key_button_template, "B")); + SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BUTTON_C, + context.getString(R.string.keyboard_key_button_template, "C")); + SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BUTTON_X, + context.getString(R.string.keyboard_key_button_template, "X")); + SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BUTTON_Y, + context.getString(R.string.keyboard_key_button_template, "Y")); + SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BUTTON_Z, + context.getString(R.string.keyboard_key_button_template, "Z")); + SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BUTTON_L1, + context.getString(R.string.keyboard_key_button_template, "L1")); + SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BUTTON_R1, + context.getString(R.string.keyboard_key_button_template, "R1")); + SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BUTTON_L2, + context.getString(R.string.keyboard_key_button_template, "L2")); + SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BUTTON_R2, + context.getString(R.string.keyboard_key_button_template, "R2")); + SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BUTTON_START, + context.getString(R.string.keyboard_key_button_template, "Start")); + SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BUTTON_SELECT, + context.getString(R.string.keyboard_key_button_template, "Select")); + SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BUTTON_MODE, + context.getString(R.string.keyboard_key_button_template, "Mode")); + SPECIAL_CHARACTER_NAMES.put( + KeyEvent.KEYCODE_FORWARD_DEL, context.getString(R.string.keyboard_key_forward_del)); + SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_ESCAPE, "Esc"); + SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_SYSRQ, "SysRq"); + SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BREAK, "Break"); + SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_SCROLL_LOCK, "Scroll Lock"); + SPECIAL_CHARACTER_NAMES.put( + KeyEvent.KEYCODE_MOVE_HOME, context.getString(R.string.keyboard_key_move_home)); + SPECIAL_CHARACTER_NAMES.put( + KeyEvent.KEYCODE_MOVE_END, context.getString(R.string.keyboard_key_move_end)); + SPECIAL_CHARACTER_NAMES.put( + KeyEvent.KEYCODE_INSERT, context.getString(R.string.keyboard_key_insert)); + SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_F1, "F1"); + SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_F2, "F2"); + SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_F3, "F3"); + SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_F4, "F4"); + SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_F5, "F5"); + SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_F6, "F6"); + SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_F7, "F7"); + SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_F8, "F8"); + SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_F9, "F9"); + SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_F10, "F10"); + SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_F11, "F11"); + SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_F12, "F12"); + SPECIAL_CHARACTER_NAMES.put( + KeyEvent.KEYCODE_NUM_LOCK, context.getString(R.string.keyboard_key_num_lock)); + SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_0, + context.getString(R.string.keyboard_key_numpad_template, "0")); + SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_1, + context.getString(R.string.keyboard_key_numpad_template, "1")); + SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_2, + context.getString(R.string.keyboard_key_numpad_template, "2")); + SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_3, + context.getString(R.string.keyboard_key_numpad_template, "3")); + SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_4, + context.getString(R.string.keyboard_key_numpad_template, "4")); + SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_5, + context.getString(R.string.keyboard_key_numpad_template, "5")); + SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_6, + context.getString(R.string.keyboard_key_numpad_template, "6")); + SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_7, + context.getString(R.string.keyboard_key_numpad_template, "7")); + SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_8, + context.getString(R.string.keyboard_key_numpad_template, "8")); + SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_9, + context.getString(R.string.keyboard_key_numpad_template, "9")); + SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_DIVIDE, + context.getString(R.string.keyboard_key_numpad_template, "/")); + SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_MULTIPLY, + context.getString(R.string.keyboard_key_numpad_template, "*")); + SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_SUBTRACT, + context.getString(R.string.keyboard_key_numpad_template, "-")); + SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_ADD, + context.getString(R.string.keyboard_key_numpad_template, "+")); + SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_DOT, + context.getString(R.string.keyboard_key_numpad_template, ".")); + SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_COMMA, + context.getString(R.string.keyboard_key_numpad_template, ",")); + SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_ENTER, + context.getString(R.string.keyboard_key_numpad_template, + context.getString(R.string.keyboard_key_enter))); + SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_EQUALS, + context.getString(R.string.keyboard_key_numpad_template, "=")); + SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_LEFT_PAREN, + context.getString(R.string.keyboard_key_numpad_template, "(")); + SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_RIGHT_PAREN, + context.getString(R.string.keyboard_key_numpad_template, ")")); + SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_ZENKAKU_HANKAKU, "半角/全角"); + SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_EISU, "英数"); + SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_MUHENKAN, "無変換"); + SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_HENKAN, "変換"); + SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_KATAKANA_HIRAGANA, "かな"); + } private final Handler mHandler = new Handler(Looper.getMainLooper()); private final Context mContext; @@ -62,12 +206,20 @@ public class KeyboardShortcuts { }; private Dialog mKeyboardShortcutsDialog; + private KeyCharacterMap mKeyCharacterMap; public KeyboardShortcuts(Context context) { this.mContext = new ContextThemeWrapper(context, android.R.style.Theme_Material_Light); + if (SPECIAL_CHARACTER_NAMES.size() == 0) { + loadSpecialCharacterNames(context); + } } - public void toggleKeyboardShortcuts() { + public void toggleKeyboardShortcuts(int deviceId) { + InputDevice inputDevice = InputManager.getInstance().getInputDevice(deviceId); + if (inputDevice != null) { + mKeyCharacterMap = inputDevice.getKeyCharacterMap(); + } if (mKeyboardShortcutsDialog == null) { Recents.getSystemServices().requestKeyboardShortcuts(mContext, new KeyboardShortcutsReceiver() { @@ -78,13 +230,13 @@ public class KeyboardShortcuts { mContext.getString(R.string.keyboard_shortcut_group_system), true); systemGroup.addItem(new KeyboardShortcutInfo( mContext.getString(R.string.keyboard_shortcut_group_system_home), - SYSTEM_HOME_BASE_CHARACTER, KeyEvent.META_META_ON)); + KeyEvent.KEYCODE_ENTER, KeyEvent.META_META_ON)); systemGroup.addItem(new KeyboardShortcutInfo( mContext.getString(R.string.keyboard_shortcut_group_system_back), - SYSTEM_BACK_BASE_CHARACTER, KeyEvent.META_META_ON)); + KeyEvent.KEYCODE_DEL, KeyEvent.META_META_ON)); systemGroup.addItem(new KeyboardShortcutInfo( mContext.getString(R.string.keyboard_shortcut_group_system_recents), - SYSTEM_RECENTS_BASE_CHARACTER, KeyEvent.META_ALT_ON)); + KeyEvent.KEYCODE_TAB, KeyEvent.META_ALT_ON)); result.add(systemGroup); showKeyboardShortcutsDialog(result); } @@ -148,6 +300,18 @@ public class KeyboardShortcuts { final int itemsSize = group.getItems().size(); for (int j = 0; j < itemsSize; j++) { KeyboardShortcutInfo info = group.getItems().get(j); + if (info.getKeycode() != KeyEvent.KEYCODE_UNKNOWN + && !KeyCharacterMap.deviceHasKey(info.getKeycode())) { + // The user can't achieve this shortcut, so skipping. + Log.w(TAG, "Keyboard Shortcut contains key not on device, skipping."); + continue; + } + List shortcutKeys = getHumanReadableShortcutKeys(info); + if (shortcutKeys == null) { + // Ignore shortcuts we can't display keys for. + Log.w(TAG, "Keyboard Shortcut contains unsupported keys, skipping."); + continue; + } View shortcutView = inflater.inflate(R.layout.keyboard_shortcut_app_item, shortcutContainer, false); TextView textView = (TextView) shortcutView @@ -156,7 +320,6 @@ public class KeyboardShortcuts { ViewGroup shortcutItemsContainer = (ViewGroup) shortcutView .findViewById(R.id.keyboard_shortcuts_item_container); - List shortcutKeys = getHumanReadableShortcutKeys(info); final int shortcutKeysSize = shortcutKeys.size(); for (int k = 0; k < shortcutKeysSize; k++) { String shortcutKey = shortcutKeys.get(k); @@ -179,10 +342,25 @@ public class KeyboardShortcuts { private List getHumanReadableShortcutKeys(KeyboardShortcutInfo info) { // TODO: fix the shortcuts. Find or build an util which can produce human readable - // names of the baseCharacter and the modifiers. + // names of the modifiers. List shortcutKeys = new ArrayList<>(); shortcutKeys.add(KeyEvent.metaStateToString(info.getModifiers()).toUpperCase()); - shortcutKeys.add(Character.getName(info.getBaseCharacter()).toUpperCase()); + String displayLabelString; + if (info.getKeycode() == KeyEvent.KEYCODE_UNKNOWN) { + displayLabelString = String.valueOf(info.getBaseCharacter()); + } else if (SPECIAL_CHARACTER_NAMES.get(info.getKeycode()) != null) { + displayLabelString = SPECIAL_CHARACTER_NAMES.get(info.getKeycode()); + } else { + // TODO: Have a generic map for when we don't have the device's. + char displayLabel = mKeyCharacterMap == null + ? 0 : mKeyCharacterMap.getDisplayLabel(info.getKeycode()); + if (displayLabel != 0) { + displayLabelString = String.valueOf(displayLabel); + } else { + return null; + } + } + shortcutKeys.add(displayLabelString.toUpperCase()); return shortcutKeys; } } diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index 0115a08cefe55..d92d942d2b910 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -3101,7 +3101,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { } else if (keyCode == KeyEvent.KEYCODE_SLASH && event.isMetaPressed()) { if (down) { if (repeatCount == 0) { - toggleKeyboardShortcutsMenu(); + toggleKeyboardShortcutsMenu(event.getDeviceId()); } } } else if (keyCode == KeyEvent.KEYCODE_ASSIST) { @@ -3576,11 +3576,11 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } - private void toggleKeyboardShortcutsMenu() { + private void toggleKeyboardShortcutsMenu(int deviceId) { try { IStatusBarService statusbar = getStatusBarService(); if (statusbar != null) { - statusbar.toggleKeyboardShortcutsMenu(); + statusbar.toggleKeyboardShortcutsMenu(deviceId); } } catch (RemoteException e) { Slog.e(TAG, "RemoteException when showing keyboard shortcuts menu", e); diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java index d24e1af3f382b..403a4c608061a 100644 --- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java +++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java @@ -564,10 +564,10 @@ public class StatusBarManagerService extends IStatusBarService.Stub { } @Override - public void toggleKeyboardShortcutsMenu() { + public void toggleKeyboardShortcutsMenu(int deviceId) { if (mBar != null) { try { - mBar.toggleKeyboardShortcutsMenu(); + mBar.toggleKeyboardShortcutsMenu(deviceId); } catch (RemoteException ex) {} } }