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

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: Use Shift, Alt and CapsLock as fallback modifiers 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 f435f4ed2b966d19a8524ccc2fe63ef61c93c91f..96f75a5a86ee918090aa4c8684ffe640764f24b7 100644
--- a/ui/events/keycodes/keyboard_code_conversion_mac.mm
+++ b/ui/events/keycodes/keyboard_code_conversion_mac.mm
@@ -9,6 +9,7 @@
#import <Carbon/Carbon.h>
#include "base/logging.h"
+#include "base/mac/scoped_cftyperef.h"
#include "base/macros.h"
#include "ui/events/keycodes/dom/keycode_converter.h"
@@ -635,6 +636,57 @@ DomKey DomKeyFromCharCode(unichar char_code) {
}
}
+UniChar KeycodeAndModifiersToCharacter(unsigned short native_key_code,
+ int modifiers,
+ bool& is_deadkey) {
+ // Convert EventRecord modifiers to format UCKeyTranslate accepts. See docs
+ // on UCKeyTranslate for more info.
+ int native_modifiersers = 0;
+ if (modifiers & NSShiftKeyMask)
+ native_modifiersers |= shiftKey;
+ if (modifiers & NSAlphaShiftKeyMask)
+ native_modifiersers |= alphaLock;
+ if (modifiers & NSControlKeyMask)
+ native_modifiersers |= controlKey;
+ if (modifiers & NSAlternateKeyMask)
+ native_modifiersers |= optionKey;
+ if (modifiers & NSCommandKeyMask)
+ native_modifiersers |= cmdKey;
+ UInt32 modifier_key_state = (native_modifiersers >> 8) & 0xFF;
+
+ base::ScopedCFTypeRef<TISInputSourceRef> input_source_copy(
+ TISCopyCurrentKeyboardLayoutInputSource());
+ CFDataRef layout_data = static_cast<CFDataRef>(TISGetInputSourceProperty(
+ input_source_copy, kTISPropertyUnicodeKeyLayoutData));
+
+ UInt32 dead_key_state = 0;
+ UniCharCount char_count = 0;
+ UniChar character = 0;
+ OSStatus status = UCKeyTranslate(
+ reinterpret_cast<const UCKeyboardLayout*>(CFDataGetBytePtr(layout_data)),
+ static_cast<UInt16>(native_key_code), kUCKeyActionDown,
+ modifier_key_state, LMGetKbdLast(), kUCKeyTranslateNoDeadKeysBit,
+ &dead_key_state, 1, &char_count, &character);
+
+ // According to Apple's doc an empty string means dead keys.
+ // https://developer.apple.com/library/mac/documentation/Cocoa/Reference/ApplicationKit/Classes/NSEvent_Class/#//apple_ref/occ/instp/NSEvent/characters
+ if (status == noErr && char_count == 0)
+ is_deadkey = true;
+ else
+ is_deadkey = false;
+
+ if (is_deadkey) {
+ // Inject space to get character value of dead key.
+ UCKeyTranslate(reinterpret_cast<const UCKeyboardLayout*>(
+ CFDataGetBytePtr(layout_data)),
+ static_cast<UInt16>(kVK_Space), kUCKeyActionDown, 0,
+ LMGetKbdLast(), kUCKeyTranslateNoDeadKeysBit,
+ &dead_key_state, 1, &char_count, &character);
+ }
+
+ return character;
+}
+
} // namespace
int MacKeyCodeForWindowsKeyCode(KeyboardCode keycode,
@@ -745,9 +797,29 @@ DomKey DomKeyFromNSEvent(NSEvent* event) {
// Keyboard layout and modifers already applied; whereas the keyCode
// doesn't.
if ([event type] == NSKeyDown || [event type] == NSKeyUp) {
+ // Need [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 =
chongz 2016/02/18 06:04:08 French [Digit2] and [Shift + Digit2] will both pro
+ [characters characterAtIndex:[characters length] - 1];
+ if ([event modifierFlags] != 0 && std::iscntrl(dom_key_char)) {
+ // 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
+ bool is_deadkey;
+ const int fallback_modifiers =
+ NSShiftKeyMask | NSAlphaShiftKeyMask | NSAlternateKeyMask;
chongz 2016/02/18 06:04:07 Use custom fallback modifiers here since NSEvent::
+ // KeycodeAndModifiersToCharacter() is efficient (around 1.2E-3 ms).
+ dom_key_char = KeycodeAndModifiersToCharacter(
chongz 2016/02/18 06:04:08 In this stage we don't care about dead keys any mo
+ [event keyCode], [event modifierFlags] & fallback_modifiers,
+ is_deadkey);
+ }
+ 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