summaryrefslogtreecommitdiffstats
path: root/include/ui/KeyCharacterMap.h
blob: 10a38109d553608558ca439b483218055bcff993 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef _UI_KEY_CHARACTER_MAP_H
#define _UI_KEY_CHARACTER_MAP_H

#include <stdint.h>

#include <ui/Input.h>
#include <utils/Errors.h>
#include <utils/KeyedVector.h>
#include <utils/Tokenizer.h>
#include <utils/String8.h>
#include <utils/Unicode.h>

namespace android {

/**
 * Describes a mapping from Android key codes to characters.
 * Also specifies other functions of the keyboard such as the keyboard type
 * and key modifier semantics.
 */
class KeyCharacterMap {
public:
    enum KeyboardType {
        KEYBOARD_TYPE_UNKNOWN = 0,
        KEYBOARD_TYPE_NUMERIC = 1,
        KEYBOARD_TYPE_PREDICTIVE = 2,
        KEYBOARD_TYPE_ALPHA = 3,
        KEYBOARD_TYPE_FULL = 4,
        KEYBOARD_TYPE_SPECIAL_FUNCTION = 5,
    };

    // Substitute key code and meta state for fallback action.
    struct FallbackAction {
        int32_t keyCode;
        int32_t metaState;
    };

    ~KeyCharacterMap();

    static status_t load(const String8& filename, KeyCharacterMap** outMap);
    static status_t loadByDeviceId(int32_t deviceId, KeyCharacterMap** outMap);

    /* Gets the keyboard type. */
    int32_t getKeyboardType() const;

    /* Gets the primary character for this key as in the label physically printed on it.
     * Returns 0 if none (eg. for non-printing keys). */
    char16_t getDisplayLabel(int32_t keyCode) const;

    /* Gets the Unicode character for the number or symbol generated by the key
     * when the keyboard is used as a dialing pad.
     * Returns 0 if no number or symbol is generated.
     */
    char16_t getNumber(int32_t keyCode) const;

    /* Gets the Unicode character generated by the key and meta key modifiers.
     * Returns 0 if no character is generated.
     */
    char16_t getCharacter(int32_t keyCode, int32_t metaState) const;

    /* Gets the fallback action to use by default if the application does not
     * handle the specified key.
     * Returns true if an action was available, false if none.
     */
    bool getFallbackAction(int32_t keyCode, int32_t metaState,
            FallbackAction* outFallbackAction) const;

    /* Gets the first matching Unicode character that can be generated by the key,
     * preferring the one with the specified meta key modifiers.
     * Returns 0 if no matching character is generated.
     */
    char16_t getMatch(int32_t keyCode, const char16_t* chars,
            size_t numChars, int32_t metaState) const;

    /* Gets a sequence of key events that could plausibly generate the specified
     * character sequence.  Returns false if some of the characters cannot be generated.
     */
    bool getEvents(int32_t deviceId, const char16_t* chars, size_t numChars,
            Vector<KeyEvent>& outEvents) const;

private:
    struct Behavior {
        Behavior();

        /* The next behavior in the list, or NULL if none. */
        Behavior* next;

        /* The meta key modifiers for this behavior. */
        int32_t metaState;

        /* The character to insert. */
        char16_t character;

        /* The fallback keycode if the key is not handled. */
        int32_t fallbackKeyCode;
    };

    struct Key {
        Key();
        ~Key();

        /* The single character label printed on the key, or 0 if none. */
        char16_t label;

        /* The number or symbol character generated by the key, or 0 if none. */
        char16_t number;

        /* The list of key behaviors sorted from most specific to least specific
         * meta key binding. */
        Behavior* firstBehavior;
    };

    class Parser {
        enum State {
            STATE_TOP = 0,
            STATE_KEY = 1,
        };

        enum {
            PROPERTY_LABEL = 1,
            PROPERTY_NUMBER = 2,
            PROPERTY_META = 3,
        };

        struct Property {
            inline Property(int32_t property = 0, int32_t metaState = 0) :
                    property(property), metaState(metaState) { }

            int32_t property;
            int32_t metaState;
        };

        KeyCharacterMap* mMap;
        Tokenizer* mTokenizer;
        State mState;
        int32_t mKeyCode;

    public:
        Parser(KeyCharacterMap* map, Tokenizer* tokenizer);
        ~Parser();
        status_t parse();

    private:
        status_t parseType();
        status_t parseKey();
        status_t parseKeyProperty();
        status_t parseModifier(const String8& token, int32_t* outMetaState);
        status_t parseCharacterLiteral(char16_t* outCharacter);
    };

    KeyedVector<int32_t, Key*> mKeys;
    int mType;

    KeyCharacterMap();

    bool getKey(int32_t keyCode, const Key** outKey) const;
    bool getKeyBehavior(int32_t keyCode, int32_t metaState,
            const Key** outKey, const Behavior** outBehavior) const;

    bool findKey(char16_t ch, int32_t* outKeyCode, int32_t* outMetaState) const;

    static void addKey(Vector<KeyEvent>& outEvents,
            int32_t deviceId, int32_t keyCode, int32_t metaState, bool down, nsecs_t time);
    static void addMetaKeys(Vector<KeyEvent>& outEvents,
            int32_t deviceId, int32_t metaState, bool down, nsecs_t time,
            int32_t* currentMetaState);
    static bool addSingleEphemeralMetaKey(Vector<KeyEvent>& outEvents,
            int32_t deviceId, int32_t metaState, bool down, nsecs_t time,
            int32_t keyCode, int32_t keyMetaState,
            int32_t* currentMetaState);
    static void addDoubleEphemeralMetaKey(Vector<KeyEvent>& outEvents,
            int32_t deviceId, int32_t metaState, bool down, nsecs_t time,
            int32_t leftKeyCode, int32_t leftKeyMetaState,
            int32_t rightKeyCode, int32_t rightKeyMetaState,
            int32_t eitherKeyMetaState,
            int32_t* currentMetaState);
    static void addLockedMetaKey(Vector<KeyEvent>& outEvents,
            int32_t deviceId, int32_t metaState, nsecs_t time,
            int32_t keyCode, int32_t keyMetaState,
            int32_t* currentMetaState);
};

} // namespace android

#endif // _UI_KEY_CHARACTER_MAP_H