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 606 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 628 return DomKey::REDO; | 629 return DomKey::REDO; |
| 629 case NSFindFunctionKey: | 630 case NSFindFunctionKey: |
| 630 return DomKey::FIND; | 631 return DomKey::FIND; |
| 631 case NSHelpFunctionKey: | 632 case NSHelpFunctionKey: |
| 632 return DomKey::HELP; | 633 return DomKey::HELP; |
| 633 default: | 634 default: |
| 634 return DomKey::FromCharacter(char_code); | 635 return DomKey::FromCharacter(char_code); |
| 635 } | 636 } |
| 636 } | 637 } |
| 637 | 638 |
| 639 UniChar KeycodeAndModifiersToCharacter(unsigned short native_key_code, | |
| 640 int modifiers, | |
| 641 bool& is_deadkey) { | |
| 642 // Convert EventRecord modifiers to format UCKeyTranslate accepts. See docs | |
| 643 // on UCKeyTranslate for more info. | |
| 644 int native_modifiersers = 0; | |
| 645 if (modifiers & NSShiftKeyMask) | |
| 646 native_modifiersers |= shiftKey; | |
| 647 if (modifiers & NSAlphaShiftKeyMask) | |
| 648 native_modifiersers |= alphaLock; | |
| 649 if (modifiers & NSControlKeyMask) | |
| 650 native_modifiersers |= controlKey; | |
| 651 if (modifiers & NSAlternateKeyMask) | |
| 652 native_modifiersers |= optionKey; | |
| 653 if (modifiers & NSCommandKeyMask) | |
| 654 native_modifiersers |= cmdKey; | |
| 655 UInt32 modifier_key_state = (native_modifiersers >> 8) & 0xFF; | |
| 656 | |
| 657 base::ScopedCFTypeRef<TISInputSourceRef> input_source_copy( | |
| 658 TISCopyCurrentKeyboardLayoutInputSource()); | |
| 659 CFDataRef layout_data = static_cast<CFDataRef>(TISGetInputSourceProperty( | |
| 660 input_source_copy, kTISPropertyUnicodeKeyLayoutData)); | |
| 661 | |
| 662 UInt32 dead_key_state = 0; | |
| 663 UniCharCount char_count = 0; | |
| 664 UniChar character = 0; | |
| 665 OSStatus status = UCKeyTranslate( | |
| 666 reinterpret_cast<const UCKeyboardLayout*>(CFDataGetBytePtr(layout_data)), | |
| 667 static_cast<UInt16>(native_key_code), kUCKeyActionDown, | |
| 668 modifier_key_state, LMGetKbdLast(), kUCKeyTranslateNoDeadKeysBit, | |
| 669 &dead_key_state, 1, &char_count, &character); | |
| 670 | |
| 671 // According to Apple's doc an empty string means dead keys. | |
| 672 // https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Appli cationKit/Classes/NSEvent_Class/#//apple_ref/occ/instp/NSEvent/characters | |
| 673 if (status == noErr && char_count == 0) | |
| 674 is_deadkey = true; | |
| 675 else | |
| 676 is_deadkey = false; | |
| 677 | |
| 678 if (is_deadkey) { | |
| 679 // Inject space to get character value of dead key. | |
| 680 UCKeyTranslate(reinterpret_cast<const UCKeyboardLayout*>( | |
| 681 CFDataGetBytePtr(layout_data)), | |
| 682 static_cast<UInt16>(kVK_Space), kUCKeyActionDown, 0, | |
| 683 LMGetKbdLast(), kUCKeyTranslateNoDeadKeysBit, | |
| 684 &dead_key_state, 1, &char_count, &character); | |
| 685 } | |
| 686 | |
| 687 return character; | |
| 688 } | |
| 689 | |
| 638 } // namespace | 690 } // namespace |
| 639 | 691 |
| 640 int MacKeyCodeForWindowsKeyCode(KeyboardCode keycode, | 692 int MacKeyCodeForWindowsKeyCode(KeyboardCode keycode, |
| 641 NSUInteger flags, | 693 NSUInteger flags, |
| 642 unichar* us_keyboard_shifted_character, | 694 unichar* us_keyboard_shifted_character, |
| 643 unichar* keyboard_character) { | 695 unichar* keyboard_character) { |
| 644 // In release code, |flags| is used to lookup accelerators, so logic to handle | 696 // In release code, |flags| is used to lookup accelerators, so logic to handle |
| 645 // caps lock properly isn't implemented. | 697 // caps lock properly isn't implemented. |
| 646 DCHECK_EQ(0u, flags & NSAlphaShiftKeyMask); | 698 DCHECK_EQ(0u, flags & NSAlphaShiftKeyMask); |
| 647 | 699 |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 738 | 790 |
| 739 DomCode DomCodeFromNSEvent(NSEvent* event) { | 791 DomCode DomCodeFromNSEvent(NSEvent* event) { |
| 740 return ui::KeycodeConverter::NativeKeycodeToDomCode([event keyCode]); | 792 return ui::KeycodeConverter::NativeKeycodeToDomCode([event keyCode]); |
| 741 } | 793 } |
| 742 | 794 |
| 743 DomKey DomKeyFromNSEvent(NSEvent* event) { | 795 DomKey DomKeyFromNSEvent(NSEvent* event) { |
| 744 // Apply the lookup based on the character first since that has the | 796 // Apply the lookup based on the character first since that has the |
| 745 // Keyboard layout and modifers already applied; whereas the keyCode | 797 // Keyboard layout and modifers already applied; whereas the keyCode |
| 746 // doesn't. | 798 // doesn't. |
| 747 if ([event type] == NSKeyDown || [event type] == NSKeyUp) { | 799 if ([event type] == NSKeyDown || [event type] == NSKeyUp) { |
| 800 // Need [event characters] to handle dead key state. | |
| 748 NSString* characters = [event characters]; | 801 NSString* characters = [event characters]; |
| 749 if ([characters length] > 0) | 802 if ([characters length] > 0) { |
| 750 return DomKeyFromCharCode([characters characterAtIndex:0]); | 803 // An invalid dead key combination will produce two characters, according |
| 804 // to spec DomKey should be the last character. | |
| 805 // e.g. On French keyboard [+a will produce "^q", DomKey should be 'q'. | |
| 806 unichar dom_key_char = | |
|
chongz
2016/02/18 06:04:08
French [Digit2] and [Shift + Digit2] will both pro
| |
| 807 [characters characterAtIndex:[characters length] - 1]; | |
| 808 if ([event modifierFlags] != 0 && std::iscntrl(dom_key_char)) { | |
| 809 // According to spec if the key combination produces a non-printable | |
| 810 // character, the key value should be the character without modifiers | |
| 811 // except Shift and AltGr. | |
| 812 // See https://w3c.github.io/uievents/#keys-guidelines | |
| 813 bool is_deadkey; | |
| 814 const int fallback_modifiers = | |
| 815 NSShiftKeyMask | NSAlphaShiftKeyMask | NSAlternateKeyMask; | |
|
chongz
2016/02/18 06:04:07
Use custom fallback modifiers here since NSEvent::
| |
| 816 // KeycodeAndModifiersToCharacter() is efficient (around 1.2E-3 ms). | |
| 817 dom_key_char = KeycodeAndModifiersToCharacter( | |
|
chongz
2016/02/18 06:04:08
In this stage we don't care about dead keys any mo
| |
| 818 [event keyCode], [event modifierFlags] & fallback_modifiers, | |
| 819 is_deadkey); | |
| 820 } | |
| 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 |