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

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: dtapuska and tdresser's review Created 4 years, 9 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
« no previous file with comments | « content/browser/renderer_host/input/web_input_event_builders_mac_unittest.mm ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/mac_logging.h"
13 #include "base/mac/scoped_cftyperef.h"
12 #include "base/macros.h" 14 #include "base/macros.h"
13 #include "ui/events/keycodes/dom/keycode_converter.h" 15 #include "ui/events/keycodes/dom/keycode_converter.h"
14 16
15 namespace ui { 17 namespace ui {
16 18
17 namespace { 19 namespace {
18 20
19 // A struct to hold a Windows keycode to Mac virtual keycode mapping. 21 // A struct to hold a Windows keycode to Mac virtual keycode mapping.
20 struct KeyCodeMap { 22 struct KeyCodeMap {
21 KeyboardCode keycode; 23 KeyboardCode keycode;
(...skipping 410 matching lines...) Expand 10 before | Expand all | Expand 10 after
432 }; 434 };
433 435
434 if (keyCode >= 0x80) 436 if (keyCode >= 0x80)
435 return VKEY_UNKNOWN; 437 return VKEY_UNKNOWN;
436 438
437 return kKeyboardCodes[keyCode]; 439 return kKeyboardCodes[keyCode];
438 } 440 }
439 441
440 DomKey DomKeyFromKeyCode(unsigned short keyCode) { 442 DomKey DomKeyFromKeyCode(unsigned short keyCode) {
441 switch (keyCode) { 443 switch (keyCode) {
444 case kVK_ANSI_KeypadEnter:
442 case kVK_Return: 445 case kVK_Return:
443 return DomKey::ENTER; 446 return DomKey::ENTER;
444 case kVK_Tab: 447 case kVK_Tab:
445 return DomKey::TAB; 448 return DomKey::TAB;
446 case kVK_Delete: 449 case kVK_Delete:
447 return DomKey::BACKSPACE; 450 return DomKey::BACKSPACE;
448 case kVK_Escape: 451 case kVK_Escape:
449 return DomKey::ESCAPE; 452 return DomKey::ESCAPE;
450 case kVK_Command: 453 case kVK_Command:
451 return DomKey::META; 454 return DomKey::META;
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
528 return DomKey::ARROW_DOWN; 531 return DomKey::ARROW_DOWN;
529 case kVK_UpArrow: 532 case kVK_UpArrow:
530 return DomKey::ARROW_UP; 533 return DomKey::ARROW_UP;
531 default: 534 default:
532 return DomKey::NONE; 535 return DomKey::NONE;
533 } 536 }
534 } 537 }
535 538
536 DomKey DomKeyFromCharCode(unichar char_code) { 539 DomKey DomKeyFromCharCode(unichar char_code) {
537 switch (char_code) { 540 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: 541 case NSUpArrowFunctionKey:
544 return DomKey::ARROW_UP; 542 return DomKey::ARROW_UP;
545 case NSDownArrowFunctionKey: 543 case NSDownArrowFunctionKey:
546 return DomKey::ARROW_DOWN; 544 return DomKey::ARROW_DOWN;
547 case NSLeftArrowFunctionKey: 545 case NSLeftArrowFunctionKey:
548 return DomKey::ARROW_LEFT; 546 return DomKey::ARROW_LEFT;
549 case NSRightArrowFunctionKey: 547 case NSRightArrowFunctionKey:
550 return DomKey::ARROW_RIGHT; 548 return DomKey::ARROW_RIGHT;
551 case NSF1FunctionKey: 549 case NSF1FunctionKey:
552 return DomKey::F1; 550 return DomKey::F1;
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
628 return DomKey::REDO; 626 return DomKey::REDO;
629 case NSFindFunctionKey: 627 case NSFindFunctionKey:
630 return DomKey::FIND; 628 return DomKey::FIND;
631 case NSHelpFunctionKey: 629 case NSHelpFunctionKey:
632 return DomKey::HELP; 630 return DomKey::HELP;
633 default: 631 default:
634 return DomKey::FromCharacter(char_code); 632 return DomKey::FromCharacter(char_code);
635 } 633 }
636 } 634 }
637 635
636 UniChar MacKeycodeAndModifiersToCharacter(unsigned short mac_keycode,
637 int modifiers) {
638 // Convert NSEvent modifiers to format UCKeyTranslate accepts. See docs
639 // on UCKeyTranslate for more info.
640 int unicode_modifiers = 0;
641 if (modifiers & NSShiftKeyMask)
642 unicode_modifiers |= shiftKey;
643 if (modifiers & NSAlphaShiftKeyMask)
644 unicode_modifiers |= alphaLock;
645 // if (modifiers & NSControlKeyMask)
646 // unicode_modifiers |= controlKey;
647 if (modifiers & NSAlternateKeyMask)
648 unicode_modifiers |= optionKey;
649 // if (modifiers & NSCommandKeyMask)
650 // unicode_modifiers |= cmdKey;
651 UInt32 modifier_key_state = (unicode_modifiers >> 8) & 0xFF;
652
653 base::ScopedCFTypeRef<TISInputSourceRef> input_source_copy(
654 TISCopyCurrentKeyboardLayoutInputSource());
655 CFDataRef layout_data = static_cast<CFDataRef>(TISGetInputSourceProperty(
656 input_source_copy, kTISPropertyUnicodeKeyLayoutData));
657 const UCKeyboardLayout* layout =
658 reinterpret_cast<const UCKeyboardLayout*>(CFDataGetBytePtr(layout_data));
659
660 UInt32 dead_key_state = 0;
661 UniCharCount char_count = 0;
662 // According Apple's doc UCKeyTranslate::maxStringLength maybe up to 255 but
663 // would actually be rare to get more than 4.
664 UniChar unicode_string[4];
665 OSStatus status =
666 UCKeyTranslate(layout, static_cast<UInt16>(mac_keycode), kUCKeyActionDown,
667 modifier_key_state, LMGetKbdLast(), 0, &dead_key_state,
668 arraysize(unicode_string), &char_count, unicode_string);
669
670 OSSTATUS_DCHECK(status == noErr, status);
671 if (dead_key_state != 0) {
672 // A dead key, injecting space to get the diacritic in an isolated form.
673 status = UCKeyTranslate(layout, static_cast<UInt16>(kVK_Space),
674 kUCKeyActionDown, 0, LMGetKbdLast(), 0,
675 &dead_key_state, arraysize(unicode_string),
676 &char_count, unicode_string);
677 OSSTATUS_DCHECK(status == noErr, status);
678 }
679
680 // TODO(chongz): Handle multiple character case. Should be rare.
681 return unicode_string[0];
682 }
683
638 } // namespace 684 } // namespace
639 685
640 int MacKeyCodeForWindowsKeyCode(KeyboardCode keycode, 686 int MacKeyCodeForWindowsKeyCode(KeyboardCode keycode,
641 NSUInteger flags, 687 NSUInteger flags,
642 unichar* us_keyboard_shifted_character, 688 unichar* us_keyboard_shifted_character,
643 unichar* keyboard_character) { 689 unichar* keyboard_character) {
644 // In release code, |flags| is used to lookup accelerators, so logic to handle 690 // In release code, |flags| is used to lookup accelerators, so logic to handle
645 // caps lock properly isn't implemented. 691 // caps lock properly isn't implemented.
646 DCHECK_EQ(0u, flags & NSAlphaShiftKeyMask); 692 DCHECK_EQ(0u, flags & NSAlphaShiftKeyMask);
647 693
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
735 } 781 }
736 return KeyboardCodeFromKeyCode([event keyCode]); 782 return KeyboardCodeFromKeyCode([event keyCode]);
737 } 783 }
738 784
739 DomCode DomCodeFromNSEvent(NSEvent* event) { 785 DomCode DomCodeFromNSEvent(NSEvent* event) {
740 return ui::KeycodeConverter::NativeKeycodeToDomCode([event keyCode]); 786 return ui::KeycodeConverter::NativeKeycodeToDomCode([event keyCode]);
741 } 787 }
742 788
743 DomKey DomKeyFromNSEvent(NSEvent* event) { 789 DomKey DomKeyFromNSEvent(NSEvent* event) {
744 // Apply the lookup based on the character first since that has the 790 // Apply the lookup based on the character first since that has the
745 // Keyboard layout and modifers already applied; whereas the keyCode 791 // Keyboard layout and modifiers already applied; whereas the keyCode
746 // doesn't. 792 // doesn't.
747 if ([event type] == NSKeyDown || [event type] == NSKeyUp) { 793 if ([event type] == NSKeyDown || [event type] == NSKeyUp) {
794 // Have to use [event characters] to handle dead key state.
748 NSString* characters = [event characters]; 795 NSString* characters = [event characters];
749 if ([characters length] > 0) 796 if ([characters length] > 0) {
750 return DomKeyFromCharCode([characters characterAtIndex:0]); 797 // An invalid dead key combination will produce two characters, according
798 // to spec DomKey should be the last character.
799 // e.g. On French keyboard [+a will produce "^q", DomKey should be 'q'.
800 unichar dom_key_char =
801 [characters characterAtIndex:[characters length] - 1];
802 const bool is_ctrl_down = ([event modifierFlags] & NSControlKeyMask) &&
803 !([event modifierFlags] & NSAlternateKeyMask);
804 const bool is_command_down = [event modifierFlags] & NSCommandKeyMask;
805 // On Mac Blink won't insert ASCII character if either Ctrl or Command, or
806 // both, are down.
807 // See EditingBehavior::shouldInsertCharacter()
808 if (std::iscntrl(dom_key_char) ||
809 (dom_key_char < 0x80 && (is_ctrl_down || is_command_down))) {
810 // According to spec if the key combination produces a non-printable
811 // character, the key value should be the character without modifiers
812 // except Shift and AltGr.
813 // See https://w3c.github.io/uievents/#keys-guidelines
814 const int kAllowedModifiersMask =
815 NSShiftKeyMask | NSAlphaShiftKeyMask | NSAlternateKeyMask;
816 // MacKeycodeAndModifiersToCharacter() is efficient (around 6E-4 ms).
817 dom_key_char = MacKeycodeAndModifiersToCharacter(
818 [event keyCode], [event modifierFlags] & kAllowedModifiersMask);
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
« no previous file with comments | « content/browser/renderer_host/input/web_input_event_builders_mac_unittest.mm ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698