OLD | NEW |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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 #include "chrome/renderer/mock_keyboard_driver_win.h" | 5 #include "chrome/renderer/mock_keyboard_driver_win.h" |
6 | 6 |
7 #include "base/basictypes.h" | 7 #include "base/basictypes.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 #include "chrome/renderer/mock_keyboard.h" | 9 #include "chrome/renderer/mock_keyboard.h" |
10 | 10 |
11 MockKeyboardDriverWin::MockKeyboardDriverWin() { | 11 MockKeyboardDriverWin::MockKeyboardDriverWin() { |
12 // Save the keyboard layout and status of the application. | 12 // Save the keyboard layout and status of the application. |
13 // This class changes the keyboard layout and status of this application. | 13 // This class changes the keyboard layout and status of this application. |
14 // This change may break succeeding tests. To prevent this possible break, we | 14 // This change may break succeeding tests. To prevent this possible break, we |
15 // should save the layout and status here to restore when this instance is | 15 // should save the layout and status here to restore when this instance is |
16 // destroyed. | 16 // destroyed. |
17 original_keyboard_layout_ = GetKeyboardLayout(0); | 17 original_keyboard_layout_ = GetKeyboardLayout(0); |
| 18 active_keyboard_layout_ = original_keyboard_layout_; |
18 GetKeyboardState(&original_keyboard_states_[0]); | 19 GetKeyboardState(&original_keyboard_states_[0]); |
19 | 20 |
20 keyboard_handle_ = NULL; | 21 const UINT num_keyboard_layouts = GetKeyboardLayoutList(0, NULL); |
| 22 DCHECK(num_keyboard_layouts > 0); |
| 23 |
| 24 orig_keyboard_layouts_list_.resize(num_keyboard_layouts); |
| 25 GetKeyboardLayoutList(num_keyboard_layouts, &orig_keyboard_layouts_list_[0]); |
| 26 |
21 memset(&keyboard_states_[0], 0, sizeof(keyboard_states_)); | 27 memset(&keyboard_states_[0], 0, sizeof(keyboard_states_)); |
22 } | 28 } |
23 | 29 |
24 MockKeyboardDriverWin::~MockKeyboardDriverWin() { | 30 MockKeyboardDriverWin::~MockKeyboardDriverWin() { |
25 // Unload the keyboard-layout driver, restore the keyboard state, and reset | 31 // Unload the keyboard-layout driver, restore the keyboard state, and reset |
26 // the keyboard layout for succeeding tests. | 32 // the keyboard layout for succeeding tests. |
27 if (keyboard_handle_) | 33 MaybeUnloadActiveLayout(); |
28 UnloadKeyboardLayout(keyboard_handle_); | |
29 SetKeyboardState(&original_keyboard_states_[0]); | 34 SetKeyboardState(&original_keyboard_states_[0]); |
30 ActivateKeyboardLayout(original_keyboard_layout_, KLF_RESET); | 35 ActivateKeyboardLayout(original_keyboard_layout_, KLF_RESET); |
31 } | 36 } |
32 | 37 |
| 38 void MockKeyboardDriverWin::MaybeUnloadActiveLayout() { |
| 39 // Workaround for http://crbug.com/12093 |
| 40 // Only unload a keyboard layout if it was loaded by this mock driver. |
| 41 // Contrary to the documentation on MSDN unloading a keyboard layout |
| 42 // previously loaded by the system causes that layout to stop working. |
| 43 // We have confirmation of this behavior on XP & Vista. |
| 44 for (size_t i = 0; i < orig_keyboard_layouts_list_.size(); ++i) { |
| 45 if (orig_keyboard_layouts_list_[i] == active_keyboard_layout_) |
| 46 return; |
| 47 } |
| 48 |
| 49 // If we got here, this keyboard layout wasn't loaded by the system so it's |
| 50 // safe to unload it ourselve's. |
| 51 UnloadKeyboardLayout(active_keyboard_layout_); |
| 52 active_keyboard_layout_ = original_keyboard_layout_; |
| 53 } |
| 54 |
33 bool MockKeyboardDriverWin::SetLayout(int layout) { | 55 bool MockKeyboardDriverWin::SetLayout(int layout) { |
34 // Unload the current keyboard-layout driver and load a new keyboard-layout | 56 // Unload the current keyboard-layout driver and load a new keyboard-layout |
35 // driver for mapping a virtual key-code to a Unicode character. | 57 // driver for mapping a virtual key-code to a Unicode character. |
36 if (keyboard_handle_) { | 58 MaybeUnloadActiveLayout(); |
37 UnloadKeyboardLayout(keyboard_handle_); | |
38 keyboard_handle_ = NULL; | |
39 } | |
40 | 59 |
41 // Scan the mapping table and retrieve a Language ID for the input layout. | 60 // Scan the mapping table and retrieve a Language ID for the input layout. |
42 // Load the keyboard-layout driver when we find a Language ID. | 61 // Load the keyboard-layout driver when we find a Language ID. |
43 // This Language IDs are copied from the registry | 62 // This Language IDs are copied from the registry |
44 // "HKLM\SYSTEM\CurrentControlSet\Control\Keyboard layouts". | 63 // "HKLM\SYSTEM\CurrentControlSet\Control\Keyboard layouts". |
45 // TODO(hbono): Add more keyboard-layout drivers. | 64 // TODO(hbono): Add more keyboard-layout drivers. |
46 static const struct { | 65 static const struct { |
47 const wchar_t* language; | 66 const wchar_t* language; |
48 MockKeyboard::Layout keyboard_layout; | 67 MockKeyboard::Layout keyboard_layout; |
49 } kLanguageIDs[] = { | 68 } kLanguageIDs[] = { |
(...skipping 24 matching lines...) Expand all Loading... |
74 {L"0000041f", MockKeyboard::LAYOUT_TURKISH_Q}, | 93 {L"0000041f", MockKeyboard::LAYOUT_TURKISH_Q}, |
75 {L"0000042a", MockKeyboard::LAYOUT_VIETNAMESE}, | 94 {L"0000042a", MockKeyboard::LAYOUT_VIETNAMESE}, |
76 {L"00000439", MockKeyboard::LAYOUT_DEVANAGARI_INSCRIPT}, | 95 {L"00000439", MockKeyboard::LAYOUT_DEVANAGARI_INSCRIPT}, |
77 {L"00000816", MockKeyboard::LAYOUT_PORTUGUESE}, | 96 {L"00000816", MockKeyboard::LAYOUT_PORTUGUESE}, |
78 {L"00001409", MockKeyboard::LAYOUT_UNITED_STATES_DVORAK}, | 97 {L"00001409", MockKeyboard::LAYOUT_UNITED_STATES_DVORAK}, |
79 {L"00001009", MockKeyboard::LAYOUT_CANADIAN_FRENCH}, | 98 {L"00001009", MockKeyboard::LAYOUT_CANADIAN_FRENCH}, |
80 }; | 99 }; |
81 | 100 |
82 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kLanguageIDs); ++i) { | 101 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kLanguageIDs); ++i) { |
83 if (layout == kLanguageIDs[i].keyboard_layout) { | 102 if (layout == kLanguageIDs[i].keyboard_layout) { |
84 keyboard_handle_ = LoadKeyboardLayout(kLanguageIDs[i].language, | 103 HKL new_keyboard_layout = LoadKeyboardLayout(kLanguageIDs[i].language, |
85 KLF_ACTIVATE); | 104 KLF_ACTIVATE); |
86 if (!keyboard_handle_) | 105 // loaded_keyboard_layout_ must always have a valid keyboard handle |
87 return false; | 106 // so we only assign upon success. |
88 return true; | 107 if (new_keyboard_layout) { |
| 108 active_keyboard_layout_ = new_keyboard_layout; |
| 109 return true; |
| 110 } |
| 111 |
| 112 return false; |
89 } | 113 } |
90 } | 114 } |
91 | 115 |
92 // Return false if there are not any matching drivers. | 116 // Return false if there are not any matching drivers. |
93 return false; | 117 return false; |
94 } | 118 } |
95 | 119 |
96 bool MockKeyboardDriverWin::SetModifiers(int modifiers) { | 120 bool MockKeyboardDriverWin::SetModifiers(int modifiers) { |
97 // Over-write the keyboard status with our modifier-key status. | 121 // Over-write the keyboard status with our modifier-key status. |
98 // WebInputEventFactory::keyboardEvent() uses GetKeyState() to retrive | 122 // WebInputEventFactory::keyboardEvent() uses GetKeyState() to retrive |
(...skipping 27 matching lines...) Expand all Loading... |
126 | 150 |
127 int MockKeyboardDriverWin::GetCharacters(int key_code, | 151 int MockKeyboardDriverWin::GetCharacters(int key_code, |
128 std::wstring* output) { | 152 std::wstring* output) { |
129 // Retrieve Unicode characters composed from the input key-code and | 153 // Retrieve Unicode characters composed from the input key-code and |
130 // the mofifiers. | 154 // the mofifiers. |
131 CHECK(output); | 155 CHECK(output); |
132 wchar_t code[16]; | 156 wchar_t code[16]; |
133 int length = ToUnicodeEx(key_code, MapVirtualKey(key_code, 0), | 157 int length = ToUnicodeEx(key_code, MapVirtualKey(key_code, 0), |
134 &keyboard_states_[0], &code[0], | 158 &keyboard_states_[0], &code[0], |
135 ARRAYSIZE_UNSAFE(code), 0, | 159 ARRAYSIZE_UNSAFE(code), 0, |
136 keyboard_handle_); | 160 active_keyboard_layout_); |
137 if (length > 0) | 161 if (length > 0) |
138 output->assign(code); | 162 output->assign(code); |
139 return length; | 163 return length; |
140 } | 164 } |
OLD | NEW |