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

Unified 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, 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 side-by-side diff with in-line comments
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 »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ui/events/keycodes/keyboard_code_conversion_mac.mm
diff --git a/ui/events/keycodes/keyboard_code_conversion_mac.mm b/ui/events/keycodes/keyboard_code_conversion_mac.mm
index 8eb5749c12bbb959e942df289da4a4ec58d772bd..9c9f72d1a338d642591c0cd9bc6ff7f9cd3eafae 100644
--- a/ui/events/keycodes/keyboard_code_conversion_mac.mm
+++ b/ui/events/keycodes/keyboard_code_conversion_mac.mm
@@ -9,6 +9,8 @@
#import <Carbon/Carbon.h>
#include "base/logging.h"
+#include "base/mac/mac_logging.h"
+#include "base/mac/scoped_cftyperef.h"
#include "base/macros.h"
#include "ui/events/keycodes/dom/keycode_converter.h"
@@ -439,6 +441,7 @@ KeyboardCode KeyboardCodeFromKeyCode(unsigned short keyCode) {
DomKey DomKeyFromKeyCode(unsigned short keyCode) {
switch (keyCode) {
+ case kVK_ANSI_KeypadEnter:
case kVK_Return:
return DomKey::ENTER;
case kVK_Tab:
@@ -535,11 +538,6 @@ DomKey DomKeyFromKeyCode(unsigned short keyCode) {
DomKey DomKeyFromCharCode(unichar char_code) {
switch (char_code) {
- case 0x03:
- return DomKey::ENTER; // Numpad Enter
- // Mac maps backspace to forward delete unicode.
- case 0x7f:
- return DomKey::BACKSPACE;
case NSUpArrowFunctionKey:
return DomKey::ARROW_UP;
case NSDownArrowFunctionKey:
@@ -635,6 +633,54 @@ DomKey DomKeyFromCharCode(unichar char_code) {
}
}
+UniChar MacKeycodeAndModifiersToCharacter(unsigned short mac_keycode,
+ int modifiers) {
+ // Convert NSEvent modifiers to format UCKeyTranslate accepts. See docs
+ // on UCKeyTranslate for more info.
+ int unicode_modifiers = 0;
+ if (modifiers & NSShiftKeyMask)
+ unicode_modifiers |= shiftKey;
+ if (modifiers & NSAlphaShiftKeyMask)
+ unicode_modifiers |= alphaLock;
+ // if (modifiers & NSControlKeyMask)
+ // unicode_modifiers |= controlKey;
+ if (modifiers & NSAlternateKeyMask)
+ unicode_modifiers |= optionKey;
+ // if (modifiers & NSCommandKeyMask)
+ // unicode_modifiers |= cmdKey;
+ UInt32 modifier_key_state = (unicode_modifiers >> 8) & 0xFF;
+
+ base::ScopedCFTypeRef<TISInputSourceRef> input_source_copy(
+ TISCopyCurrentKeyboardLayoutInputSource());
+ CFDataRef layout_data = static_cast<CFDataRef>(TISGetInputSourceProperty(
+ input_source_copy, kTISPropertyUnicodeKeyLayoutData));
+ const UCKeyboardLayout* layout =
+ reinterpret_cast<const UCKeyboardLayout*>(CFDataGetBytePtr(layout_data));
+
+ UInt32 dead_key_state = 0;
+ UniCharCount char_count = 0;
+ // According Apple's doc UCKeyTranslate::maxStringLength maybe up to 255 but
+ // would actually be rare to get more than 4.
+ UniChar unicode_string[4];
+ OSStatus status =
+ UCKeyTranslate(layout, static_cast<UInt16>(mac_keycode), kUCKeyActionDown,
+ modifier_key_state, LMGetKbdLast(), 0, &dead_key_state,
+ arraysize(unicode_string), &char_count, unicode_string);
+
+ OSSTATUS_DCHECK(status == noErr, status);
+ if (dead_key_state != 0) {
+ // A dead key, injecting space to get the diacritic in an isolated form.
+ status = UCKeyTranslate(layout, static_cast<UInt16>(kVK_Space),
+ kUCKeyActionDown, 0, LMGetKbdLast(), 0,
+ &dead_key_state, arraysize(unicode_string),
+ &char_count, unicode_string);
+ OSSTATUS_DCHECK(status == noErr, status);
+ }
+
+ // TODO(chongz): Handle multiple character case. Should be rare.
+ return unicode_string[0];
+}
+
} // namespace
int MacKeyCodeForWindowsKeyCode(KeyboardCode keycode,
@@ -742,12 +788,38 @@ DomCode DomCodeFromNSEvent(NSEvent* event) {
DomKey DomKeyFromNSEvent(NSEvent* event) {
// Apply the lookup based on the character first since that has the
- // Keyboard layout and modifers already applied; whereas the keyCode
+ // Keyboard layout and modifiers already applied; whereas the keyCode
// doesn't.
if ([event type] == NSKeyDown || [event type] == NSKeyUp) {
+ // Have to use [event characters] to handle dead key state.
NSString* characters = [event characters];
- if ([characters length] > 0)
- return DomKeyFromCharCode([characters characterAtIndex:0]);
+ if ([characters length] > 0) {
+ // An invalid dead key combination will produce two characters, according
+ // to spec DomKey should be the last character.
+ // e.g. On French keyboard [+a will produce "^q", DomKey should be 'q'.
+ unichar dom_key_char =
+ [characters characterAtIndex:[characters length] - 1];
+ const bool is_ctrl_down = ([event modifierFlags] & NSControlKeyMask) &&
+ !([event modifierFlags] & NSAlternateKeyMask);
+ const bool is_command_down = [event modifierFlags] & NSCommandKeyMask;
+ // On Mac Blink won't insert ASCII character if either Ctrl or Command, or
+ // both, are down.
+ // See EditingBehavior::shouldInsertCharacter()
+ if (std::iscntrl(dom_key_char) ||
+ (dom_key_char < 0x80 && (is_ctrl_down || is_command_down))) {
+ // According to spec if the key combination produces a non-printable
+ // character, the key value should be the character without modifiers
+ // except Shift and AltGr.
+ // See https://w3c.github.io/uievents/#keys-guidelines
+ const int kAllowedModifiersMask =
+ NSShiftKeyMask | NSAlphaShiftKeyMask | NSAlternateKeyMask;
+ // MacKeycodeAndModifiersToCharacter() is efficient (around 6E-4 ms).
+ dom_key_char = MacKeycodeAndModifiersToCharacter(
+ [event keyCode], [event modifierFlags] & kAllowedModifiersMask);
+ }
+ if (!std::iscntrl(dom_key_char))
+ return DomKeyFromCharCode(dom_key_char);
+ }
}
return DomKeyFromKeyCode([event keyCode]);
}
« 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