Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2016 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ui/events/keycodes/platform_key_map_win.h" | 5 #include "ui/events/keycodes/platform_key_map_win.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/lazy_instance.h" | 9 #include "base/lazy_instance.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| 11 #include "base/macros.h" | 11 #include "base/macros.h" |
| 12 #include "base/threading/thread_local_storage.h" | 12 #include "base/threading/thread_local_storage.h" |
| 13 | 13 |
| 14 #include "ui/events/event_constants.h" | 14 #include "ui/events/event_constants.h" |
| 15 #include "ui/events/keycodes/dom/dom_code.h" | 15 #include "ui/events/keycodes/dom/dom_code.h" |
| 16 #include "ui/events/keycodes/keyboard_code_conversion.h" | |
| 16 | 17 |
| 17 namespace ui { | 18 namespace ui { |
| 18 | 19 |
| 19 namespace { | 20 namespace { |
| 20 | 21 |
| 21 struct DomCodeEntry { | 22 struct DomCodeEntry { |
| 22 DomCode dom_code; | 23 DomCode dom_code; |
| 23 int scan_code; | 24 int scan_code; |
| 24 }; | 25 }; |
| 25 #define USB_KEYMAP_DECLARATION const DomCodeEntry supported_dom_code_list[] = | 26 #define USB_KEYMAP_DECLARATION const DomCodeEntry supported_dom_code_list[] = |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 80 if (flags & EF_NUM_LOCK_ON) | 81 if (flags & EF_NUM_LOCK_ON) |
| 81 keyboard_state[VK_NUMLOCK] |= 0x01; | 82 keyboard_state[VK_NUMLOCK] |= 0x01; |
| 82 | 83 |
| 83 if (flags & EF_CAPS_LOCK_ON) | 84 if (flags & EF_CAPS_LOCK_ON) |
| 84 keyboard_state[VK_CAPITAL] |= 0x01; | 85 keyboard_state[VK_CAPITAL] |= 0x01; |
| 85 | 86 |
| 86 if (flags & EF_SCROLL_LOCK_ON) | 87 if (flags & EF_SCROLL_LOCK_ON) |
| 87 keyboard_state[VK_SCROLL] |= 0x01; | 88 keyboard_state[VK_SCROLL] |= 0x01; |
| 88 } | 89 } |
| 89 | 90 |
| 91 DomKey NonPrintableNumPadKeyCodeToDomKey(KeyboardCode key_code) { | |
| 92 switch (key_code) { | |
| 93 case VKEY_CLEAR: | |
| 94 return DomKey::CLEAR; | |
| 95 case VKEY_PRIOR: | |
| 96 return DomKey::PAGE_UP; | |
| 97 case VKEY_NEXT: | |
| 98 return DomKey::PAGE_DOWN; | |
| 99 case VKEY_END: | |
| 100 return DomKey::END; | |
| 101 case VKEY_HOME: | |
| 102 return DomKey::HOME; | |
| 103 case VKEY_LEFT: | |
| 104 return DomKey::ARROW_LEFT; | |
| 105 case VKEY_UP: | |
| 106 return DomKey::ARROW_UP; | |
| 107 case VKEY_RIGHT: | |
| 108 return DomKey::ARROW_RIGHT; | |
| 109 case VKEY_DOWN: | |
| 110 return DomKey::ARROW_DOWN; | |
| 111 case VKEY_INSERT: | |
| 112 return DomKey::INSERT; | |
| 113 case VKEY_DELETE: | |
| 114 return DomKey::DEL; | |
| 115 default: | |
| 116 return DomKey::NONE; | |
| 117 } | |
| 118 } | |
| 119 | |
| 90 void CleanupKeyMapTls(void* data) { | 120 void CleanupKeyMapTls(void* data) { |
| 91 PlatformKeyMap* key_map = reinterpret_cast<PlatformKeyMap*>(data); | 121 PlatformKeyMap* key_map = reinterpret_cast<PlatformKeyMap*>(data); |
| 92 delete key_map; | 122 delete key_map; |
| 93 } | 123 } |
| 94 | 124 |
| 95 struct PlatformKeyMapInstanceTlsTraits | 125 struct PlatformKeyMapInstanceTlsTraits |
| 96 : public base::DefaultLazyInstanceTraits<base::ThreadLocalStorage::Slot> { | 126 : public base::DefaultLazyInstanceTraits<base::ThreadLocalStorage::Slot> { |
| 97 static base::ThreadLocalStorage::Slot* New(void* instance) { | 127 static base::ThreadLocalStorage::Slot* New(void* instance) { |
| 98 // Use placement new to initialize our instance in our preallocated space. | 128 // Use placement new to initialize our instance in our preallocated space. |
| 99 // TODO(chongz): Use std::default_delete instead of providing own function. | 129 // TODO(chongz): Use std::default_delete instead of providing own function. |
| 100 return new (instance) base::ThreadLocalStorage::Slot(CleanupKeyMapTls); | 130 return new (instance) base::ThreadLocalStorage::Slot(CleanupKeyMapTls); |
| 101 } | 131 } |
| 102 }; | 132 }; |
| 103 | 133 |
| 104 base::LazyInstance<base::ThreadLocalStorage::Slot, | 134 base::LazyInstance<base::ThreadLocalStorage::Slot, |
| 105 PlatformKeyMapInstanceTlsTraits> | 135 PlatformKeyMapInstanceTlsTraits> |
| 106 g_platform_key_map_tls_lazy = LAZY_INSTANCE_INITIALIZER; | 136 g_platform_key_map_tls_lazy = LAZY_INSTANCE_INITIALIZER; |
| 107 | 137 |
| 108 } // anonymous namespace | 138 } // anonymous namespace |
| 109 | 139 |
| 110 PlatformKeyMap::PlatformKeyMap() {} | 140 PlatformKeyMap::PlatformKeyMap() {} |
| 111 | 141 |
| 112 PlatformKeyMap::PlatformKeyMap(HKL layout) { | 142 PlatformKeyMap::PlatformKeyMap(HKL layout) { |
| 113 UpdateLayout(layout); | 143 UpdateLayout(layout); |
| 114 } | 144 } |
| 115 | 145 |
| 116 PlatformKeyMap::~PlatformKeyMap() {} | 146 PlatformKeyMap::~PlatformKeyMap() {} |
| 117 | 147 |
| 118 DomKey PlatformKeyMap::DomCodeAndFlagsToDomKey(DomCode code, int flags) const { | 148 DomKey PlatformKeyMap::DomCodeAndFlagsToDomKey(DomCode code, |
| 149 KeyboardCode key_code, | |
| 150 int flags) const { | |
| 151 // Try printable key map first. | |
| 119 const int flags_to_try[] = { | 152 const int flags_to_try[] = { |
| 120 // Trying to match Firefox's behavior and UIEvents DomKey guidelines. | 153 // Trying to match Firefox's behavior and UIEvents DomKey guidelines. |
| 121 // If the combination doesn't produce a printable character, the key value | 154 // If the combination doesn't produce a printable character, the key value |
| 122 // should be the key with no modifiers except for Shift and AltGr. | 155 // should be the key with no modifiers except for Shift and AltGr. |
| 123 // See https://w3c.github.io/uievents/#keys-guidelines | 156 // See https://w3c.github.io/uievents/#keys-guidelines |
| 124 flags, | 157 flags, |
| 125 flags & (EF_SHIFT_DOWN | EF_ALTGR_DOWN | EF_CAPS_LOCK_ON), | 158 flags & (EF_SHIFT_DOWN | EF_ALTGR_DOWN | EF_CAPS_LOCK_ON), |
| 126 flags & (EF_SHIFT_DOWN | EF_CAPS_LOCK_ON), | 159 flags & (EF_SHIFT_DOWN | EF_CAPS_LOCK_ON), |
| 127 EF_NONE, | 160 EF_NONE, |
| 128 }; | 161 }; |
| 129 | 162 |
| 130 DomKey key = DomKey::NONE; | 163 DomKey key = DomKey::NONE; |
| 131 for (auto try_flags : flags_to_try) { | 164 for (auto try_flags : flags_to_try) { |
| 132 const auto& it = code_to_key_.find(std::make_pair(static_cast<int>(code), | 165 const auto& it = code_to_key_.find(std::make_pair(static_cast<int>(code), |
| 133 try_flags)); | 166 try_flags)); |
| 134 if (it != code_to_key_.end()) { | 167 if (it != code_to_key_.end()) { |
| 135 key = it->second; | 168 key = it->second; |
| 136 if (key != DomKey::NONE) | 169 if (key != DomKey::NONE) |
| 137 break; | 170 break; |
| 138 } | 171 } |
| 139 } | 172 } |
| 173 | |
| 174 // Handle non-printable key produced by NumPad. | |
| 175 if (key == DomKey::NONE) { | |
|
Wez
2016/03/16 21:03:06
IMO it would be cleaner & easier to understand thi
| |
| 176 // Have to use KeyboardCode instead of DomCode because NumLockOn+Shift+4 | |
| 177 // will generate keydown event with EF_SHIFT_DOWN modifier set to false, so | |
| 178 // we have no way to know whether Shift is down. | |
| 179 key = NonPrintableNumPadKeyCodeToDomKey(key_code); | |
| 180 } | |
| 181 | |
| 182 // Use US layout for other non-printable key. | |
|
dtapuska
2016/03/10 20:51:44
This is a bit odd that this is done here; because
chongz
2016/03/10 21:03:32
Yes it will simplify the tests, otherwise I will n
Wez
2016/03/16 21:03:06
Sorry, I didn't get the logic here; are you sugges
| |
| 183 if (key == DomKey::NONE) { | |
| 184 KeyboardCode dummy_key_code; | |
| 185 DomCodeToUsLayoutDomKey(code, flags, &key, &dummy_key_code); | |
| 186 } | |
| 187 | |
| 140 return key; | 188 return key; |
| 141 } | 189 } |
| 142 | 190 |
| 143 // static | 191 // static |
| 144 DomKey PlatformKeyMap::DomCodeAndFlagsToDomKeyStatic(DomCode code, int flags) { | 192 DomKey PlatformKeyMap::DomCodeAndFlagsToDomKeyStatic(DomCode code, |
| 193 KeyboardCode key_code, | |
| 194 int flags) { | |
| 145 // Use TLS because KeyboardLayout is per thread. | 195 // Use TLS because KeyboardLayout is per thread. |
| 146 // However currently PlatformKeyMap will only be used by the host application, | 196 // However currently PlatformKeyMap will only be used by the host application, |
| 147 // which is just one process and one thread. | 197 // which is just one process and one thread. |
| 148 base::ThreadLocalStorage::Slot* platform_key_map_tls = | 198 base::ThreadLocalStorage::Slot* platform_key_map_tls = |
| 149 g_platform_key_map_tls_lazy.Pointer(); | 199 g_platform_key_map_tls_lazy.Pointer(); |
| 150 PlatformKeyMap* platform_key_map = | 200 PlatformKeyMap* platform_key_map = |
| 151 reinterpret_cast<PlatformKeyMap*>(platform_key_map_tls->Get()); | 201 reinterpret_cast<PlatformKeyMap*>(platform_key_map_tls->Get()); |
| 152 if (!platform_key_map) { | 202 if (!platform_key_map) { |
| 153 platform_key_map = new PlatformKeyMap(); | 203 platform_key_map = new PlatformKeyMap(); |
| 154 platform_key_map_tls->Set(platform_key_map); | 204 platform_key_map_tls->Set(platform_key_map); |
| 155 } | 205 } |
| 156 | 206 |
| 157 HKL current_layout = ::GetKeyboardLayout(0); | 207 HKL current_layout = ::GetKeyboardLayout(0); |
| 158 platform_key_map->UpdateLayout(current_layout); | 208 platform_key_map->UpdateLayout(current_layout); |
| 159 return platform_key_map->DomCodeAndFlagsToDomKey(code, flags); | 209 return platform_key_map->DomCodeAndFlagsToDomKey(code, key_code, flags); |
| 160 } | 210 } |
| 161 | 211 |
| 162 void PlatformKeyMap::UpdateLayout(HKL layout) { | 212 void PlatformKeyMap::UpdateLayout(HKL layout) { |
| 163 if (layout == keyboard_layout_) | 213 if (layout == keyboard_layout_) |
| 164 return; | 214 return; |
| 165 | 215 |
| 166 BYTE keyboard_state_to_restore[256]; | 216 BYTE keyboard_state_to_restore[256]; |
| 167 if (!::GetKeyboardState(keyboard_state_to_restore)) | 217 if (!::GetKeyboardState(keyboard_state_to_restore)) |
| 168 return; | 218 return; |
| 169 | 219 |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 210 } | 260 } |
| 211 } else { | 261 } else { |
| 212 // TODO(chongz): Handle rv <= -2 and rv >= 2. | 262 // TODO(chongz): Handle rv <= -2 and rv >= 2. |
| 213 } | 263 } |
| 214 } | 264 } |
| 215 } | 265 } |
| 216 ::SetKeyboardState(keyboard_state_to_restore); | 266 ::SetKeyboardState(keyboard_state_to_restore); |
| 217 } | 267 } |
| 218 | 268 |
| 219 } // namespace ui | 269 } // namespace ui |
| OLD | NEW |