Merge "Add Dvorak keyboard layout."

This commit is contained in:
Jeff Brown
2012-04-17 19:21:34 -07:00
committed by Android (Google) Code Review
6 changed files with 186 additions and 26 deletions

View File

@@ -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);

View File

@@ -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());

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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);