Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(321)

Side by Side Diff: ui/events/keycodes/key_map_win.cc

Issue 1585193002: Build key map DomCodeToKey() for Windows (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Wez's review Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2016 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.
4
5 #include "ui/events/keycodes/key_map_win.h"
6
7 #include <utility>
8
9 #include "base/logging.h"
10 #include "base/macros.h"
11
12 #include "ui/events/event_constants.h"
13 #include "ui/events/keycodes/dom/dom_code.h"
14
15 namespace ui {
16
17 namespace {
18
19 struct DomCodeEntry {
20 DomCode dom_code;
21 int scan_code;
22 };
23 #define USB_KEYMAP_DECLARATION const DomCodeEntry supported_dom_code_list[] =
24 #define USB_KEYMAP(usb, evdev, xkb, win, mac, code, id) {DomCode::id, win}
25 #include "ui/events/keycodes/dom/keycode_converter_data.inc"
26 #undef USB_KEYMAP
27 #undef USB_KEYMAP_DECLARATION
28
29 // List of modifiers mentioned in https://w3c.github.io/uievents/#keys-modifiers
30 // Some modifiers are commented out because they usually don't change keys.
31 const EventFlags flags_index[] = {
Wez 2016/02/09 00:18:57 nit: This is the list of interesting modifier flag
32 EF_SHIFT_DOWN,
33 EF_CONTROL_DOWN,
34 EF_ALT_DOWN,
35 // EF_COMMAND_DOWN,
36 EF_ALTGR_DOWN,
37 // EF_NUM_LOCK_ON,
38 EF_CAPS_LOCK_ON,
39 // EF_SCROLL_LOCK_ON
40 };
41 const int kMaxEventFlagsIndex = (1 << arraysize(flags_index)) - 1;
Wez 2016/02/09 00:18:57 This still isn't the maximum index of the flags_in
42
43 int GetEventFlagsIndex(int flags) {
Wez 2016/02/09 00:18:57 I don't see this used anywhere?
44 int index = 0;
45 for (int i = 0; i < arraysize(flags_index); ++i) {
46 if (flags & flags_index[i])
47 index |= 1 << i;
48 }
49 return index;
50 }
51
52 int EventFlagsFromIndex(int index) {
Wez 2016/02/09 00:18:57 nit: Suggest GetModifierFlags(int combination) if
53 int flags = EF_NONE;
54 for (int i = 0; i < arraysize(flags_index); ++i) {
55 if (index & (1 << i))
56 flags |= flags_index[i];
57 }
58 return flags;
59 }
60
61 void SetModifierState(BYTE* keyboard_state, int flags) {
62 if (flags & EF_SHIFT_DOWN)
63 keyboard_state[VK_SHIFT] |= 0x80;
64
65 if (flags & EF_CONTROL_DOWN)
66 keyboard_state[VK_CONTROL] |= 0x80;
67
68 if (flags & EF_ALT_DOWN)
69 keyboard_state[VK_MENU] |= 0x80;
70
71 if (flags & EF_ALTGR_DOWN) {
72 // AltGr should be RightAlt+LeftControl within Windows, but actually only
73 // the non-located keys will work here.
74 keyboard_state[VK_MENU] |= 0x80;
chongz 2016/02/04 21:10:25 I'm not sure why but only the non-located Alt+Cont
Wez 2016/02/09 00:18:57 OK, sorry for the misleading comment earlier! Not
75 keyboard_state[VK_CONTROL] |= 0x80;
76 }
77
78 if (flags & EF_COMMAND_DOWN)
79 keyboard_state[VK_LWIN] |= 0x80;
80
81 if (flags & EF_NUM_LOCK_ON)
82 keyboard_state[VK_NUMLOCK] |= 0x01;
83
84 if (flags & EF_CAPS_LOCK_ON)
85 keyboard_state[VK_CAPITAL] |= 0x01;
86
87 if (flags & EF_SCROLL_LOCK_ON)
88 keyboard_state[VK_SCROLL] |= 0x01;
89 }
90
91 } // anonymous namespace
92
93 WindowsKeyMap::WindowsKeyMap() : keyboard_layout_(0) {}
Wez 2016/02/09 00:18:57 nit: You can set this via inline initializer in th
94
95 WindowsKeyMap::WindowsKeyMap(HKL layout) : WindowsKeyMap() {
Wez 2016/02/09 00:18:57 See above re inline initializer for |keyboard_layo
96 LoadLayout(layout);
97 }
98
99 DomKey WindowsKeyMap::DomCodeToKey(DomCode code, int flags) const {
100 const int flags_to_try[] = {
101 // Trying to match Firefox's behavior and UIEvents DomKey guidelines.
102 // If the combination doesn't produce a printable character, the key value
103 // should be the key with no modifiers except for Shift and AltGr.
104 // See https://w3c.github.io/uievents/#keys-guidelines
105 flags,
106 flags & (EF_SHIFT_DOWN | EF_ALTGR_DOWN | EF_CAPS_LOCK_ON),
107 flags & (EF_SHIFT_DOWN | EF_CAPS_LOCK_ON),
108 EF_NONE,
109 };
110
111 DomKey key = DomKey::NONE;
112 for (auto try_flags : flags_to_try) {
113 const auto& it = key_map_.find(std::make_pair(code, try_flags));
114 if (it != key_map_.end())
115 key = it->second.key;
116 if (key != DomKey::NONE)
Wez 2016/02/09 00:18:57 nit: You're doing this if() even if you didn't cha
117 break;
118 }
119 return key;
120 }
121
122 KeyboardCode WindowsKeyMap::DomCodeToKeyboardCode(DomCode code) const {
123 const auto& it = key_map_.find(std::make_pair(code, EF_NONE));
124 if (it != key_map_.end())
125 return it->second.legacy_key_code;
126 return static_cast<KeyboardCode>(0);
127 }
128
129 DomCode WindowsKeyMap::KeyboardCodeToDomCode(KeyboardCode key_code) const {
dtapuska 2016/02/04 20:31:45 Is this really required? I'm not sure if we need a
chongz 2016/02/04 21:10:25 I guess Wez wants it in case user only gives us Ke
Wez 2016/02/09 00:18:57 Let's add it if/when it's actually used! I was th
130 // TODO(chongz): Could create another map to improve efficiency if necessary.
131 for (const auto& dom_code_entry : supported_dom_code_list) {
132 if (DomCodeToKeyboardCode(dom_code_entry.dom_code) == key_code)
133 return dom_code_entry.dom_code;
134 }
135 return DomCode::NONE;
136 }
137
138 DomKey WindowsKeyMap::DomCodeToSystemLayoutKey(DomCode code, int flags) {
Wez 2016/02/09 00:18:57 static methods should be prefixed with a "// stati
139 static base::LazyInstance<WindowsKeyMap>::Leaky s_instance =
140 LAZY_INSTANCE_INITIALIZER;
Wez 2016/02/09 00:18:57 Note that the LazyInstance header says it "really
141 HKL current_layout = ::GetKeyboardLayout(0);
chongz 2016/02/04 21:10:25 Still, should I add a lock or only allow it to be
Wez 2016/02/09 00:18:57 GetKeyboardLayout(0) gets the current layout for t
dtapuska 2016/02/09 16:46:39 Likely this code is probably only going to execute
Wez 2016/02/09 22:40:01 On-demand thread-local instance SGTM - do we have
142 if (s_instance.Get().keyboard_layout_ != current_layout)
143 s_instance.Get().LoadLayout(current_layout);
144 return s_instance.Get().DomCodeToKey(code, flags);
145 }
146
147 void WindowsKeyMap::LoadLayout(HKL layout) {
148 keyboard_layout_ = layout;
149 key_map_.clear();
150
151 BYTE keyboard_state_to_restore[256];
152 ::GetKeyboardState(keyboard_state_to_restore);
153
154 for (int eindex = 0; eindex <= kMaxEventFlagsIndex; ++eindex) {
155 BYTE keyboard_state[256];
156 memset(keyboard_state, 0, sizeof(keyboard_state));
157 int flags = EventFlagsFromIndex(eindex);
158 SetModifierState(keyboard_state, flags);
159 for (const auto& dom_code_entry : supported_dom_code_list) {
160 wchar_t translated_chars[5];
161 int key_code = ::MapVirtualKeyEx(dom_code_entry.scan_code,
162 MAPVK_VSC_TO_VK, keyboard_layout_);
163 int rv = ::ToUnicodeEx(key_code, 0, keyboard_state, translated_chars,
164 arraysize(translated_chars), 0, keyboard_layout_);
165
166 if (rv < 0) {
167 // Dead key, injecting VK_SPACE to get character representation.
168 BYTE empty_state[256];
169 memset(empty_state, 0, sizeof(empty_state));
170 rv = ::ToUnicodeEx(VK_SPACE, 0, empty_state, translated_chars,
171 arraysize(translated_chars), 0, keyboard_layout_);
172 // Must be a repeat of dead key character.
173 DCHECK(rv == 2);
174 AddKeyMapEntry(
175 dom_code_entry.dom_code,
176 DomKey::DeadKeyFromCombiningCharacter(translated_chars[0]),
177 static_cast<KeyboardCode>(key_code), flags);
178 } else if (rv == 1) {
179 if (translated_chars[0] >= 0x20) {
180 AddKeyMapEntry(dom_code_entry.dom_code,
181 DomKey::FromCharacter(translated_chars[0]),
182 static_cast<KeyboardCode>(key_code), flags);
183 } else {
184 // Ignores legacy non-printable control characters.
185 }
186 } else {
187 // TODO(chongz): Handle multiple characters case.
dtapuska 2016/02/04 20:31:45 What are we going to do with non-printable charact
chongz 2016/02/04 21:10:25 I will add (copy?) the US non-printable table here
188 }
189 }
190 }
191 ::SetKeyboardState(keyboard_state_to_restore);
192 }
193
194 void WindowsKeyMap::AddKeyMapEntry(DomCode code,
195 DomKey key,
196 KeyboardCode legacy_key_code,
197 int flags) {
198 key_map_[std::make_pair(code, flags)] =
199 KeyMapEntry{code, key, legacy_key_code, flags};
200 }
201
202 } // namespace ui
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698