diff options
author | Jeff Brown <jeffbrown@google.com> | 2010-12-06 17:13:33 -0800 |
---|---|---|
committer | Jeff Brown <jeffbrown@google.com> | 2010-12-07 17:35:26 -0800 |
commit | 49ed71db425c5054e3ad9526496a7e116c89556b (patch) | |
tree | 3d3b28bdaf76d5cc531fd3b52fcbb0efb32a05ba /core | |
parent | f30c8287525ac049d4d7589a330be5713256046b (diff) | |
download | frameworks_base-49ed71db425c5054e3ad9526496a7e116c89556b.zip frameworks_base-49ed71db425c5054e3ad9526496a7e116c89556b.tar.gz frameworks_base-49ed71db425c5054e3ad9526496a7e116c89556b.tar.bz2 |
Add support for fallback keycodes.
This change enables the framework to synthesize key events to implement
default behavior when an application does not handle a key.
For example, this change enables numeric keypad keys to perform
their associated special function when numlock is off.
The application is informed that it is processing a fallback keypress
so it can choose to ignore it.
Added a new keycode for switching applications.
Added ALT key deadkeys.
New default key mappings:
- ESC -> BACK
- Meta+ESC -> HOME
- Alt+ESC -> MENU
- Meta+Space -> SEARCH
- Meta+Tab -> APP_SWITCH
Fixed some comments.
Fixed some tests.
Change-Id: Id7f3b6645f3a350275e624547822f72652f3defe
Diffstat (limited to 'core')
-rw-r--r-- | core/java/android/view/KeyCharacterMap.java | 61 | ||||
-rwxr-xr-x | core/java/android/view/KeyEvent.java | 19 | ||||
-rw-r--r-- | core/java/android/view/View.java | 2 | ||||
-rw-r--r-- | core/java/android/view/ViewRoot.java | 28 | ||||
-rw-r--r-- | core/java/android/view/WindowManagerPolicy.java | 5 | ||||
-rw-r--r-- | core/jni/Android.mk | 2 | ||||
-rw-r--r-- | core/jni/android_view_KeyCharacterMap.cpp (renamed from core/jni/android_text_KeyCharacterMap.cpp) | 37 | ||||
-rwxr-xr-x | core/res/res/values/attrs.xml | 1 |
8 files changed, 131 insertions, 24 deletions
diff --git a/core/java/android/view/KeyCharacterMap.java b/core/java/android/view/KeyCharacterMap.java index 97bd8dd..5c4abd5 100644 --- a/core/java/android/view/KeyCharacterMap.java +++ b/core/java/android/view/KeyCharacterMap.java @@ -144,6 +144,8 @@ public class KeyCharacterMap { private static native void nativeDispose(int ptr); private static native char nativeGetCharacter(int ptr, int keyCode, int metaState); + private static native boolean nativeGetFallbackAction(int ptr, int keyCode, int metaState, + FallbackAction outFallbackAction); private static native char nativeGetNumber(int ptr, int keyCode); private static native char nativeGetMatch(int ptr, int keyCode, char[] chars, int metaState); private static native char nativeGetDisplayLabel(int ptr, int keyCode); @@ -206,14 +208,9 @@ public class KeyCharacterMap { * @return The associated character or combining accent, or 0 if none. */ public int get(int keyCode, int metaState) { - if ((metaState & MetaKeyKeyListener.META_CAP_LOCKED) != 0) { - metaState |= KeyEvent.META_CAPS_LOCK_ON; - } - if ((metaState & MetaKeyKeyListener.META_ALT_LOCKED) != 0) { - metaState |= KeyEvent.META_ALT_ON; - } - + metaState = applyLockedModifiers(metaState); char ch = nativeGetCharacter(mPtr, keyCode, metaState); + int map = COMBINING.get(ch); if (map != 0) { return map; @@ -223,6 +220,34 @@ public class KeyCharacterMap { } /** + * Gets the fallback action to perform if the application does not + * handle the specified key. + * <p> + * When an application does not handle a particular key, the system may + * translate the key to an alternate fallback key (specified in the + * fallback action) and dispatch it to the application. + * The event containing the fallback key is flagged + * with {@link KeyEvent#FLAG_FALLBACK}. + * </p> + * + * @param keyCode The key code. + * @param metaState The meta key modifier state. + * @param outFallbackAction The fallback action object to populate. + * @return True if a fallback action was found, false otherwise. + * + * @hide + */ + public boolean getFallbackAction(int keyCode, int metaState, + FallbackAction outFallbackAction) { + if (outFallbackAction == null) { + throw new IllegalArgumentException("fallbackAction must not be null"); + } + + metaState = applyLockedModifiers(metaState); + return nativeGetFallbackAction(mPtr, keyCode, metaState, outFallbackAction); + } + + /** * Gets the number or symbol associated with the key. * <p> * The character value is returned, not the numeric value. @@ -277,6 +302,8 @@ public class KeyCharacterMap { if (chars == null) { throw new IllegalArgumentException("chars must not be null."); } + + metaState = applyLockedModifiers(metaState); return nativeGetMatch(mPtr, keyCode, chars, metaState); } @@ -509,6 +536,16 @@ public class KeyCharacterMap { return ret; } + private static int applyLockedModifiers(int metaState) { + if ((metaState & MetaKeyKeyListener.META_CAP_LOCKED) != 0) { + metaState |= KeyEvent.META_CAPS_LOCK_ON; + } + if ((metaState & MetaKeyKeyListener.META_ALT_LOCKED) != 0) { + metaState |= KeyEvent.META_ALT_ON; + } + return metaState; + } + /** * Maps Unicode combining diacritical to display-form dead key * (display character shifted left 16 bits). @@ -670,4 +707,14 @@ public class KeyCharacterMap { super(msg); } } + + /** + * Specifies a substitute key code and meta state as a fallback action + * for an unhandled key. + * @hide + */ + public static final class FallbackAction { + public int keyCode; + public int metaState; + } } diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java index 03407a3..43b77e6 100755 --- a/core/java/android/view/KeyEvent.java +++ b/core/java/android/view/KeyEvent.java @@ -529,15 +529,17 @@ public class KeyEvent extends InputEvent implements Parcelable { /** Key code constant: Blue "programmable" key. * On TV remotes, acts as a contextual/programmable key. */ public static final int KEYCODE_PROG_BLUE = 186; + /** Key code constant: App switch key. + * Should bring up the application switcher dialog. */ + public static final int KEYCODE_APP_SWITCH = 187; - private static final int LAST_KEYCODE = KEYCODE_PROG_BLUE; + private static final int LAST_KEYCODE = KEYCODE_APP_SWITCH; // NOTE: If you add a new keycode here you must also add it to: // isSystem() // native/include/android/keycodes.h // frameworks/base/include/ui/KeycodeLabels.h // external/webkit/WebKit/android/plugins/ANPKeyCodes.h - // tools/puppet_master/PuppetMaster/nav_keys.py // frameworks/base/core/res/res/values/attrs.xml // emulator? // @@ -737,6 +739,7 @@ public class KeyEvent extends InputEvent implements Parcelable { "KEYCODE_PROG_GREEN", "KEYCODE_PROG_YELLOW", "KEYCODE_PROG_BLUE", + "KEYCODE_APP_SWITCH", }; // Symbolic names of all metakeys in bit order from least significant to most significant. @@ -1056,7 +1059,17 @@ public class KeyEvent extends InputEvent implements Parcelable { * the tracking to be canceled. */ public static final int FLAG_TRACKING = 0x200; - + + /** + * Set when a key event has been synthesized to implement default behavior + * for an event that the application did not handle. + * Fallback key events are generated by unhandled trackball motions + * (to emulate a directional keypad) and by certain unhandled key presses + * that are declared in the key map (such as special function numeric keypad + * keys when numlock is off). + */ + public static final int FLAG_FALLBACK = 0x400; + /** * Private control to determine when an app is tracking a key sequence. * @hide diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 1f5bb5d..ad96686 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -556,7 +556,7 @@ import java.util.WeakHashMap; * improve the security of views that provide access to sensitive functionality. * </p><p> * To enable touch filtering, call {@link #setFilterTouchesWhenObscured} or set the - * andoird:filterTouchesWhenObscured attribute to true. When enabled, the framework + * android:filterTouchesWhenObscured layout attribute to true. When enabled, the framework * will discard touches that are received whenever the view's window is obscured by * another visible window. As a result, the view will not receive touches whenever a * toast, dialog or other window appears above the view's window. diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java index 53cff91..9bda637 100644 --- a/core/java/android/view/ViewRoot.java +++ b/core/java/android/view/ViewRoot.java @@ -2310,21 +2310,23 @@ public final class ViewRoot extends Handler implements ViewParent, } final int action = event.getAction(); - final int metastate = event.getMetaState(); + final int metaState = event.getMetaState(); switch (action) { case MotionEvent.ACTION_DOWN: x.reset(2); y.reset(2); deliverKeyEvent(new KeyEvent(curTime, curTime, - KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_CENTER, - 0, metastate), false); + KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_CENTER, 0, metaState, + KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FALLBACK, + InputDevice.SOURCE_KEYBOARD), false); break; case MotionEvent.ACTION_UP: x.reset(2); y.reset(2); deliverKeyEvent(new KeyEvent(curTime, curTime, - KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_CENTER, - 0, metastate), false); + KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_CENTER, 0, metaState, + KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FALLBACK, + InputDevice.SOURCE_KEYBOARD), false); break; } @@ -2374,9 +2376,11 @@ public final class ViewRoot extends Handler implements ViewParent, if (DEBUG_TRACKBALL) Log.v("foo", "Delivering fake DPAD: " + keycode); movement--; + int repeatCount = accelMovement - movement; deliverKeyEvent(new KeyEvent(curTime, curTime, - KeyEvent.ACTION_MULTIPLE, keycode, - accelMovement-movement, metastate), false); + KeyEvent.ACTION_MULTIPLE, keycode, repeatCount, metaState, + KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FALLBACK, + InputDevice.SOURCE_KEYBOARD), false); } while (movement > 0) { if (DEBUG_TRACKBALL) Log.v("foo", "Delivering fake DPAD: " @@ -2384,10 +2388,14 @@ public final class ViewRoot extends Handler implements ViewParent, movement--; curTime = SystemClock.uptimeMillis(); deliverKeyEvent(new KeyEvent(curTime, curTime, - KeyEvent.ACTION_DOWN, keycode, 0, event.getMetaState()), false); + KeyEvent.ACTION_DOWN, keycode, 0, metaState, + KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FALLBACK, + InputDevice.SOURCE_KEYBOARD), false); deliverKeyEvent(new KeyEvent(curTime, curTime, - KeyEvent.ACTION_UP, keycode, 0, metastate), false); - } + KeyEvent.ACTION_UP, keycode, 0, metaState, + KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FALLBACK, + InputDevice.SOURCE_KEYBOARD), false); + } mLastTrackballTime = curTime; } diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java index af36d80..3479bf5 100644 --- a/core/java/android/view/WindowManagerPolicy.java +++ b/core/java/android/view/WindowManagerPolicy.java @@ -587,9 +587,10 @@ public interface WindowManagerPolicy { * event will normally go. * @param event The key event. * @param policyFlags The policy flags associated with the key. - * @return Returns true if the policy consumed the event. + * @return Returns an alternate key event to redispatch as a fallback, or null to give up. + * The caller is responsible for recycling the key event. */ - public boolean dispatchUnhandledKey(WindowState win, KeyEvent event, int policyFlags); + public KeyEvent dispatchUnhandledKey(WindowState win, KeyEvent event, int policyFlags); /** * Called when layout of the windows is about to start. diff --git a/core/jni/Android.mk b/core/jni/Android.mk index bcd7bae..8eeed3d 100644 --- a/core/jni/Android.mk +++ b/core/jni/Android.mk @@ -51,11 +51,11 @@ LOCAL_SRC_FILES:= \ android_view_InputChannel.cpp \ android_view_InputQueue.cpp \ android_view_KeyEvent.cpp \ + android_view_KeyCharacterMap.cpp \ android_view_GLES20Canvas.cpp \ android_view_MotionEvent.cpp \ android_text_AndroidCharacter.cpp \ android_text_AndroidBidi.cpp \ - android_text_KeyCharacterMap.cpp \ android_os_Debug.cpp \ android_os_FileUtils.cpp \ android_os_MemoryFile.cpp \ diff --git a/core/jni/android_text_KeyCharacterMap.cpp b/core/jni/android_view_KeyCharacterMap.cpp index a7e62c1..bfeec4f 100644 --- a/core/jni/android_text_KeyCharacterMap.cpp +++ b/core/jni/android_view_KeyCharacterMap.cpp @@ -29,6 +29,14 @@ static struct { jclass clazz; } gKeyEventClassInfo; +static struct { + jclass clazz; + + jfieldID keyCode; + jfieldID metaState; +} gFallbackActionClassInfo; + + static jint nativeLoad(JNIEnv *env, jobject clazz, jint deviceId) { KeyCharacterMap* map; status_t status = KeyCharacterMap::loadByDeviceId(deviceId, &map); @@ -54,6 +62,21 @@ static jchar nativeGetCharacter(JNIEnv *env, jobject clazz, jint ptr, return map->getCharacter(keyCode, metaState); } +static jboolean nativeGetFallbackAction(JNIEnv *env, jobject clazz, jint ptr, jint keyCode, + jint metaState, jobject fallbackActionObj) { + KeyCharacterMap* map = reinterpret_cast<KeyCharacterMap*>(ptr); + KeyCharacterMap::FallbackAction fallbackAction; + + bool result = map->getFallbackAction(keyCode, metaState, &fallbackAction); + if (result) { + env->SetIntField(fallbackActionObj, gFallbackActionClassInfo.keyCode, + fallbackAction.keyCode); + env->SetIntField(fallbackActionObj, gFallbackActionClassInfo.metaState, + fallbackAction.metaState); + } + return result; +} + static jchar nativeGetNumber(JNIEnv *env, jobject clazz, jint ptr, jint keyCode) { KeyCharacterMap* map = reinterpret_cast<KeyCharacterMap*>(ptr); return map->getNumber(keyCode); @@ -126,6 +149,8 @@ static JNINativeMethod g_methods[] = { (void*)nativeDispose }, { "nativeGetCharacter", "(III)C", (void*)nativeGetCharacter }, + { "nativeGetFallbackAction", "(IIILandroid/view/KeyCharacterMap$FallbackAction;)Z", + (void*)nativeGetFallbackAction }, { "nativeGetNumber", "(II)C", (void*)nativeGetNumber }, { "nativeGetMatch", "(II[CI)C", @@ -143,10 +168,22 @@ static JNINativeMethod g_methods[] = { LOG_FATAL_IF(! var, "Unable to find class " className); \ var = jclass(env->NewGlobalRef(var)); +#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \ + var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \ + LOG_FATAL_IF(! var, "Unable to find field " fieldName); + int register_android_text_KeyCharacterMap(JNIEnv* env) { FIND_CLASS(gKeyEventClassInfo.clazz, "android/view/KeyEvent"); + FIND_CLASS(gFallbackActionClassInfo.clazz, "android/view/KeyCharacterMap$FallbackAction"); + + GET_FIELD_ID(gFallbackActionClassInfo.keyCode, gFallbackActionClassInfo.clazz, + "keyCode", "I"); + + GET_FIELD_ID(gFallbackActionClassInfo.metaState, gFallbackActionClassInfo.clazz, + "metaState", "I"); + return AndroidRuntime::registerNativeMethods(env, "android/view/KeyCharacterMap", g_methods, NELEM(g_methods)); } diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 81191ff..4bd91b3 100755 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -1267,6 +1267,7 @@ <enum name="KEYCODE_PROG_GREEN" value="184" /> <enum name="KEYCODE_PROG_YELLOW" value="185" /> <enum name="KEYCODE_PROG_BLUE" value="186" /> + <enum name="KEYCODE_APP_SWITCH" value="187" /> </attr> <!-- ***************************************************************** --> |