1 // Copyright (c) 2011 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/keyboard_code_conversion.h"
9 #include "ui/events/event_constants.h"
10 #include "ui/events/keycodes/dom/dom_code.h"
11 #include "ui/events/keycodes/dom/dom_key.h"
12 #include "ui/events/keycodes/dom_us_layout_data.h"
18 bool IsRightSideDomCode(DomCode code
) {
19 return (code
== DomCode::SHIFT_RIGHT
) || (code
== DomCode::CONTROL_RIGHT
) ||
20 (code
== DomCode::ALT_RIGHT
) || (code
== DomCode::OS_RIGHT
);
23 bool IsModifierDomCode(DomCode code
) {
24 return (code
== DomCode::CONTROL_LEFT
) || (code
== DomCode::CONTROL_RIGHT
) ||
25 (code
== DomCode::SHIFT_LEFT
) || (code
== DomCode::SHIFT_RIGHT
) ||
26 (code
== DomCode::ALT_LEFT
) || (code
== DomCode::ALT_RIGHT
) ||
27 (code
== DomCode::OS_LEFT
) || (code
== DomCode::OS_RIGHT
);
30 } // anonymous namespace
32 base::char16
DomCodeToUsLayoutCharacter(DomCode dom_code
, int flags
) {
34 KeyboardCode key_code
;
35 if (DomCodeToUsLayoutDomKey(dom_code
, flags
, &dom_key
, &key_code
) &&
36 dom_key
.IsCharacter()) {
37 return dom_key
.ToCharacter();
42 bool DomCodeToUsLayoutDomKey(DomCode dom_code
,
45 KeyboardCode
* out_key_code
) {
46 if ((flags
& EF_CONTROL_DOWN
) == EF_CONTROL_DOWN
) {
47 if (DomCodeToControlCharacter(dom_code
, flags
, out_dom_key
, out_key_code
)) {
50 if (!IsModifierDomCode(dom_code
)) {
51 *out_dom_key
= DomKey::UNIDENTIFIED
;
52 *out_key_code
= LocatedToNonLocatedKeyboardCode(
53 DomCodeToUsLayoutKeyboardCode(dom_code
));
57 for (const auto& it
: kPrintableCodeMap
) {
58 if (it
.dom_code
== dom_code
) {
59 int state
= ((flags
& EF_SHIFT_DOWN
) == EF_SHIFT_DOWN
);
60 base::char16 ch
= it
.character
[state
];
61 if ((flags
& EF_CAPS_LOCK_DOWN
) == EF_CAPS_LOCK_DOWN
) {
63 if ((ch
>= 'a') && (ch
<= 'z'))
64 ch
= it
.character
[state
^ 1];
66 *out_dom_key
= DomKey::FromCharacter(ch
);
67 *out_key_code
= LocatedToNonLocatedKeyboardCode(
68 DomCodeToUsLayoutKeyboardCode(dom_code
));
73 for (const auto& it
: kNonPrintableCodeMap
) {
74 if (it
.dom_code
== dom_code
) {
75 *out_dom_key
= it
.dom_key
;
76 *out_key_code
= NonPrintableDomKeyToKeyboardCode(it
.dom_key
);
80 if ((flags
& EF_CONTROL_DOWN
) == EF_CONTROL_DOWN
) {
81 *out_dom_key
= DomKey::UNIDENTIFIED
;
82 *out_key_code
= LocatedToNonLocatedKeyboardCode(
83 DomCodeToUsLayoutKeyboardCode(dom_code
));
89 bool DomCodeToControlCharacter(DomCode dom_code
,
92 KeyboardCode
* key_code
) {
93 if ((flags
& EF_CONTROL_DOWN
) == 0)
96 int code
= static_cast<int>(dom_code
);
97 const int kKeyA
= static_cast<int>(DomCode::KEY_A
);
98 // Control-A - Control-Z map to 0x01 - 0x1A.
99 if (code
>= kKeyA
&& code
<= static_cast<int>(DomCode::KEY_Z
)) {
100 *dom_key
= DomKey::FromCharacter(code
- kKeyA
+ 1);
101 *key_code
= static_cast<KeyboardCode
>(code
- kKeyA
+ VKEY_A
);
104 *key_code
= VKEY_BACK
;
107 *key_code
= VKEY_TAB
;
110 *key_code
= VKEY_RETURN
;
118 if (flags
& EF_SHIFT_DOWN
) {
120 case DomCode::DIGIT2
:
122 *dom_key
= DomKey::FromCharacter(0);
125 case DomCode::DIGIT6
:
127 *dom_key
= DomKey::FromCharacter(0x1E);
132 *dom_key
= DomKey::FromCharacter(0x1F);
133 *key_code
= VKEY_OEM_MINUS
;
143 *dom_key
= DomKey::FromCharacter(0x0A);
144 *key_code
= VKEY_RETURN
;
146 case DomCode::BRACKET_LEFT
:
148 *dom_key
= DomKey::FromCharacter(0x1B);
149 *key_code
= VKEY_OEM_4
;
151 case DomCode::BACKSLASH
:
153 *dom_key
= DomKey::FromCharacter(0x1C);
154 *key_code
= VKEY_OEM_5
;
156 case DomCode::BRACKET_RIGHT
:
158 *dom_key
= DomKey::FromCharacter(0x1D);
159 *key_code
= VKEY_OEM_6
;
166 // Returns a Windows-based VKEY for a non-printable DOM Level 3 |key|.
167 // The returned VKEY is non-positional (e.g. VKEY_SHIFT).
168 KeyboardCode
NonPrintableDomKeyToKeyboardCode(DomKey dom_key
) {
169 for (const auto& it
: kDomKeyToKeyboardCodeMap
) {
170 if (it
.dom_key
== dom_key
)
176 // Determine the non-located VKEY corresponding to a located VKEY.
177 KeyboardCode
LocatedToNonLocatedKeyboardCode(KeyboardCode key_code
) {
215 // Determine the located VKEY corresponding to a non-located VKEY.
216 KeyboardCode
NonLocatedToLocatedKeyboardCode(KeyboardCode key_code
,
220 return IsRightSideDomCode(dom_code
) ? VKEY_RSHIFT
: VKEY_LSHIFT
;
222 return IsRightSideDomCode(dom_code
) ? VKEY_RCONTROL
: VKEY_LCONTROL
;
224 return IsRightSideDomCode(dom_code
) ? VKEY_RMENU
: VKEY_LMENU
;
226 return IsRightSideDomCode(dom_code
) ? VKEY_RWIN
: VKEY_LWIN
;
228 return (dom_code
== DomCode::NUMPAD0
) ? VKEY_NUMPAD0
: VKEY_0
;
230 return (dom_code
== DomCode::NUMPAD1
) ? VKEY_NUMPAD1
: VKEY_1
;
232 return (dom_code
== DomCode::NUMPAD2
) ? VKEY_NUMPAD2
: VKEY_2
;
234 return (dom_code
== DomCode::NUMPAD3
) ? VKEY_NUMPAD3
: VKEY_3
;
236 return (dom_code
== DomCode::NUMPAD4
) ? VKEY_NUMPAD4
: VKEY_4
;
238 return (dom_code
== DomCode::NUMPAD5
) ? VKEY_NUMPAD5
: VKEY_5
;
240 return (dom_code
== DomCode::NUMPAD6
) ? VKEY_NUMPAD6
: VKEY_6
;
242 return (dom_code
== DomCode::NUMPAD7
) ? VKEY_NUMPAD7
: VKEY_7
;
244 return (dom_code
== DomCode::NUMPAD8
) ? VKEY_NUMPAD8
: VKEY_8
;
246 return (dom_code
== DomCode::NUMPAD9
) ? VKEY_NUMPAD9
: VKEY_9
;
252 DomCode
UsLayoutKeyboardCodeToDomCode(KeyboardCode key_code
) {
253 key_code
= NonLocatedToLocatedKeyboardCode(key_code
, DomCode::NONE
);
254 for (const auto& it
: kDomCodeToKeyboardCodeMap
) {
255 if (it
.key_code
== key_code
)
258 for (const auto& it
: kFallbackKeyboardCodeToDomCodeMap
) {
259 if (it
.key_code
== key_code
)
262 return DomCode::NONE
;
265 KeyboardCode
DomCodeToUsLayoutKeyboardCode(DomCode dom_code
) {
266 const DomCodeToKeyboardCodeEntry
* end
=
267 kDomCodeToKeyboardCodeMap
+ arraysize(kDomCodeToKeyboardCodeMap
);
268 const DomCodeToKeyboardCodeEntry
* found
= std::lower_bound(
269 kDomCodeToKeyboardCodeMap
, end
, dom_code
,
270 [](const DomCodeToKeyboardCodeEntry
& a
, DomCode b
) {
271 return static_cast<int>(a
.dom_code
) < static_cast<int>(b
);
273 if ((found
!= end
) && (found
->dom_code
== dom_code
))
274 return found
->key_code
;