OLD | NEW |
| (Empty) |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "chrome/test/webdriver/keycode_text_conversion.h" | |
6 | |
7 #import <Carbon/Carbon.h> | |
8 | |
9 #include <cctype> | |
10 | |
11 #include "base/mac/scoped_cftyperef.h" | |
12 #include "base/strings/utf_string_conversions.h" | |
13 #include "chrome/common/automation_constants.h" | |
14 #include "ui/base/keycodes/keyboard_code_conversion_mac.h" | |
15 | |
16 namespace webdriver { | |
17 | |
18 std::string ConvertKeyCodeToText(ui::KeyboardCode key_code, int modifiers) { | |
19 int mac_key_code = 0; | |
20 { | |
21 unichar character, unmodified_character; | |
22 mac_key_code = ui::MacKeyCodeForWindowsKeyCode( | |
23 key_code, | |
24 0, | |
25 &character, | |
26 &unmodified_character); | |
27 } | |
28 if (mac_key_code < 0) | |
29 return ""; | |
30 | |
31 int mac_modifiers = 0; | |
32 if (modifiers & automation::kShiftKeyMask) | |
33 mac_modifiers |= shiftKey; | |
34 if (modifiers & automation::kControlKeyMask) | |
35 mac_modifiers |= controlKey; | |
36 if (modifiers & automation::kAltKeyMask) | |
37 mac_modifiers |= optionKey; | |
38 if (modifiers & automation::kMetaKeyMask) | |
39 mac_modifiers |= cmdKey; | |
40 // Convert EventRecord modifiers to format UCKeyTranslate accepts. See docs | |
41 // on UCKeyTranslate for more info. | |
42 UInt32 modifier_key_state = (mac_modifiers >> 8) & 0xFF; | |
43 | |
44 base::ScopedCFTypeRef<TISInputSourceRef> input_source_copy( | |
45 TISCopyCurrentKeyboardLayoutInputSource()); | |
46 CFDataRef layout_data = static_cast<CFDataRef>(TISGetInputSourceProperty( | |
47 input_source_copy, kTISPropertyUnicodeKeyLayoutData)); | |
48 | |
49 UInt32 dead_key_state = 0; | |
50 UniCharCount char_count = 0; | |
51 UniChar character = 0; | |
52 OSStatus status = UCKeyTranslate( | |
53 reinterpret_cast<const UCKeyboardLayout*>(CFDataGetBytePtr(layout_data)), | |
54 static_cast<UInt16>(mac_key_code), | |
55 kUCKeyActionDown, | |
56 modifier_key_state, | |
57 LMGetKbdLast(), | |
58 kUCKeyTranslateNoDeadKeysBit, | |
59 &dead_key_state, | |
60 1, | |
61 &char_count, | |
62 &character); | |
63 if (status == noErr && char_count == 1 && !std::iscntrl(character)) { | |
64 string16 text; | |
65 text.push_back(character); | |
66 return UTF16ToUTF8(text); | |
67 } else { | |
68 return ""; | |
69 } | |
70 } | |
71 | |
72 bool ConvertCharToKeyCode( | |
73 char16 key, ui::KeyboardCode* key_code, int *necessary_modifiers) { | |
74 string16 key_string; | |
75 key_string.push_back(key); | |
76 std::string key_string_utf8 = UTF16ToUTF8(key_string); | |
77 bool found_code = false; | |
78 // There doesn't seem to be a way to get a mac key code for a given unicode | |
79 // character. So here we check every key code to see if it produces the | |
80 // right character. We could cache the results and regenerate everytime the | |
81 // language changes, but this brute force technique has negligble performance | |
82 // effects (on my laptop it is a submillisecond difference). | |
83 for (int i = 0; i < 256; ++i) { | |
84 ui::KeyboardCode code = static_cast<ui::KeyboardCode>(i); | |
85 // Skip the numpad keys. | |
86 if (code >= ui::VKEY_NUMPAD0 && code <= ui::VKEY_DIVIDE) | |
87 continue; | |
88 found_code = key_string_utf8 == ConvertKeyCodeToText(code, 0); | |
89 if (!found_code && key_string_utf8 == ConvertKeyCodeToText( | |
90 code, automation::kShiftKeyMask)) { | |
91 *necessary_modifiers = automation::kShiftKeyMask; | |
92 found_code = true; | |
93 } | |
94 if (found_code) { | |
95 *key_code = code; | |
96 break; | |
97 } | |
98 } | |
99 return found_code; | |
100 } | |
101 | |
102 } // namespace webdriver | |
OLD | NEW |