| 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/event_utils.h" |
| 15 #include "ui/events/keycodes/dom/dom_code.h" | 16 #include "ui/events/keycodes/dom/dom_code.h" |
| 17 #include "ui/events/keycodes/dom/keycode_converter.h" |
| 18 #include "ui/events/keycodes/keyboard_code_conversion.h" |
| 16 | 19 |
| 17 namespace ui { | 20 namespace ui { |
| 18 | 21 |
| 19 namespace { | 22 namespace { |
| 20 | 23 |
| 21 struct DomCodeEntry { | 24 struct DomCodeEntry { |
| 22 DomCode dom_code; | 25 DomCode dom_code; |
| 23 int scan_code; | 26 int scan_code; |
| 24 }; | 27 }; |
| 25 #define USB_KEYMAP_DECLARATION const DomCodeEntry supported_dom_code_list[] = | 28 #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) | 83 if (flags & EF_NUM_LOCK_ON) |
| 81 keyboard_state[VK_NUMLOCK] |= 0x01; | 84 keyboard_state[VK_NUMLOCK] |= 0x01; |
| 82 | 85 |
| 83 if (flags & EF_CAPS_LOCK_ON) | 86 if (flags & EF_CAPS_LOCK_ON) |
| 84 keyboard_state[VK_CAPITAL] |= 0x01; | 87 keyboard_state[VK_CAPITAL] |= 0x01; |
| 85 | 88 |
| 86 if (flags & EF_SCROLL_LOCK_ON) | 89 if (flags & EF_SCROLL_LOCK_ON) |
| 87 keyboard_state[VK_SCROLL] |= 0x01; | 90 keyboard_state[VK_SCROLL] |= 0x01; |
| 88 } | 91 } |
| 89 | 92 |
| 93 DomKey NumPadKeyCodeToDomKey(KeyboardCode key_code) { |
| 94 switch (key_code) { |
| 95 case VKEY_NUMPAD0: |
| 96 return DomKey::Constant<'0'>::Character; |
| 97 case VKEY_NUMPAD1: |
| 98 return DomKey::Constant<'1'>::Character; |
| 99 case VKEY_NUMPAD2: |
| 100 return DomKey::Constant<'2'>::Character; |
| 101 case VKEY_NUMPAD3: |
| 102 return DomKey::Constant<'3'>::Character; |
| 103 case VKEY_NUMPAD4: |
| 104 return DomKey::Constant<'4'>::Character; |
| 105 case VKEY_NUMPAD5: |
| 106 return DomKey::Constant<'5'>::Character; |
| 107 case VKEY_NUMPAD6: |
| 108 return DomKey::Constant<'6'>::Character; |
| 109 case VKEY_NUMPAD7: |
| 110 return DomKey::Constant<'7'>::Character; |
| 111 case VKEY_NUMPAD8: |
| 112 return DomKey::Constant<'8'>::Character; |
| 113 case VKEY_NUMPAD9: |
| 114 return DomKey::Constant<'9'>::Character; |
| 115 case VKEY_CLEAR: |
| 116 return DomKey::CLEAR; |
| 117 case VKEY_PRIOR: |
| 118 return DomKey::PAGE_UP; |
| 119 case VKEY_NEXT: |
| 120 return DomKey::PAGE_DOWN; |
| 121 case VKEY_END: |
| 122 return DomKey::END; |
| 123 case VKEY_HOME: |
| 124 return DomKey::HOME; |
| 125 case VKEY_LEFT: |
| 126 return DomKey::ARROW_LEFT; |
| 127 case VKEY_UP: |
| 128 return DomKey::ARROW_UP; |
| 129 case VKEY_RIGHT: |
| 130 return DomKey::ARROW_RIGHT; |
| 131 case VKEY_DOWN: |
| 132 return DomKey::ARROW_DOWN; |
| 133 case VKEY_INSERT: |
| 134 return DomKey::INSERT; |
| 135 case VKEY_DELETE: |
| 136 return DomKey::DEL; |
| 137 default: |
| 138 return DomKey::NONE; |
| 139 } |
| 140 } |
| 141 |
| 90 void CleanupKeyMapTls(void* data) { | 142 void CleanupKeyMapTls(void* data) { |
| 91 PlatformKeyMap* key_map = reinterpret_cast<PlatformKeyMap*>(data); | 143 PlatformKeyMap* key_map = reinterpret_cast<PlatformKeyMap*>(data); |
| 92 delete key_map; | 144 delete key_map; |
| 93 } | 145 } |
| 94 | 146 |
| 95 struct PlatformKeyMapInstanceTlsTraits | 147 struct PlatformKeyMapInstanceTlsTraits |
| 96 : public base::DefaultLazyInstanceTraits<base::ThreadLocalStorage::Slot> { | 148 : public base::DefaultLazyInstanceTraits<base::ThreadLocalStorage::Slot> { |
| 97 static base::ThreadLocalStorage::Slot* New(void* instance) { | 149 static base::ThreadLocalStorage::Slot* New(void* instance) { |
| 98 // Use placement new to initialize our instance in our preallocated space. | 150 // Use placement new to initialize our instance in our preallocated space. |
| 99 // TODO(chongz): Use std::default_delete instead of providing own function. | 151 // TODO(chongz): Use std::default_delete instead of providing own function. |
| 100 return new (instance) base::ThreadLocalStorage::Slot(CleanupKeyMapTls); | 152 return new (instance) base::ThreadLocalStorage::Slot(CleanupKeyMapTls); |
| 101 } | 153 } |
| 102 }; | 154 }; |
| 103 | 155 |
| 104 base::LazyInstance<base::ThreadLocalStorage::Slot, | 156 base::LazyInstance<base::ThreadLocalStorage::Slot, |
| 105 PlatformKeyMapInstanceTlsTraits> | 157 PlatformKeyMapInstanceTlsTraits> |
| 106 g_platform_key_map_tls_lazy = LAZY_INSTANCE_INITIALIZER; | 158 g_platform_key_map_tls_lazy = LAZY_INSTANCE_INITIALIZER; |
| 107 | 159 |
| 108 } // anonymous namespace | 160 } // anonymous namespace |
| 109 | 161 |
| 110 PlatformKeyMap::PlatformKeyMap() {} | 162 PlatformKeyMap::PlatformKeyMap() {} |
| 111 | 163 |
| 112 PlatformKeyMap::PlatformKeyMap(HKL layout) { | 164 PlatformKeyMap::PlatformKeyMap(HKL layout) { |
| 113 UpdateLayout(layout); | 165 UpdateLayout(layout); |
| 114 } | 166 } |
| 115 | 167 |
| 116 PlatformKeyMap::~PlatformKeyMap() {} | 168 PlatformKeyMap::~PlatformKeyMap() {} |
| 117 | 169 |
| 118 DomKey PlatformKeyMap::DomCodeAndFlagsToDomKey(DomCode code, int flags) const { | 170 DomKey PlatformKeyMap::DomKeyFromNativeImpl(DomCode code, |
| 171 KeyboardCode key_code, |
| 172 int flags) const { |
| 173 if (KeycodeConverter::DomCodeToLocation(code) == DomKeyLocation::NUMPAD) { |
| 174 // Derived the DOM Key value from |key_code| instead of |code|, to address |
| 175 // Windows Numlock/Shift interaction - see crbug.com/594552. |
| 176 return NumPadKeyCodeToDomKey(key_code); |
| 177 } |
| 178 |
| 119 const int flags_to_try[] = { | 179 const int flags_to_try[] = { |
| 120 // Trying to match Firefox's behavior and UIEvents DomKey guidelines. | 180 // Trying to match Firefox's behavior and UIEvents DomKey guidelines. |
| 121 // If the combination doesn't produce a printable character, the key value | 181 // 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. | 182 // should be the key with no modifiers except for Shift and AltGr. |
| 123 // See https://w3c.github.io/uievents/#keys-guidelines | 183 // See https://w3c.github.io/uievents/#keys-guidelines |
| 124 flags, | 184 flags, |
| 125 flags & (EF_SHIFT_DOWN | EF_ALTGR_DOWN | EF_CAPS_LOCK_ON), | 185 flags & (EF_SHIFT_DOWN | EF_ALTGR_DOWN | EF_CAPS_LOCK_ON), |
| 126 flags & (EF_SHIFT_DOWN | EF_CAPS_LOCK_ON), | 186 flags & (EF_SHIFT_DOWN | EF_CAPS_LOCK_ON), |
| 127 EF_NONE, | 187 EF_NONE, |
| 128 }; | 188 }; |
| 129 | 189 |
| 130 DomKey key = DomKey::NONE; | 190 DomKey key = DomKey::NONE; |
| 131 for (auto try_flags : flags_to_try) { | 191 for (auto try_flags : flags_to_try) { |
| 132 const auto& it = code_to_key_.find(std::make_pair(static_cast<int>(code), | 192 const auto& it = code_to_key_.find(std::make_pair(static_cast<int>(code), |
| 133 try_flags)); | 193 try_flags)); |
| 134 if (it != code_to_key_.end()) { | 194 if (it != code_to_key_.end()) { |
| 135 key = it->second; | 195 key = it->second; |
| 136 if (key != DomKey::NONE) | 196 if (key != DomKey::NONE) |
| 137 break; | 197 break; |
| 138 } | 198 } |
| 139 } | 199 } |
| 140 return key; | 200 return key; |
| 141 } | 201 } |
| 142 | 202 |
| 143 // static | 203 // static |
| 144 DomKey PlatformKeyMap::DomCodeAndFlagsToDomKeyStatic(DomCode code, int flags) { | 204 DomKey PlatformKeyMap::DomKeyFromNative(const base::NativeEvent& native_event) { |
| 145 // Use TLS because KeyboardLayout is per thread. | 205 // Use TLS because KeyboardLayout is per thread. |
| 146 // However currently PlatformKeyMap will only be used by the host application, | 206 // However currently PlatformKeyMap will only be used by the host application, |
| 147 // which is just one process and one thread. | 207 // which is just one process and one thread. |
| 148 base::ThreadLocalStorage::Slot* platform_key_map_tls = | 208 base::ThreadLocalStorage::Slot* platform_key_map_tls = |
| 149 g_platform_key_map_tls_lazy.Pointer(); | 209 g_platform_key_map_tls_lazy.Pointer(); |
| 150 PlatformKeyMap* platform_key_map = | 210 PlatformKeyMap* platform_key_map = |
| 151 reinterpret_cast<PlatformKeyMap*>(platform_key_map_tls->Get()); | 211 reinterpret_cast<PlatformKeyMap*>(platform_key_map_tls->Get()); |
| 152 if (!platform_key_map) { | 212 if (!platform_key_map) { |
| 153 platform_key_map = new PlatformKeyMap(); | 213 platform_key_map = new PlatformKeyMap(); |
| 154 platform_key_map_tls->Set(platform_key_map); | 214 platform_key_map_tls->Set(platform_key_map); |
| 155 } | 215 } |
| 156 | 216 |
| 157 HKL current_layout = ::GetKeyboardLayout(0); | 217 HKL current_layout = ::GetKeyboardLayout(0); |
| 158 platform_key_map->UpdateLayout(current_layout); | 218 platform_key_map->UpdateLayout(current_layout); |
| 159 return platform_key_map->DomCodeAndFlagsToDomKey(code, flags); | 219 return platform_key_map->DomKeyFromNativeImpl( |
| 220 CodeFromNative(native_event), KeyboardCodeFromNative(native_event), |
| 221 EventFlagsFromNative(native_event)); |
| 160 } | 222 } |
| 161 | 223 |
| 162 void PlatformKeyMap::UpdateLayout(HKL layout) { | 224 void PlatformKeyMap::UpdateLayout(HKL layout) { |
| 163 if (layout == keyboard_layout_) | 225 if (layout == keyboard_layout_) |
| 164 return; | 226 return; |
| 165 | 227 |
| 166 BYTE keyboard_state_to_restore[256]; | 228 BYTE keyboard_state_to_restore[256]; |
| 167 if (!::GetKeyboardState(keyboard_state_to_restore)) | 229 if (!::GetKeyboardState(keyboard_state_to_restore)) |
| 168 return; | 230 return; |
| 169 | 231 |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 210 } | 272 } |
| 211 } else { | 273 } else { |
| 212 // TODO(chongz): Handle rv <= -2 and rv >= 2. | 274 // TODO(chongz): Handle rv <= -2 and rv >= 2. |
| 213 } | 275 } |
| 214 } | 276 } |
| 215 } | 277 } |
| 216 ::SetKeyboardState(keyboard_state_to_restore); | 278 ::SetKeyboardState(keyboard_state_to_restore); |
| 217 } | 279 } |
| 218 | 280 |
| 219 } // namespace ui | 281 } // namespace ui |
| OLD | NEW |