widget/gonk/libui/Keyboard.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /*
     2  * Copyright (C) 2010 The Android Open Source Project
     3  *
     4  * Licensed under the Apache License, Version 2.0 (the "License");
     5  * you may not use this file except in compliance with the License.
     6  * You may obtain a copy of the License at
     7  *
     8  *      http://www.apache.org/licenses/LICENSE-2.0
     9  *
    10  * Unless required by applicable law or agreed to in writing, software
    11  * distributed under the License is distributed on an "AS IS" BASIS,
    12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  * See the License for the specific language governing permissions and
    14  * limitations under the License.
    15  */
    17 #define LOG_TAG "Keyboard"
    18 #include "cutils_log.h"
    20 #include <stdlib.h>
    21 #include <unistd.h>
    22 #include <limits.h>
    24 #include "Keyboard.h"
    25 #include "KeycodeLabels.h"
    26 #include "KeyLayoutMap.h"
    27 #include "KeyCharacterMap.h"
    28 #include "InputDevice.h"
    29 #include <utils/Errors.h>
    30 #include <cutils/properties.h>
    32 namespace android {
    34 // --- KeyMap ---
    36 KeyMap::KeyMap() {
    37 }
    39 KeyMap::~KeyMap() {
    40 }
    42 status_t KeyMap::load(const InputDeviceIdentifier& deviceIdenfifier,
    43         const PropertyMap* deviceConfiguration) {
    44     // Use the configured key layout if available.
    45     if (deviceConfiguration) {
    46         String8 keyLayoutName;
    47         if (deviceConfiguration->tryGetProperty(String8("keyboard.layout"),
    48                 keyLayoutName)) {
    49             status_t status = loadKeyLayout(deviceIdenfifier, keyLayoutName);
    50             if (status == NAME_NOT_FOUND) {
    51                 ALOGE("Configuration for keyboard device '%s' requested keyboard layout '%s' but "
    52                         "it was not found.",
    53                         deviceIdenfifier.name.string(), keyLayoutName.string());
    54             }
    55         }
    57         String8 keyCharacterMapName;
    58         if (deviceConfiguration->tryGetProperty(String8("keyboard.characterMap"),
    59                 keyCharacterMapName)) {
    60             status_t status = loadKeyCharacterMap(deviceIdenfifier, keyCharacterMapName);
    61             if (status == NAME_NOT_FOUND) {
    62                 ALOGE("Configuration for keyboard device '%s' requested keyboard character "
    63                         "map '%s' but it was not found.",
    64                         deviceIdenfifier.name.string(), keyLayoutName.string());
    65             }
    66         }
    68         if (isComplete()) {
    69             return OK;
    70         }
    71     }
    73     // Try searching by device identifier.
    74     if (probeKeyMap(deviceIdenfifier, String8::empty())) {
    75         return OK;
    76     }
    78     // Fall back on the Generic key map.
    79     // TODO Apply some additional heuristics here to figure out what kind of
    80     //      generic key map to use (US English, etc.) for typical external keyboards.
    81     if (probeKeyMap(deviceIdenfifier, String8("Generic"))) {
    82         return OK;
    83     }
    85     // Try the Virtual key map as a last resort.
    86     if (probeKeyMap(deviceIdenfifier, String8("Virtual"))) {
    87         return OK;
    88     }
    90     // Give up!
    91     ALOGE("Could not determine key map for device '%s' and no default key maps were found!",
    92             deviceIdenfifier.name.string());
    93     return NAME_NOT_FOUND;
    94 }
    96 bool KeyMap::probeKeyMap(const InputDeviceIdentifier& deviceIdentifier,
    97         const String8& keyMapName) {
    98     if (!haveKeyLayout()) {
    99         loadKeyLayout(deviceIdentifier, keyMapName);
   100     }
   101     if (!haveKeyCharacterMap()) {
   102         loadKeyCharacterMap(deviceIdentifier, keyMapName);
   103     }
   104     return isComplete();
   105 }
   107 status_t KeyMap::loadKeyLayout(const InputDeviceIdentifier& deviceIdentifier,
   108         const String8& name) {
   109     String8 path(getPath(deviceIdentifier, name,
   110             INPUT_DEVICE_CONFIGURATION_FILE_TYPE_KEY_LAYOUT));
   111     if (path.isEmpty()) {
   112         return NAME_NOT_FOUND;
   113     }
   115     status_t status = KeyLayoutMap::load(path, &keyLayoutMap);
   116     if (status) {
   117         return status;
   118     }
   120     keyLayoutFile.setTo(path);
   121     return OK;
   122 }
   124 status_t KeyMap::loadKeyCharacterMap(const InputDeviceIdentifier& deviceIdentifier,
   125         const String8& name) {
   126     String8 path(getPath(deviceIdentifier, name,
   127             INPUT_DEVICE_CONFIGURATION_FILE_TYPE_KEY_CHARACTER_MAP));
   128     if (path.isEmpty()) {
   129         return NAME_NOT_FOUND;
   130     }
   132     status_t status = KeyCharacterMap::load(path,
   133             KeyCharacterMap::FORMAT_BASE, &keyCharacterMap);
   134     if (status) {
   135         return status;
   136     }
   138     keyCharacterMapFile.setTo(path);
   139     return OK;
   140 }
   142 String8 KeyMap::getPath(const InputDeviceIdentifier& deviceIdentifier,
   143         const String8& name, InputDeviceConfigurationFileType type) {
   144     return name.isEmpty()
   145             ? getInputDeviceConfigurationFilePathByDeviceIdentifier(deviceIdentifier, type)
   146             : getInputDeviceConfigurationFilePathByName(name, type);
   147 }
   150 // --- Global functions ---
   152 bool isEligibleBuiltInKeyboard(const InputDeviceIdentifier& deviceIdentifier,
   153         const PropertyMap* deviceConfiguration, const KeyMap* keyMap) {
   154     if (!keyMap->haveKeyCharacterMap()
   155             || keyMap->keyCharacterMap->getKeyboardType()
   156                     == KeyCharacterMap::KEYBOARD_TYPE_SPECIAL_FUNCTION) {
   157         return false;
   158     }
   160     if (deviceConfiguration) {
   161         bool builtIn = false;
   162         if (deviceConfiguration->tryGetProperty(String8("keyboard.builtIn"), builtIn)
   163                 && builtIn) {
   164             return true;
   165         }
   166     }
   168     return strstr(deviceIdentifier.name.string(), "-keypad");
   169 }
   171 static int lookupValueByLabel(const char* literal, const KeycodeLabel *list) {
   172     while (list->literal) {
   173         if (strcmp(literal, list->literal) == 0) {
   174             return list->value;
   175         }
   176         list++;
   177     }
   178     return list->value;
   179 }
   181 static const char* lookupLabelByValue(int value, const KeycodeLabel *list) {
   182     while (list->literal) {
   183         if (list->value == value) {
   184             return list->literal;
   185         }
   186         list++;
   187     }
   188     return NULL;
   189 }
   191 int32_t getKeyCodeByLabel(const char* label) {
   192     return int32_t(lookupValueByLabel(label, KEYCODES));
   193 }
   195 uint32_t getKeyFlagByLabel(const char* label) {
   196     return uint32_t(lookupValueByLabel(label, FLAGS));
   197 }
   199 int32_t getAxisByLabel(const char* label) {
   200     return int32_t(lookupValueByLabel(label, AXES));
   201 }
   203 const char* getAxisLabel(int32_t axisId) {
   204     return lookupLabelByValue(axisId, AXES);
   205 }
   207 static int32_t setEphemeralMetaState(int32_t mask, bool down, int32_t oldMetaState) {
   208     int32_t newMetaState;
   209     if (down) {
   210         newMetaState = oldMetaState | mask;
   211     } else {
   212         newMetaState = oldMetaState &
   213                 ~(mask | AMETA_ALT_ON | AMETA_SHIFT_ON | AMETA_CTRL_ON | AMETA_META_ON);
   214     }
   216     if (newMetaState & (AMETA_ALT_LEFT_ON | AMETA_ALT_RIGHT_ON)) {
   217         newMetaState |= AMETA_ALT_ON;
   218     }
   220     if (newMetaState & (AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_RIGHT_ON)) {
   221         newMetaState |= AMETA_SHIFT_ON;
   222     }
   224     if (newMetaState & (AMETA_CTRL_LEFT_ON | AMETA_CTRL_RIGHT_ON)) {
   225         newMetaState |= AMETA_CTRL_ON;
   226     }
   228     if (newMetaState & (AMETA_META_LEFT_ON | AMETA_META_RIGHT_ON)) {
   229         newMetaState |= AMETA_META_ON;
   230     }
   231     return newMetaState;
   232 }
   234 static int32_t toggleLockedMetaState(int32_t mask, bool down, int32_t oldMetaState) {
   235     if (down) {
   236         return oldMetaState;
   237     } else {
   238         return oldMetaState ^ mask;
   239     }
   240 }
   242 int32_t updateMetaState(int32_t keyCode, bool down, int32_t oldMetaState) {
   243     int32_t mask;
   244     switch (keyCode) {
   245     case AKEYCODE_ALT_LEFT:
   246         return setEphemeralMetaState(AMETA_ALT_LEFT_ON, down, oldMetaState);
   247     case AKEYCODE_ALT_RIGHT:
   248         return setEphemeralMetaState(AMETA_ALT_RIGHT_ON, down, oldMetaState);
   249     case AKEYCODE_SHIFT_LEFT:
   250         return setEphemeralMetaState(AMETA_SHIFT_LEFT_ON, down, oldMetaState);
   251     case AKEYCODE_SHIFT_RIGHT:
   252         return setEphemeralMetaState(AMETA_SHIFT_RIGHT_ON, down, oldMetaState);
   253     case AKEYCODE_SYM:
   254         return setEphemeralMetaState(AMETA_SYM_ON, down, oldMetaState);
   255     case AKEYCODE_FUNCTION:
   256         return setEphemeralMetaState(AMETA_FUNCTION_ON, down, oldMetaState);
   257     case AKEYCODE_CTRL_LEFT:
   258         return setEphemeralMetaState(AMETA_CTRL_LEFT_ON, down, oldMetaState);
   259     case AKEYCODE_CTRL_RIGHT:
   260         return setEphemeralMetaState(AMETA_CTRL_RIGHT_ON, down, oldMetaState);
   261     case AKEYCODE_META_LEFT:
   262         return setEphemeralMetaState(AMETA_META_LEFT_ON, down, oldMetaState);
   263     case AKEYCODE_META_RIGHT:
   264         return setEphemeralMetaState(AMETA_META_RIGHT_ON, down, oldMetaState);
   265     case AKEYCODE_CAPS_LOCK:
   266         return toggleLockedMetaState(AMETA_CAPS_LOCK_ON, down, oldMetaState);
   267     case AKEYCODE_NUM_LOCK:
   268         return toggleLockedMetaState(AMETA_NUM_LOCK_ON, down, oldMetaState);
   269     case AKEYCODE_SCROLL_LOCK:
   270         return toggleLockedMetaState(AMETA_SCROLL_LOCK_ON, down, oldMetaState);
   271     default:
   272         return oldMetaState;
   273     }
   274 }
   276 bool isMetaKey(int32_t keyCode) {
   277     switch (keyCode) {
   278     case AKEYCODE_ALT_LEFT:
   279     case AKEYCODE_ALT_RIGHT:
   280     case AKEYCODE_SHIFT_LEFT:
   281     case AKEYCODE_SHIFT_RIGHT:
   282     case AKEYCODE_SYM:
   283     case AKEYCODE_FUNCTION:
   284     case AKEYCODE_CTRL_LEFT:
   285     case AKEYCODE_CTRL_RIGHT:
   286     case AKEYCODE_META_LEFT:
   287     case AKEYCODE_META_RIGHT:
   288     case AKEYCODE_CAPS_LOCK:
   289     case AKEYCODE_NUM_LOCK:
   290     case AKEYCODE_SCROLL_LOCK:
   291         return true;
   292     default:
   293         return false;
   294     }
   295 }
   298 } // namespace android

mercurial