Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 #import "ui/events/keycodes/keyboard_code_conversion_mac.h" | 5 #import "ui/events/keycodes/keyboard_code_conversion_mac.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #import <Carbon/Carbon.h> | 9 #import <Carbon/Carbon.h> |
| 10 | 10 |
| 11 #include "base/logging.h" | 11 #include "base/logging.h" |
| 12 #include "base/mac/scoped_cftyperef.h" | |
| 12 #include "base/macros.h" | 13 #include "base/macros.h" |
| 13 #include "ui/events/keycodes/dom/keycode_converter.h" | 14 #include "ui/events/keycodes/dom/keycode_converter.h" |
| 14 | 15 |
| 15 namespace ui { | 16 namespace ui { |
| 16 | 17 |
| 17 namespace { | 18 namespace { |
| 18 | 19 |
| 19 // A struct to hold a Windows keycode to Mac virtual keycode mapping. | 20 // A struct to hold a Windows keycode to Mac virtual keycode mapping. |
| 20 struct KeyCodeMap { | 21 struct KeyCodeMap { |
| 21 KeyboardCode keycode; | 22 KeyboardCode keycode; |
| (...skipping 410 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 432 }; | 433 }; |
| 433 | 434 |
| 434 if (keyCode >= 0x80) | 435 if (keyCode >= 0x80) |
| 435 return VKEY_UNKNOWN; | 436 return VKEY_UNKNOWN; |
| 436 | 437 |
| 437 return kKeyboardCodes[keyCode]; | 438 return kKeyboardCodes[keyCode]; |
| 438 } | 439 } |
| 439 | 440 |
| 440 DomKey DomKeyFromKeyCode(unsigned short keyCode) { | 441 DomKey DomKeyFromKeyCode(unsigned short keyCode) { |
| 441 switch (keyCode) { | 442 switch (keyCode) { |
| 443 case kVK_ANSI_KeypadEnter: | |
| 442 case kVK_Return: | 444 case kVK_Return: |
| 443 return DomKey::ENTER; | 445 return DomKey::ENTER; |
| 444 case kVK_Tab: | 446 case kVK_Tab: |
| 445 return DomKey::TAB; | 447 return DomKey::TAB; |
| 446 case kVK_Delete: | 448 case kVK_Delete: |
| 447 return DomKey::BACKSPACE; | 449 return DomKey::BACKSPACE; |
| 448 case kVK_Escape: | 450 case kVK_Escape: |
| 449 return DomKey::ESCAPE; | 451 return DomKey::ESCAPE; |
| 450 case kVK_Command: | 452 case kVK_Command: |
| 451 return DomKey::META; | 453 return DomKey::META; |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 528 return DomKey::ARROW_DOWN; | 530 return DomKey::ARROW_DOWN; |
| 529 case kVK_UpArrow: | 531 case kVK_UpArrow: |
| 530 return DomKey::ARROW_UP; | 532 return DomKey::ARROW_UP; |
| 531 default: | 533 default: |
| 532 return DomKey::NONE; | 534 return DomKey::NONE; |
| 533 } | 535 } |
| 534 } | 536 } |
| 535 | 537 |
| 536 DomKey DomKeyFromCharCode(unichar char_code) { | 538 DomKey DomKeyFromCharCode(unichar char_code) { |
| 537 switch (char_code) { | 539 switch (char_code) { |
| 538 case 0x03: | |
| 539 return DomKey::ENTER; // Numpad Enter | |
| 540 // Mac maps backspace to forward delete unicode. | |
| 541 case 0x7f: | |
| 542 return DomKey::BACKSPACE; | |
| 543 case NSUpArrowFunctionKey: | 540 case NSUpArrowFunctionKey: |
| 544 return DomKey::ARROW_UP; | 541 return DomKey::ARROW_UP; |
| 545 case NSDownArrowFunctionKey: | 542 case NSDownArrowFunctionKey: |
| 546 return DomKey::ARROW_DOWN; | 543 return DomKey::ARROW_DOWN; |
| 547 case NSLeftArrowFunctionKey: | 544 case NSLeftArrowFunctionKey: |
| 548 return DomKey::ARROW_LEFT; | 545 return DomKey::ARROW_LEFT; |
| 549 case NSRightArrowFunctionKey: | 546 case NSRightArrowFunctionKey: |
| 550 return DomKey::ARROW_RIGHT; | 547 return DomKey::ARROW_RIGHT; |
| 551 case NSF1FunctionKey: | 548 case NSF1FunctionKey: |
| 552 return DomKey::F1; | 549 return DomKey::F1; |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 628 return DomKey::REDO; | 625 return DomKey::REDO; |
| 629 case NSFindFunctionKey: | 626 case NSFindFunctionKey: |
| 630 return DomKey::FIND; | 627 return DomKey::FIND; |
| 631 case NSHelpFunctionKey: | 628 case NSHelpFunctionKey: |
| 632 return DomKey::HELP; | 629 return DomKey::HELP; |
| 633 default: | 630 default: |
| 634 return DomKey::FromCharacter(char_code); | 631 return DomKey::FromCharacter(char_code); |
| 635 } | 632 } |
| 636 } | 633 } |
| 637 | 634 |
| 635 UniChar KeycodeAndModifiersToCharacter(unsigned short native_key_code, | |
| 636 int modifiers, | |
| 637 bool& is_deadkey) { | |
|
tapted
2016/02/23 23:55:52
bool& -> bool* (non-const refs aren't allowed in C
| |
| 638 // Convert EventRecord modifiers to format UCKeyTranslate accepts. See docs | |
| 639 // on UCKeyTranslate for more info. | |
| 640 int native_modifiersers = 0; | |
|
tapted
2016/02/23 23:55:52
modifiersers ? "native" is a bit confusing too sin
| |
| 641 if (modifiers & NSShiftKeyMask) | |
| 642 native_modifiersers |= shiftKey; | |
| 643 if (modifiers & NSAlphaShiftKeyMask) | |
| 644 native_modifiersers |= alphaLock; | |
| 645 if (modifiers & NSControlKeyMask) | |
|
tapted
2016/02/23 23:55:52
aren't some of these effectively deadcode since yo
| |
| 646 native_modifiersers |= controlKey; | |
| 647 if (modifiers & NSAlternateKeyMask) | |
| 648 native_modifiersers |= optionKey; | |
| 649 if (modifiers & NSCommandKeyMask) | |
| 650 native_modifiersers |= cmdKey; | |
| 651 UInt32 modifier_key_state = (native_modifiersers >> 8) & 0xFF; | |
| 652 | |
| 653 base::ScopedCFTypeRef<TISInputSourceRef> input_source_copy( | |
| 654 TISCopyCurrentKeyboardLayoutInputSource()); | |
| 655 CFDataRef layout_data = static_cast<CFDataRef>(TISGetInputSourceProperty( | |
|
tapted
2016/02/23 23:55:52
Since it's used a couple of times (and layout_data
| |
| 656 input_source_copy, kTISPropertyUnicodeKeyLayoutData)); | |
| 657 | |
| 658 UInt32 dead_key_state = 0; | |
| 659 UniCharCount char_count = 0; | |
| 660 UniChar character = 0; | |
| 661 OSStatus status = UCKeyTranslate( | |
| 662 reinterpret_cast<const UCKeyboardLayout*>(CFDataGetBytePtr(layout_data)), | |
| 663 static_cast<UInt16>(native_key_code), kUCKeyActionDown, | |
| 664 modifier_key_state, LMGetKbdLast(), kUCKeyTranslateNoDeadKeysBit, | |
| 665 &dead_key_state, 1, &char_count, &character); | |
| 666 | |
| 667 // According to Apple's doc an empty string means dead keys. | |
| 668 // https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Appli cationKit/Classes/NSEvent_Class/#//apple_ref/occ/instp/NSEvent/characters | |
| 669 if (status == noErr && char_count == 0) | |
|
tapted
2016/02/23 23:55:52
*is_deadkey = status == noErr && char_count == 0;
| |
| 670 is_deadkey = true; | |
| 671 else | |
| 672 is_deadkey = false; | |
| 673 | |
| 674 if (is_deadkey) { | |
| 675 // Inject space to get character value of dead key. | |
|
tapted
2016/02/23 23:55:52
I don't really understand what this means
| |
| 676 UCKeyTranslate(reinterpret_cast<const UCKeyboardLayout*>( | |
|
tapted
2016/02/23 23:55:52
Assign result and do
OSSTATUS_DCHECK(status == no
| |
| 677 CFDataGetBytePtr(layout_data)), | |
| 678 static_cast<UInt16>(kVK_Space), kUCKeyActionDown, 0, | |
| 679 LMGetKbdLast(), kUCKeyTranslateNoDeadKeysBit, | |
| 680 &dead_key_state, 1, &char_count, &character); | |
| 681 } | |
| 682 | |
| 683 return character; | |
| 684 } | |
| 685 | |
| 638 } // namespace | 686 } // namespace |
| 639 | 687 |
| 640 int MacKeyCodeForWindowsKeyCode(KeyboardCode keycode, | 688 int MacKeyCodeForWindowsKeyCode(KeyboardCode keycode, |
| 641 NSUInteger flags, | 689 NSUInteger flags, |
| 642 unichar* us_keyboard_shifted_character, | 690 unichar* us_keyboard_shifted_character, |
| 643 unichar* keyboard_character) { | 691 unichar* keyboard_character) { |
| 644 // In release code, |flags| is used to lookup accelerators, so logic to handle | 692 // In release code, |flags| is used to lookup accelerators, so logic to handle |
| 645 // caps lock properly isn't implemented. | 693 // caps lock properly isn't implemented. |
| 646 DCHECK_EQ(0u, flags & NSAlphaShiftKeyMask); | 694 DCHECK_EQ(0u, flags & NSAlphaShiftKeyMask); |
| 647 | 695 |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 735 } | 783 } |
| 736 return KeyboardCodeFromKeyCode([event keyCode]); | 784 return KeyboardCodeFromKeyCode([event keyCode]); |
| 737 } | 785 } |
| 738 | 786 |
| 739 DomCode DomCodeFromNSEvent(NSEvent* event) { | 787 DomCode DomCodeFromNSEvent(NSEvent* event) { |
| 740 return ui::KeycodeConverter::NativeKeycodeToDomCode([event keyCode]); | 788 return ui::KeycodeConverter::NativeKeycodeToDomCode([event keyCode]); |
| 741 } | 789 } |
| 742 | 790 |
| 743 DomKey DomKeyFromNSEvent(NSEvent* event) { | 791 DomKey DomKeyFromNSEvent(NSEvent* event) { |
| 744 // Apply the lookup based on the character first since that has the | 792 // Apply the lookup based on the character first since that has the |
| 745 // Keyboard layout and modifers already applied; whereas the keyCode | 793 // Keyboard layout and modifiers already applied; whereas the keyCode |
| 746 // doesn't. | 794 // doesn't. |
| 747 if ([event type] == NSKeyDown || [event type] == NSKeyUp) { | 795 if ([event type] == NSKeyDown || [event type] == NSKeyUp) { |
| 796 // Have to use [event characters] to handle dead key state. | |
| 748 NSString* characters = [event characters]; | 797 NSString* characters = [event characters]; |
| 749 if ([characters length] > 0) | 798 if ([characters length] > 0) { |
| 750 return DomKeyFromCharCode([characters characterAtIndex:0]); | 799 // An invalid dead key combination will produce two characters, according |
| 800 // to spec DomKey should be the last character. | |
| 801 // e.g. On French keyboard [+a will produce "^q", DomKey should be 'q'. | |
| 802 unichar dom_key_char = | |
| 803 [characters characterAtIndex:[characters length] - 1]; | |
| 804 const int kCtrlCmdKeyMask = NSControlKeyMask | NSCommandKeyMask; | |
| 805 // On Mac Blink won't insert ASCII character if Ctrl/Command is down. | |
|
tapted
2016/02/23 23:55:52
`Ctrl/Command is` -> `either Ctrl or Command, or b
| |
| 806 // See EditingBehavior::shouldInsertCharacter() | |
|
tapted
2016/02/23 23:55:52
full stop after comment
| |
| 807 if (dom_key_char < 0x80 && ([event modifierFlags] & kCtrlCmdKeyMask)) { | |
|
chongz
2016/02/22 20:17:18
I'm trying to match the logic here https://code.go
tapted
2016/02/24 00:05:51
Also I'm not sure what you're asking here. If you
chongz
2016/02/24 15:12:30
Yes that's exactly what I need, thanks!
| |
| 808 // According to spec if the key combination produces a non-printable | |
| 809 // character, the key value should be the character without modifiers | |
| 810 // except Shift and AltGr. | |
| 811 // See https://w3c.github.io/uievents/#keys-guidelines | |
| 812 bool is_deadkey; | |
| 813 const int fallback_modifiers = | |
|
tapted
2016/02/23 23:55:52
kFallbackModifiers or perhaps kAllowedModifiersMas
| |
| 814 NSShiftKeyMask | NSAlphaShiftKeyMask | NSAlternateKeyMask; | |
| 815 // KeycodeAndModifiersToCharacter() is efficient (around 1.2E-3 ms). | |
| 816 dom_key_char = KeycodeAndModifiersToCharacter( | |
| 817 [event keyCode], [event modifierFlags] & fallback_modifiers, | |
| 818 is_deadkey); | |
|
tapted
2016/02/23 23:55:52
is_deadkey isn't used after this - remove?
| |
| 819 } | |
| 820 if (!std::iscntrl(dom_key_char)) | |
| 821 return DomKeyFromCharCode(dom_key_char); | |
| 822 } | |
| 751 } | 823 } |
| 752 return DomKeyFromKeyCode([event keyCode]); | 824 return DomKeyFromKeyCode([event keyCode]); |
| 753 } | 825 } |
| 754 | 826 |
| 755 } // namespace ui | 827 } // namespace ui |
| OLD | NEW |