summaryrefslogtreecommitdiffstats
path: root/libs/input
diff options
context:
space:
mode:
authorDmitry Torokhov <dtor@google.com>2015-09-17 18:04:50 -0700
committerDmitry Torokhov <dtor@google.com>2015-09-29 13:26:30 -0700
commit115f93eeebf7f33b56ed090de70d6e8c733e5d88 (patch)
tree5cfb07f29be5d8a907e903b9ff5304213b73fbb7 /libs/input
parentce92ce9bef5942435bb49474f0e5e4b29cfc5e97 (diff)
downloadframeworks_native-115f93eeebf7f33b56ed090de70d6e8c733e5d88.zip
frameworks_native-115f93eeebf7f33b56ed090de70d6e8c733e5d88.tar.gz
frameworks_native-115f93eeebf7f33b56ed090de70d6e8c733e5d88.tar.bz2
Allow defining replacement key events in keymap
Currently keyboard maps allow to assign character sequences to key events and allow specifying a so-called "fallback" key events that are re-injected into input stream if target application indicates that it was not able to handle the original key event. Unfortunately there is no way to perform substitution before handing the event to applicationis. This change adds a new keymap keyword "replace" that allows users query "replacement" actions for key (if any), with the intent that such replacement happens early in the event handling process. Bug: 24504154 Change-Id: I3e6a2476c856524171df00ad22ff56f2018c1278
Diffstat (limited to 'libs/input')
-rw-r--r--libs/input/KeyCharacterMap.cpp108
-rw-r--r--libs/input/Keyboard.cpp5
2 files changed, 100 insertions, 13 deletions
diff --git a/libs/input/KeyCharacterMap.cpp b/libs/input/KeyCharacterMap.cpp
index b03e01e..df3f0dd 100644
--- a/libs/input/KeyCharacterMap.cpp
+++ b/libs/input/KeyCharacterMap.cpp
@@ -332,33 +332,75 @@ status_t KeyCharacterMap::mapKey(int32_t scanCode, int32_t usageCode, int32_t* o
if (usageCode) {
ssize_t index = mKeysByUsageCode.indexOfKey(usageCode);
if (index >= 0) {
+ *outKeyCode = mKeysByUsageCode.valueAt(index);
#if DEBUG_MAPPING
- ALOGD("mapKey: scanCode=%d, usageCode=0x%08x ~ Result keyCode=%d.",
- scanCode, usageCode, *outKeyCode);
+ ALOGD("mapKey: scanCode=%d, usageCode=0x%08x ~ Result keyCode=%d.",
+ scanCode, usageCode, *outKeyCode);
#endif
- *outKeyCode = mKeysByUsageCode.valueAt(index);
return OK;
}
}
if (scanCode) {
ssize_t index = mKeysByScanCode.indexOfKey(scanCode);
if (index >= 0) {
+ *outKeyCode = mKeysByScanCode.valueAt(index);
#if DEBUG_MAPPING
- ALOGD("mapKey: scanCode=%d, usageCode=0x%08x ~ Result keyCode=%d.",
- scanCode, usageCode, *outKeyCode);
+ ALOGD("mapKey: scanCode=%d, usageCode=0x%08x ~ Result keyCode=%d.",
+ scanCode, usageCode, *outKeyCode);
#endif
- *outKeyCode = mKeysByScanCode.valueAt(index);
return OK;
}
}
#if DEBUG_MAPPING
- ALOGD("mapKey: scanCode=%d, usageCode=0x%08x ~ Failed.", scanCode, usageCode);
+ ALOGD("mapKey: scanCode=%d, usageCode=0x%08x ~ Failed.", scanCode, usageCode);
#endif
*outKeyCode = AKEYCODE_UNKNOWN;
return NAME_NOT_FOUND;
}
+void KeyCharacterMap::tryRemapKey(int32_t keyCode, int32_t metaState,
+ int32_t *outKeyCode, int32_t *outMetaState) const {
+ *outKeyCode = keyCode;
+ *outMetaState = metaState;
+
+ const Key* key;
+ const Behavior* behavior;
+ if (getKeyBehavior(keyCode, metaState, &key, &behavior)) {
+ if (behavior->replacementKeyCode) {
+ *outKeyCode = behavior->replacementKeyCode;
+ int32_t newMetaState = metaState & ~behavior->metaState;
+ // Reset dependent meta states.
+ if (behavior->metaState & AMETA_ALT_ON) {
+ newMetaState &= ~(AMETA_ALT_LEFT_ON | AMETA_ALT_RIGHT_ON);
+ }
+ if (behavior->metaState & (AMETA_ALT_LEFT_ON | AMETA_ALT_RIGHT_ON)) {
+ newMetaState &= ~AMETA_ALT_ON;
+ }
+ if (behavior->metaState & AMETA_CTRL_ON) {
+ newMetaState &= ~(AMETA_CTRL_LEFT_ON | AMETA_CTRL_RIGHT_ON);
+ }
+ if (behavior->metaState & (AMETA_CTRL_LEFT_ON | AMETA_CTRL_RIGHT_ON)) {
+ newMetaState &= ~AMETA_CTRL_ON;
+ }
+ if (behavior->metaState & AMETA_SHIFT_ON) {
+ newMetaState &= ~(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_RIGHT_ON);
+ }
+ if (behavior->metaState & (AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_RIGHT_ON)) {
+ newMetaState &= ~AMETA_SHIFT_ON;
+ }
+ // ... and put universal bits back if needed
+ *outMetaState = normalizeMetaState(newMetaState);
+ }
+ }
+
+#if DEBUG_MAPPING
+ ALOGD("tryRemapKey: keyCode=%d, metaState=0x%08x ~ "
+ "replacement keyCode=%d, replacement metaState=0x%08x.",
+ keyCode, metaState, *outKeyCode, *outMetaState);
+#endif
+}
+
bool KeyCharacterMap::getKey(int32_t keyCode, const Key** outKey) const {
ssize_t index = mKeys.indexOfKey(keyCode);
if (index >= 0) {
@@ -584,6 +626,7 @@ sp<KeyCharacterMap> KeyCharacterMap::readFromParcel(Parcel* parcel) {
int32_t metaState = parcel->readInt32();
char16_t character = parcel->readInt32();
int32_t fallbackKeyCode = parcel->readInt32();
+ int32_t replacementKeyCode = parcel->readInt32();
if (parcel->errorCheck()) {
return NULL;
}
@@ -592,6 +635,7 @@ sp<KeyCharacterMap> KeyCharacterMap::readFromParcel(Parcel* parcel) {
behavior->metaState = metaState;
behavior->character = character;
behavior->fallbackKeyCode = fallbackKeyCode;
+ behavior->replacementKeyCode = replacementKeyCode;
if (lastBehavior) {
lastBehavior->next = behavior;
} else {
@@ -624,6 +668,7 @@ void KeyCharacterMap::writeToParcel(Parcel* parcel) const {
parcel->writeInt32(behavior->metaState);
parcel->writeInt32(behavior->character);
parcel->writeInt32(behavior->fallbackKeyCode);
+ parcel->writeInt32(behavior->replacementKeyCode);
}
parcel->writeInt32(0);
}
@@ -655,13 +700,14 @@ KeyCharacterMap::Key::~Key() {
// --- KeyCharacterMap::Behavior ---
KeyCharacterMap::Behavior::Behavior() :
- next(NULL), metaState(0), character(0), fallbackKeyCode(0) {
+ next(NULL), metaState(0), character(0), fallbackKeyCode(0), replacementKeyCode(0) {
}
KeyCharacterMap::Behavior::Behavior(const Behavior& other) :
next(other.next ? new Behavior(*other.next) : NULL),
metaState(other.metaState), character(other.character),
- fallbackKeyCode(other.fallbackKeyCode) {
+ fallbackKeyCode(other.fallbackKeyCode),
+ replacementKeyCode(other.replacementKeyCode) {
}
@@ -923,6 +969,7 @@ status_t KeyCharacterMap::Parser::parseKeyProperty() {
Behavior behavior;
bool haveCharacter = false;
bool haveFallback = false;
+ bool haveReplacement = false;
do {
char ch = mTokenizer->peekChar();
@@ -939,6 +986,11 @@ status_t KeyCharacterMap::Parser::parseKeyProperty() {
mTokenizer->getLocation().string());
return BAD_VALUE;
}
+ if (haveReplacement) {
+ ALOGE("%s: Cannot combine character literal with replace action.",
+ mTokenizer->getLocation().string());
+ return BAD_VALUE;
+ }
behavior.character = character;
haveCharacter = true;
} else {
@@ -949,6 +1001,11 @@ status_t KeyCharacterMap::Parser::parseKeyProperty() {
mTokenizer->getLocation().string());
return BAD_VALUE;
}
+ if (haveReplacement) {
+ ALOGE("%s: Cannot combine 'none' with replace action.",
+ mTokenizer->getLocation().string());
+ return BAD_VALUE;
+ }
haveCharacter = true;
} else if (token == "fallback") {
mTokenizer->skipDelimiters(WHITESPACE);
@@ -960,13 +1017,36 @@ status_t KeyCharacterMap::Parser::parseKeyProperty() {
token.string());
return BAD_VALUE;
}
- if (haveFallback) {
- ALOGE("%s: Cannot combine multiple fallback key codes.",
+ if (haveFallback || haveReplacement) {
+ ALOGE("%s: Cannot combine multiple fallback/replacement key codes.",
mTokenizer->getLocation().string());
return BAD_VALUE;
}
behavior.fallbackKeyCode = keyCode;
haveFallback = true;
+ } else if (token == "replace") {
+ mTokenizer->skipDelimiters(WHITESPACE);
+ token = mTokenizer->nextToken(WHITESPACE);
+ int32_t keyCode = getKeyCodeByLabel(token.string());
+ if (!keyCode) {
+ ALOGE("%s: Invalid key code label for replace, got '%s'.",
+ mTokenizer->getLocation().string(),
+ token.string());
+ return BAD_VALUE;
+ }
+ if (haveCharacter) {
+ ALOGE("%s: Cannot combine character literal with replace action.",
+ mTokenizer->getLocation().string());
+ return BAD_VALUE;
+ }
+ if (haveFallback || haveReplacement) {
+ ALOGE("%s: Cannot combine multiple fallback/replacement key codes.",
+ mTokenizer->getLocation().string());
+ return BAD_VALUE;
+ }
+ behavior.replacementKeyCode = keyCode;
+ haveReplacement = true;
+
} else {
ALOGE("%s: Expected a key behavior after ':'.",
mTokenizer->getLocation().string());
@@ -1016,8 +1096,10 @@ status_t KeyCharacterMap::Parser::parseKeyProperty() {
newBehavior->next = key->firstBehavior;
key->firstBehavior = newBehavior;
#if DEBUG_PARSER
- ALOGD("Parsed key meta: keyCode=%d, meta=0x%x, char=%d, fallback=%d.", mKeyCode,
- newBehavior->metaState, newBehavior->character, newBehavior->fallbackKeyCode);
+ ALOGD("Parsed key meta: keyCode=%d, meta=0x%x, char=%d, fallback=%d replace=%d.",
+ mKeyCode,
+ newBehavior->metaState, newBehavior->character,
+ newBehavior->fallbackKeyCode, newBehavior->replacementKeyCode);
#endif
break;
}
diff --git a/libs/input/Keyboard.cpp b/libs/input/Keyboard.cpp
index f4d9507..9a01395 100644
--- a/libs/input/Keyboard.cpp
+++ b/libs/input/Keyboard.cpp
@@ -176,6 +176,11 @@ static int32_t setEphemeralMetaState(int32_t mask, bool down, int32_t oldMetaSta
~(mask | AMETA_ALT_ON | AMETA_SHIFT_ON | AMETA_CTRL_ON | AMETA_META_ON);
}
+ return normalizeMetaState(newMetaState);
+}
+
+int32_t normalizeMetaState(int32_t oldMetaState) {
+ int32_t newMetaState = oldMetaState;
if (newMetaState & (AMETA_ALT_LEFT_ON | AMETA_ALT_RIGHT_ON)) {
newMetaState |= AMETA_ALT_ON;
}