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/dom3/dom_code.h"
11 #include "ui/events/keycodes/dom3/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 // Returns the Windows-based VKEY value corresponding to a DOM Level 3 |code|,
31 // assuming a base US English layout. The returned VKEY is located
32 // (e.g. VKEY_LSHIFT).
33 KeyboardCode
DomCodeToUsLayoutKeyboardCode(DomCode dom_code
) {
34 const DomCodeToKeyboardCodeEntry
* end
=
35 kDomCodeToKeyboardCodeMap
+ arraysize(kDomCodeToKeyboardCodeMap
);
36 const DomCodeToKeyboardCodeEntry
* found
=
37 std::lower_bound(kDomCodeToKeyboardCodeMap
, end
, dom_code
,
38 [](const DomCodeToKeyboardCodeEntry
& a
, DomCode b
) {
39 return static_cast<int>(a
.dom_code
) < static_cast<int>(b
);
41 if ((found
!= end
) && (found
->dom_code
== dom_code
))
42 return found
->key_code
;
46 } // anonymous namespace
48 base::char16
DomCodeToUsLayoutCharacter(DomCode dom_code
, int flags
) {
49 base::char16 character
;
51 KeyboardCode key_code
;
52 if (DomCodeToUsLayoutMeaning(dom_code
, flags
, &dom_key
, &character
,
58 bool DomCodeToUsLayoutMeaning(DomCode dom_code
,
61 base::char16
* out_character
,
62 KeyboardCode
* out_key_code
) {
63 if ((flags
& EF_CONTROL_DOWN
) == EF_CONTROL_DOWN
) {
64 if (DomCodeToControlCharacter(dom_code
, flags
, out_dom_key
, out_character
,
68 if (!IsModifierDomCode(dom_code
)) {
69 *out_dom_key
= DomKey::UNIDENTIFIED
;
71 *out_key_code
= LocatedToNonLocatedKeyboardCode(
72 DomCodeToUsLayoutKeyboardCode(dom_code
));
76 for (const auto& it
: kPrintableCodeMap
) {
77 if (it
.dom_code
== dom_code
) {
78 int state
= ((flags
& EF_SHIFT_DOWN
) == EF_SHIFT_DOWN
);
79 base::char16 ch
= it
.character
[state
];
80 *out_dom_key
= DomKey::CHARACTER
;
82 if ((flags
& EF_CAPS_LOCK_DOWN
) == EF_CAPS_LOCK_DOWN
) {
84 if ((ch
>= 'a') && (ch
<= 'z'))
85 *out_character
= it
.character
[state
^ 1];
87 *out_key_code
= LocatedToNonLocatedKeyboardCode(
88 DomCodeToUsLayoutKeyboardCode(dom_code
));
93 for (const auto& it
: kNonPrintableCodeMap
) {
94 if (it
.dom_code
== dom_code
) {
95 *out_dom_key
= it
.dom_key
;
96 *out_character
= it
.character
;
97 *out_key_code
= NonPrintableDomKeyToKeyboardCode(it
.dom_key
);
104 bool DomCodeToControlCharacter(DomCode dom_code
,
107 base::char16
* character
,
108 KeyboardCode
* key_code
) {
109 if ((flags
& EF_CONTROL_DOWN
) == 0)
112 int code
= static_cast<int>(dom_code
);
113 const int kKeyA
= static_cast<int>(DomCode::KEY_A
);
114 // Control-A - Control-Z map to 0x01 - 0x1A.
115 if (code
>= kKeyA
&& code
<= static_cast<int>(DomCode::KEY_Z
)) {
116 *character
= static_cast<base::char16
>(code
- kKeyA
+ 1);
119 *dom_key
= DomKey::BACKSPACE
;
120 *key_code
= VKEY_BACK
;
123 *dom_key
= DomKey::TAB
;
124 *key_code
= VKEY_TAB
;
127 *dom_key
= DomKey::ENTER
;
128 *key_code
= VKEY_RETURN
;
131 *dom_key
= DomKey::CHARACTER
;
132 *key_code
= static_cast<KeyboardCode
>(code
- kKeyA
+ VKEY_A
);
138 if (flags
& EF_SHIFT_DOWN
) {
140 case DomCode::DIGIT2
:
143 *dom_key
= DomKey::CHARACTER
;
146 case DomCode::DIGIT6
:
149 *dom_key
= DomKey::CHARACTER
;
155 *dom_key
= DomKey::CHARACTER
;
156 *key_code
= VKEY_OEM_MINUS
;
167 *dom_key
= DomKey::CHARACTER
;
168 *key_code
= VKEY_RETURN
;
170 case DomCode::BRACKET_LEFT
:
173 *dom_key
= DomKey::ESCAPE
;
174 *key_code
= VKEY_OEM_4
;
176 case DomCode::BACKSLASH
:
179 *dom_key
= DomKey::CHARACTER
;
180 *key_code
= VKEY_OEM_5
;
182 case DomCode::BRACKET_RIGHT
:
185 *dom_key
= DomKey::CHARACTER
;
186 *key_code
= VKEY_OEM_6
;
193 // Returns a Windows-based VKEY for a non-printable DOM Level 3 |key|.
194 // The returned VKEY is non-positional (e.g. VKEY_SHIFT).
195 KeyboardCode
NonPrintableDomKeyToKeyboardCode(DomKey dom_key
) {
196 for (const auto& it
: kDomKeyToKeyboardCodeMap
) {
197 if (it
.dom_key
== dom_key
)
203 // Determine the non-located VKEY corresponding to a located VKEY.
204 KeyboardCode
LocatedToNonLocatedKeyboardCode(KeyboardCode key_code
) {
242 // Determine the located VKEY corresponding to a non-located VKEY.
243 KeyboardCode
NonLocatedToLocatedKeyboardCode(KeyboardCode key_code
,
247 return IsRightSideDomCode(dom_code
) ? VKEY_RSHIFT
: VKEY_LSHIFT
;
249 return IsRightSideDomCode(dom_code
) ? VKEY_RCONTROL
: VKEY_LCONTROL
;
251 return IsRightSideDomCode(dom_code
) ? VKEY_RMENU
: VKEY_LMENU
;
253 return IsRightSideDomCode(dom_code
) ? VKEY_RWIN
: VKEY_LWIN
;
255 return (dom_code
== DomCode::NUMPAD0
) ? VKEY_NUMPAD0
: VKEY_0
;
257 return (dom_code
== DomCode::NUMPAD1
) ? VKEY_NUMPAD1
: VKEY_1
;
259 return (dom_code
== DomCode::NUMPAD2
) ? VKEY_NUMPAD2
: VKEY_2
;
261 return (dom_code
== DomCode::NUMPAD3
) ? VKEY_NUMPAD3
: VKEY_3
;
263 return (dom_code
== DomCode::NUMPAD4
) ? VKEY_NUMPAD4
: VKEY_4
;
265 return (dom_code
== DomCode::NUMPAD5
) ? VKEY_NUMPAD5
: VKEY_5
;
267 return (dom_code
== DomCode::NUMPAD6
) ? VKEY_NUMPAD6
: VKEY_6
;
269 return (dom_code
== DomCode::NUMPAD7
) ? VKEY_NUMPAD7
: VKEY_7
;
271 return (dom_code
== DomCode::NUMPAD8
) ? VKEY_NUMPAD8
: VKEY_8
;
273 return (dom_code
== DomCode::NUMPAD9
) ? VKEY_NUMPAD9
: VKEY_9
;
279 DomCode
UsLayoutKeyboardCodeToDomCode(KeyboardCode key_code
) {
280 key_code
= NonLocatedToLocatedKeyboardCode(key_code
, DomCode::NONE
);
281 for (const auto& it
: kDomCodeToKeyboardCodeMap
) {
282 if (it
.key_code
== key_code
)
285 for (const auto& it
: kFallbackKeyboardCodeToDomCodeMap
) {
286 if (it
.key_code
== key_code
)
289 return DomCode::NONE
;