diff options
5 files changed, 59 insertions, 24 deletions
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 8fda48b1a36a..258359e98264 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -15272,7 +15272,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @param event the KeyEvent object that defines the button action */ public boolean onKeyDown(int keyCode, KeyEvent event) { - if (KeyEvent.isConfirmKey(keyCode)) { + if (event.hasNoModifiers() && KeyEvent.isConfirmKey(keyCode)) { if ((mViewFlags & ENABLED_MASK) == DISABLED) { return true; } @@ -15329,7 +15329,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @param event The KeyEvent object that defines the button action. */ public boolean onKeyUp(int keyCode, KeyEvent event) { - if (KeyEvent.isConfirmKey(keyCode)) { + if (event.hasNoModifiers() && KeyEvent.isConfirmKey(keyCode)) { if ((mViewFlags & ENABLED_MASK) == DISABLED) { return true; } diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 748e551ecfc4..f86abec353cc 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -7596,7 +7596,7 @@ public final class ViewRootImpl implements ViewParent, // When a new focused view is selected, we consume the navigation key because // navigation doesn't make much sense unless a view already has focus so // the key's purpose is to set focus. - if (isNavigationKey(event)) { + if (event.hasNoModifiers() && isNavigationKey(event)) { return ensureTouchMode(false); } diff --git a/services/core/java/com/android/server/input/InputShellCommand.java b/services/core/java/com/android/server/input/InputShellCommand.java index 9fa6fad4f926..773dc680d4cb 100644 --- a/services/core/java/com/android/server/input/InputShellCommand.java +++ b/services/core/java/com/android/server/input/InputShellCommand.java @@ -560,7 +560,12 @@ public class InputShellCommand extends ShellCommand { sleep(duration); for (KeyEvent event: events) { - injectKeyEventAsync(KeyEvent.changeAction(event, KeyEvent.ACTION_UP)); + final int keyCode = event.getKeyCode(); + final KeyEvent upEvent = new KeyEvent(now, now, KeyEvent.ACTION_UP, keyCode, + 0, metaState, KeyCharacterMap.VIRTUAL_KEYBOARD, 0 /*scancode*/, 0 /*flags*/, + inputSource); + injectKeyEventAsync(upEvent); + metaState &= ~MODIFIER.getOrDefault(keyCode, 0); } } diff --git a/services/core/java/com/android/server/policy/ModifierShortcutManager.java b/services/core/java/com/android/server/policy/ModifierShortcutManager.java index e857d32c3449..784e177d6362 100644 --- a/services/core/java/com/android/server/policy/ModifierShortcutManager.java +++ b/services/core/java/com/android/server/policy/ModifierShortcutManager.java @@ -112,10 +112,15 @@ class ModifierShortcutManager { * @return The intent that matches the shortcut, or null if not found. */ private Intent getIntent(KeyCharacterMap kcm, int keyCode, int metaState) { + // If a modifier key other than shift is also pressed, skip it. + final boolean isShiftOn = KeyEvent.metaStateHasModifiers(metaState, KeyEvent.META_SHIFT_ON); + if (!isShiftOn && !KeyEvent.metaStateHasNoModifiers(metaState)) { + return null; + } + ShortcutInfo shortcut = null; // If the Shift key is pressed, then search for the shift shortcuts. - boolean isShiftOn = (metaState & KeyEvent.META_SHIFT_ON) == KeyEvent.META_SHIFT_ON; SparseArray<ShortcutInfo> shortcutMap = isShiftOn ? mShiftShortcuts : mIntentShortcuts; // First try the exact keycode (with modifiers). diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index 4cced17917f6..28f65cf6d1a0 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -2696,6 +2696,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { final boolean canceled = event.isCanceled(); final int displayId = event.getDisplayId(); final long key_consumed = -1; + final long key_not_consumed = 0; if (DEBUG_INPUT) { Log.d(TAG, "interceptKeyTi keyCode=" + keyCode + " down=" + down + " repeatCount=" @@ -2885,7 +2886,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { case KeyEvent.KEYCODE_TAB: if (event.isMetaPressed()) { // Pass through keyboard navigation keys. - return 0; + return key_not_consumed; } // Display task switcher for ALT-TAB. if (down && repeatCount == 0) { @@ -2916,9 +2917,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { return key_consumed; case KeyEvent.KEYCODE_SPACE: - // Handle keyboard layout switching. - if ((metaState & (KeyEvent.META_CTRL_MASK | KeyEvent.META_META_MASK)) == 0) { - return 0; + // Handle keyboard layout switching. (META + SPACE) + if ((metaState & KeyEvent.META_META_MASK) == 0) { + return key_not_consumed; } // Share the same behavior with KEYCODE_LANGUAGE_SWITCH. case KeyEvent.KEYCODE_LANGUAGE_SWITCH: @@ -2992,7 +2993,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { } // Let the application handle the key. - return 0; + return key_not_consumed; } /** @@ -3058,6 +3059,10 @@ public class PhoneWindowManager implements WindowManagerPolicy { + ", policyFlags=" + policyFlags); } + if (interceptUnhandledKey(event)) { + return null; + } + KeyEvent fallbackEvent = null; if ((event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) { final KeyCharacterMap kcm = event.getKeyCharacterMap(); @@ -3112,13 +3117,46 @@ public class PhoneWindowManager implements WindowManagerPolicy { return fallbackEvent; } + private boolean interceptUnhandledKey(KeyEvent event) { + final int keyCode = event.getKeyCode(); + final int repeatCount = event.getRepeatCount(); + final boolean down = event.getAction() == KeyEvent.ACTION_DOWN; + final int metaState = event.getModifiers(); + + switch(keyCode) { + case KeyEvent.KEYCODE_SPACE: + if (down && repeatCount == 0) { + // Handle keyboard layout switching. (CTRL + SPACE) + if (KeyEvent.metaStateHasModifiers(metaState, KeyEvent.META_CTRL_ON)) { + int direction = (metaState & KeyEvent.META_SHIFT_MASK) != 0 ? -1 : 1; + mWindowManagerFuncs.switchKeyboardLayout(event.getDeviceId(), direction); + return true; + } + } + break; + case KeyEvent.KEYCODE_Z: + if (down && KeyEvent.metaStateHasModifiers(metaState, + KeyEvent.META_CTRL_ON | KeyEvent.META_ALT_ON)) { + // Intercept the Accessibility keychord (CTRL + ALT + Z) for keyboard users. + if (mAccessibilityShortcutController + .isAccessibilityShortcutAvailable(isKeyguardLocked())) { + mHandler.sendMessage(mHandler.obtainMessage(MSG_ACCESSIBILITY_SHORTCUT)); + return true; + } + } + break; + } + + return false; + } + private boolean interceptFallback(IBinder focusedToken, KeyEvent fallbackEvent, int policyFlags) { int actions = interceptKeyBeforeQueueing(fallbackEvent, policyFlags); if ((actions & ACTION_PASS_TO_USER) != 0) { long delayMillis = interceptKeyBeforeDispatching( focusedToken, fallbackEvent, policyFlags); - if (delayMillis == 0) { + if (delayMillis == 0 && !interceptUnhandledKey(fallbackEvent)) { return true; } } @@ -3989,19 +4027,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } - // Intercept the Accessibility keychord (CTRL + ALT + Z) for keyboard users. - if (mAccessibilityShortcutController.isAccessibilityShortcutAvailable(isKeyguardLocked())) { - switch (keyCode) { - case KeyEvent.KEYCODE_Z: { - if (down && event.isCtrlPressed() && event.isAltPressed()) { - mHandler.sendMessage(mHandler.obtainMessage(MSG_ACCESSIBILITY_SHORTCUT)); - result &= ~ACTION_PASS_TO_USER; - } - break; - } - } - } - if (useHapticFeedback) { performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY, false, "Virtual Key - Press"); |