1/*
2 * Copyright (C) 2008 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 */
16
17#ifndef _UI_KEY_CHARACTER_MAP_H
18#define _UI_KEY_CHARACTER_MAP_H
19
20#include <stdint.h>
21
22#include <ui/Input.h>
23#include <utils/Errors.h>
24#include <utils/KeyedVector.h>
25#include <utils/Tokenizer.h>
26#include <utils/String8.h>
27#include <utils/Unicode.h>
28
29namespace android {
30
31/**
32 * Describes a mapping from Android key codes to characters.
33 * Also specifies other functions of the keyboard such as the keyboard type
34 * and key modifier semantics.
35 */
36class KeyCharacterMap {
37public:
38    enum KeyboardType {
39        KEYBOARD_TYPE_UNKNOWN = 0,
40        KEYBOARD_TYPE_NUMERIC = 1,
41        KEYBOARD_TYPE_PREDICTIVE = 2,
42        KEYBOARD_TYPE_ALPHA = 3,
43        KEYBOARD_TYPE_FULL = 4,
44        KEYBOARD_TYPE_SPECIAL_FUNCTION = 5,
45    };
46
47    // Substitute key code and meta state for fallback action.
48    struct FallbackAction {
49        int32_t keyCode;
50        int32_t metaState;
51    };
52
53    ~KeyCharacterMap();
54
55    static status_t load(const String8& filename, KeyCharacterMap** outMap);
56
57    /* Gets the keyboard type. */
58    int32_t getKeyboardType() const;
59
60    /* Gets the primary character for this key as in the label physically printed on it.
61     * Returns 0 if none (eg. for non-printing keys). */
62    char16_t getDisplayLabel(int32_t keyCode) const;
63
64    /* Gets the Unicode character for the number or symbol generated by the key
65     * when the keyboard is used as a dialing pad.
66     * Returns 0 if no number or symbol is generated.
67     */
68    char16_t getNumber(int32_t keyCode) const;
69
70    /* Gets the Unicode character generated by the key and meta key modifiers.
71     * Returns 0 if no character is generated.
72     */
73    char16_t getCharacter(int32_t keyCode, int32_t metaState) const;
74
75    /* Gets the fallback action to use by default if the application does not
76     * handle the specified key.
77     * Returns true if an action was available, false if none.
78     */
79    bool getFallbackAction(int32_t keyCode, int32_t metaState,
80            FallbackAction* outFallbackAction) const;
81
82    /* Gets the first matching Unicode character that can be generated by the key,
83     * preferring the one with the specified meta key modifiers.
84     * Returns 0 if no matching character is generated.
85     */
86    char16_t getMatch(int32_t keyCode, const char16_t* chars,
87            size_t numChars, int32_t metaState) const;
88
89    /* Gets a sequence of key events that could plausibly generate the specified
90     * character sequence.  Returns false if some of the characters cannot be generated.
91     */
92    bool getEvents(int32_t deviceId, const char16_t* chars, size_t numChars,
93            Vector<KeyEvent>& outEvents) const;
94
95private:
96    struct Behavior {
97        Behavior();
98
99        /* The next behavior in the list, or NULL if none. */
100        Behavior* next;
101
102        /* The meta key modifiers for this behavior. */
103        int32_t metaState;
104
105        /* The character to insert. */
106        char16_t character;
107
108        /* The fallback keycode if the key is not handled. */
109        int32_t fallbackKeyCode;
110    };
111
112    struct Key {
113        Key();
114        ~Key();
115
116        /* The single character label printed on the key, or 0 if none. */
117        char16_t label;
118
119        /* The number or symbol character generated by the key, or 0 if none. */
120        char16_t number;
121
122        /* The list of key behaviors sorted from most specific to least specific
123         * meta key binding. */
124        Behavior* firstBehavior;
125    };
126
127    class Parser {
128        enum State {
129            STATE_TOP = 0,
130            STATE_KEY = 1,
131        };
132
133        enum {
134            PROPERTY_LABEL = 1,
135            PROPERTY_NUMBER = 2,
136            PROPERTY_META = 3,
137        };
138
139        struct Property {
140            inline Property(int32_t property = 0, int32_t metaState = 0) :
141                    property(property), metaState(metaState) { }
142
143            int32_t property;
144            int32_t metaState;
145        };
146
147        KeyCharacterMap* mMap;
148        Tokenizer* mTokenizer;
149        State mState;
150        int32_t mKeyCode;
151
152    public:
153        Parser(KeyCharacterMap* map, Tokenizer* tokenizer);
154        ~Parser();
155        status_t parse();
156
157    private:
158        status_t parseType();
159        status_t parseKey();
160        status_t parseKeyProperty();
161        status_t parseModifier(const String8& token, int32_t* outMetaState);
162        status_t parseCharacterLiteral(char16_t* outCharacter);
163    };
164
165    KeyedVector<int32_t, Key*> mKeys;
166    int mType;
167
168    KeyCharacterMap();
169
170    bool getKey(int32_t keyCode, const Key** outKey) const;
171    bool getKeyBehavior(int32_t keyCode, int32_t metaState,
172            const Key** outKey, const Behavior** outBehavior) const;
173
174    bool findKey(char16_t ch, int32_t* outKeyCode, int32_t* outMetaState) const;
175
176    static void addKey(Vector<KeyEvent>& outEvents,
177            int32_t deviceId, int32_t keyCode, int32_t metaState, bool down, nsecs_t time);
178    static void addMetaKeys(Vector<KeyEvent>& outEvents,
179            int32_t deviceId, int32_t metaState, bool down, nsecs_t time,
180            int32_t* currentMetaState);
181    static bool addSingleEphemeralMetaKey(Vector<KeyEvent>& outEvents,
182            int32_t deviceId, int32_t metaState, bool down, nsecs_t time,
183            int32_t keyCode, int32_t keyMetaState,
184            int32_t* currentMetaState);
185    static void addDoubleEphemeralMetaKey(Vector<KeyEvent>& outEvents,
186            int32_t deviceId, int32_t metaState, bool down, nsecs_t time,
187            int32_t leftKeyCode, int32_t leftKeyMetaState,
188            int32_t rightKeyCode, int32_t rightKeyMetaState,
189            int32_t eitherKeyMetaState,
190            int32_t* currentMetaState);
191    static void addLockedMetaKey(Vector<KeyEvent>& outEvents,
192            int32_t deviceId, int32_t metaState, nsecs_t time,
193            int32_t keyCode, int32_t keyMetaState,
194            int32_t* currentMetaState);
195};
196
197} // namespace android
198
199#endif // _UI_KEY_CHARACTER_MAP_H
200