Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(349)

Side by Side Diff: ui/events/keycodes/keyboard_code_conversion_mac.mm

Issue 1706683002: [Mac] Produce correct DomKey when Ctrl/Shift/Command is down (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix Ctrl/Ctrl+Shift to pass garykac's keyboard tester Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698