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.
5 #include "content/test/mock_keyboard_driver_win.h"
7 #include "base/basictypes.h"
8 #include "base/logging.h"
9 #include "content/test/mock_keyboard.h"
13 MockKeyboardDriverWin::MockKeyboardDriverWin() {
14 // Save the keyboard layout and status of the application.
15 // This class changes the keyboard layout and status of this application.
16 // This change may break succeeding tests. To prevent this possible break, we
17 // should save the layout and status here to restore when this instance is
19 original_keyboard_layout_
= GetKeyboardLayout(0);
20 active_keyboard_layout_
= original_keyboard_layout_
;
21 GetKeyboardState(&original_keyboard_states_
[0]);
23 const UINT num_keyboard_layouts
= GetKeyboardLayoutList(0, NULL
);
24 DCHECK(num_keyboard_layouts
> 0);
26 orig_keyboard_layouts_list_
.resize(num_keyboard_layouts
);
27 GetKeyboardLayoutList(num_keyboard_layouts
, &orig_keyboard_layouts_list_
[0]);
29 memset(&keyboard_states_
[0], 0, sizeof(keyboard_states_
));
32 MockKeyboardDriverWin::~MockKeyboardDriverWin() {
33 // Unload the keyboard-layout driver, restore the keyboard state, and reset
34 // the keyboard layout for succeeding tests.
35 MaybeUnloadActiveLayout();
36 SetKeyboardState(&original_keyboard_states_
[0]);
37 ActivateKeyboardLayout(original_keyboard_layout_
, KLF_RESET
);
40 void MockKeyboardDriverWin::MaybeUnloadActiveLayout() {
41 // Workaround for http://crbug.com/12093
42 // Only unload a keyboard layout if it was loaded by this mock driver.
43 // Contrary to the documentation on MSDN unloading a keyboard layout
44 // previously loaded by the system causes that layout to stop working.
45 // We have confirmation of this behavior on XP & Vista.
46 for (size_t i
= 0; i
< orig_keyboard_layouts_list_
.size(); ++i
) {
47 if (orig_keyboard_layouts_list_
[i
] == active_keyboard_layout_
)
51 // If we got here, this keyboard layout wasn't loaded by the system so it's
52 // safe to unload it ourselve's.
53 UnloadKeyboardLayout(active_keyboard_layout_
);
54 active_keyboard_layout_
= original_keyboard_layout_
;
57 bool MockKeyboardDriverWin::SetLayout(int layout
) {
58 // Unload the current keyboard-layout driver and load a new keyboard-layout
59 // driver for mapping a virtual key-code to a Unicode character.
60 MaybeUnloadActiveLayout();
62 // Scan the mapping table and retrieve a Language ID for the input layout.
63 // Load the keyboard-layout driver when we find a Language ID.
64 // This Language IDs are copied from the registry
65 // "HKLM\SYSTEM\CurrentControlSet\Control\Keyboard layouts".
66 // TODO(hbono): Add more keyboard-layout drivers.
68 const wchar_t* language
;
69 MockKeyboard::Layout keyboard_layout
;
71 {L
"00000401", MockKeyboard::LAYOUT_ARABIC
},
72 {L
"00000402", MockKeyboard::LAYOUT_BULGARIAN
},
73 {L
"00000404", MockKeyboard::LAYOUT_CHINESE_TRADITIONAL
},
74 {L
"00000405", MockKeyboard::LAYOUT_CZECH
},
75 {L
"00000406", MockKeyboard::LAYOUT_DANISH
},
76 {L
"00000407", MockKeyboard::LAYOUT_GERMAN
},
77 {L
"00000408", MockKeyboard::LAYOUT_GREEK
},
78 {L
"00000409", MockKeyboard::LAYOUT_UNITED_STATES
},
79 {L
"0000040a", MockKeyboard::LAYOUT_SPANISH
},
80 {L
"0000040b", MockKeyboard::LAYOUT_FINNISH
},
81 {L
"0000040c", MockKeyboard::LAYOUT_FRENCH
},
82 {L
"0000040d", MockKeyboard::LAYOUT_HEBREW
},
83 {L
"0000040e", MockKeyboard::LAYOUT_HUNGARIAN
},
84 {L
"00000410", MockKeyboard::LAYOUT_ITALIAN
},
85 {L
"00000411", MockKeyboard::LAYOUT_JAPANESE
},
86 {L
"00000412", MockKeyboard::LAYOUT_KOREAN
},
87 {L
"00000415", MockKeyboard::LAYOUT_POLISH
},
88 {L
"00000416", MockKeyboard::LAYOUT_PORTUGUESE_BRAZILIAN
},
89 {L
"00000418", MockKeyboard::LAYOUT_ROMANIAN
},
90 {L
"00000419", MockKeyboard::LAYOUT_RUSSIAN
},
91 {L
"0000041a", MockKeyboard::LAYOUT_CROATIAN
},
92 {L
"0000041b", MockKeyboard::LAYOUT_SLOVAK
},
93 {L
"0000041e", MockKeyboard::LAYOUT_THAI
},
94 {L
"0000041d", MockKeyboard::LAYOUT_SWEDISH
},
95 {L
"0000041f", MockKeyboard::LAYOUT_TURKISH_Q
},
96 {L
"0000042a", MockKeyboard::LAYOUT_VIETNAMESE
},
97 {L
"00000439", MockKeyboard::LAYOUT_DEVANAGARI_INSCRIPT
},
98 {L
"00000816", MockKeyboard::LAYOUT_PORTUGUESE
},
99 {L
"00001409", MockKeyboard::LAYOUT_UNITED_STATES_DVORAK
},
100 {L
"00001009", MockKeyboard::LAYOUT_CANADIAN_FRENCH
},
103 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(kLanguageIDs
); ++i
) {
104 if (layout
== kLanguageIDs
[i
].keyboard_layout
) {
105 HKL new_keyboard_layout
= LoadKeyboardLayout(kLanguageIDs
[i
].language
,
107 // loaded_keyboard_layout_ must always have a valid keyboard handle
108 // so we only assign upon success.
109 if (new_keyboard_layout
) {
110 active_keyboard_layout_
= new_keyboard_layout
;
118 // Return false if there are not any matching drivers.
122 bool MockKeyboardDriverWin::SetModifiers(int modifiers
) {
123 // Over-write the keyboard status with our modifier-key status.
124 // WebInputEventFactory::keyboardEvent() uses GetKeyState() to retrive
125 // modifier-key status. So, we update the modifier-key status with this
126 // SetKeyboardState() call before creating NativeWebKeyboardEvent
128 memset(&keyboard_states_
[0], 0, sizeof(keyboard_states_
));
129 static const struct {
132 } kModifierMasks
[] = {
133 {VK_SHIFT
, MockKeyboard::LEFT_SHIFT
| MockKeyboard::RIGHT_SHIFT
},
134 {VK_CONTROL
, MockKeyboard::LEFT_CONTROL
| MockKeyboard::RIGHT_CONTROL
},
135 {VK_MENU
, MockKeyboard::LEFT_ALT
| MockKeyboard::RIGHT_ALT
},
136 {VK_LSHIFT
, MockKeyboard::LEFT_SHIFT
},
137 {VK_LCONTROL
, MockKeyboard::LEFT_CONTROL
},
138 {VK_LMENU
, MockKeyboard::LEFT_ALT
},
139 {VK_RSHIFT
, MockKeyboard::RIGHT_SHIFT
},
140 {VK_RCONTROL
, MockKeyboard::RIGHT_CONTROL
},
141 {VK_RMENU
, MockKeyboard::RIGHT_ALT
},
143 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(kModifierMasks
); ++i
) {
144 const int kKeyDownMask
= 0x80;
145 if (modifiers
& kModifierMasks
[i
].mask
)
146 keyboard_states_
[kModifierMasks
[i
].key_code
] = kKeyDownMask
;
148 SetKeyboardState(&keyboard_states_
[0]);
153 int MockKeyboardDriverWin::GetCharacters(int key_code
,
154 std::wstring
* output
) {
155 // Retrieve Unicode characters composed from the input key-code and
159 int length
= ToUnicodeEx(key_code
, MapVirtualKey(key_code
, 0),
160 &keyboard_states_
[0], &code
[0], arraysize(code
), 0,
161 active_keyboard_layout_
);
163 output
->assign(code
);
167 } // namespace content