Chromium Code Reviews| Index: ui/events/keycodes/dom/dom_key.h |
| diff --git a/ui/events/keycodes/dom/dom_key.h b/ui/events/keycodes/dom/dom_key.h |
| index 25ea09209b522e649fae8c8f5fe6e6a3438974d8..e692733ee8a1389dfc3355c14aafb088b3db8e78 100644 |
| --- a/ui/events/keycodes/dom/dom_key.h |
| +++ b/ui/events/keycodes/dom/dom_key.h |
| @@ -5,13 +5,154 @@ |
| #ifndef UI_EVENTS_KEYCODES_DOM3_DOM_KEY_H_ |
| #define UI_EVENTS_KEYCODES_DOM3_DOM_KEY_H_ |
| +#include <stdint.h> |
| + |
| +#include "base/logging.h" |
| + |
| namespace ui { |
| +// Integer representation of UI Events KeyboardEvent.key value. |
| +// |
| +// The semantics follow the web string form[1]: the value is either a |
| +// Unicode character or one of a defined set of additional values[2]. |
| +// There is one notable difference from the UI Events string key: for |
| +// the 'Dead' key, this type provides a whole range of values that also |
| +// encode the associated combining character. (They are not quite the |
| +// same thing: a dead key is a non-printing operator that modifies a |
| +// subsequent printing character, whereas a Unicode combining character |
| +// is a printable character in its own right that attaches to a preceding |
| +// character in a string.) This allows the interpretation of any keystroke |
| +// to be carried as a single integer value. |
| +// |
| +// DomKey::NONE is a sentinel used to indicate an error or undefined value. |
| +// It is not the same as Unicode code point 0 (ASCII NUL) or the valid DOM |
| +// key 'Unidentified'. |
|
Wez
2015/08/26 23:38:33
nit: It's confusing to mention "undefined value" a
kpschoedel
2015/08/27 15:47:54
I'm not sure how to write this. DomKey::UNIDENTIFI
|
| +// |
| +// References: |
| +// [1] http://www.w3.org/TR/uievents/#widl-KeyboardEvent-key |
| +// [2] http://www.w3.org/TR/DOM-Level-3-Events-key/ |
| +// |
| +class DomKey { |
| + public: |
| + using Base = int32_t; |
| + |
| + private: |
| + // Integer representation of DomKey. This is arranged so that DomKey encoded |
| + // values are distinct from Unicode code points, so that we can dynamically |
| + // verify that they are not accidentally conflated. |
| + // |
| + // 31 24 16 8 0 |
| + // | | | | | | | | | |
| + // | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| + // | z |c|s| v | |
| + // |
| + // From low to high: |
| + // - |v| is a value whose interpretation depends on the kind of key: |
| + // - for a Unicode value, it is the code point (0 <= v <= 0x10FFFF); |
| + // - for a dead key, the code point of the associated combining character; |
| + // - for others, an arbitrary distinct value. |
| + // - |s| is set for a valid symbolic key (i.e. not a Unicode character). |
| + // - |c| is set if |v| holds a code point (for either a Unicode character |
| + // directly, or a dead-key combining character). |
| + // - |z| is reserved and always zero. |
| + // |
| + // As consequences of this representation, |
| + // - all valid DomKey encodings have at least one of |c| or |s| set, so |
| + // they can't be confused with raw Unicode characters (where both are 0). |
| + // - integer 0 is not a valid encoding, and can be used for DomKey::NONE. |
| + // |
| + enum { VALUE_BITS = 21 }; |
| + enum Type : Base { |
| + VALUE_MASK = (1L << VALUE_BITS) - 1, |
| + TF_SYMBOLIC = (1L << VALUE_BITS), |
| + TF_CODEPOINT = (1L << (VALUE_BITS + 1)), |
| + TYPE_MASK = TF_CODEPOINT | TF_SYMBOLIC, |
| + TYPE_UNICODE = TF_CODEPOINT, |
| + TYPE_NON_UNICODE = TF_SYMBOLIC, |
| + TYPE_DEAD = TF_CODEPOINT | TF_SYMBOLIC, |
| + }; |
| + static_assert(TYPE_UNICODE != 0 && TYPE_NON_UNICODE != 0 && TYPE_DEAD != 0, |
| + "suspicious representation change"); |
|
Wez
2015/08/26 23:38:33
:D
|
| + |
| + public: |
| + enum InvalidKey : Base { NONE = 0 }; |
| +// |dom_key_data.inc| describes the non-printable DomKey values, and is |
| +// included here to create constants for them in the DomKey:: scope. |
| +#define DOM_KEY_MAP_DECLARATION enum Key : Base |
| +#define DOM_KEY_UNI(key, id, value) id = (TYPE_UNICODE | (value)) |
| +#define DOM_KEY_MAP_BEGIN FIRST_NON_UNICODE = TYPE_NON_UNICODE, |
| #define DOM_KEY_MAP(key, id) id |
| -#define DOM_KEY_MAP_DECLARATION enum class DomKey |
| +#define DOM_KEY_MAP_END LAST_NON_UNICODE |
| #include "ui/events/keycodes/dom/dom_key_data.inc" |
| -#undef DOM_KEY_MAP |
| #undef DOM_KEY_MAP_DECLARATION |
| +#undef DOM_KEY_MAP_BEGIN |
| +#undef DOM_KEY_MAP |
| +#undef DOM_KEY_MAP_END |
| +#undef DOM_KEY_UNI |
| + |
| + // Create a DomKey, with the undefined-value sentinel DomKey::NONE. |
| + DomKey() : value_(NONE) {} |
| + |
| + // Create a DomKey from an encoded integer value. This is implicit so |
| + // that DomKey::NAME constants don't need to be explicitly converted |
| + // to DomKey. |
| + DomKey(Base value) : value_(value) { |
| + DCHECK(value == 0 || IsValid()) << value; |
| + } |
| + |
| + // Obtain the encoded integer representation of the DomKey. |
| + operator Base() const { return value_; } |
| + |
| + // True if the value is a valid DomKey (which excludes DomKey::NONE and |
| + // integers not following the DomKey format). |
| + bool IsValid() const { return (value_ & TYPE_MASK) != 0; } |
| + |
| + // True if the value is a Unicode code point. |
| + bool IsCharacter() const { return (value_ & TYPE_MASK) == TYPE_UNICODE; } |
| + |
| + // True if the value is a dead key. |
| + bool IsDead() const { return (value_ & TYPE_MASK) == TYPE_DEAD; } |
|
Wez
2015/08/26 23:38:33
nit: Name this and ToDeadKeyCharacter, below, cons
|
| + |
| + // Returns the Unicode code point for a Unicode key. |
| + // It is incorrect to call this for other kinds of key. |
| + int32_t ToCharacter() const { |
| + DCHECK(IsCharacter()) << value_; |
| + return value_ & VALUE_MASK; |
| + } |
| + |
| + // Returns the associated combining code point for a dead key. |
| + // It is incorrect to call this for other kinds of key. |
| + int32_t ToDeadKeyCharacter() const { |
| + DCHECK(IsDead()) << value_; |
| + return value_ & VALUE_MASK; |
| + } |
| + |
| + // Returns a DomKey for the given Unicode character. |
| + static DomKey FromCharacter(int32_t character) { |
| + DCHECK(character >= 0 && character <= 0x10FFFF); |
| + return DomKey(TYPE_UNICODE | character); |
| + } |
| + |
| + // Returns a dead-key DomKey for the given combining character. |
| + static DomKey Dead(int32_t combining_character) { |
|
Wez
2015/08/26 23:38:33
nit: Name this consistently w/ FromCharacter and I
kpschoedel
2015/08/27 15:47:54
For dead keys, the combining character is an added
|
| + DCHECK(combining_character >= 0 && combining_character <= 0x10FFFF); |
| + return DomKey(TYPE_DEAD | combining_character); |
| + } |
| + |
| + // Provide means to generate constant DomKey::Base values, primarily to |
| + // allow conversion tables to be constant, without startup construction. |
| + // In the future (cue the theremin) this can be replaced with constexpr |
| + // functions. |
| + template<Base C> struct Constant { |
| + enum : Base { |
| + Character = TYPE_UNICODE | C, |
| + Dead = TYPE_DEAD | C, |
| + }; |
| + }; |
| + |
| + private: |
| + Base value_; |
| +}; |
| } // namespace ui |