OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef UI_EVENTS_KEYCODES_DOM3_DOM_KEY_H_ | 5 #ifndef UI_EVENTS_KEYCODES_DOM3_DOM_KEY_H_ |
6 #define UI_EVENTS_KEYCODES_DOM3_DOM_KEY_H_ | 6 #define UI_EVENTS_KEYCODES_DOM3_DOM_KEY_H_ |
7 | 7 |
8 #include <stdint.h> | |
9 | |
10 #include "base/logging.h" | |
11 | |
8 namespace ui { | 12 namespace ui { |
9 | 13 |
14 // Integer representation of UI Events KeyboardEvent.key value. | |
15 // | |
16 // The semantics follow the web string form[1]: the value is either a | |
17 // Unicode character or one of a defined set of additional values[2]. | |
18 // There is one notable difference from the UI Events string key: for | |
19 // the 'Dead' key, this type provides a whole range of values that also | |
20 // encode the associated combining character. (They are not quite the | |
21 // same thing: a dead key is a non-printing operator that modifies a | |
22 // subsequent printing character, whereas a Unicode combining character | |
23 // is a printable character in its own right that attaches to a preceding | |
24 // character in a string.) This allows the interpretation of any keystroke | |
25 // to be carried as a single integer value. | |
26 // | |
27 // DomKey::NONE is a sentinel used to indicate an error or undefined value. | |
28 // It is not the same as Unicode code point 0 (ASCII NUL) or the valid DOM | |
29 // 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
| |
30 // | |
31 // References: | |
32 // [1] http://www.w3.org/TR/uievents/#widl-KeyboardEvent-key | |
33 // [2] http://www.w3.org/TR/DOM-Level-3-Events-key/ | |
34 // | |
35 class DomKey { | |
36 public: | |
37 using Base = int32_t; | |
38 | |
39 private: | |
40 // Integer representation of DomKey. This is arranged so that DomKey encoded | |
41 // values are distinct from Unicode code points, so that we can dynamically | |
42 // verify that they are not accidentally conflated. | |
43 // | |
44 // 31 24 16 8 0 | |
45 // | | | | | | | | | | |
46 // | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
47 // | z |c|s| v | | |
48 // | |
49 // From low to high: | |
50 // - |v| is a value whose interpretation depends on the kind of key: | |
51 // - for a Unicode value, it is the code point (0 <= v <= 0x10FFFF); | |
52 // - for a dead key, the code point of the associated combining character; | |
53 // - for others, an arbitrary distinct value. | |
54 // - |s| is set for a valid symbolic key (i.e. not a Unicode character). | |
55 // - |c| is set if |v| holds a code point (for either a Unicode character | |
56 // directly, or a dead-key combining character). | |
57 // - |z| is reserved and always zero. | |
58 // | |
59 // As consequences of this representation, | |
60 // - all valid DomKey encodings have at least one of |c| or |s| set, so | |
61 // they can't be confused with raw Unicode characters (where both are 0). | |
62 // - integer 0 is not a valid encoding, and can be used for DomKey::NONE. | |
63 // | |
64 enum { VALUE_BITS = 21 }; | |
65 enum Type : Base { | |
66 VALUE_MASK = (1L << VALUE_BITS) - 1, | |
67 TF_SYMBOLIC = (1L << VALUE_BITS), | |
68 TF_CODEPOINT = (1L << (VALUE_BITS + 1)), | |
69 TYPE_MASK = TF_CODEPOINT | TF_SYMBOLIC, | |
70 TYPE_UNICODE = TF_CODEPOINT, | |
71 TYPE_NON_UNICODE = TF_SYMBOLIC, | |
72 TYPE_DEAD = TF_CODEPOINT | TF_SYMBOLIC, | |
73 }; | |
74 static_assert(TYPE_UNICODE != 0 && TYPE_NON_UNICODE != 0 && TYPE_DEAD != 0, | |
75 "suspicious representation change"); | |
Wez
2015/08/26 23:38:33
:D
| |
76 | |
77 public: | |
78 enum InvalidKey : Base { NONE = 0 }; | |
79 // |dom_key_data.inc| describes the non-printable DomKey values, and is | |
80 // included here to create constants for them in the DomKey:: scope. | |
81 #define DOM_KEY_MAP_DECLARATION enum Key : Base | |
82 #define DOM_KEY_UNI(key, id, value) id = (TYPE_UNICODE | (value)) | |
83 #define DOM_KEY_MAP_BEGIN FIRST_NON_UNICODE = TYPE_NON_UNICODE, | |
10 #define DOM_KEY_MAP(key, id) id | 84 #define DOM_KEY_MAP(key, id) id |
11 #define DOM_KEY_MAP_DECLARATION enum class DomKey | 85 #define DOM_KEY_MAP_END LAST_NON_UNICODE |
12 #include "ui/events/keycodes/dom/dom_key_data.inc" | 86 #include "ui/events/keycodes/dom/dom_key_data.inc" |
87 #undef DOM_KEY_MAP_DECLARATION | |
88 #undef DOM_KEY_MAP_BEGIN | |
13 #undef DOM_KEY_MAP | 89 #undef DOM_KEY_MAP |
14 #undef DOM_KEY_MAP_DECLARATION | 90 #undef DOM_KEY_MAP_END |
91 #undef DOM_KEY_UNI | |
92 | |
93 // Create a DomKey, with the undefined-value sentinel DomKey::NONE. | |
94 DomKey() : value_(NONE) {} | |
95 | |
96 // Create a DomKey from an encoded integer value. This is implicit so | |
97 // that DomKey::NAME constants don't need to be explicitly converted | |
98 // to DomKey. | |
99 DomKey(Base value) : value_(value) { | |
100 DCHECK(value == 0 || IsValid()) << value; | |
101 } | |
102 | |
103 // Obtain the encoded integer representation of the DomKey. | |
104 operator Base() const { return value_; } | |
105 | |
106 // True if the value is a valid DomKey (which excludes DomKey::NONE and | |
107 // integers not following the DomKey format). | |
108 bool IsValid() const { return (value_ & TYPE_MASK) != 0; } | |
109 | |
110 // True if the value is a Unicode code point. | |
111 bool IsCharacter() const { return (value_ & TYPE_MASK) == TYPE_UNICODE; } | |
112 | |
113 // True if the value is a dead key. | |
114 bool IsDead() const { return (value_ & TYPE_MASK) == TYPE_DEAD; } | |
Wez
2015/08/26 23:38:33
nit: Name this and ToDeadKeyCharacter, below, cons
| |
115 | |
116 // Returns the Unicode code point for a Unicode key. | |
117 // It is incorrect to call this for other kinds of key. | |
118 int32_t ToCharacter() const { | |
119 DCHECK(IsCharacter()) << value_; | |
120 return value_ & VALUE_MASK; | |
121 } | |
122 | |
123 // Returns the associated combining code point for a dead key. | |
124 // It is incorrect to call this for other kinds of key. | |
125 int32_t ToDeadKeyCharacter() const { | |
126 DCHECK(IsDead()) << value_; | |
127 return value_ & VALUE_MASK; | |
128 } | |
129 | |
130 // Returns a DomKey for the given Unicode character. | |
131 static DomKey FromCharacter(int32_t character) { | |
132 DCHECK(character >= 0 && character <= 0x10FFFF); | |
133 return DomKey(TYPE_UNICODE | character); | |
134 } | |
135 | |
136 // Returns a dead-key DomKey for the given combining character. | |
137 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
| |
138 DCHECK(combining_character >= 0 && combining_character <= 0x10FFFF); | |
139 return DomKey(TYPE_DEAD | combining_character); | |
140 } | |
141 | |
142 // Provide means to generate constant DomKey::Base values, primarily to | |
143 // allow conversion tables to be constant, without startup construction. | |
144 // In the future (cue the theremin) this can be replaced with constexpr | |
145 // functions. | |
146 template<Base C> struct Constant { | |
147 enum : Base { | |
148 Character = TYPE_UNICODE | C, | |
149 Dead = TYPE_DEAD | C, | |
150 }; | |
151 }; | |
152 | |
153 private: | |
154 Base value_; | |
155 }; | |
15 | 156 |
16 } // namespace ui | 157 } // namespace ui |
17 | 158 |
18 #endif // UI_EVENTS_KEYCODES_DOM3_DOM_KEY_H_ | 159 #endif // UI_EVENTS_KEYCODES_DOM3_DOM_KEY_H_ |
OLD | NEW |