OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 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 | 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/keyboard_code_conversion.h" | 5 #include "ui/events/keycodes/keyboard_code_conversion.h" |
6 | 6 |
| 7 #include <algorithm> |
| 8 |
7 #include "ui/events/event_constants.h" | 9 #include "ui/events/event_constants.h" |
8 #include "ui/events/keycodes/dom3/dom_code.h" | 10 #include "ui/events/keycodes/dom3/dom_code.h" |
9 #include "ui/events/keycodes/dom3/dom_key.h" | 11 #include "ui/events/keycodes/dom3/dom_key.h" |
| 12 #include "ui/events/keycodes/dom_us_layout_data.h" |
10 | 13 |
11 namespace ui { | 14 namespace ui { |
12 | 15 |
13 namespace { | 16 namespace { |
14 | 17 |
15 // This table maps a subset of |KeyboardCode| (VKEYs) to DomKey and character. | 18 // This table maps a subset of |KeyboardCode| (VKEYs) to DomKey and character. |
16 // Only values not otherwise handled by GetMeaningFromKeyCode() are here. | 19 // Only values not otherwise handled by GetMeaningFromKeyCode() are here. |
17 const struct KeyboardCodeToMeaning { | 20 const struct KeyboardCodeToMeaning { |
18 KeyboardCode key_code; | 21 KeyboardCode key_code; |
19 DomKey key; | 22 DomKey key; |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
123 {VKEY_OEM_103, DomKey::MEDIA_REWIND, 0, 0}, | 126 {VKEY_OEM_103, DomKey::MEDIA_REWIND, 0, 0}, |
124 {VKEY_OEM_104, DomKey::MEDIA_FAST_FORWARD, 0, 0}, | 127 {VKEY_OEM_104, DomKey::MEDIA_FAST_FORWARD, 0, 0}, |
125 #endif | 128 #endif |
126 }; | 129 }; |
127 | 130 |
128 bool IsRightSideDomCode(DomCode code) { | 131 bool IsRightSideDomCode(DomCode code) { |
129 return (code == DomCode::SHIFT_RIGHT) || (code == DomCode::CONTROL_RIGHT) || | 132 return (code == DomCode::SHIFT_RIGHT) || (code == DomCode::CONTROL_RIGHT) || |
130 (code == DomCode::ALT_RIGHT) || (code == DomCode::OS_RIGHT); | 133 (code == DomCode::ALT_RIGHT) || (code == DomCode::OS_RIGHT); |
131 } | 134 } |
132 | 135 |
| 136 bool IsModifierDomCode(DomCode code) { |
| 137 return (code == DomCode::CONTROL_LEFT) || (code == DomCode::CONTROL_RIGHT) || |
| 138 (code == DomCode::SHIFT_LEFT) || (code == DomCode::SHIFT_RIGHT) || |
| 139 (code == DomCode::ALT_LEFT) || (code == DomCode::ALT_RIGHT) || |
| 140 (code == DomCode::OS_LEFT) || (code == DomCode::OS_RIGHT); |
| 141 } |
| 142 |
133 } // anonymous namespace | 143 } // anonymous namespace |
134 | 144 |
135 base::char16 GetCharacterFromKeyCode(KeyboardCode key_code, int flags) { | 145 base::char16 GetCharacterFromKeyCode(KeyboardCode key_code, int flags) { |
136 ui::DomKey dom_key; | 146 ui::DomKey dom_key; |
137 base::char16 character; | 147 base::char16 character; |
138 if (GetMeaningFromKeyCode(key_code, flags, &dom_key, &character)) | 148 if (GetMeaningFromKeyCode(key_code, flags, &dom_key, &character)) |
139 return character; | 149 return character; |
140 return 0; | 150 return 0; |
141 } | 151 } |
142 | 152 |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
260 *character = (shift && p->shift_character) ? p->shift_character | 270 *character = (shift && p->shift_character) ? p->shift_character |
261 : p->plain_character; | 271 : p->plain_character; |
262 return true; | 272 return true; |
263 } | 273 } |
264 } | 274 } |
265 *dom_key = DomKey::UNIDENTIFIED; | 275 *dom_key = DomKey::UNIDENTIFIED; |
266 *character = 0; | 276 *character = 0; |
267 return false; | 277 return false; |
268 } | 278 } |
269 | 279 |
| 280 bool DomCodeToMeaning(DomCode dom_code, |
| 281 int flags, |
| 282 DomKey* out_dom_key, |
| 283 base::char16* out_character, |
| 284 KeyboardCode* out_key_code) { |
| 285 if ((flags & EF_CONTROL_DOWN) == EF_CONTROL_DOWN) { |
| 286 if (DomCodeToControlCharacter(dom_code, flags, out_dom_key, out_character, |
| 287 out_key_code)) { |
| 288 return true; |
| 289 } |
| 290 if (!IsModifierDomCode(dom_code)) { |
| 291 *out_dom_key = DomKey::UNIDENTIFIED; |
| 292 *out_character = 0; |
| 293 *out_key_code = VKEY_UNKNOWN; |
| 294 return true; |
| 295 } |
| 296 } else { |
| 297 for (const auto& it : kPrintableCodeMap) { |
| 298 if (it.dom_code == dom_code) { |
| 299 int state = (((flags & EF_ALTGR_DOWN) == EF_ALTGR_DOWN) << 1) | |
| 300 ((flags & EF_SHIFT_DOWN) == EF_SHIFT_DOWN); |
| 301 base::char16 ch = it.character[state]; |
| 302 *out_dom_key = (ch & kDeadKey) ? DomKey::DEAD : DomKey::CHARACTER; |
| 303 *out_character = ch; |
| 304 if ((flags & EF_CAPS_LOCK_DOWN) == EF_CAPS_LOCK_DOWN) { |
| 305 ch = (ch & ~kDeadKey) | 0x20; |
| 306 if ((ch >= 'a') && (ch <= 'z')) |
| 307 *out_character = it.character[state ^ 1]; |
| 308 } |
| 309 *out_key_code = |
| 310 LocatedToNonLocatedKeyboardCode(DomCodeToKeyboardCode(dom_code)); |
| 311 return true; |
| 312 } |
| 313 } |
| 314 } |
| 315 for (const auto& it : kNonPrintableCodeMap) { |
| 316 if (it.dom_code == dom_code) { |
| 317 *out_dom_key = it.dom_key; |
| 318 *out_character = it.character; |
| 319 *out_key_code = NonPrintableDomKeyToKeyboardCode(it.dom_key); |
| 320 return true; |
| 321 } |
| 322 } |
| 323 return false; |
| 324 } |
| 325 |
| 326 bool DomCodeToControlCharacter(DomCode dom_code, |
| 327 int flags, |
| 328 DomKey* dom_key, |
| 329 base::char16* character, |
| 330 KeyboardCode* key_code) { |
| 331 if ((flags & EF_CONTROL_DOWN) == 0) |
| 332 return false; |
| 333 |
| 334 int code = static_cast<int>(dom_code); |
| 335 const int kKeyA = static_cast<int>(DomCode::KEY_A); |
| 336 // Control-A - Control-Z map to 0x01 - 0x1A. |
| 337 if (code >= kKeyA && code <= static_cast<int>(DomCode::KEY_Z)) { |
| 338 *character = static_cast<base::char16>(code - kKeyA + 1); |
| 339 switch (dom_code) { |
| 340 case DomCode::KEY_H: |
| 341 *dom_key = DomKey::BACKSPACE; |
| 342 *key_code = VKEY_BACK; |
| 343 break; |
| 344 case DomCode::KEY_I: |
| 345 *dom_key = DomKey::TAB; |
| 346 *key_code = VKEY_TAB; |
| 347 break; |
| 348 case DomCode::KEY_M: |
| 349 *dom_key = DomKey::ENTER; |
| 350 *key_code = VKEY_RETURN; |
| 351 break; |
| 352 default: |
| 353 *dom_key = DomKey::CHARACTER; |
| 354 *key_code = static_cast<KeyboardCode>(code - kKeyA + VKEY_A); |
| 355 break; |
| 356 } |
| 357 return true; |
| 358 } |
| 359 |
| 360 if (flags & EF_SHIFT_DOWN) { |
| 361 switch (dom_code) { |
| 362 case DomCode::DIGIT2: |
| 363 // NUL |
| 364 *character = 0; |
| 365 *dom_key = DomKey::CHARACTER; |
| 366 *key_code = VKEY_2; |
| 367 return true; |
| 368 case DomCode::DIGIT6: |
| 369 // RS |
| 370 *character = 0x1E; |
| 371 *dom_key = DomKey::CHARACTER; |
| 372 *key_code = VKEY_6; |
| 373 return true; |
| 374 case DomCode::MINUS: |
| 375 // US |
| 376 *character = 0x1F; |
| 377 *dom_key = DomKey::CHARACTER; |
| 378 *key_code = VKEY_OEM_MINUS; |
| 379 return true; |
| 380 default: |
| 381 return false; |
| 382 } |
| 383 } |
| 384 |
| 385 switch (dom_code) { |
| 386 case DomCode::ENTER: |
| 387 // NL |
| 388 *character = 0x0A; |
| 389 *dom_key = DomKey::CHARACTER; |
| 390 *key_code = VKEY_RETURN; |
| 391 return true; |
| 392 case DomCode::BRACKET_LEFT: |
| 393 // ESC |
| 394 *character = 0x1B; |
| 395 *dom_key = DomKey::ESCAPE; |
| 396 *key_code = VKEY_OEM_4; |
| 397 return true; |
| 398 case DomCode::BACKSLASH: |
| 399 // FS |
| 400 *character = 0x1C; |
| 401 *dom_key = DomKey::CHARACTER; |
| 402 *key_code = VKEY_OEM_5; |
| 403 return true; |
| 404 case DomCode::BRACKET_RIGHT: |
| 405 // GS |
| 406 *character = 0x1D; |
| 407 *dom_key = DomKey::CHARACTER; |
| 408 *key_code = VKEY_OEM_6; |
| 409 return true; |
| 410 default: |
| 411 return false; |
| 412 } |
| 413 } |
| 414 |
| 415 // Returns a Windows-based VKEY for a non-printable DOM Level 3 |key|. |
| 416 // The returned VKEY is non-positional (e.g. VKEY_SHIFT). |
| 417 KeyboardCode NonPrintableDomKeyToKeyboardCode(DomKey dom_key) { |
| 418 for (const auto& it : kDomKeyToKeyboardCodeMap) { |
| 419 if (it.dom_key == dom_key) |
| 420 return it.key_code; |
| 421 } |
| 422 return VKEY_UNKNOWN; |
| 423 } |
| 424 |
| 425 // Returns the Windows-based VKEY value corresponding to a DOM Level 3 |code|. |
| 426 // The returned VKEY is located (e.g. VKEY_LSHIFT). |
| 427 KeyboardCode DomCodeToKeyboardCode(DomCode dom_code) { |
| 428 const DomCodeToKeyboardCodeEntry* end = |
| 429 dom_code_to_keyboard_code + arraysize(dom_code_to_keyboard_code); |
| 430 const DomCodeToKeyboardCodeEntry* found = |
| 431 std::lower_bound(dom_code_to_keyboard_code, end, dom_code, |
| 432 [](const DomCodeToKeyboardCodeEntry& a, DomCode b) { |
| 433 return static_cast<int>(a.dom_code) < static_cast<int>(b); |
| 434 }); |
| 435 if ((found != end) && (found->dom_code == dom_code)) |
| 436 return found->key_code; |
| 437 return VKEY_UNKNOWN; |
| 438 } |
| 439 |
| 440 // Returns a DOM Level 3 |code| from a Windows-based VKEY value. |
| 441 // This assumes a US layout and should only be used when |code| cannot be |
| 442 // determined from a physical scan code. |
| 443 DomCode KeyboardCodeToDomCode(KeyboardCode key_code) { |
| 444 key_code = NonLocatedToLocatedKeyboardCode(key_code, DomCode::NONE); |
| 445 for (const auto& it : dom_code_to_keyboard_code) { |
| 446 if (it.key_code == key_code) |
| 447 return it.dom_code; |
| 448 } |
| 449 return DomCode::NONE; |
| 450 } |
| 451 |
270 // Determine the non-located VKEY corresponding to a located VKEY. | 452 // Determine the non-located VKEY corresponding to a located VKEY. |
271 KeyboardCode LocatedToNonLocatedKeyboardCode(KeyboardCode key_code) { | 453 KeyboardCode LocatedToNonLocatedKeyboardCode(KeyboardCode key_code) { |
272 switch (key_code) { | 454 switch (key_code) { |
273 case VKEY_RWIN: | 455 case VKEY_RWIN: |
274 return VKEY_LWIN; | 456 return VKEY_LWIN; |
275 case VKEY_LSHIFT: | 457 case VKEY_LSHIFT: |
276 case VKEY_RSHIFT: | 458 case VKEY_RSHIFT: |
277 return VKEY_SHIFT; | 459 return VKEY_SHIFT; |
278 case VKEY_LCONTROL: | 460 case VKEY_LCONTROL: |
279 case VKEY_RCONTROL: | 461 case VKEY_RCONTROL: |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
337 case VKEY_8: | 519 case VKEY_8: |
338 return (dom_code == DomCode::NUMPAD8) ? VKEY_NUMPAD8 : VKEY_8; | 520 return (dom_code == DomCode::NUMPAD8) ? VKEY_NUMPAD8 : VKEY_8; |
339 case VKEY_9: | 521 case VKEY_9: |
340 return (dom_code == DomCode::NUMPAD9) ? VKEY_NUMPAD9 : VKEY_9; | 522 return (dom_code == DomCode::NUMPAD9) ? VKEY_NUMPAD9 : VKEY_9; |
341 default: | 523 default: |
342 return key_code; | 524 return key_code; |
343 } | 525 } |
344 } | 526 } |
345 | 527 |
346 } // namespace ui | 528 } // namespace ui |
OLD | NEW |