Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(128)

Side by Side Diff: chrome/browser/automation/ui_controls_win.cc

Issue 8212006: base::Bind: Cleanup in automation. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Review fixes. Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 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 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 "base/bind.h"
8 #include "base/callback.h"
7 #include "base/logging.h" 9 #include "base/logging.h"
8 #include "base/memory/ref_counted.h" 10 #include "base/memory/ref_counted.h"
9 #include "base/message_loop.h" 11 #include "base/message_loop.h"
10 #include "base/task.h" 12 #include "base/task.h"
11 #include "ui/base/keycodes/keyboard_codes.h" 13 #include "ui/base/keycodes/keyboard_codes.h"
12 #include "ui/base/keycodes/keyboard_code_conversion_win.h" 14 #include "ui/base/keycodes/keyboard_code_conversion_win.h"
13 #include "views/view.h" 15 #include "views/view.h"
14 16
15 namespace ui_controls { 17 namespace ui_controls {
16 18
17 namespace { 19 namespace {
18 20
19 // InputDispatcher ------------------------------------------------------------ 21 // InputDispatcher ------------------------------------------------------------
20 22
21 // InputDispatcher is used to listen for a mouse/keyboard event. When the 23 // InputDispatcher is used to listen for a mouse/keyboard event. When the
22 // appropriate event is received the task is notified. 24 // appropriate event is received the task is notified.
23 class InputDispatcher : public base::RefCounted<InputDispatcher> { 25 class InputDispatcher : public base::RefCounted<InputDispatcher> {
24 public: 26 public:
25 InputDispatcher(Task* task, WPARAM message_waiting_for); 27 InputDispatcher(const base::Closure& task, WPARAM message_waiting_for);
26 28
27 // Invoked from the hook. If mouse_message matches message_waiting_for_ 29 // Invoked from the hook. If mouse_message matches message_waiting_for_
28 // MatchingMessageFound is invoked. 30 // MatchingMessageFound is invoked.
29 void DispatchedMessage(WPARAM mouse_message); 31 void DispatchedMessage(WPARAM mouse_message);
30 32
31 // Invoked when a matching event is found. Uninstalls the hook and schedules 33 // Invoked when a matching event is found. Uninstalls the hook and schedules
32 // an event that notifies the task. 34 // an event that notifies the task.
33 void MatchingMessageFound(); 35 void MatchingMessageFound();
34 36
35 private: 37 private:
36 friend class base::RefCounted<InputDispatcher>; 38 friend class base::RefCounted<InputDispatcher>;
37 39
38 ~InputDispatcher(); 40 ~InputDispatcher();
39 41
40 // Notifies the task and release this (which should delete it). 42 // Notifies the task and release this (which should delete it).
41 void NotifyTask(); 43 void NotifyTask();
42 44
43 // The task we notify. 45 // The task we notify.
44 scoped_ptr<Task> task_; 46 base::Closure task_;
45 47
46 // Message we're waiting for. Not used for keyboard events. 48 // Message we're waiting for. Not used for keyboard events.
47 const WPARAM message_waiting_for_; 49 const WPARAM message_waiting_for_;
48 50
49 DISALLOW_COPY_AND_ASSIGN(InputDispatcher); 51 DISALLOW_COPY_AND_ASSIGN(InputDispatcher);
50 }; 52 };
51 53
52 // Have we installed the hook? 54 // Have we installed the hook?
53 bool installed_hook_ = false; 55 bool installed_hook_ = false;
54 56
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
100 102
101 // Uninstalls the hook set in InstallHook. 103 // Uninstalls the hook set in InstallHook.
102 void UninstallHook(InputDispatcher* dispatcher) { 104 void UninstallHook(InputDispatcher* dispatcher) {
103 if (current_dispatcher_ == dispatcher) { 105 if (current_dispatcher_ == dispatcher) {
104 installed_hook_ = false; 106 installed_hook_ = false;
105 current_dispatcher_ = NULL; 107 current_dispatcher_ = NULL;
106 UnhookWindowsHookEx(next_hook_); 108 UnhookWindowsHookEx(next_hook_);
107 } 109 }
108 } 110 }
109 111
110 InputDispatcher::InputDispatcher(Task* task, UINT message_waiting_for) 112 InputDispatcher::InputDispatcher(const base::Closure& task,
113 UINT message_waiting_for)
111 : task_(task), message_waiting_for_(message_waiting_for) { 114 : task_(task), message_waiting_for_(message_waiting_for) {
112 InstallHook(this, message_waiting_for == WM_KEYUP); 115 InstallHook(this, message_waiting_for == WM_KEYUP);
113 } 116 }
114 117
115 InputDispatcher::~InputDispatcher() { 118 InputDispatcher::~InputDispatcher() {
116 // Make sure the hook isn't installed. 119 // Make sure the hook isn't installed.
117 UninstallHook(this); 120 UninstallHook(this);
118 } 121 }
119 122
120 void InputDispatcher::DispatchedMessage(WPARAM message) { 123 void InputDispatcher::DispatchedMessage(WPARAM message) {
121 if (message == message_waiting_for_) 124 if (message == message_waiting_for_)
122 MatchingMessageFound(); 125 MatchingMessageFound();
123 } 126 }
124 127
125 void InputDispatcher::MatchingMessageFound() { 128 void InputDispatcher::MatchingMessageFound() {
126 UninstallHook(this); 129 UninstallHook(this);
127 // At the time we're invoked the event has not actually been processed. 130 // At the time we're invoked the event has not actually been processed.
128 // Use PostTask to make sure the event has been processed before notifying. 131 // Use PostTask to make sure the event has been processed before notifying.
129 MessageLoop::current()->PostDelayedTask( 132 MessageLoop::current()->PostTask(
130 FROM_HERE, NewRunnableMethod(this, &InputDispatcher::NotifyTask), 0); 133 FROM_HERE, base::Bind(&InputDispatcher::NotifyTask, this));
131 } 134 }
132 135
133 void InputDispatcher::NotifyTask() { 136 void InputDispatcher::NotifyTask() {
134 task_->Run(); 137 task_.Run();
135 Release(); 138 Release();
136 } 139 }
137 140
138 // Private functions ---------------------------------------------------------- 141 // Private functions ----------------------------------------------------------
139 142
140 // Populate the INPUT structure with the appropriate keyboard event 143 // Populate the INPUT structure with the appropriate keyboard event
141 // parameters required by SendInput 144 // parameters required by SendInput
142 bool FillKeyboardInput(ui::KeyboardCode key, INPUT* input, bool key_up) { 145 bool FillKeyboardInput(ui::KeyboardCode key, INPUT* input, bool key_up) {
143 memset(input, 0, sizeof(INPUT)); 146 memset(input, 0, sizeof(INPUT));
144 input->type = INPUT_KEYBOARD; 147 input->type = INPUT_KEYBOARD;
(...skipping 12 matching lines...) Expand all
157 return false; 160 return false;
158 161
159 if (!::SendInput(1, &input, sizeof(INPUT))) 162 if (!::SendInput(1, &input, sizeof(INPUT)))
160 return false; 163 return false;
161 164
162 return true; 165 return true;
163 } 166 }
164 167
165 bool SendKeyPressImpl(ui::KeyboardCode key, 168 bool SendKeyPressImpl(ui::KeyboardCode key,
166 bool control, bool shift, bool alt, 169 bool control, bool shift, bool alt,
167 Task* task) { 170 const base::Closure& task) {
168 scoped_refptr<InputDispatcher> dispatcher( 171 scoped_refptr<InputDispatcher> dispatcher(
169 task ? new InputDispatcher(task, WM_KEYUP) : NULL); 172 !task.is_null() ? new InputDispatcher(task, WM_KEYUP) : NULL);
170 173
171 // If a pop-up menu is open, it won't receive events sent using SendInput. 174 // If a pop-up menu is open, it won't receive events sent using SendInput.
172 // Check for a pop-up menu using its window class (#32768) and if one 175 // Check for a pop-up menu using its window class (#32768) and if one
173 // exists, send the key event directly there. 176 // exists, send the key event directly there.
174 HWND popup_menu = ::FindWindow(L"#32768", 0); 177 HWND popup_menu = ::FindWindow(L"#32768", 0);
175 if (popup_menu != NULL && popup_menu == ::GetTopWindow(NULL)) { 178 if (popup_menu != NULL && popup_menu == ::GetTopWindow(NULL)) {
176 WPARAM w_param = ui::WindowsKeyCodeForKeyboardCode(key); 179 WPARAM w_param = ui::WindowsKeyCodeForKeyboardCode(key);
177 LPARAM l_param = 0; 180 LPARAM l_param = 0;
178 ::SendMessage(popup_menu, WM_KEYDOWN, w_param, l_param); 181 ::SendMessage(popup_menu, WM_KEYDOWN, w_param, l_param);
179 ::SendMessage(popup_menu, WM_KEYUP, w_param, l_param); 182 ::SendMessage(popup_menu, WM_KEYUP, w_param, l_param);
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
232 235
233 if (::SendInput(i, input, sizeof(INPUT)) != i) 236 if (::SendInput(i, input, sizeof(INPUT)) != i)
234 return false; 237 return false;
235 238
236 if (dispatcher.get()) 239 if (dispatcher.get())
237 dispatcher->AddRef(); 240 dispatcher->AddRef();
238 241
239 return true; 242 return true;
240 } 243 }
241 244
242 bool SendMouseMoveImpl(long x, long y, Task* task) { 245 bool SendMouseMoveImpl(long x, long y, const base::Closure& task) {
243 // First check if the mouse is already there. 246 // First check if the mouse is already there.
244 POINT current_pos; 247 POINT current_pos;
245 ::GetCursorPos(&current_pos); 248 ::GetCursorPos(&current_pos);
246 if (x == current_pos.x && y == current_pos.y) { 249 if (x == current_pos.x && y == current_pos.y) {
247 if (task) 250 if (!task.is_null())
248 MessageLoop::current()->PostTask(FROM_HERE, task); 251 MessageLoop::current()->PostTask(FROM_HERE, task);
249 return true; 252 return true;
250 } 253 }
251 254
252 INPUT input = { 0 }; 255 INPUT input = { 0 };
253 256
254 int screen_width = ::GetSystemMetrics(SM_CXSCREEN) - 1; 257 int screen_width = ::GetSystemMetrics(SM_CXSCREEN) - 1;
255 int screen_height = ::GetSystemMetrics(SM_CYSCREEN) - 1; 258 int screen_height = ::GetSystemMetrics(SM_CYSCREEN) - 1;
256 LONG pixel_x = static_cast<LONG>(x * (65535.0f / screen_width)); 259 LONG pixel_x = static_cast<LONG>(x * (65535.0f / screen_width));
257 LONG pixel_y = static_cast<LONG>(y * (65535.0f / screen_height)); 260 LONG pixel_y = static_cast<LONG>(y * (65535.0f / screen_height));
258 261
259 input.type = INPUT_MOUSE; 262 input.type = INPUT_MOUSE;
260 input.mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE; 263 input.mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE;
261 input.mi.dx = pixel_x; 264 input.mi.dx = pixel_x;
262 input.mi.dy = pixel_y; 265 input.mi.dy = pixel_y;
263 266
264 scoped_refptr<InputDispatcher> dispatcher( 267 scoped_refptr<InputDispatcher> dispatcher(
265 task ? new InputDispatcher(task, WM_MOUSEMOVE) : NULL); 268 !task.is_null() ? new InputDispatcher(task, WM_MOUSEMOVE) : NULL);
266 269
267 if (!::SendInput(1, &input, sizeof(INPUT))) 270 if (!::SendInput(1, &input, sizeof(INPUT)))
268 return false; 271 return false;
269 272
270 if (dispatcher.get()) 273 if (dispatcher.get())
271 dispatcher->AddRef(); 274 dispatcher->AddRef();
272 275
273 return true; 276 return true;
274 } 277 }
275 278
276 bool SendMouseEventsImpl(MouseButton type, int state, Task* task) { 279 bool SendMouseEventsImpl(MouseButton type, int state,
280 const base::Closure& task) {
277 DWORD down_flags = MOUSEEVENTF_ABSOLUTE; 281 DWORD down_flags = MOUSEEVENTF_ABSOLUTE;
278 DWORD up_flags = MOUSEEVENTF_ABSOLUTE; 282 DWORD up_flags = MOUSEEVENTF_ABSOLUTE;
279 UINT last_event; 283 UINT last_event;
280 284
281 switch (type) { 285 switch (type) {
282 case LEFT: 286 case LEFT:
283 down_flags |= MOUSEEVENTF_LEFTDOWN; 287 down_flags |= MOUSEEVENTF_LEFTDOWN;
284 up_flags |= MOUSEEVENTF_LEFTUP; 288 up_flags |= MOUSEEVENTF_LEFTUP;
285 last_event = (state & UP) ? WM_LBUTTONUP : WM_LBUTTONDOWN; 289 last_event = (state & UP) ? WM_LBUTTONUP : WM_LBUTTONDOWN;
286 break; 290 break;
287 291
288 case MIDDLE: 292 case MIDDLE:
289 down_flags |= MOUSEEVENTF_MIDDLEDOWN; 293 down_flags |= MOUSEEVENTF_MIDDLEDOWN;
290 up_flags |= MOUSEEVENTF_MIDDLEUP; 294 up_flags |= MOUSEEVENTF_MIDDLEUP;
291 last_event = (state & UP) ? WM_MBUTTONUP : WM_MBUTTONDOWN; 295 last_event = (state & UP) ? WM_MBUTTONUP : WM_MBUTTONDOWN;
292 break; 296 break;
293 297
294 case RIGHT: 298 case RIGHT:
295 down_flags |= MOUSEEVENTF_RIGHTDOWN; 299 down_flags |= MOUSEEVENTF_RIGHTDOWN;
296 up_flags |= MOUSEEVENTF_RIGHTUP; 300 up_flags |= MOUSEEVENTF_RIGHTUP;
297 last_event = (state & UP) ? WM_RBUTTONUP : WM_RBUTTONDOWN; 301 last_event = (state & UP) ? WM_RBUTTONUP : WM_RBUTTONDOWN;
298 break; 302 break;
299 303
300 default: 304 default:
301 NOTREACHED(); 305 NOTREACHED();
302 return false; 306 return false;
303 } 307 }
304 308
305 scoped_refptr<InputDispatcher> dispatcher( 309 scoped_refptr<InputDispatcher> dispatcher(
306 task ? new InputDispatcher(task, last_event) : NULL); 310 !task.is_null() ? new InputDispatcher(task, last_event) : NULL);
307 311
308 INPUT input = { 0 }; 312 INPUT input = { 0 };
309 input.type = INPUT_MOUSE; 313 input.type = INPUT_MOUSE;
310 input.mi.dwFlags = down_flags; 314 input.mi.dwFlags = down_flags;
311 if ((state & DOWN) && !::SendInput(1, &input, sizeof(INPUT))) 315 if ((state & DOWN) && !::SendInput(1, &input, sizeof(INPUT)))
312 return false; 316 return false;
313 317
314 input.mi.dwFlags = up_flags; 318 input.mi.dwFlags = up_flags;
315 if ((state & UP) && !::SendInput(1, &input, sizeof(INPUT))) 319 if ((state & UP) && !::SendInput(1, &input, sizeof(INPUT)))
316 return false; 320 return false;
317 321
318 if (dispatcher.get()) 322 if (dispatcher.get())
319 dispatcher->AddRef(); 323 dispatcher->AddRef();
320 324
321 return true; 325 return true;
322 } 326 }
323 327
324 } // namespace 328 } // namespace
325 329
326 // public functions ----------------------------------------------------------- 330 // public functions -----------------------------------------------------------
327 331
328 bool SendKeyPress(gfx::NativeWindow window, 332 bool SendKeyPress(gfx::NativeWindow window,
329 ui::KeyboardCode key, 333 ui::KeyboardCode key,
330 bool control, 334 bool control,
331 bool shift, 335 bool shift,
332 bool alt, 336 bool alt,
333 bool command) { 337 bool command) {
334 DCHECK(!command); // No command key on Windows 338 DCHECK(!command); // No command key on Windows
335 return SendKeyPressImpl(key, control, shift, alt, NULL); 339 return SendKeyPressImpl(key, control, shift, alt, base::Closure());
336 } 340 }
337 341
338 bool SendKeyPressNotifyWhenDone(gfx::NativeWindow window, 342 bool SendKeyPressNotifyWhenDone(gfx::NativeWindow window,
339 ui::KeyboardCode key, 343 ui::KeyboardCode key,
340 bool control, 344 bool control,
341 bool shift, 345 bool shift,
342 bool alt, 346 bool alt,
343 bool command, 347 bool command,
344 Task* task) { 348 const base::Closure& task) {
345 DCHECK(!command); // No command key on Windows 349 DCHECK(!command); // No command key on Windows
346 return SendKeyPressImpl(key, control, shift, alt, task); 350 return SendKeyPressImpl(key, control, shift, alt, task);
347 } 351 }
348 352
349 bool SendMouseMove(long x, long y) { 353 bool SendMouseMove(long x, long y) {
350 return SendMouseMoveImpl(x, y, NULL); 354 return SendMouseMoveImpl(x, y, base::Closure());
351 } 355 }
352 356
353 bool SendMouseMoveNotifyWhenDone(long x, long y, Task* task) { 357 bool SendMouseMoveNotifyWhenDone(long x, long y, const base::Closure& task) {
354 return SendMouseMoveImpl(x, y, task); 358 return SendMouseMoveImpl(x, y, task);
355 } 359 }
356 360
357 bool SendMouseEvents(MouseButton type, int state) { 361 bool SendMouseEvents(MouseButton type, int state) {
358 return SendMouseEventsImpl(type, state, NULL); 362 return SendMouseEventsImpl(type, state, base::Closure());
359 } 363 }
360 364
361 bool SendMouseEventsNotifyWhenDone(MouseButton type, int state, Task* task) { 365 bool SendMouseEventsNotifyWhenDone(MouseButton type, int state,
366 const base::Closure& task) {
362 return SendMouseEventsImpl(type, state, task); 367 return SendMouseEventsImpl(type, state, task);
363 } 368 }
364 369
365 bool SendMouseClick(MouseButton type) { 370 bool SendMouseClick(MouseButton type) {
366 return SendMouseEventsImpl(type, UP | DOWN, NULL); 371 return SendMouseEventsImpl(type, UP | DOWN, base::Closure());
367 } 372 }
368 373
369 void MoveMouseToCenterAndPress(views::View* view, 374 void MoveMouseToCenterAndPress(views::View* view,
370 MouseButton button, 375 MouseButton button,
371 int state, 376 int state,
372 Task* task) { 377 const base::Closure& task) {
373 DCHECK(view); 378 DCHECK(view);
374 DCHECK(view->GetWidget()); 379 DCHECK(view->GetWidget());
375 gfx::Point view_center(view->width() / 2, view->height() / 2); 380 gfx::Point view_center(view->width() / 2, view->height() / 2);
376 views::View::ConvertPointToScreen(view, &view_center); 381 views::View::ConvertPointToScreen(view, &view_center);
377 SendMouseMove(view_center.x(), view_center.y()); 382 SendMouseMove(view_center.x(), view_center.y());
378 SendMouseEventsNotifyWhenDone(button, state, task); 383 SendMouseEventsNotifyWhenDone(button, state, task);
379 } 384 }
380 385
381 } // ui_controls 386 } // ui_controls
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698