From 112d05678b7de53da8948f62dd2e968274f62244 Mon Sep 17 00:00:00 2001 From: Andrii Kulian Date: Tue, 8 Mar 2016 10:44:22 -0800 Subject: [PATCH] Caps Lock toggle with Meta + Alt (2/2) Caps Lock implementation in frameworks/base Bug: 27482276 Change-Id: Ie0d8145c049197d4591e012832a710e4f751d2ac --- core/java/android/hardware/input/InputManager.java | 2 -- .../hardware/input/InputManagerInternal.java | 7 ++++ core/java/android/view/KeyEvent.java | 5 +++ .../android/server/input/InputManagerService.java | 6 ++++ .../android/server/policy/PhoneWindowManager.java | 42 ++++++++++++++++++++++ ...om_android_server_input_InputManagerService.cpp | 8 +++++ 6 files changed, 68 insertions(+), 2 deletions(-) diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java index fbac58c039c6..47440de62827 100644 --- a/core/java/android/hardware/input/InputManager.java +++ b/core/java/android/hardware/input/InputManager.java @@ -16,9 +16,7 @@ package android.hardware.input; -import com.android.internal.inputmethod.InputMethodSubtypeHandle; import com.android.internal.os.SomeArgs; -import com.android.internal.util.ArrayUtils; import android.annotation.IntDef; import android.annotation.SdkConstant; diff --git a/core/java/android/hardware/input/InputManagerInternal.java b/core/java/android/hardware/input/InputManagerInternal.java index 014e73fd8aeb..10fc8e6e366a 100644 --- a/core/java/android/hardware/input/InputManagerInternal.java +++ b/core/java/android/hardware/input/InputManagerInternal.java @@ -52,4 +52,11 @@ public abstract class InputManagerInternal { */ public abstract void onInputMethodSubtypeChanged(int userId, @Nullable InputMethodInfo inputMethodInfo, @Nullable InputMethodSubtype subtype); + + /** + * Toggles Caps Lock state for input device with specific id. + * + * @param deviceId The id of input device. + */ + public abstract void toggleCapsLock(int deviceId); } diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java index e0c6770ecb38..636384c616e0 100644 --- a/core/java/android/view/KeyEvent.java +++ b/core/java/android/view/KeyEvent.java @@ -1870,6 +1870,11 @@ public class KeyEvent extends InputEvent implements Parcelable { return keyCode == KeyEvent.KEYCODE_META_LEFT || keyCode == KeyEvent.KEYCODE_META_RIGHT; } + /** @hide */ + public static final boolean isAltKey(int keyCode) { + return keyCode == KeyEvent.KEYCODE_ALT_LEFT || keyCode == KeyEvent.KEYCODE_ALT_RIGHT; + } + /** {@inheritDoc} */ @Override public final int getDeviceId() { diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java index e73beaab6f0b..c7c765bb431e 100644 --- a/services/core/java/com/android/server/input/InputManagerService.java +++ b/services/core/java/com/android/server/input/InputManagerService.java @@ -200,6 +200,7 @@ public class InputManagerService extends IInputManager.Stub private static native int nativeInjectInputEvent(long ptr, InputEvent event, int displayId, int injectorPid, int injectorUid, int syncMode, int timeoutMillis, int policyFlags); + private static native void nativeToggleCapsLock(long ptr, int deviceId); private static native void nativeSetInputWindows(long ptr, InputWindowHandle[] windowHandles); private static native void nativeSetInputDispatchMode(long ptr, boolean enabled, boolean frozen); private static native void nativeSetSystemUiVisibility(long ptr, int visibility); @@ -2279,5 +2280,10 @@ public class InputManagerService extends IInputManager.Stub mHandler.obtainMessage(MSG_INPUT_METHOD_SUBTYPE_CHANGED, userId, 0, someArgs) .sendToTarget(); } + + @Override + public void toggleCapsLock(int deviceId) { + nativeToggleCapsLock(mPtr, deviceId); + } } } diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index 14d0457e41c1..e2bfe43cecfa 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -69,6 +69,7 @@ import android.graphics.Rect; import android.hardware.hdmi.HdmiControlManager; import android.hardware.hdmi.HdmiPlaybackClient; import android.hardware.hdmi.HdmiPlaybackClient.OneTouchPlayCallback; +import android.hardware.input.InputManagerInternal; import android.media.AudioAttributes; import android.media.AudioManager; import android.media.AudioSystem; @@ -304,6 +305,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { WindowManagerInternal mWindowManagerInternal; PowerManager mPowerManager; ActivityManagerInternal mActivityManagerInternal; + InputManagerInternal mInputManagerInternal; DreamManagerInternal mDreamManagerInternal; PowerManagerInternal mPowerManagerInternal; IStatusBarService mStatusBarService; @@ -601,6 +603,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { boolean mConsumeSearchKeyUp; boolean mAssistKeyLongPressed; boolean mPendingMetaAction; + boolean mPendingCapsLockToggle; + int mMetaState; + int mInitialMetaState; boolean mForceShowSystemBars; // support for activating the lock screen while the screen is on @@ -1486,6 +1491,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { mWindowManagerFuncs = windowManagerFuncs; mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class); mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class); + mInputManagerInternal = LocalServices.getService(InputManagerInternal.class); mDreamManagerInternal = LocalServices.getService(DreamManagerInternal.class); mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class); mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE); @@ -2954,6 +2960,10 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (mPendingMetaAction && !KeyEvent.isMetaKey(keyCode)) { mPendingMetaAction = false; } + // Any key that is not Alt or Meta cancels Caps Lock combo tracking. + if (mPendingCapsLockToggle && !KeyEvent.isMetaKey(keyCode) && !KeyEvent.isAltKey(keyCode)) { + mPendingCapsLockToggle = false; + } // First we always handle the home key here, so applications // can never break it, although if keyguard is on, we do let @@ -3202,6 +3212,38 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } + // Toggle Caps Lock on META-ALT. + boolean actionTriggered = false; + if (KeyEvent.isModifierKey(keyCode)) { + if (!mPendingCapsLockToggle) { + // Start tracking meta state for combo. + mInitialMetaState = mMetaState; + mPendingCapsLockToggle = true; + } else if (event.getAction() == KeyEvent.ACTION_UP) { + int altOnMask = mMetaState & KeyEvent.META_ALT_MASK; + int metaOnMask = mMetaState & KeyEvent.META_META_MASK; + + // Check for Caps Lock toggle + if ((metaOnMask != 0) && (altOnMask != 0)) { + // Check if nothing else is pressed + if (mInitialMetaState == (mMetaState ^ (altOnMask | metaOnMask))) { + // Handle Caps Lock Toggle + mInputManagerInternal.toggleCapsLock(event.getDeviceId()); + actionTriggered = true; + } + } + + // Always stop tracking when key goes up. + mPendingCapsLockToggle = false; + } + } + // Store current meta state to be able to evaluate it later. + mMetaState = metaState; + + if (actionTriggered) { + return -1; + } + if (KeyEvent.isMetaKey(keyCode)) { if (down) { mPendingMetaAction = true; diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp index a5237ca89520..cd485c55c816 100644 --- a/services/core/jni/com_android_server_input_InputManagerService.cpp +++ b/services/core/jni/com_android_server_input_InputManagerService.cpp @@ -1312,6 +1312,12 @@ static jint nativeInjectInputEvent(JNIEnv* env, jclass /* clazz */, } } +static void nativeToggleCapsLock(JNIEnv* env, jclass /* clazz */, + jlong ptr, jint deviceId) { + NativeInputManager* im = reinterpret_cast(ptr); + im->getInputManager()->getReader()->toggleCapsLockState(deviceId); +} + static void nativeSetInputWindows(JNIEnv* env, jclass /* clazz */, jlong ptr, jobjectArray windowHandleObjArray) { NativeInputManager* im = reinterpret_cast(ptr); @@ -1508,6 +1514,8 @@ static const JNINativeMethod gInputManagerMethods[] = { (void*) nativeSetInputFilterEnabled }, { "nativeInjectInputEvent", "(JLandroid/view/InputEvent;IIIIII)I", (void*) nativeInjectInputEvent }, + { "nativeToggleCapsLock", "(JI)V", + (void*) nativeToggleCapsLock }, { "nativeSetInputWindows", "(J[Lcom/android/server/input/InputWindowHandle;)V", (void*) nativeSetInputWindows }, { "nativeSetFocusedApplication", "(JLcom/android/server/input/InputApplicationHandle;)V", -- 2.11.0