OLD | NEW |
---|---|
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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/browser/automation/ui_controls.h" | 5 #include "chrome/browser/automation/ui_controls.h" |
6 | 6 |
7 #include "app/keyboard_code_conversion_win.h" | 7 #include "app/keyboard_code_conversion_win.h" |
8 #include "app/keyboard_codes.h" | 8 #include "app/keyboard_codes.h" |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/message_loop.h" | 10 #include "base/message_loop.h" |
11 #include "base/string_util.h" | |
12 #include "base/win_util.h" | 11 #include "base/win_util.h" |
13 #include "base/ref_counted.h" | 12 #include "base/ref_counted.h" |
14 #include "base/task.h" | 13 #include "base/task.h" |
15 #include "views/view.h" | 14 #include "views/view.h" |
16 | 15 |
17 namespace ui_controls { | 16 namespace ui_controls { |
18 | 17 |
19 namespace { | 18 namespace { |
20 | 19 |
21 void Checkpoint(const char* message, const base::TimeTicks& start_time) { | |
22 LOG(INFO) << message << " : " | |
23 << (base::TimeTicks::Now() - start_time).InMilliseconds() | |
24 << " ms" << std::flush; | |
25 } | |
26 | |
27 // InputDispatcher ------------------------------------------------------------ | 20 // InputDispatcher ------------------------------------------------------------ |
28 | 21 |
29 // InputDispatcher is used to listen for a mouse/keyboard event. When the | 22 // InputDispatcher is used to listen for a mouse/keyboard event. When the |
30 // appropriate event is received the task is notified. | 23 // appropriate event is received the task is notified. |
31 class InputDispatcher : public base::RefCounted<InputDispatcher> { | 24 class InputDispatcher : public base::RefCounted<InputDispatcher> { |
32 public: | 25 public: |
33 InputDispatcher(Task* task, WPARAM message_waiting_for); | 26 InputDispatcher(Task* task, WPARAM message_waiting_for); |
34 | 27 |
35 // Invoked from the hook. If mouse_message matches message_waiting_for_ | 28 // Invoked from the hook. If mouse_message matches message_waiting_for_ |
36 // MatchingMessageFound is invoked. | 29 // MatchingMessageFound is invoked. |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
71 HHOOK next_hook = next_hook_; | 64 HHOOK next_hook = next_hook_; |
72 if (n_code == HC_ACTION) { | 65 if (n_code == HC_ACTION) { |
73 DCHECK(current_dispatcher_); | 66 DCHECK(current_dispatcher_); |
74 current_dispatcher_->DispatchedMessage(w_param); | 67 current_dispatcher_->DispatchedMessage(w_param); |
75 } | 68 } |
76 return CallNextHookEx(next_hook, n_code, w_param, l_param); | 69 return CallNextHookEx(next_hook, n_code, w_param, l_param); |
77 } | 70 } |
78 | 71 |
79 // Callback from hook when a key message is received. | 72 // Callback from hook when a key message is received. |
80 LRESULT CALLBACK KeyHook(int n_code, WPARAM w_param, LPARAM l_param) { | 73 LRESULT CALLBACK KeyHook(int n_code, WPARAM w_param, LPARAM l_param) { |
81 base::TimeTicks start_time = base::TimeTicks::Now(); | |
82 char msg[512]; | |
83 base::snprintf(msg, 512, "KeyHook starts: %d", n_code); | |
84 Checkpoint(msg, start_time); | |
85 | |
86 HHOOK next_hook = next_hook_; | 74 HHOOK next_hook = next_hook_; |
87 base::snprintf(msg, 512, "n_code == HC_ACTION: %d, %d", | |
88 l_param, !!(l_param & (1 << 30))); | |
89 Checkpoint(msg, start_time); | |
90 if (n_code == HC_ACTION) { | 75 if (n_code == HC_ACTION) { |
91 DCHECK(current_dispatcher_); | 76 DCHECK(current_dispatcher_); |
92 if (l_param & (1 << 30)) { // Only send on key up. | 77 if (l_param & (1 << 30)) // Only send on key up. |
M-A Ruel
2010/12/01 14:22:35
style nit: Ugh, I hate comments positioned like th
Finnur
2010/12/01 14:40:35
This is the way I arrived at it before adding trac
| |
93 Checkpoint("MatchingMessageFound", start_time); | |
94 current_dispatcher_->MatchingMessageFound(); | 78 current_dispatcher_->MatchingMessageFound(); |
95 } else { | |
96 Checkpoint("Not key up", start_time); | |
97 } | |
98 } | 79 } |
99 Checkpoint("KeyHook ends, calling next hook.", start_time); | |
100 return CallNextHookEx(next_hook, n_code, w_param, l_param); | 80 return CallNextHookEx(next_hook, n_code, w_param, l_param); |
101 } | 81 } |
102 | 82 |
103 // Installs dispatcher as the current hook. | 83 // Installs dispatcher as the current hook. |
104 void InstallHook(InputDispatcher* dispatcher, bool key_hook) { | 84 void InstallHook(InputDispatcher* dispatcher, bool key_hook) { |
105 DCHECK(!installed_hook_); | 85 DCHECK(!installed_hook_); |
106 current_dispatcher_ = dispatcher; | 86 current_dispatcher_ = dispatcher; |
107 installed_hook_ = true; | 87 installed_hook_ = true; |
108 if (key_hook) { | 88 if (key_hook) { |
109 next_hook_ = SetWindowsHookEx(WH_KEYBOARD, &KeyHook, NULL, | 89 next_hook_ = SetWindowsHookEx(WH_KEYBOARD, &KeyHook, NULL, |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
177 | 157 |
178 if (!::SendInput(1, &input, sizeof(INPUT))) | 158 if (!::SendInput(1, &input, sizeof(INPUT))) |
179 return false; | 159 return false; |
180 | 160 |
181 return true; | 161 return true; |
182 } | 162 } |
183 | 163 |
184 bool SendKeyPressImpl(app::KeyboardCode key, | 164 bool SendKeyPressImpl(app::KeyboardCode key, |
185 bool control, bool shift, bool alt, | 165 bool control, bool shift, bool alt, |
186 Task* task) { | 166 Task* task) { |
187 base::TimeTicks start_time = base::TimeTicks::Now(); | |
188 Checkpoint("SendKeyPressImpl starts", start_time); | |
189 | |
190 scoped_refptr<InputDispatcher> dispatcher( | 167 scoped_refptr<InputDispatcher> dispatcher( |
191 task ? new InputDispatcher(task, WM_KEYUP) : NULL); | 168 task ? new InputDispatcher(task, WM_KEYUP) : NULL); |
192 | 169 |
193 // If a pop-up menu is open, it won't receive events sent using SendInput. | 170 // If a pop-up menu is open, it won't receive events sent using SendInput. |
194 // Check for a pop-up menu using its window class (#32768) and if one | 171 // Check for a pop-up menu using its window class (#32768) and if one |
195 // exists, send the key event directly there. | 172 // exists, send the key event directly there. |
196 Checkpoint("FindWindow", start_time); | |
197 HWND popup_menu = ::FindWindow(L"#32768", 0); | 173 HWND popup_menu = ::FindWindow(L"#32768", 0); |
198 if (popup_menu != NULL && popup_menu == ::GetTopWindow(NULL)) { | 174 if (popup_menu != NULL && popup_menu == ::GetTopWindow(NULL)) { |
199 Checkpoint("Found popup window", start_time); | |
200 WPARAM w_param = app::WindowsKeyCodeForKeyboardCode(key); | 175 WPARAM w_param = app::WindowsKeyCodeForKeyboardCode(key); |
201 LPARAM l_param = 0; | 176 LPARAM l_param = 0; |
202 Checkpoint("Send WM_KEYDOWN", start_time); | |
203 ::SendMessage(popup_menu, WM_KEYDOWN, w_param, l_param); | 177 ::SendMessage(popup_menu, WM_KEYDOWN, w_param, l_param); |
204 Checkpoint("Send WM_KEYUP", start_time); | |
205 ::SendMessage(popup_menu, WM_KEYUP, w_param, l_param); | 178 ::SendMessage(popup_menu, WM_KEYUP, w_param, l_param); |
206 | 179 |
207 Checkpoint("Send Done", start_time); | |
208 if (dispatcher.get()) | 180 if (dispatcher.get()) |
209 dispatcher->AddRef(); | 181 dispatcher->AddRef(); |
210 return true; | 182 return true; |
211 } | 183 } |
212 | 184 |
213 Checkpoint("Found no popup window", start_time); | |
214 | |
215 INPUT input[8] = { 0 }; // 8, assuming all the modifiers are activated | 185 INPUT input[8] = { 0 }; // 8, assuming all the modifiers are activated |
216 | 186 |
217 UINT i = 0; | 187 UINT i = 0; |
218 if (control) { | 188 if (control) { |
219 Checkpoint("FillKeyboardInput Control", start_time); | |
220 if (!FillKeyboardInput(app::VKEY_CONTROL, &input[i], false)) | 189 if (!FillKeyboardInput(app::VKEY_CONTROL, &input[i], false)) |
221 return false; | 190 return false; |
222 i++; | 191 i++; |
223 } | 192 } |
224 | 193 |
225 if (shift) { | 194 if (shift) { |
226 Checkpoint("FillKeyboardInput Shift", start_time); | |
227 if (!FillKeyboardInput(app::VKEY_SHIFT, &input[i], false)) | 195 if (!FillKeyboardInput(app::VKEY_SHIFT, &input[i], false)) |
228 return false; | 196 return false; |
229 i++; | 197 i++; |
230 } | 198 } |
231 | 199 |
232 if (alt) { | 200 if (alt) { |
233 Checkpoint("FillKeyboardInput Alt", start_time); | |
234 if (!FillKeyboardInput(app::VKEY_MENU, &input[i], false)) | 201 if (!FillKeyboardInput(app::VKEY_MENU, &input[i], false)) |
235 return false; | 202 return false; |
236 i++; | 203 i++; |
237 } | 204 } |
238 | 205 |
239 Checkpoint("FillKeyboardInput 1", start_time); | |
240 if (!FillKeyboardInput(key, &input[i], false)) | 206 if (!FillKeyboardInput(key, &input[i], false)) |
241 return false; | 207 return false; |
242 i++; | 208 i++; |
243 | 209 |
244 Checkpoint("FillKeyboardInput 2", start_time); | |
245 if (!FillKeyboardInput(key, &input[i], true)) | 210 if (!FillKeyboardInput(key, &input[i], true)) |
246 return false; | 211 return false; |
247 i++; | 212 i++; |
248 | 213 |
249 if (alt) { | 214 if (alt) { |
250 Checkpoint("FillKeyboardInput Alt2", start_time); | |
251 if (!FillKeyboardInput(app::VKEY_MENU, &input[i], true)) | 215 if (!FillKeyboardInput(app::VKEY_MENU, &input[i], true)) |
252 return false; | 216 return false; |
253 i++; | 217 i++; |
254 } | 218 } |
255 | 219 |
256 if (shift) { | 220 if (shift) { |
257 Checkpoint("FillKeyboardInput Shift2", start_time); | |
258 if (!FillKeyboardInput(app::VKEY_SHIFT, &input[i], true)) | 221 if (!FillKeyboardInput(app::VKEY_SHIFT, &input[i], true)) |
259 return false; | 222 return false; |
260 i++; | 223 i++; |
261 } | 224 } |
262 | 225 |
263 if (control) { | 226 if (control) { |
264 Checkpoint("FillKeyboardInput Ctrl2", start_time); | |
265 if (!FillKeyboardInput(app::VKEY_CONTROL, &input[i], true)) | 227 if (!FillKeyboardInput(app::VKEY_CONTROL, &input[i], true)) |
266 return false; | 228 return false; |
267 i++; | 229 i++; |
268 } | 230 } |
269 | 231 |
270 Checkpoint("SendInput called", start_time); | |
271 if (::SendInput(i, input, sizeof(INPUT)) != i) | 232 if (::SendInput(i, input, sizeof(INPUT)) != i) |
272 return false; | 233 return false; |
273 | 234 |
274 Checkpoint("SendInput done", start_time); | |
275 | |
276 if (dispatcher.get()) | 235 if (dispatcher.get()) |
277 dispatcher->AddRef(); | 236 dispatcher->AddRef(); |
278 | 237 |
279 Checkpoint("Test done", start_time); | |
280 return true; | 238 return true; |
281 } | 239 } |
282 | 240 |
283 bool SendMouseMoveImpl(long x, long y, Task* task) { | 241 bool SendMouseMoveImpl(long x, long y, Task* task) { |
284 // First check if the mouse is already there. | 242 // First check if the mouse is already there. |
285 POINT current_pos; | 243 POINT current_pos; |
286 ::GetCursorPos(¤t_pos); | 244 ::GetCursorPos(¤t_pos); |
287 if (x == current_pos.x && y == current_pos.y) { | 245 if (x == current_pos.x && y == current_pos.y) { |
288 if (task) | 246 if (task) |
289 MessageLoop::current()->PostTask(FROM_HERE, task); | 247 MessageLoop::current()->PostTask(FROM_HERE, task); |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
405 int state, Task* task) { | 363 int state, Task* task) { |
406 DCHECK(view); | 364 DCHECK(view); |
407 DCHECK(view->GetWidget()); | 365 DCHECK(view->GetWidget()); |
408 gfx::Point view_center(view->width() / 2, view->height() / 2); | 366 gfx::Point view_center(view->width() / 2, view->height() / 2); |
409 views::View::ConvertPointToScreen(view, &view_center); | 367 views::View::ConvertPointToScreen(view, &view_center); |
410 SendMouseMove(view_center.x(), view_center.y()); | 368 SendMouseMove(view_center.x(), view_center.y()); |
411 SendMouseEventsNotifyWhenDone(button, state, task); | 369 SendMouseEventsNotifyWhenDone(button, state, task); |
412 } | 370 } |
413 | 371 |
414 } // ui_controls | 372 } // ui_controls |
OLD | NEW |