Add ICU message format support
[chromium-blink-merge.git] / ui / events / keycodes / dom / keycode_converter.cc
blob9aef53f29716fb41f263f52538ee9179a0a32699
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ui/events/keycodes/dom/keycode_converter.h"
7 #include "base/logging.h"
8 #include "ui/events/keycodes/dom/dom_code.h"
9 #include "ui/events/keycodes/dom/dom_key.h"
11 namespace ui {
13 namespace {
15 // Table of USB codes (equivalent to DomCode values), native scan codes,
16 // and DOM Level 3 |code| strings.
17 #if defined(OS_WIN)
18 #define USB_KEYMAP(usb, xkb, win, mac, code, id) {usb, win, code}
19 #elif defined(OS_LINUX)
20 #define USB_KEYMAP(usb, xkb, win, mac, code, id) {usb, xkb, code}
21 #elif defined(OS_MACOSX)
22 #define USB_KEYMAP(usb, xkb, win, mac, code, id) {usb, mac, code}
23 #else
24 #define USB_KEYMAP(usb, xkb, win, mac, code, id) {usb, 0, code}
25 #endif
26 #define USB_KEYMAP_DECLARATION const KeycodeMapEntry usb_keycode_map[] =
27 #include "ui/events/keycodes/dom/keycode_converter_data.inc"
28 #undef USB_KEYMAP
29 #undef USB_KEYMAP_DECLARATION
31 const size_t kKeycodeMapEntries = arraysize(usb_keycode_map);
33 // Table of DomKey enum values and DOM Level 3 |key| strings.
34 struct DomKeyMapEntry {
35 DomKey dom_key;
36 const char* string;
39 #define DOM_KEY_MAP(key, id) {DomKey::id, key}
40 #define DOM_KEY_MAP_DECLARATION const DomKeyMapEntry dom_key_map[] =
41 #include "ui/events/keycodes/dom/dom_key_data.inc"
42 #undef DOM_KEY_MAP
43 #undef DOM_KEY_MAP_DECLARATION
45 const size_t kDomKeyMapEntries = arraysize(dom_key_map);
47 } // namespace
49 // static
50 size_t KeycodeConverter::NumKeycodeMapEntriesForTest() {
51 return kKeycodeMapEntries;
54 // static
55 const KeycodeMapEntry* KeycodeConverter::GetKeycodeMapForTest() {
56 return &usb_keycode_map[0];
59 // static
60 const char* KeycodeConverter::DomKeyStringForTest(size_t index) {
61 if (index >= kDomKeyMapEntries)
62 return nullptr;
63 return dom_key_map[index].string;
66 // static
67 int KeycodeConverter::InvalidNativeKeycode() {
68 return usb_keycode_map[0].native_keycode;
71 // static
72 DomCode KeycodeConverter::NativeKeycodeToDomCode(int native_keycode) {
73 for (size_t i = 0; i < kKeycodeMapEntries; ++i) {
74 if (usb_keycode_map[i].native_keycode == native_keycode) {
75 if (usb_keycode_map[i].code != NULL)
76 return static_cast<DomCode>(usb_keycode_map[i].usb_keycode);
77 break;
80 return DomCode::NONE;
83 // static
84 int KeycodeConverter::DomCodeToNativeKeycode(DomCode code) {
85 return UsbKeycodeToNativeKeycode(static_cast<uint32_t>(code));
88 // static
89 DomCode KeycodeConverter::CodeStringToDomCode(const char* code) {
90 if (!code || !*code) {
91 LOG(WARNING) << "empty code string";
92 return DomCode::NONE;
94 for (size_t i = 0; i < kKeycodeMapEntries; ++i) {
95 if (usb_keycode_map[i].code &&
96 strcmp(usb_keycode_map[i].code, code) == 0) {
97 return static_cast<DomCode>(usb_keycode_map[i].usb_keycode);
100 LOG(WARNING) << "unrecognized code string '" << code << "'";
101 return DomCode::NONE;
104 // static
105 const char* KeycodeConverter::DomCodeToCodeString(DomCode dom_code) {
106 for (size_t i = 0; i < kKeycodeMapEntries; ++i) {
107 if (usb_keycode_map[i].usb_keycode == static_cast<uint32_t>(dom_code)) {
108 if (usb_keycode_map[i].code)
109 return usb_keycode_map[i].code;
110 break;
113 return "";
116 // static
117 DomKeyLocation KeycodeConverter::DomCodeToLocation(DomCode dom_code) {
118 static const struct {
119 DomCode code;
120 DomKeyLocation location;
121 } kLocations[] = {{DomCode::CONTROL_LEFT, DomKeyLocation::LEFT},
122 {DomCode::SHIFT_LEFT, DomKeyLocation::LEFT},
123 {DomCode::ALT_LEFT, DomKeyLocation::LEFT},
124 {DomCode::OS_LEFT, DomKeyLocation::LEFT},
125 {DomCode::CONTROL_RIGHT, DomKeyLocation::RIGHT},
126 {DomCode::SHIFT_RIGHT, DomKeyLocation::RIGHT},
127 {DomCode::ALT_RIGHT, DomKeyLocation::RIGHT},
128 {DomCode::OS_RIGHT, DomKeyLocation::RIGHT},
129 {DomCode::NUMPAD_DIVIDE, DomKeyLocation::NUMPAD},
130 {DomCode::NUMPAD_MULTIPLY, DomKeyLocation::NUMPAD},
131 {DomCode::NUMPAD_SUBTRACT, DomKeyLocation::NUMPAD},
132 {DomCode::NUMPAD_ADD, DomKeyLocation::NUMPAD},
133 {DomCode::NUMPAD_ENTER, DomKeyLocation::NUMPAD},
134 {DomCode::NUMPAD1, DomKeyLocation::NUMPAD},
135 {DomCode::NUMPAD2, DomKeyLocation::NUMPAD},
136 {DomCode::NUMPAD3, DomKeyLocation::NUMPAD},
137 {DomCode::NUMPAD4, DomKeyLocation::NUMPAD},
138 {DomCode::NUMPAD5, DomKeyLocation::NUMPAD},
139 {DomCode::NUMPAD6, DomKeyLocation::NUMPAD},
140 {DomCode::NUMPAD7, DomKeyLocation::NUMPAD},
141 {DomCode::NUMPAD8, DomKeyLocation::NUMPAD},
142 {DomCode::NUMPAD9, DomKeyLocation::NUMPAD},
143 {DomCode::NUMPAD0, DomKeyLocation::NUMPAD},
144 {DomCode::NUMPAD_DECIMAL, DomKeyLocation::NUMPAD},
145 {DomCode::NUMPAD_EQUAL, DomKeyLocation::NUMPAD},
146 {DomCode::NUMPAD_COMMA, DomKeyLocation::NUMPAD},
147 {DomCode::NUMPAD_PAREN_LEFT, DomKeyLocation::NUMPAD},
148 {DomCode::NUMPAD_PAREN_RIGHT, DomKeyLocation::NUMPAD},
149 {DomCode::NUMPAD_BACKSPACE, DomKeyLocation::NUMPAD},
150 {DomCode::NUMPAD_MEMORY_STORE, DomKeyLocation::NUMPAD},
151 {DomCode::NUMPAD_MEMORY_RECALL, DomKeyLocation::NUMPAD},
152 {DomCode::NUMPAD_MEMORY_CLEAR, DomKeyLocation::NUMPAD},
153 {DomCode::NUMPAD_MEMORY_ADD, DomKeyLocation::NUMPAD},
154 {DomCode::NUMPAD_MEMORY_SUBTRACT, DomKeyLocation::NUMPAD},
155 {DomCode::NUMPAD_SIGN_CHANGE, DomKeyLocation::NUMPAD},
156 {DomCode::NUMPAD_CLEAR, DomKeyLocation::NUMPAD},
157 {DomCode::NUMPAD_CLEAR_ENTRY, DomKeyLocation::NUMPAD}};
158 for (const auto& key : kLocations) {
159 if (key.code == dom_code)
160 return key.location;
162 return DomKeyLocation::STANDARD;
165 // static
166 DomKey KeycodeConverter::KeyStringToDomKey(const char* key) {
167 if (!key || !*key)
168 return DomKey::NONE;
169 for (size_t i = 0; i < kDomKeyMapEntries; ++i) {
170 if (dom_key_map[i].string &&
171 strcmp(dom_key_map[i].string, key) == 0) {
172 return dom_key_map[i].dom_key;
175 return DomKey::NONE;
178 // static
179 const char* KeycodeConverter::DomKeyToKeyString(DomKey dom_key) {
180 for (size_t i = 0; i < kDomKeyMapEntries; ++i) {
181 if (dom_key_map[i].dom_key == dom_key)
182 return dom_key_map[i].string;
184 return "";
187 // static
188 bool KeycodeConverter::IsDomKeyForModifier(DomKey dom_key) {
189 switch (dom_key) {
190 case DomKey::ACCEL:
191 case DomKey::ALT:
192 case DomKey::ALT_GRAPH:
193 case DomKey::CAPS_LOCK:
194 case DomKey::CONTROL:
195 case DomKey::FN:
196 case DomKey::FN_LOCK:
197 case DomKey::HYPER:
198 case DomKey::META:
199 case DomKey::NUM_LOCK:
200 case DomKey::OS:
201 case DomKey::SCROLL_LOCK:
202 case DomKey::SHIFT:
203 case DomKey::SUPER:
204 case DomKey::SYMBOL:
205 case DomKey::SYMBOL_LOCK:
206 case DomKey::SHIFT_LEVEL5:
207 return true;
208 default:
209 return false;
213 // USB keycodes
214 // Note that USB keycodes are not part of any web standard.
215 // Please don't use USB keycodes in new code.
217 // static
218 uint32_t KeycodeConverter::InvalidUsbKeycode() {
219 return usb_keycode_map[0].usb_keycode;
222 // static
223 int KeycodeConverter::UsbKeycodeToNativeKeycode(uint32_t usb_keycode) {
224 // Deal with some special-cases that don't fit the 1:1 mapping.
225 if (usb_keycode == 0x070032) // non-US hash.
226 usb_keycode = 0x070031; // US backslash.
227 #if defined(OS_MACOSX)
228 if (usb_keycode == 0x070046) // PrintScreen.
229 usb_keycode = 0x070068; // F13.
230 #endif
232 for (size_t i = 0; i < kKeycodeMapEntries; ++i) {
233 if (usb_keycode_map[i].usb_keycode == usb_keycode)
234 return usb_keycode_map[i].native_keycode;
236 return InvalidNativeKeycode();
239 // static
240 uint32_t KeycodeConverter::NativeKeycodeToUsbKeycode(int native_keycode) {
241 for (size_t i = 0; i < kKeycodeMapEntries; ++i) {
242 if (usb_keycode_map[i].native_keycode == native_keycode)
243 return usb_keycode_map[i].usb_keycode;
245 return InvalidUsbKeycode();
248 // static
249 DomCode KeycodeConverter::UsbKeycodeToDomCode(uint32_t usb_keycode) {
250 for (size_t i = 0; i < kKeycodeMapEntries; ++i) {
251 if (usb_keycode_map[i].usb_keycode == usb_keycode)
252 return static_cast<DomCode>(usb_keycode);
254 return DomCode::NONE;
257 // static
258 uint32_t KeycodeConverter::DomCodeToUsbKeycode(DomCode dom_code) {
259 for (size_t i = 0; i < kKeycodeMapEntries; ++i) {
260 if (usb_keycode_map[i].usb_keycode == static_cast<uint32_t>(dom_code))
261 return usb_keycode_map[i].usb_keycode;
263 return InvalidUsbKeycode();
266 // static
267 uint32_t KeycodeConverter::CodeToUsbKeycode(const char* code) {
268 if (!code || !*code)
269 return InvalidUsbKeycode();
271 for (size_t i = 0; i < kKeycodeMapEntries; ++i) {
272 if (usb_keycode_map[i].code &&
273 strcmp(usb_keycode_map[i].code, code) == 0) {
274 return usb_keycode_map[i].usb_keycode;
277 return InvalidUsbKeycode();
280 } // namespace ui