diff options
-rw-r--r-- | include/androidfw/KeyCharacterMap.h | 9 | ||||
-rw-r--r-- | libs/androidfw/KeyCharacterMap.cpp | 100 | ||||
-rw-r--r-- | libs/androidfw/KeyLayoutMap.cpp | 28 | ||||
-rw-r--r-- | packages/InputDevices/res/raw/keyboard_layout_english_us_dvorak.kcm | 42 | ||||
-rw-r--r-- | services/input/EventHub.cpp | 26 | ||||
-rw-r--r-- | services/input/EventHub.h | 7 |
6 files changed, 186 insertions, 26 deletions
diff --git a/include/androidfw/KeyCharacterMap.h b/include/androidfw/KeyCharacterMap.h index e0e6ffa73e82..8db578129707 100644 --- a/include/androidfw/KeyCharacterMap.h +++ b/include/androidfw/KeyCharacterMap.h @@ -120,6 +120,10 @@ public: bool getEvents(int32_t deviceId, const char16_t* chars, size_t numChars, Vector<KeyEvent>& outEvents) const; + /* Maps a scan code and usage code to a key code, in case this key map overrides + * the mapping in some way. */ + status_t mapKey(int32_t scanCode, int32_t usageCode, int32_t* outKeyCode) const; + #if HAVE_ANDROID_OS /* Reads a key map from a parcel. */ static sp<KeyCharacterMap> readFromParcel(Parcel* parcel); @@ -198,6 +202,8 @@ private: private: status_t parseType(); + status_t parseMap(); + status_t parseMapKey(); status_t parseKey(); status_t parseKeyProperty(); status_t parseModifier(const String8& token, int32_t* outMetaState); @@ -209,6 +215,9 @@ private: KeyedVector<int32_t, Key*> mKeys; int mType; + KeyedVector<int32_t, int32_t> mKeysByScanCode; + KeyedVector<int32_t, int32_t> mKeysByUsageCode; + KeyCharacterMap(); KeyCharacterMap(const KeyCharacterMap& other); diff --git a/libs/androidfw/KeyCharacterMap.cpp b/libs/androidfw/KeyCharacterMap.cpp index 66fdfd7828ec..c8f94390e4bf 100644 --- a/libs/androidfw/KeyCharacterMap.cpp +++ b/libs/androidfw/KeyCharacterMap.cpp @@ -90,7 +90,8 @@ KeyCharacterMap::KeyCharacterMap() : } KeyCharacterMap::KeyCharacterMap(const KeyCharacterMap& other) : - RefBase(), mType(other.mType) { + RefBase(), mType(other.mType), mKeysByScanCode(other.mKeysByScanCode), + mKeysByUsageCode(other.mKeysByUsageCode) { for (size_t i = 0; i < other.mKeys.size(); i++) { mKeys.add(other.mKeys.keyAt(i), new Key(*other.mKeys.valueAt(i))); } @@ -180,6 +181,16 @@ sp<KeyCharacterMap> KeyCharacterMap::combine(const sp<KeyCharacterMap>& base, map->mKeys.add(keyCode, new Key(*key)); } } + + for (size_t i = 0; i < overlay->mKeysByScanCode.size(); i++) { + map->mKeysByScanCode.replaceValueFor(overlay->mKeysByScanCode.keyAt(i), + overlay->mKeysByScanCode.valueAt(i)); + } + + for (size_t i = 0; i < overlay->mKeysByUsageCode.size(); i++) { + map->mKeysByUsageCode.replaceValueFor(overlay->mKeysByUsageCode.keyAt(i), + overlay->mKeysByUsageCode.valueAt(i)); + } return map; } @@ -315,6 +326,37 @@ bool KeyCharacterMap::getEvents(int32_t deviceId, const char16_t* chars, size_t return true; } +status_t KeyCharacterMap::mapKey(int32_t scanCode, int32_t usageCode, int32_t* outKeyCode) const { + if (usageCode) { + ssize_t index = mKeysByUsageCode.indexOfKey(usageCode); + if (index >= 0) { +#if DEBUG_MAPPING + 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) { +#if DEBUG_MAPPING + 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); +#endif + *outKeyCode = AKEYCODE_UNKNOWN; + return NAME_NOT_FOUND; +} + bool KeyCharacterMap::getKey(int32_t keyCode, const Key** outKey) const { ssize_t index = mKeys.indexOfKey(keyCode); if (index >= 0) { @@ -616,6 +658,10 @@ status_t KeyCharacterMap::Parser::parse() { mTokenizer->skipDelimiters(WHITESPACE); status_t status = parseType(); if (status) return status; + } else if (keywordToken == "map") { + mTokenizer->skipDelimiters(WHITESPACE); + status_t status = parseMap(); + if (status) return status; } else if (keywordToken == "key") { mTokenizer->skipDelimiters(WHITESPACE); status_t status = parseKey(); @@ -710,6 +756,58 @@ status_t KeyCharacterMap::Parser::parseType() { return NO_ERROR; } +status_t KeyCharacterMap::Parser::parseMap() { + String8 keywordToken = mTokenizer->nextToken(WHITESPACE); + if (keywordToken == "key") { + mTokenizer->skipDelimiters(WHITESPACE); + return parseMapKey(); + } + ALOGE("%s: Expected keyword after 'map', got '%s'.", mTokenizer->getLocation().string(), + keywordToken.string()); + return BAD_VALUE; +} + +status_t KeyCharacterMap::Parser::parseMapKey() { + String8 codeToken = mTokenizer->nextToken(WHITESPACE); + bool mapUsage = false; + if (codeToken == "usage") { + mapUsage = true; + mTokenizer->skipDelimiters(WHITESPACE); + codeToken = mTokenizer->nextToken(WHITESPACE); + } + + char* end; + int32_t code = int32_t(strtol(codeToken.string(), &end, 0)); + if (*end) { + ALOGE("%s: Expected key %s number, got '%s'.", mTokenizer->getLocation().string(), + mapUsage ? "usage" : "scan code", codeToken.string()); + return BAD_VALUE; + } + KeyedVector<int32_t, int32_t>& map = + mapUsage ? mMap->mKeysByUsageCode : mMap->mKeysByScanCode; + if (map.indexOfKey(code) >= 0) { + ALOGE("%s: Duplicate entry for key %s '%s'.", mTokenizer->getLocation().string(), + mapUsage ? "usage" : "scan code", codeToken.string()); + return BAD_VALUE; + } + + mTokenizer->skipDelimiters(WHITESPACE); + String8 keyCodeToken = mTokenizer->nextToken(WHITESPACE); + int32_t keyCode = getKeyCodeByLabel(keyCodeToken.string()); + if (!keyCode) { + ALOGE("%s: Expected key code label, got '%s'.", mTokenizer->getLocation().string(), + keyCodeToken.string()); + return BAD_VALUE; + } + +#if DEBUG_PARSER + ALOGD("Parsed map key %s: code=%d, keyCode=%d.", + mapUsage ? "usage" : "scan code", code, keyCode); +#endif + map.add(code, keyCode); + return NO_ERROR; +} + status_t KeyCharacterMap::Parser::parseKey() { String8 keyCodeToken = mTokenizer->nextToken(WHITESPACE); int32_t keyCode = getKeyCodeByLabel(keyCodeToken.string()); diff --git a/libs/androidfw/KeyLayoutMap.cpp b/libs/androidfw/KeyLayoutMap.cpp index a7c219965262..2db19c5ff72f 100644 --- a/libs/androidfw/KeyLayoutMap.cpp +++ b/libs/androidfw/KeyLayoutMap.cpp @@ -199,17 +199,26 @@ status_t KeyLayoutMap::Parser::parse() { } status_t KeyLayoutMap::Parser::parseKey() { - String8 scanCodeToken = mTokenizer->nextToken(WHITESPACE); + String8 codeToken = mTokenizer->nextToken(WHITESPACE); + bool mapUsage = false; + if (codeToken == "usage") { + mapUsage = true; + mTokenizer->skipDelimiters(WHITESPACE); + codeToken = mTokenizer->nextToken(WHITESPACE); + } + char* end; - int32_t scanCode = int32_t(strtol(scanCodeToken.string(), &end, 0)); + int32_t code = int32_t(strtol(codeToken.string(), &end, 0)); if (*end) { - ALOGE("%s: Expected key scan code number, got '%s'.", mTokenizer->getLocation().string(), - scanCodeToken.string()); + ALOGE("%s: Expected key %s number, got '%s'.", mTokenizer->getLocation().string(), + mapUsage ? "usage" : "scan code", codeToken.string()); return BAD_VALUE; } - if (mMap->mKeysByScanCode.indexOfKey(scanCode) >= 0) { - ALOGE("%s: Duplicate entry for key scan code '%s'.", mTokenizer->getLocation().string(), - scanCodeToken.string()); + KeyedVector<int32_t, Key>& map = + mapUsage ? mMap->mKeysByUsageCode : mMap->mKeysByScanCode; + if (map.indexOfKey(code) >= 0) { + ALOGE("%s: Duplicate entry for key %s '%s'.", mTokenizer->getLocation().string(), + mapUsage ? "usage" : "scan code", codeToken.string()); return BAD_VALUE; } @@ -243,12 +252,13 @@ status_t KeyLayoutMap::Parser::parseKey() { } #if DEBUG_PARSER - ALOGD("Parsed key: scanCode=%d, keyCode=%d, flags=0x%08x.", scanCode, keyCode, flags); + ALOGD("Parsed key %s: code=%d, keyCode=%d, flags=0x%08x.", + mapUsage ? "usage" : "scan code", code, keyCode, flags); #endif Key key; key.keyCode = keyCode; key.flags = flags; - mMap->mKeysByScanCode.add(scanCode, key); + map.add(code, key); return NO_ERROR; } diff --git a/packages/InputDevices/res/raw/keyboard_layout_english_us_dvorak.kcm b/packages/InputDevices/res/raw/keyboard_layout_english_us_dvorak.kcm index b5bf2ef44eb4..a2d110ea1eae 100644 --- a/packages/InputDevices/res/raw/keyboard_layout_english_us_dvorak.kcm +++ b/packages/InputDevices/res/raw/keyboard_layout_english_us_dvorak.kcm @@ -19,10 +19,38 @@ type OVERLAY -# Test -key A { - label: 'X' - base: 'x' - shift, capslock: 'X' - ctrl, alt, meta: none -} +map key 12 LEFT_BRACKET +map key 13 RIGHT_BRACKET +map key 16 APOSTROPHE +map key 17 COMMA +map key 18 PERIOD +map key 19 P +map key 20 Y +map key 21 F +map key 22 G +map key 23 C +map key 24 R +map key 25 L +map key 26 SLASH +map key 27 EQUALS +map key 30 A +map key 31 O +map key 32 E +map key 33 U +map key 34 I +map key 35 D +map key 36 H +map key 37 T +map key 38 N +map key 39 S +map key 40 MINUS +map key 44 SEMICOLON +map key 45 Q +map key 46 J +map key 47 K +map key 48 X +map key 49 B +map key 50 M +map key 51 W +map key 52 V +map key 53 Z diff --git a/services/input/EventHub.cpp b/services/input/EventHub.cpp index b788e16f1f5e..326dc3267e26 100644 --- a/services/input/EventHub.cpp +++ b/services/input/EventHub.cpp @@ -443,11 +443,22 @@ status_t EventHub::mapKey(int32_t deviceId, int32_t scanCode, int32_t usageCode, AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); - if (device && device->keyMap.haveKeyLayout()) { - status_t err = device->keyMap.keyLayoutMap->mapKey( - scanCode, usageCode, outKeycode, outFlags); - if (err == NO_ERROR) { - return NO_ERROR; + if (device) { + // Check the key character map first. + sp<KeyCharacterMap> kcm = device->getKeyCharacterMap(); + if (kcm != NULL) { + if (!kcm->mapKey(scanCode, usageCode, outKeycode)) { + *outFlags = 0; + return NO_ERROR; + } + } + + // Check the key layout next. + if (device->keyMap.haveKeyLayout()) { + if (!device->keyMap.keyLayoutMap->mapKey( + scanCode, usageCode, outKeycode, outFlags)) { + return NO_ERROR; + } } } @@ -531,10 +542,7 @@ sp<KeyCharacterMap> EventHub::getKeyCharacterMap(int32_t deviceId) const { AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); if (device) { - if (device->combinedKeyMap != NULL) { - return device->combinedKeyMap; - } - return device->keyMap.keyCharacterMap; + return device->getKeyCharacterMap(); } return NULL; } diff --git a/services/input/EventHub.h b/services/input/EventHub.h index f885f4da7e00..afc12ef1aa45 100644 --- a/services/input/EventHub.h +++ b/services/input/EventHub.h @@ -335,6 +335,13 @@ private: void close(); inline bool isVirtual() const { return fd < 0; } + + const sp<KeyCharacterMap>& getKeyCharacterMap() const { + if (combinedKeyMap != NULL) { + return combinedKeyMap; + } + return keyMap.keyCharacterMap; + } }; status_t openDeviceLocked(const char *devicePath); |