Merge "Add Dvorak keyboard layout."
This commit is contained in:
@@ -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);
|
||||
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user