16b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown/* 26b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown * Copyright (C) 2010 The Android Open Source Project 36b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown * 46b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown * Licensed under the Apache License, Version 2.0 (the "License"); 56b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown * you may not use this file except in compliance with the License. 66b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown * You may obtain a copy of the License at 76b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown * 86b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown * http://www.apache.org/licenses/LICENSE-2.0 96b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown * 106b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown * Unless required by applicable law or agreed to in writing, software 116b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown * distributed under the License is distributed on an "AS IS" BASIS, 126b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown * See the License for the specific language governing permissions and 146b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown * limitations under the License. 156b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown */ 166b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown 176b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown#define LOG_TAG "Keyboard" 186b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown 196b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown#include <stdlib.h> 206b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown#include <unistd.h> 216b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown#include <limits.h> 226b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown 23b93a03f841d93498bfea6cc92a22faa34bce1337Mathias Agopian#include <androidfw/Keyboard.h> 24b93a03f841d93498bfea6cc92a22faa34bce1337Mathias Agopian#include <androidfw/KeycodeLabels.h> 25b93a03f841d93498bfea6cc92a22faa34bce1337Mathias Agopian#include <androidfw/KeyLayoutMap.h> 26b93a03f841d93498bfea6cc92a22faa34bce1337Mathias Agopian#include <androidfw/KeyCharacterMap.h> 279f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown#include <androidfw/InputDevice.h> 286b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown#include <utils/Errors.h> 296b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown#include <utils/Log.h> 306b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown#include <cutils/properties.h> 316b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown 326b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brownnamespace android { 336b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown 349065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown// --- KeyMap --- 356b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown 369f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff BrownKeyMap::KeyMap() { 379065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown} 386b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown 399065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff BrownKeyMap::~KeyMap() { 406b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown} 416b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown 429065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brownstatus_t KeyMap::load(const InputDeviceIdentifier& deviceIdenfifier, 439065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown const PropertyMap* deviceConfiguration) { 4447e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown // Use the configured key layout if available. 4547e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown if (deviceConfiguration) { 4647e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown String8 keyLayoutName; 4747e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown if (deviceConfiguration->tryGetProperty(String8("keyboard.layout"), 4847e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown keyLayoutName)) { 499065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown status_t status = loadKeyLayout(deviceIdenfifier, keyLayoutName); 509065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown if (status == NAME_NOT_FOUND) { 513762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("Configuration for keyboard device '%s' requested keyboard layout '%s' but " 5247e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown "it was not found.", 539065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown deviceIdenfifier.name.string(), keyLayoutName.string()); 5447e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown } 5547e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown } 566b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown 5747e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown String8 keyCharacterMapName; 5847e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown if (deviceConfiguration->tryGetProperty(String8("keyboard.characterMap"), 5947e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown keyCharacterMapName)) { 609065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown status_t status = loadKeyCharacterMap(deviceIdenfifier, keyCharacterMapName); 619065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown if (status == NAME_NOT_FOUND) { 623762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("Configuration for keyboard device '%s' requested keyboard character " 6347e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown "map '%s' but it was not found.", 649065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown deviceIdenfifier.name.string(), keyLayoutName.string()); 6547e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown } 6647e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown } 676b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown 689065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown if (isComplete()) { 6947e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown return OK; 7047e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown } 7147e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown } 7247e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown 739065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown // Try searching by device identifier. 749065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown if (probeKeyMap(deviceIdenfifier, String8::empty())) { 7547e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown return OK; 7647e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown } 776b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown 7847e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown // Fall back on the Generic key map. 796b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown // TODO Apply some additional heuristics here to figure out what kind of 809065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown // generic key map to use (US English, etc.) for typical external keyboards. 819065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown if (probeKeyMap(deviceIdenfifier, String8("Generic"))) { 829065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown return OK; 839065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown } 849065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown 859065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown // Try the Virtual key map as a last resort. 869065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown if (probeKeyMap(deviceIdenfifier, String8("Virtual"))) { 8747e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown return OK; 8847e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown } 896b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown 906b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown // Give up! 913762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("Could not determine key map for device '%s' and no default key maps were found!", 929065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown deviceIdenfifier.name.string()); 936b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown return NAME_NOT_FOUND; 946b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown} 956b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown 969065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brownbool KeyMap::probeKeyMap(const InputDeviceIdentifier& deviceIdentifier, 979065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown const String8& keyMapName) { 989065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown if (!haveKeyLayout()) { 999065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown loadKeyLayout(deviceIdentifier, keyMapName); 1009065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown } 1019065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown if (!haveKeyCharacterMap()) { 1029065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown loadKeyCharacterMap(deviceIdentifier, keyMapName); 1039065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown } 1049065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown return isComplete(); 1059065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown} 1069065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown 1079065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brownstatus_t KeyMap::loadKeyLayout(const InputDeviceIdentifier& deviceIdentifier, 1089065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown const String8& name) { 1099065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown String8 path(getPath(deviceIdentifier, name, 1109065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown INPUT_DEVICE_CONFIGURATION_FILE_TYPE_KEY_LAYOUT)); 1119065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown if (path.isEmpty()) { 1129065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown return NAME_NOT_FOUND; 1139065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown } 1149065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown 1159f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown status_t status = KeyLayoutMap::load(path, &keyLayoutMap); 1169065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown if (status) { 1179065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown return status; 1189065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown } 1199065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown 1209065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown keyLayoutFile.setTo(path); 1219065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown return OK; 1229065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown} 1239065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown 1249065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brownstatus_t KeyMap::loadKeyCharacterMap(const InputDeviceIdentifier& deviceIdentifier, 1259065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown const String8& name) { 1269065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown String8 path(getPath(deviceIdentifier, name, 1279065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown INPUT_DEVICE_CONFIGURATION_FILE_TYPE_KEY_CHARACTER_MAP)); 1289065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown if (path.isEmpty()) { 1299065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown return NAME_NOT_FOUND; 1309065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown } 1319065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown 1326ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown status_t status = KeyCharacterMap::load(path, 1336ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown KeyCharacterMap::FORMAT_BASE, &keyCharacterMap); 1349065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown if (status) { 1359065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown return status; 1369065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown } 1379065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown 1389065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown keyCharacterMapFile.setTo(path); 1399065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown return OK; 1409065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown} 1419065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown 1429065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff BrownString8 KeyMap::getPath(const InputDeviceIdentifier& deviceIdentifier, 1439065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown const String8& name, InputDeviceConfigurationFileType type) { 1449065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown return name.isEmpty() 1459065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown ? getInputDeviceConfigurationFilePathByDeviceIdentifier(deviceIdentifier, type) 1469065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown : getInputDeviceConfigurationFilePathByName(name, type); 1479065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown} 1489065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown 1499065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown 1509065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown// --- Global functions --- 1519065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown 1529065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brownbool isEligibleBuiltInKeyboard(const InputDeviceIdentifier& deviceIdentifier, 1539065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown const PropertyMap* deviceConfiguration, const KeyMap* keyMap) { 1549065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown if (!keyMap->haveKeyCharacterMap() 1559065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown || keyMap->keyCharacterMap->getKeyboardType() 1569065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown == KeyCharacterMap::KEYBOARD_TYPE_SPECIAL_FUNCTION) { 1579065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown return false; 1589065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown } 1599065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown 1609065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown if (deviceConfiguration) { 1619065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown bool builtIn = false; 1629065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown if (deviceConfiguration->tryGetProperty(String8("keyboard.builtIn"), builtIn) 1639065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown && builtIn) { 1649065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown return true; 1659065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown } 1669065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown } 1679065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown 1689065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown return strstr(deviceIdentifier.name.string(), "-keypad"); 1699065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown} 1709065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown 1716f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brownstatic int lookupValueByLabel(const char* literal, const KeycodeLabel *list) { 1726b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown while (list->literal) { 1736b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown if (strcmp(literal, list->literal) == 0) { 1746b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown return list->value; 1756b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown } 1766b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown list++; 1776b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown } 1786b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown return list->value; 1796b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown} 1806b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown 1816f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brownstatic const char* lookupLabelByValue(int value, const KeycodeLabel *list) { 1826f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown while (list->literal) { 1836f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown if (list->value == value) { 1846f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown return list->literal; 1856f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown } 1866f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown list++; 1876f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown } 1886f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown return NULL; 1896f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown} 1906f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown 1916b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brownint32_t getKeyCodeByLabel(const char* label) { 1926f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown return int32_t(lookupValueByLabel(label, KEYCODES)); 1936b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown} 1946b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown 1956b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brownuint32_t getKeyFlagByLabel(const char* label) { 1966f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown return uint32_t(lookupValueByLabel(label, FLAGS)); 1976f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown} 1986f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown 1996f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brownint32_t getAxisByLabel(const char* label) { 2006f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown return int32_t(lookupValueByLabel(label, AXES)); 2016f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown} 2026f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown 2036f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brownconst char* getAxisLabel(int32_t axisId) { 2046f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown return lookupLabelByValue(axisId, AXES); 2056b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown} 2066b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown 2076b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brownstatic int32_t setEphemeralMetaState(int32_t mask, bool down, int32_t oldMetaState) { 2086b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown int32_t newMetaState; 2096b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown if (down) { 2106b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown newMetaState = oldMetaState | mask; 2116b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown } else { 2126b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown newMetaState = oldMetaState & 2136b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown ~(mask | AMETA_ALT_ON | AMETA_SHIFT_ON | AMETA_CTRL_ON | AMETA_META_ON); 2146b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown } 2156b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown 2166b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown if (newMetaState & (AMETA_ALT_LEFT_ON | AMETA_ALT_RIGHT_ON)) { 2176b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown newMetaState |= AMETA_ALT_ON; 2186b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown } 2196b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown 2206b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown if (newMetaState & (AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_RIGHT_ON)) { 2216b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown newMetaState |= AMETA_SHIFT_ON; 2226b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown } 2236b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown 2246b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown if (newMetaState & (AMETA_CTRL_LEFT_ON | AMETA_CTRL_RIGHT_ON)) { 2256b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown newMetaState |= AMETA_CTRL_ON; 2266b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown } 2276b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown 2286b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown if (newMetaState & (AMETA_META_LEFT_ON | AMETA_META_RIGHT_ON)) { 2296b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown newMetaState |= AMETA_META_ON; 2306b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown } 2316b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown return newMetaState; 2326b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown} 2336b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown 2346b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brownstatic int32_t toggleLockedMetaState(int32_t mask, bool down, int32_t oldMetaState) { 2356b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown if (down) { 2366b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown return oldMetaState; 2376b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown } else { 2386b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown return oldMetaState ^ mask; 2396b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown } 2406b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown} 2416b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown 2426b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brownint32_t updateMetaState(int32_t keyCode, bool down, int32_t oldMetaState) { 2436b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown int32_t mask; 2446b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown switch (keyCode) { 2456b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown case AKEYCODE_ALT_LEFT: 2466b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown return setEphemeralMetaState(AMETA_ALT_LEFT_ON, down, oldMetaState); 2476b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown case AKEYCODE_ALT_RIGHT: 2486b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown return setEphemeralMetaState(AMETA_ALT_RIGHT_ON, down, oldMetaState); 2496b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown case AKEYCODE_SHIFT_LEFT: 2506b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown return setEphemeralMetaState(AMETA_SHIFT_LEFT_ON, down, oldMetaState); 2516b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown case AKEYCODE_SHIFT_RIGHT: 2526b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown return setEphemeralMetaState(AMETA_SHIFT_RIGHT_ON, down, oldMetaState); 2536b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown case AKEYCODE_SYM: 2546b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown return setEphemeralMetaState(AMETA_SYM_ON, down, oldMetaState); 2556b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown case AKEYCODE_FUNCTION: 2566b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown return setEphemeralMetaState(AMETA_FUNCTION_ON, down, oldMetaState); 2576b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown case AKEYCODE_CTRL_LEFT: 2586b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown return setEphemeralMetaState(AMETA_CTRL_LEFT_ON, down, oldMetaState); 2596b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown case AKEYCODE_CTRL_RIGHT: 2606b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown return setEphemeralMetaState(AMETA_CTRL_RIGHT_ON, down, oldMetaState); 2616b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown case AKEYCODE_META_LEFT: 2626b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown return setEphemeralMetaState(AMETA_META_LEFT_ON, down, oldMetaState); 2636b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown case AKEYCODE_META_RIGHT: 2646b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown return setEphemeralMetaState(AMETA_META_RIGHT_ON, down, oldMetaState); 2656b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown case AKEYCODE_CAPS_LOCK: 2666b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown return toggleLockedMetaState(AMETA_CAPS_LOCK_ON, down, oldMetaState); 2676b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown case AKEYCODE_NUM_LOCK: 2686b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown return toggleLockedMetaState(AMETA_NUM_LOCK_ON, down, oldMetaState); 2696b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown case AKEYCODE_SCROLL_LOCK: 2706b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown return toggleLockedMetaState(AMETA_SCROLL_LOCK_ON, down, oldMetaState); 2716b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown default: 2726b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown return oldMetaState; 2736b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown } 2746b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown} 2756b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown 27605dc66ada6b61a6bdf806ffaa62617ac5394695dJeff Brownbool isMetaKey(int32_t keyCode) { 27705dc66ada6b61a6bdf806ffaa62617ac5394695dJeff Brown switch (keyCode) { 27805dc66ada6b61a6bdf806ffaa62617ac5394695dJeff Brown case AKEYCODE_ALT_LEFT: 27905dc66ada6b61a6bdf806ffaa62617ac5394695dJeff Brown case AKEYCODE_ALT_RIGHT: 28005dc66ada6b61a6bdf806ffaa62617ac5394695dJeff Brown case AKEYCODE_SHIFT_LEFT: 28105dc66ada6b61a6bdf806ffaa62617ac5394695dJeff Brown case AKEYCODE_SHIFT_RIGHT: 28205dc66ada6b61a6bdf806ffaa62617ac5394695dJeff Brown case AKEYCODE_SYM: 28305dc66ada6b61a6bdf806ffaa62617ac5394695dJeff Brown case AKEYCODE_FUNCTION: 28405dc66ada6b61a6bdf806ffaa62617ac5394695dJeff Brown case AKEYCODE_CTRL_LEFT: 28505dc66ada6b61a6bdf806ffaa62617ac5394695dJeff Brown case AKEYCODE_CTRL_RIGHT: 28605dc66ada6b61a6bdf806ffaa62617ac5394695dJeff Brown case AKEYCODE_META_LEFT: 28705dc66ada6b61a6bdf806ffaa62617ac5394695dJeff Brown case AKEYCODE_META_RIGHT: 28805dc66ada6b61a6bdf806ffaa62617ac5394695dJeff Brown case AKEYCODE_CAPS_LOCK: 28905dc66ada6b61a6bdf806ffaa62617ac5394695dJeff Brown case AKEYCODE_NUM_LOCK: 29005dc66ada6b61a6bdf806ffaa62617ac5394695dJeff Brown case AKEYCODE_SCROLL_LOCK: 29105dc66ada6b61a6bdf806ffaa62617ac5394695dJeff Brown return true; 29205dc66ada6b61a6bdf806ffaa62617ac5394695dJeff Brown default: 29305dc66ada6b61a6bdf806ffaa62617ac5394695dJeff Brown return false; 29405dc66ada6b61a6bdf806ffaa62617ac5394695dJeff Brown } 29505dc66ada6b61a6bdf806ffaa62617ac5394695dJeff Brown} 29605dc66ada6b61a6bdf806ffaa62617ac5394695dJeff Brown 2976b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown 2986b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown} // namespace android 299