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"
15 // Table of USB codes (equivalent to DomCode values), native scan codes,
16 // and DOM Level 3 |code| strings.
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}
24 #define USB_KEYMAP(usb, xkb, win, mac, code, id) {usb, 0, code}
26 #define USB_KEYMAP_DECLARATION const KeycodeMapEntry usb_keycode_map[] =
27 #include "ui/events/keycodes/dom/keycode_converter_data.inc"
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
{
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"
43 #undef DOM_KEY_MAP_DECLARATION
45 const size_t kDomKeyMapEntries
= arraysize(dom_key_map
);
50 size_t KeycodeConverter::NumKeycodeMapEntriesForTest() {
51 return kKeycodeMapEntries
;
55 const KeycodeMapEntry
* KeycodeConverter::GetKeycodeMapForTest() {
56 return &usb_keycode_map
[0];
60 const char* KeycodeConverter::DomKeyStringForTest(size_t index
) {
61 if (index
>= kDomKeyMapEntries
)
63 return dom_key_map
[index
].string
;
67 int KeycodeConverter::InvalidNativeKeycode() {
68 return usb_keycode_map
[0].native_keycode
;
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
);
84 int KeycodeConverter::DomCodeToNativeKeycode(DomCode code
) {
85 return UsbKeycodeToNativeKeycode(static_cast<uint32_t>(code
));
89 DomCode
KeycodeConverter::CodeStringToDomCode(const char* code
) {
90 if (!code
|| !*code
) {
91 LOG(WARNING
) << "empty code string";
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
;
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
;
117 DomKeyLocation
KeycodeConverter::DomCodeToLocation(DomCode dom_code
) {
118 static const struct {
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
)
162 return DomKeyLocation::STANDARD
;
166 DomKey
KeycodeConverter::KeyStringToDomKey(const char* key
) {
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
;
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
;
188 bool KeycodeConverter::IsDomKeyForModifier(DomKey dom_key
) {
192 case DomKey::ALT_GRAPH
:
193 case DomKey::CAPS_LOCK
:
194 case DomKey::CONTROL
:
196 case DomKey::FN_LOCK
:
199 case DomKey::NUM_LOCK
:
201 case DomKey::SCROLL_LOCK
:
205 case DomKey::SYMBOL_LOCK
:
206 case DomKey::SHIFT_LEVEL5
:
214 // Note that USB keycodes are not part of any web standard.
215 // Please don't use USB keycodes in new code.
218 uint32_t KeycodeConverter::InvalidUsbKeycode() {
219 return usb_keycode_map
[0].usb_keycode
;
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.
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();
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();
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
;
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();
267 uint32_t KeycodeConverter::CodeToUsbKeycode(const char* 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();