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