michael@0: /* michael@0: * Copyright (C) 2008 The Android Open Source Project michael@0: * michael@0: * Licensed under the Apache License, Version 2.0 (the "License"); michael@0: * you may not use this file except in compliance with the License. michael@0: * You may obtain a copy of the License at michael@0: * michael@0: * http://www.apache.org/licenses/LICENSE-2.0 michael@0: * michael@0: * Unless required by applicable law or agreed to in writing, software michael@0: * distributed under the License is distributed on an "AS IS" BASIS, michael@0: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. michael@0: * See the License for the specific language governing permissions and michael@0: * limitations under the License. michael@0: */ michael@0: michael@0: #ifndef _ANDROIDFW_KEY_CHARACTER_MAP_H michael@0: #define _ANDROIDFW_KEY_CHARACTER_MAP_H michael@0: michael@0: #include michael@0: michael@0: #if HAVE_ANDROID_OS michael@0: #include michael@0: #endif michael@0: michael@0: #include "Input.h" michael@0: #include michael@0: #include michael@0: #include "Tokenizer.h" michael@0: #include michael@0: #include michael@0: #include michael@0: michael@0: namespace android { michael@0: michael@0: /** michael@0: * Describes a mapping from Android key codes to characters. michael@0: * Also specifies other functions of the keyboard such as the keyboard type michael@0: * and key modifier semantics. michael@0: * michael@0: * This object is immutable after it has been loaded. michael@0: */ michael@0: class KeyCharacterMap : public RefBase { michael@0: public: michael@0: enum KeyboardType { michael@0: KEYBOARD_TYPE_UNKNOWN = 0, michael@0: KEYBOARD_TYPE_NUMERIC = 1, michael@0: KEYBOARD_TYPE_PREDICTIVE = 2, michael@0: KEYBOARD_TYPE_ALPHA = 3, michael@0: KEYBOARD_TYPE_FULL = 4, michael@0: KEYBOARD_TYPE_SPECIAL_FUNCTION = 5, michael@0: KEYBOARD_TYPE_OVERLAY = 6, michael@0: }; michael@0: michael@0: enum Format { michael@0: // Base keyboard layout, may contain device-specific options, such as "type" declaration. michael@0: FORMAT_BASE = 0, michael@0: // Overlay keyboard layout, more restrictive, may be published by applications, michael@0: // cannot override device-specific options. michael@0: FORMAT_OVERLAY = 1, michael@0: // Either base or overlay layout ok. michael@0: FORMAT_ANY = 2, michael@0: }; michael@0: michael@0: // Substitute key code and meta state for fallback action. michael@0: struct FallbackAction { michael@0: int32_t keyCode; michael@0: int32_t metaState; michael@0: }; michael@0: michael@0: /* Loads a key character map from a file. */ michael@0: static status_t load(const String8& filename, Format format, sp* outMap); michael@0: michael@0: /* Loads a key character map from its string contents. */ michael@0: static status_t loadContents(const String8& filename, michael@0: const char* contents, Format format, sp* outMap); michael@0: michael@0: /* Combines a base key character map and an overlay. */ michael@0: static sp combine(const sp& base, michael@0: const sp& overlay); michael@0: michael@0: /* Returns an empty key character map. */ michael@0: static sp empty(); michael@0: michael@0: /* Gets the keyboard type. */ michael@0: int32_t getKeyboardType() const; michael@0: michael@0: /* Gets the primary character for this key as in the label physically printed on it. michael@0: * Returns 0 if none (eg. for non-printing keys). */ michael@0: char16_t getDisplayLabel(int32_t keyCode) const; michael@0: michael@0: /* Gets the Unicode character for the number or symbol generated by the key michael@0: * when the keyboard is used as a dialing pad. michael@0: * Returns 0 if no number or symbol is generated. michael@0: */ michael@0: char16_t getNumber(int32_t keyCode) const; michael@0: michael@0: /* Gets the Unicode character generated by the key and meta key modifiers. michael@0: * Returns 0 if no character is generated. michael@0: */ michael@0: char16_t getCharacter(int32_t keyCode, int32_t metaState) const; michael@0: michael@0: /* Gets the fallback action to use by default if the application does not michael@0: * handle the specified key. michael@0: * Returns true if an action was available, false if none. michael@0: */ michael@0: bool getFallbackAction(int32_t keyCode, int32_t metaState, michael@0: FallbackAction* outFallbackAction) const; michael@0: michael@0: /* Gets the first matching Unicode character that can be generated by the key, michael@0: * preferring the one with the specified meta key modifiers. michael@0: * Returns 0 if no matching character is generated. michael@0: */ michael@0: char16_t getMatch(int32_t keyCode, const char16_t* chars, michael@0: size_t numChars, int32_t metaState) const; michael@0: michael@0: /* Gets a sequence of key events that could plausibly generate the specified michael@0: * character sequence. Returns false if some of the characters cannot be generated. michael@0: */ michael@0: bool getEvents(int32_t deviceId, const char16_t* chars, size_t numChars, michael@0: Vector& outEvents) const; michael@0: michael@0: /* Maps a scan code and usage code to a key code, in case this key map overrides michael@0: * the mapping in some way. */ michael@0: status_t mapKey(int32_t scanCode, int32_t usageCode, int32_t* outKeyCode) const; michael@0: michael@0: #if HAVE_ANDROID_OS michael@0: /* Reads a key map from a parcel. */ michael@0: static sp readFromParcel(Parcel* parcel); michael@0: michael@0: /* Writes a key map to a parcel. */ michael@0: void writeToParcel(Parcel* parcel) const; michael@0: #endif michael@0: michael@0: protected: michael@0: virtual ~KeyCharacterMap(); michael@0: michael@0: private: michael@0: struct Behavior { michael@0: Behavior(); michael@0: Behavior(const Behavior& other); michael@0: michael@0: /* The next behavior in the list, or NULL if none. */ michael@0: Behavior* next; michael@0: michael@0: /* The meta key modifiers for this behavior. */ michael@0: int32_t metaState; michael@0: michael@0: /* The character to insert. */ michael@0: char16_t character; michael@0: michael@0: /* The fallback keycode if the key is not handled. */ michael@0: int32_t fallbackKeyCode; michael@0: }; michael@0: michael@0: struct Key { michael@0: Key(); michael@0: Key(const Key& other); michael@0: ~Key(); michael@0: michael@0: /* The single character label printed on the key, or 0 if none. */ michael@0: char16_t label; michael@0: michael@0: /* The number or symbol character generated by the key, or 0 if none. */ michael@0: char16_t number; michael@0: michael@0: /* The list of key behaviors sorted from most specific to least specific michael@0: * meta key binding. */ michael@0: Behavior* firstBehavior; michael@0: }; michael@0: michael@0: class Parser { michael@0: enum State { michael@0: STATE_TOP = 0, michael@0: STATE_KEY = 1, michael@0: }; michael@0: michael@0: enum { michael@0: PROPERTY_LABEL = 1, michael@0: PROPERTY_NUMBER = 2, michael@0: PROPERTY_META = 3, michael@0: }; michael@0: michael@0: struct Property { michael@0: inline Property(int32_t property = 0, int32_t metaState = 0) : michael@0: property(property), metaState(metaState) { } michael@0: michael@0: int32_t property; michael@0: int32_t metaState; michael@0: }; michael@0: michael@0: KeyCharacterMap* mMap; michael@0: Tokenizer* mTokenizer; michael@0: Format mFormat; michael@0: State mState; michael@0: int32_t mKeyCode; michael@0: michael@0: public: michael@0: Parser(KeyCharacterMap* map, Tokenizer* tokenizer, Format format); michael@0: ~Parser(); michael@0: status_t parse(); michael@0: michael@0: private: michael@0: status_t parseType(); michael@0: status_t parseMap(); michael@0: status_t parseMapKey(); michael@0: status_t parseKey(); michael@0: status_t parseKeyProperty(); michael@0: status_t finishKey(Key* key); michael@0: status_t parseModifier(const String8& token, int32_t* outMetaState); michael@0: status_t parseCharacterLiteral(char16_t* outCharacter); michael@0: }; michael@0: michael@0: static sp sEmpty; michael@0: michael@0: KeyedVector mKeys; michael@0: int mType; michael@0: michael@0: KeyedVector mKeysByScanCode; michael@0: KeyedVector mKeysByUsageCode; michael@0: michael@0: KeyCharacterMap(); michael@0: KeyCharacterMap(const KeyCharacterMap& other); michael@0: michael@0: bool getKey(int32_t keyCode, const Key** outKey) const; michael@0: bool getKeyBehavior(int32_t keyCode, int32_t metaState, michael@0: const Key** outKey, const Behavior** outBehavior) const; michael@0: static bool matchesMetaState(int32_t eventMetaState, int32_t behaviorMetaState); michael@0: michael@0: bool findKey(char16_t ch, int32_t* outKeyCode, int32_t* outMetaState) const; michael@0: michael@0: static status_t load(Tokenizer* tokenizer, Format format, sp* outMap); michael@0: michael@0: static void addKey(Vector& outEvents, michael@0: int32_t deviceId, int32_t keyCode, int32_t metaState, bool down, nsecs_t time); michael@0: static void addMetaKeys(Vector& outEvents, michael@0: int32_t deviceId, int32_t metaState, bool down, nsecs_t time, michael@0: int32_t* currentMetaState); michael@0: static bool addSingleEphemeralMetaKey(Vector& outEvents, michael@0: int32_t deviceId, int32_t metaState, bool down, nsecs_t time, michael@0: int32_t keyCode, int32_t keyMetaState, michael@0: int32_t* currentMetaState); michael@0: static void addDoubleEphemeralMetaKey(Vector& outEvents, michael@0: int32_t deviceId, int32_t metaState, bool down, nsecs_t time, michael@0: int32_t leftKeyCode, int32_t leftKeyMetaState, michael@0: int32_t rightKeyCode, int32_t rightKeyMetaState, michael@0: int32_t eitherKeyMetaState, michael@0: int32_t* currentMetaState); michael@0: static void addLockedMetaKey(Vector& outEvents, michael@0: int32_t deviceId, int32_t metaState, nsecs_t time, michael@0: int32_t keyCode, int32_t keyMetaState, michael@0: int32_t* currentMetaState); michael@0: }; michael@0: michael@0: } // namespace android michael@0: michael@0: #endif // _ANDROIDFW_KEY_CHARACTER_MAP_H