summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorJeff Brown <jeffbrown@google.com>2010-12-06 17:13:33 -0800
committerJeff Brown <jeffbrown@google.com>2010-12-07 17:35:26 -0800
commit49ed71db425c5054e3ad9526496a7e116c89556b (patch)
tree3d3b28bdaf76d5cc531fd3b52fcbb0efb32a05ba /core
parentf30c8287525ac049d4d7589a330be5713256046b (diff)
downloadframeworks_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.java61
-rwxr-xr-xcore/java/android/view/KeyEvent.java19
-rw-r--r--core/java/android/view/View.java2
-rw-r--r--core/java/android/view/ViewRoot.java28
-rw-r--r--core/java/android/view/WindowManagerPolicy.java5
-rw-r--r--core/jni/Android.mk2
-rw-r--r--core/jni/android_view_KeyCharacterMap.cpp (renamed from core/jni/android_text_KeyCharacterMap.cpp)37
-rwxr-xr-xcore/res/res/values/attrs.xml1
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>
<!-- ***************************************************************** -->