Merge "Refactor PWM to fully capture shortcut gesture" into udc-qpr-dev am: 1b25d291a9

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/23663163

Change-Id: I716f779be614ce58e8f9f36951acb61c2c803e3c
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Vaibhav Devmurari
2023-07-06 12:33:42 +00:00
committed by Automerger Merge Worker

View File

@@ -91,6 +91,7 @@ import android.accessibilityservice.AccessibilityService;
import android.accessibilityservice.AccessibilityServiceInfo; import android.accessibilityservice.AccessibilityServiceInfo;
import android.annotation.NonNull; import android.annotation.NonNull;
import android.annotation.Nullable; import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.app.ActivityManager; import android.app.ActivityManager;
import android.app.ActivityManager.RecentTaskInfo; import android.app.ActivityManager.RecentTaskInfo;
import android.app.ActivityManagerInternal; import android.app.ActivityManagerInternal;
@@ -632,6 +633,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
SettingsObserver mSettingsObserver; SettingsObserver mSettingsObserver;
ModifierShortcutManager mModifierShortcutManager; ModifierShortcutManager mModifierShortcutManager;
/** Currently fully consumed key codes per device */
private final SparseArray<Set<Integer>> mConsumedKeysForDevice = new SparseArray<>();
PowerManager.WakeLock mBroadcastWakeLock; PowerManager.WakeLock mBroadcastWakeLock;
PowerManager.WakeLock mPowerKeyWakeLock; PowerManager.WakeLock mPowerKeyWakeLock;
boolean mHavePendingMediaKeyRepeatWithWakeLock; boolean mHavePendingMediaKeyRepeatWithWakeLock;
@@ -1817,7 +1820,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mDisplayId = displayId; mDisplayId = displayId;
} }
int handleHomeButton(IBinder focusedToken, KeyEvent event) { boolean handleHomeButton(IBinder focusedToken, KeyEvent event) {
final boolean keyguardOn = keyguardOn(); final boolean keyguardOn = keyguardOn();
final int repeatCount = event.getRepeatCount(); final int repeatCount = event.getRepeatCount();
final boolean down = event.getAction() == KeyEvent.ACTION_DOWN; final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
@@ -1838,12 +1841,12 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mHomePressed = false; mHomePressed = false;
if (mHomeConsumed) { if (mHomeConsumed) {
mHomeConsumed = false; mHomeConsumed = false;
return -1; return true;
} }
if (canceled) { if (canceled) {
Log.i(TAG, "Ignoring HOME; event canceled."); Log.i(TAG, "Ignoring HOME; event canceled.");
return -1; return true;
} }
// Delay handling home if a double-tap is possible. // Delay handling home if a double-tap is possible.
@@ -1855,13 +1858,13 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mHomeDoubleTapPending = true; mHomeDoubleTapPending = true;
mHandler.postDelayed(mHomeDoubleTapTimeoutRunnable, mHandler.postDelayed(mHomeDoubleTapTimeoutRunnable,
ViewConfiguration.getDoubleTapTimeout()); ViewConfiguration.getDoubleTapTimeout());
return -1; return true;
} }
} }
// Post to main thread to avoid blocking input pipeline. // Post to main thread to avoid blocking input pipeline.
mHandler.post(() -> handleShortPressOnHome(mDisplayId)); mHandler.post(() -> handleShortPressOnHome(mDisplayId));
return -1; return true;
} }
final KeyInterceptionInfo info = final KeyInterceptionInfo info =
@@ -1873,12 +1876,12 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|| (info.layoutParamsType == TYPE_NOTIFICATION_SHADE || (info.layoutParamsType == TYPE_NOTIFICATION_SHADE
&& isKeyguardShowing())) { && isKeyguardShowing())) {
// the "app" is keyguard, so give it the key // the "app" is keyguard, so give it the key
return 0; return false;
} }
for (int t : WINDOW_TYPES_WHERE_HOME_DOESNT_WORK) { for (int t : WINDOW_TYPES_WHERE_HOME_DOESNT_WORK) {
if (info.layoutParamsType == t) { if (info.layoutParamsType == t) {
// don't do anything, but also don't pass it to the app // don't do anything, but also don't pass it to the app
return -1; return true;
} }
} }
} }
@@ -1903,7 +1906,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
event.getEventTime())); event.getEventTime()));
} }
} }
return -1; return true;
} }
private void handleDoubleTapOnHome() { private void handleDoubleTapOnHome() {
@@ -2949,24 +2952,21 @@ public class PhoneWindowManager implements WindowManagerPolicy {
@Override @Override
public long interceptKeyBeforeDispatching(IBinder focusedToken, KeyEvent event, public long interceptKeyBeforeDispatching(IBinder focusedToken, KeyEvent event,
int policyFlags) { int policyFlags) {
final boolean keyguardOn = keyguardOn();
final int keyCode = event.getKeyCode(); final int keyCode = event.getKeyCode();
final int repeatCount = event.getRepeatCount();
final int metaState = event.getMetaState();
final int flags = event.getFlags(); final int flags = event.getFlags();
final boolean down = event.getAction() == KeyEvent.ACTION_DOWN; final long keyConsumed = -1;
final boolean canceled = event.isCanceled(); final long keyNotConsumed = 0;
final int displayId = event.getDisplayId(); final int deviceId = event.getDeviceId();
final long key_consumed = -1;
final long key_not_consumed = 0;
if (DEBUG_INPUT) { if (DEBUG_INPUT) {
Log.d(TAG, "interceptKeyTi keyCode=" + keyCode + " down=" + down + " repeatCount=" Log.d(TAG,
+ repeatCount + " keyguardOn=" + keyguardOn + " canceled=" + canceled); "interceptKeyTi keyCode=" + keyCode + " action=" + event.getAction()
+ " repeatCount=" + event.getRepeatCount() + " keyguardOn="
+ keyguardOn() + " canceled=" + event.isCanceled());
} }
if (mKeyCombinationManager.isKeyConsumed(event)) { if (mKeyCombinationManager.isKeyConsumed(event)) {
return key_consumed; return keyConsumed;
} }
if ((flags & KeyEvent.FLAG_FALLBACK) == 0) { if ((flags & KeyEvent.FLAG_FALLBACK) == 0) {
@@ -2977,8 +2977,54 @@ public class PhoneWindowManager implements WindowManagerPolicy {
} }
} }
// Cancel any pending meta actions if we see any other keys being pressed between the down Set<Integer> consumedKeys = mConsumedKeysForDevice.get(deviceId);
// of the meta key and its corresponding up. if (consumedKeys == null) {
consumedKeys = new HashSet<>();
mConsumedKeysForDevice.put(deviceId, consumedKeys);
}
if (interceptSystemKeysAndShortcuts(focusedToken, event)
&& event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) {
consumedKeys.add(keyCode);
return keyConsumed;
}
boolean needToConsumeKey = consumedKeys.contains(keyCode);
if (event.getAction() == KeyEvent.ACTION_UP || event.isCanceled()) {
consumedKeys.remove(keyCode);
if (consumedKeys.isEmpty()) {
mConsumedKeysForDevice.remove(deviceId);
}
}
return needToConsumeKey ? keyConsumed : keyNotConsumed;
}
// You can only start consuming the key gesture if ACTION_DOWN and repeat count
// is 0. If you start intercepting the key halfway, then key will not be consumed
// and will be sent to apps for processing too.
// e.g. If a certain combination is only handled on ACTION_UP (i.e.
// interceptShortcut() returns true only for ACTION_UP), then since we already
// sent the ACTION_DOWN events to the application, we MUST also send the
// ACTION_UP to the application.
// So, to ensure that your intercept logic works properly, and we don't send any
// conflicting events to application, make sure to consume the event on
// ACTION_DOWN even if you want to do something on ACTION_UP. This is essential
// to maintain event parity and to not have incomplete key gestures.
@SuppressLint("MissingPermission")
private boolean interceptSystemKeysAndShortcuts(IBinder focusedToken, KeyEvent event) {
final boolean keyguardOn = keyguardOn();
final int keyCode = event.getKeyCode();
final int repeatCount = event.getRepeatCount();
final int metaState = event.getMetaState();
final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
final boolean canceled = event.isCanceled();
final int displayId = event.getDisplayId();
final int deviceId = event.getDeviceId();
final boolean firstDown = down && repeatCount == 0;
// Cancel any pending meta actions if we see any other keys being pressed between the
// down of the meta key and its corresponding up.
if (mPendingMetaAction && !KeyEvent.isMetaKey(keyCode)) { if (mPendingMetaAction && !KeyEvent.isMetaKey(keyCode)) {
mPendingMetaAction = false; mPendingMetaAction = false;
} }
@@ -2992,50 +3038,49 @@ public class PhoneWindowManager implements WindowManagerPolicy {
dismissKeyboardShortcutsMenu(); dismissKeyboardShortcutsMenu();
mPendingMetaAction = false; mPendingMetaAction = false;
mPendingCapsLockToggle = false; mPendingCapsLockToggle = false;
return key_consumed; return true;
} }
} }
switch (keyCode) { switch (keyCode) {
case KeyEvent.KEYCODE_HOME: case KeyEvent.KEYCODE_HOME:
logKeyboardSystemsEvent(event, FrameworkStatsLog logKeyboardSystemsEvent(event,
.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__HOME); FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__HOME);
return handleHomeShortcuts(displayId, focusedToken, event); return handleHomeShortcuts(displayId, focusedToken, event);
case KeyEvent.KEYCODE_MENU: case KeyEvent.KEYCODE_MENU:
// Hijack modified menu keys for debugging features // Hijack modified menu keys for debugging features
final int chordBug = KeyEvent.META_SHIFT_ON; final int chordBug = KeyEvent.META_SHIFT_ON;
if (down && repeatCount == 0) { if (mEnableShiftMenuBugReports && firstDown
if (mEnableShiftMenuBugReports && (metaState & chordBug) == chordBug) { && (metaState & chordBug) == chordBug) {
Intent intent = new Intent(Intent.ACTION_BUG_REPORT); Intent intent = new Intent(Intent.ACTION_BUG_REPORT);
mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT, mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT,
null, null, null, 0, null, null); null, null, null, 0, null, null);
return key_consumed; return true;
}
} }
break; break;
case KeyEvent.KEYCODE_RECENT_APPS: case KeyEvent.KEYCODE_RECENT_APPS:
if (down && repeatCount == 0) { if (firstDown) {
showRecentApps(false /* triggeredFromAltTab */); showRecentApps(false /* triggeredFromAltTab */);
logKeyboardSystemsEvent(event, FrameworkStatsLog logKeyboardSystemsEvent(event,
.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__RECENT_APPS); FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__RECENT_APPS);
} }
return key_consumed; return true;
case KeyEvent.KEYCODE_APP_SWITCH: case KeyEvent.KEYCODE_APP_SWITCH:
if (!keyguardOn) { if (!keyguardOn) {
if (down && repeatCount == 0) { if (firstDown) {
preloadRecentApps(); preloadRecentApps();
} else if (!down) { } else if (!down) {
toggleRecentApps(); toggleRecentApps();
} }
} }
return key_consumed; return true;
case KeyEvent.KEYCODE_A: case KeyEvent.KEYCODE_A:
if (down && event.isMetaPressed()) { if (firstDown && event.isMetaPressed()) {
launchAssistAction(Intent.EXTRA_ASSIST_INPUT_HINT_KEYBOARD, launchAssistAction(Intent.EXTRA_ASSIST_INPUT_HINT_KEYBOARD,
event.getDeviceId(), deviceId, event.getEventTime(),
event.getEventTime(), AssistUtils.INVOCATION_TYPE_UNKNOWN); AssistUtils.INVOCATION_TYPE_UNKNOWN);
return key_consumed; return true;
} }
break; break;
case KeyEvent.KEYCODE_H: case KeyEvent.KEYCODE_H:
@@ -3045,73 +3090,73 @@ public class PhoneWindowManager implements WindowManagerPolicy {
} }
break; break;
case KeyEvent.KEYCODE_I: case KeyEvent.KEYCODE_I:
if (down && event.isMetaPressed()) { if (firstDown && event.isMetaPressed()) {
showSystemSettings(); showSystemSettings();
return key_consumed; return true;
} }
break; break;
case KeyEvent.KEYCODE_L: case KeyEvent.KEYCODE_L:
if (down && event.isMetaPressed() && repeatCount == 0) { if (firstDown && event.isMetaPressed()) {
lockNow(null /* options */); lockNow(null /* options */);
return key_consumed; return true;
} }
break; break;
case KeyEvent.KEYCODE_N: case KeyEvent.KEYCODE_N:
if (down && event.isMetaPressed()) { if (firstDown && event.isMetaPressed()) {
if (event.isCtrlPressed()) { if (event.isCtrlPressed()) {
sendSystemKeyToStatusBarAsync(event); sendSystemKeyToStatusBarAsync(event);
} else { } else {
toggleNotificationPanel(); toggleNotificationPanel();
} }
return key_consumed; return true;
} }
break; break;
case KeyEvent.KEYCODE_S: case KeyEvent.KEYCODE_S:
if (down && event.isMetaPressed() && event.isCtrlPressed() && repeatCount == 0) { if (firstDown && event.isMetaPressed() && event.isCtrlPressed()) {
interceptScreenshotChord(SCREENSHOT_KEY_OTHER, 0 /*pressDelay*/); interceptScreenshotChord(SCREENSHOT_KEY_OTHER, 0 /*pressDelay*/);
return key_consumed; return true;
} }
break; break;
case KeyEvent.KEYCODE_T: case KeyEvent.KEYCODE_T:
if (down && event.isMetaPressed()) { if (firstDown && event.isMetaPressed()) {
toggleTaskbar(); toggleTaskbar();
return key_consumed; return true;
} }
break; break;
case KeyEvent.KEYCODE_DPAD_UP: case KeyEvent.KEYCODE_DPAD_UP:
if (down && event.isMetaPressed() && event.isCtrlPressed() && repeatCount == 0) { if (firstDown && event.isMetaPressed() && event.isCtrlPressed()) {
StatusBarManagerInternal statusbar = getStatusBarManagerInternal(); StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
if (statusbar != null) { if (statusbar != null) {
statusbar.goToFullscreenFromSplit(); statusbar.goToFullscreenFromSplit();
return true;
} }
return key_consumed;
} }
break; break;
case KeyEvent.KEYCODE_DPAD_LEFT: case KeyEvent.KEYCODE_DPAD_LEFT:
if (down && event.isMetaPressed() && event.isCtrlPressed() && repeatCount == 0) { if (firstDown && event.isMetaPressed() && event.isCtrlPressed()) {
enterStageSplitFromRunningApp(true /* leftOrTop */); enterStageSplitFromRunningApp(true /* leftOrTop */);
return key_consumed; return true;
} }
break; break;
case KeyEvent.KEYCODE_DPAD_RIGHT: case KeyEvent.KEYCODE_DPAD_RIGHT:
if (down && event.isMetaPressed() && event.isCtrlPressed() && repeatCount == 0) { if (firstDown && event.isMetaPressed() && event.isCtrlPressed()) {
enterStageSplitFromRunningApp(false /* leftOrTop */); enterStageSplitFromRunningApp(false /* leftOrTop */);
return key_consumed; return true;
} }
break; break;
case KeyEvent.KEYCODE_SLASH: case KeyEvent.KEYCODE_SLASH:
if (down && repeatCount == 0 && event.isMetaPressed() && !keyguardOn) { if (firstDown && event.isMetaPressed() && !keyguardOn) {
toggleKeyboardShortcutsMenu(event.getDeviceId()); toggleKeyboardShortcutsMenu(event.getDeviceId());
return key_consumed; return true;
} }
break; break;
case KeyEvent.KEYCODE_ASSIST: case KeyEvent.KEYCODE_ASSIST:
Slog.wtf(TAG, "KEYCODE_ASSIST should be handled in interceptKeyBeforeQueueing"); Slog.wtf(TAG, "KEYCODE_ASSIST should be handled in interceptKeyBeforeQueueing");
return key_consumed; return true;
case KeyEvent.KEYCODE_VOICE_ASSIST: case KeyEvent.KEYCODE_VOICE_ASSIST:
Slog.wtf(TAG, "KEYCODE_VOICE_ASSIST should be handled in" Slog.wtf(TAG, "KEYCODE_VOICE_ASSIST should be handled in"
+ " interceptKeyBeforeQueueing"); + " interceptKeyBeforeQueueing");
return key_consumed; return true;
case KeyEvent.KEYCODE_VIDEO_APP_1: case KeyEvent.KEYCODE_VIDEO_APP_1:
case KeyEvent.KEYCODE_VIDEO_APP_2: case KeyEvent.KEYCODE_VIDEO_APP_2:
case KeyEvent.KEYCODE_VIDEO_APP_3: case KeyEvent.KEYCODE_VIDEO_APP_3:
@@ -3129,7 +3174,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
case KeyEvent.KEYCODE_DEMO_APP_3: case KeyEvent.KEYCODE_DEMO_APP_3:
case KeyEvent.KEYCODE_DEMO_APP_4: case KeyEvent.KEYCODE_DEMO_APP_4:
Slog.wtf(TAG, "KEYCODE_APP_X should be handled in interceptKeyBeforeQueueing"); Slog.wtf(TAG, "KEYCODE_APP_X should be handled in interceptKeyBeforeQueueing");
return key_consumed; return true;
case KeyEvent.KEYCODE_BRIGHTNESS_UP: case KeyEvent.KEYCODE_BRIGHTNESS_UP:
case KeyEvent.KEYCODE_BRIGHTNESS_DOWN: case KeyEvent.KEYCODE_BRIGHTNESS_DOWN:
if (down) { if (down) {
@@ -3169,20 +3214,20 @@ public class PhoneWindowManager implements WindowManagerPolicy {
startActivityAsUser(new Intent(Intent.ACTION_SHOW_BRIGHTNESS_DIALOG), startActivityAsUser(new Intent(Intent.ACTION_SHOW_BRIGHTNESS_DIALOG),
UserHandle.CURRENT_OR_SELF); UserHandle.CURRENT_OR_SELF);
} }
return key_consumed; return true;
case KeyEvent.KEYCODE_KEYBOARD_BACKLIGHT_DOWN: case KeyEvent.KEYCODE_KEYBOARD_BACKLIGHT_DOWN:
if (down) { if (down) {
mInputManagerInternal.decrementKeyboardBacklight(event.getDeviceId()); mInputManagerInternal.decrementKeyboardBacklight(event.getDeviceId());
} }
return key_consumed; return true;
case KeyEvent.KEYCODE_KEYBOARD_BACKLIGHT_UP: case KeyEvent.KEYCODE_KEYBOARD_BACKLIGHT_UP:
if (down) { if (down) {
mInputManagerInternal.incrementKeyboardBacklight(event.getDeviceId()); mInputManagerInternal.incrementKeyboardBacklight(event.getDeviceId());
} }
return key_consumed; return true;
case KeyEvent.KEYCODE_KEYBOARD_BACKLIGHT_TOGGLE: case KeyEvent.KEYCODE_KEYBOARD_BACKLIGHT_TOGGLE:
// TODO: Add logic // TODO: Add logic
return key_consumed; return true;
case KeyEvent.KEYCODE_VOLUME_UP: case KeyEvent.KEYCODE_VOLUME_UP:
case KeyEvent.KEYCODE_VOLUME_DOWN: case KeyEvent.KEYCODE_VOLUME_DOWN:
case KeyEvent.KEYCODE_VOLUME_MUTE: case KeyEvent.KEYCODE_VOLUME_MUTE:
@@ -3190,7 +3235,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// On TVs or when the configuration is enabled, volume keys never // On TVs or when the configuration is enabled, volume keys never
// go to the foreground app. // go to the foreground app.
dispatchDirectAudioEvent(event); dispatchDirectAudioEvent(event);
return key_consumed; return true;
} }
// If the device is in VR mode and keys are "internal" (e.g. on the side of the // If the device is in VR mode and keys are "internal" (e.g. on the side of the
@@ -3199,26 +3244,23 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (mDefaultDisplayPolicy.isPersistentVrModeEnabled()) { if (mDefaultDisplayPolicy.isPersistentVrModeEnabled()) {
final InputDevice d = event.getDevice(); final InputDevice d = event.getDevice();
if (d != null && !d.isExternal()) { if (d != null && !d.isExternal()) {
return key_consumed; return true;
} }
} }
break; break;
case KeyEvent.KEYCODE_TAB: case KeyEvent.KEYCODE_TAB:
if (down && event.isMetaPressed()) { if (firstDown && !keyguardOn && isUserSetupComplete()) {
if (!keyguardOn && isUserSetupComplete()) { if (event.isMetaPressed()) {
showRecentApps(false); showRecentApps(false);
return key_consumed; return true;
} } else if (mRecentAppsHeldModifiers == 0) {
} else if (down && repeatCount == 0) {
// Display task switcher for ALT-TAB.
if (mRecentAppsHeldModifiers == 0 && !keyguardOn && isUserSetupComplete()) {
final int shiftlessModifiers = final int shiftlessModifiers =
event.getModifiers() & ~KeyEvent.META_SHIFT_MASK; event.getModifiers() & ~KeyEvent.META_SHIFT_MASK;
if (KeyEvent.metaStateHasModifiers( if (KeyEvent.metaStateHasModifiers(
shiftlessModifiers, KeyEvent.META_ALT_ON)) { shiftlessModifiers, KeyEvent.META_ALT_ON)) {
mRecentAppsHeldModifiers = shiftlessModifiers; mRecentAppsHeldModifiers = shiftlessModifiers;
showRecentApps(true); showRecentApps(true);
return key_consumed; return true;
} }
} }
} }
@@ -3230,18 +3272,18 @@ public class PhoneWindowManager implements WindowManagerPolicy {
msg.setAsynchronous(true); msg.setAsynchronous(true);
msg.sendToTarget(); msg.sendToTarget();
} }
return key_consumed; return true;
case KeyEvent.KEYCODE_NOTIFICATION: case KeyEvent.KEYCODE_NOTIFICATION:
if (!down) { if (!down) {
toggleNotificationPanel(); toggleNotificationPanel();
} }
return key_consumed; return true;
case KeyEvent.KEYCODE_SEARCH: case KeyEvent.KEYCODE_SEARCH:
if (down && repeatCount == 0 && !keyguardOn()) { if (firstDown && !keyguardOn) {
switch (mSearchKeyBehavior) { switch (mSearchKeyBehavior) {
case SEARCH_BEHAVIOR_TARGET_ACTIVITY: { case SEARCH_BEHAVIOR_TARGET_ACTIVITY: {
launchTargetSearchActivity(); launchTargetSearchActivity();
return key_consumed; return true;
} }
case SEARCH_BEHAVIOR_DEFAULT_SEARCH: case SEARCH_BEHAVIOR_DEFAULT_SEARCH:
default: default:
@@ -3250,21 +3292,18 @@ public class PhoneWindowManager implements WindowManagerPolicy {
} }
break; break;
case KeyEvent.KEYCODE_LANGUAGE_SWITCH: case KeyEvent.KEYCODE_LANGUAGE_SWITCH:
if (down && repeatCount == 0) { if (firstDown) {
int direction = (metaState & KeyEvent.META_SHIFT_MASK) != 0 ? -1 : 1; int direction = (metaState & KeyEvent.META_SHIFT_MASK) != 0 ? -1 : 1;
sendSwitchKeyboardLayout(event, direction); sendSwitchKeyboardLayout(event, direction);
return key_consumed; return true;
} }
break; break;
case KeyEvent.KEYCODE_SPACE: case KeyEvent.KEYCODE_SPACE:
// Handle keyboard layout switching. (META + SPACE) // Handle keyboard layout switching. (META + SPACE)
if ((metaState & KeyEvent.META_META_MASK) == 0) { if (firstDown && event.isMetaPressed()) {
return key_not_consumed;
}
if (down && repeatCount == 0) {
int direction = (metaState & KeyEvent.META_SHIFT_MASK) != 0 ? -1 : 1; int direction = (metaState & KeyEvent.META_SHIFT_MASK) != 0 ? -1 : 1;
sendSwitchKeyboardLayout(event, direction); sendSwitchKeyboardLayout(event, direction);
return key_consumed; return true;
} }
break; break;
case KeyEvent.KEYCODE_META_LEFT: case KeyEvent.KEYCODE_META_LEFT:
@@ -3289,7 +3328,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mPendingMetaAction = false; mPendingMetaAction = false;
} }
} }
return key_consumed; return true;
case KeyEvent.KEYCODE_ALT_LEFT: case KeyEvent.KEYCODE_ALT_LEFT:
case KeyEvent.KEYCODE_ALT_RIGHT: case KeyEvent.KEYCODE_ALT_RIGHT:
if (down) { if (down) {
@@ -3305,14 +3344,14 @@ public class PhoneWindowManager implements WindowManagerPolicy {
&& (metaState & mRecentAppsHeldModifiers) == 0) { && (metaState & mRecentAppsHeldModifiers) == 0) {
mRecentAppsHeldModifiers = 0; mRecentAppsHeldModifiers = 0;
hideRecentApps(true, false); hideRecentApps(true, false);
return key_consumed; return true;
} }
// Toggle Caps Lock on META-ALT. // Toggle Caps Lock on META-ALT.
if (mPendingCapsLockToggle) { if (mPendingCapsLockToggle) {
mInputManagerInternal.toggleCapsLock(event.getDeviceId()); mInputManagerInternal.toggleCapsLock(event.getDeviceId());
mPendingCapsLockToggle = false; mPendingCapsLockToggle = false;
return key_consumed; return true;
} }
} }
break; break;
@@ -3322,24 +3361,18 @@ public class PhoneWindowManager implements WindowManagerPolicy {
case KeyEvent.KEYCODE_STYLUS_BUTTON_TAIL: case KeyEvent.KEYCODE_STYLUS_BUTTON_TAIL:
Slog.wtf(TAG, "KEYCODE_STYLUS_BUTTON_* should be handled in" Slog.wtf(TAG, "KEYCODE_STYLUS_BUTTON_* should be handled in"
+ " interceptKeyBeforeQueueing"); + " interceptKeyBeforeQueueing");
return key_consumed; return true;
} }
if (isValidGlobalKey(keyCode) if (isValidGlobalKey(keyCode)
&& mGlobalKeyManager.handleGlobalKey(mContext, keyCode, event)) { && mGlobalKeyManager.handleGlobalKey(mContext, keyCode, event)) {
return key_consumed; return true;
} }
// Reserve all the META modifier combos for system behavior // Reserve all the META modifier combos for system behavior
if ((metaState & KeyEvent.META_META_ON) != 0) { return (metaState & KeyEvent.META_META_ON) != 0;
return key_consumed;
} }
// Let the application handle the key. private boolean handleHomeShortcuts(int displayId, IBinder focusedToken, KeyEvent event) {
return key_not_consumed;
}
private int handleHomeShortcuts(int displayId, IBinder focusedToken, KeyEvent event) {
// First we always handle the home key here, so applications // First we always handle the home key here, so applications
// can never break it, although if keyguard is on, we do let // can never break it, although if keyguard is on, we do let
// it handle it, because that gives us the correct 5 second // it handle it, because that gives us the correct 5 second