OLD | NEW |
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 #import <Cocoa/Cocoa.h> | 7 #import <Cocoa/Cocoa.h> |
8 #include <mach/mach_time.h> | 8 #include <mach/mach_time.h> |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
| 11 #include "base/callback.h" |
11 #include "base/message_loop.h" | 12 #include "base/message_loop.h" |
12 #include "chrome/browser/automation/ui_controls_internal.h" | 13 #include "chrome/browser/automation/ui_controls_internal.h" |
13 #include "content/browser/browser_thread.h" | 14 #include "content/browser/browser_thread.h" |
14 #include "ui/base/keycodes/keyboard_code_conversion_mac.h" | 15 #include "ui/base/keycodes/keyboard_code_conversion_mac.h" |
15 | 16 |
16 // Implementation details: We use [NSApplication sendEvent:] instead | 17 // Implementation details: We use [NSApplication sendEvent:] instead |
17 // of [NSApplication postEvent:atStart:] so that the event gets sent | 18 // of [NSApplication postEvent:atStart:] so that the event gets sent |
18 // immediately. This lets us run the post-event task right | 19 // immediately. This lets us run the post-event task right |
19 // immediately as well. Unfortunately I cannot subclass NSEvent (it's | 20 // immediately as well. Unfortunately I cannot subclass NSEvent (it's |
20 // probably a class cluster) to allow other easy answers. For | 21 // probably a class cluster) to allow other easy answers. For |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
182 if (control) { | 183 if (control) { |
183 flags &= ~NSControlKeyMask; | 184 flags &= ~NSControlKeyMask; |
184 event = SynthesizeKeyEvent(window, false, ui::VKEY_CONTROL, flags); | 185 event = SynthesizeKeyEvent(window, false, ui::VKEY_CONTROL, flags); |
185 DCHECK(event); | 186 DCHECK(event); |
186 events->push_back(event); | 187 events->push_back(event); |
187 } | 188 } |
188 } | 189 } |
189 | 190 |
190 // A task class to watch for the event queue. The specific task will be fired | 191 // A task class to watch for the event queue. The specific task will be fired |
191 // when there is no more event in the queue. | 192 // when there is no more event in the queue. |
192 class EventQueueWatcher : public Task { | 193 class EventQueueWatcher : public base::Closure { |
193 public: | 194 public: |
194 EventQueueWatcher(Task* task) : task_(task) {} | 195 EventQueueWatcher(const base::Closure& task) : task_(task) {} |
195 | |
196 virtual ~EventQueueWatcher() {} | 196 virtual ~EventQueueWatcher() {} |
197 | 197 |
198 virtual void Run() { | 198 virtual void Run() { |
199 NSEvent* event = [NSApp nextEventMatchingMask:NSAnyEventMask | 199 NSEvent* event = [NSApp nextEventMatchingMask:NSAnyEventMask |
200 untilDate:nil | 200 untilDate:nil |
201 inMode:NSDefaultRunLoopMode | 201 inMode:NSDefaultRunLoopMode |
202 dequeue:NO]; | 202 dequeue:NO]; |
203 // If there is still event in the queue, then we need to check again. | 203 // If there is still event in the queue, then we need to check again. |
204 if (event) | 204 if (event) |
205 MessageLoop::current()->PostTask(FROM_HERE, new EventQueueWatcher(task_)); | 205 MessageLoop::current()->PostTask(FROM_HERE, EventQueueWatcher(task_)); |
206 else | 206 else |
207 MessageLoop::current()->PostTask(FROM_HERE, task_); | 207 MessageLoop::current()->PostTask(FROM_HERE, task_); |
208 } | 208 } |
209 | 209 |
210 private: | 210 private: |
211 Task* task_; | 211 base::Closure task_; |
212 }; | 212 }; |
213 | 213 |
214 // Stores the current mouse location on the screen. So that we can use it | 214 // Stores the current mouse location on the screen. So that we can use it |
215 // when firing keyboard and mouse click events. | 215 // when firing keyboard and mouse click events. |
216 NSPoint g_mouse_location = { 0, 0 }; | 216 NSPoint g_mouse_location = { 0, 0 }; |
217 | 217 |
218 } // anonymous namespace | 218 } // anonymous namespace |
219 | 219 |
220 | 220 |
221 namespace ui_controls { | 221 namespace ui_controls { |
222 | 222 |
223 bool SendKeyPress(gfx::NativeWindow window, | 223 bool SendKeyPress(gfx::NativeWindow window, |
224 ui::KeyboardCode key, | 224 ui::KeyboardCode key, |
225 bool control, | 225 bool control, |
226 bool shift, | 226 bool shift, |
227 bool alt, | 227 bool alt, |
228 bool command) { | 228 bool command) { |
229 return SendKeyPressNotifyWhenDone(window, key, | 229 return SendKeyPressNotifyWhenDone(window, key, |
230 control, shift, alt, command, | 230 control, shift, alt, command, |
231 NULL); | 231 base::Closure()); |
232 } | 232 } |
233 | 233 |
234 // Win and Linux implement a SendKeyPress() this as a | 234 // Win and Linux implement a SendKeyPress() this as a |
235 // SendKeyPressAndRelease(), so we should as well (despite the name). | 235 // SendKeyPressAndRelease(), so we should as well (despite the name). |
236 bool SendKeyPressNotifyWhenDone(gfx::NativeWindow window, | 236 bool SendKeyPressNotifyWhenDone(gfx::NativeWindow window, |
237 ui::KeyboardCode key, | 237 ui::KeyboardCode key, |
238 bool control, | 238 bool control, |
239 bool shift, | 239 bool shift, |
240 bool alt, | 240 bool alt, |
241 bool command, | 241 bool command, |
242 Task* task) { | 242 const base::Closure& task) { |
243 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 243 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
244 | 244 |
245 std::vector<NSEvent*> events; | 245 std::vector<NSEvent*> events; |
246 SynthesizeKeyEventsSequence( | 246 SynthesizeKeyEventsSequence( |
247 window, key, control, shift, alt, command, &events); | 247 window, key, control, shift, alt, command, &events); |
248 | 248 |
249 // TODO(suzhe): Using [NSApplication postEvent:atStart:] here causes | 249 // TODO(suzhe): Using [NSApplication postEvent:atStart:] here causes |
250 // BrowserKeyEventsTest.CommandKeyEvents to fail. See http://crbug.com/49270 | 250 // BrowserKeyEventsTest.CommandKeyEvents to fail. See http://crbug.com/49270 |
251 // But using [NSApplication sendEvent:] should be safe for keyboard events, | 251 // But using [NSApplication sendEvent:] should be safe for keyboard events, |
252 // because until now, no code wants to retrieve the next event when handling | 252 // because until now, no code wants to retrieve the next event when handling |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
354 } | 354 } |
355 | 355 |
356 bool SendMouseClick(MouseButton type) { | 356 bool SendMouseClick(MouseButton type) { |
357 return SendMouseEventsNotifyWhenDone(type, UP|DOWN, NULL); | 357 return SendMouseEventsNotifyWhenDone(type, UP|DOWN, NULL); |
358 } | 358 } |
359 | 359 |
360 void MoveMouseToCenterAndPress( | 360 void MoveMouseToCenterAndPress( |
361 NSView* view, | 361 NSView* view, |
362 MouseButton button, | 362 MouseButton button, |
363 int state, | 363 int state, |
364 Task* task) { | 364 const base::Closure& task) { |
365 DCHECK(view); | 365 DCHECK(view); |
366 NSWindow* window = [view window]; | 366 NSWindow* window = [view window]; |
367 DCHECK(window); | 367 DCHECK(window); |
368 NSScreen* screen = [window screen]; | 368 NSScreen* screen = [window screen]; |
369 DCHECK(screen); | 369 DCHECK(screen); |
370 | 370 |
371 // Converts the center position of the view into the coordinates accepted | 371 // Converts the center position of the view into the coordinates accepted |
372 // by SendMouseMoveNotifyWhenDone() method. | 372 // by SendMouseMoveNotifyWhenDone() method. |
373 NSRect bounds = [view bounds]; | 373 NSRect bounds = [view bounds]; |
374 NSPoint center = NSMakePoint(NSMidX(bounds), NSMidY(bounds)); | 374 NSPoint center = NSMakePoint(NSMidX(bounds), NSMidY(bounds)); |
375 center = [view convertPoint:center toView:nil]; | 375 center = [view convertPoint:center toView:nil]; |
376 center = [window convertBaseToScreen:center]; | 376 center = [window convertBaseToScreen:center]; |
377 center = NSMakePoint(center.x, [screen frame].size.height - center.y); | 377 center = NSMakePoint(center.x, [screen frame].size.height - center.y); |
378 | 378 |
379 SendMouseMoveNotifyWhenDone(center.x, center.y, | 379 SendMouseMoveNotifyWhenDone(center.x, center.y, |
380 new ClickTask(button, state, task)); | 380 ClickTask(button, state, task)); |
381 } | 381 } |
382 | 382 |
383 } // ui_controls | 383 } // ui_controls |
OLD | NEW |