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

Side by Side Diff: ui/base/test/ui_controls_mac.mm

Issue 1877043003: [EXPERIMENT] MacViews: Implement Tab Dragging Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: git cl format Created 4 years, 8 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
« no previous file with comments | « ui/base/test/ui_controls.h ('k') | ui/gfx/geometry/rect.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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 "ui/base/test/ui_controls.h" 5 #include "ui/base/test/ui_controls.h"
6 6
7 #import <Cocoa/Cocoa.h> 7 #import <Cocoa/Cocoa.h>
8 #include <memory>
8 #include <vector> 9 #include <vector>
9 10
10 #include "base/bind.h" 11 #include "base/bind.h"
11 #include "base/callback.h" 12 #include "base/callback.h"
13 #import "base/mac/foundation_util.h"
14 #import "base/mac/scoped_nsobject.h"
15 #import "base/mac/scoped_objc_class_swizzler.h"
12 #include "base/message_loop/message_loop.h" 16 #include "base/message_loop/message_loop.h"
17 #include "base/thread_task_runner_handle.h"
13 #include "ui/base/cocoa/cocoa_base_utils.h" 18 #include "ui/base/cocoa/cocoa_base_utils.h"
14 #include "ui/events/keycodes/keyboard_code_conversion_mac.h" 19 #include "ui/events/keycodes/keyboard_code_conversion_mac.h"
15 #import "ui/events/test/cocoa_test_event_utils.h" 20 #import "ui/events/test/cocoa_test_event_utils.h"
21 #import "ui/gfx/mac/coordinate_conversion.h"
22 #include "ui/gfx/screen.h"
16 23
17 // Implementation details: We use [NSApplication sendEvent:] instead 24 // Implementation details: We use [NSApplication sendEvent:] instead
18 // of [NSApplication postEvent:atStart:] so that the event gets sent 25 // of [NSApplication postEvent:atStart:] so that the event gets sent
19 // immediately. This lets us run the post-event task right 26 // immediately. This lets us run the post-event task right
20 // immediately as well. Unfortunately I cannot subclass NSEvent (it's 27 // immediately as well. Unfortunately I cannot subclass NSEvent (it's
21 // probably a class cluster) to allow other easy answers. For 28 // probably a class cluster) to allow other easy answers. For
22 // example, if I could subclass NSEvent, I could run the Task in it's 29 // example, if I could subclass NSEvent, I could run the Task in it's
23 // dealloc routine (which necessarily happens after the event is 30 // dealloc routine (which necessarily happens after the event is
24 // dispatched). Unlike Linux, Mac does not have message loop 31 // dispatched). Unlike Linux, Mac does not have message loop
25 // observer/notification. Unlike windows, I cannot post non-events 32 // observer/notification. Unlike windows, I cannot post non-events
(...skipping 15 matching lines...) Expand all
41 // events causes BrowserKeyEventsTest.CommandKeyEvents to fail. 48 // events causes BrowserKeyEventsTest.CommandKeyEvents to fail.
42 // See http://crbug.com/49270 49 // See http://crbug.com/49270
43 // 2. On OSX 10.6, [NSEvent addLocalMonitorForEventsMatchingMask:handler:] may 50 // 2. On OSX 10.6, [NSEvent addLocalMonitorForEventsMatchingMask:handler:] may
44 // be used, so that we don't need to poll the event queue time to time. 51 // be used, so that we don't need to poll the event queue time to time.
45 52
46 using cocoa_test_event_utils::SynthesizeKeyEvent; 53 using cocoa_test_event_utils::SynthesizeKeyEvent;
47 using cocoa_test_event_utils::TimeIntervalSinceSystemStartup; 54 using cocoa_test_event_utils::TimeIntervalSinceSystemStartup;
48 55
49 namespace { 56 namespace {
50 57
58 // When enabled, all simulated mouse events will be posted to
59 // the WindowServer, and the actual mouse will move on the screen.
60 bool g_use_cgevents = false;
61
51 // Stores the current mouse location on the screen. So that we can use it 62 // Stores the current mouse location on the screen. So that we can use it
52 // when firing keyboard and mouse click events. 63 // when firing keyboard and mouse click events.
53 NSPoint g_mouse_location = { 0, 0 }; 64 NSPoint g_mouse_location = { 0, 0 };
54 65
66 // If enabled overrides results returned by +[NSEvent mouseLocation] and
67 // -[NSWindow mouseLocationOutsideOfEventStream]
68 NSPoint g_mouse_location_override = {0, 0};
69 bool g_mouse_location_override_enabled = false;
70
71 // Stores the current pressed mouse buttons. Indexed by
72 // ui_controls::MouseButton.
73 bool g_mouse_button_down[3] = {false, false, false};
74
55 bool g_ui_controls_enabled = false; 75 bool g_ui_controls_enabled = false;
56 76
57 // Creates the proper sequence of autoreleased key events for a key down + up. 77 // Creates the proper sequence of autoreleased key events for a key down + up.
58 void SynthesizeKeyEventsSequence(NSWindow* window, 78 void SynthesizeKeyEventsSequence(NSWindow* window,
59 ui::KeyboardCode keycode, 79 ui::KeyboardCode keycode,
60 bool control, 80 bool control,
61 bool shift, 81 bool shift,
62 bool alt, 82 bool alt,
63 bool command, 83 bool command,
64 std::vector<NSEvent*>* events) { 84 std::vector<NSEvent*>* events) {
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
115 events->push_back(event); 135 events->push_back(event);
116 } 136 }
117 if (control) { 137 if (control) {
118 flags &= ~NSControlKeyMask; 138 flags &= ~NSControlKeyMask;
119 event = SynthesizeKeyEvent(window, false, ui::VKEY_CONTROL, flags); 139 event = SynthesizeKeyEvent(window, false, ui::VKEY_CONTROL, flags);
120 DCHECK(event); 140 DCHECK(event);
121 events->push_back(event); 141 events->push_back(event);
122 } 142 }
123 } 143 }
124 144
145 void RunTaskInTaskRunner(
146 scoped_refptr<base::SingleThreadTaskRunner> task_runner,
147 const base::Closure& task) {
148 task_runner->PostTask(FROM_HERE, task);
149 }
150
125 // A helper function to watch for the event queue. The specific task will be 151 // A helper function to watch for the event queue. The specific task will be
126 // fired when there is no more event in the queue. 152 // fired when there is no more event in the queue.
127 void EventQueueWatcher(const base::Closure& task) { 153 void EventQueueWatcher(const base::Closure& task) {
154 DCHECK_EQ(dispatch_get_current_queue(), dispatch_get_main_queue())
155 << "It should be run on the UI thread, as otherwise it will always "
156 "report there are no pending events";
128 NSEvent* event = [NSApp nextEventMatchingMask:NSAnyEventMask 157 NSEvent* event = [NSApp nextEventMatchingMask:NSAnyEventMask
129 untilDate:nil 158 untilDate:nil
130 inMode:NSDefaultRunLoopMode 159 inMode:NSDefaultRunLoopMode
131 dequeue:NO]; 160 dequeue:NO];
132 // If there is still event in the queue, then we need to check again. 161 // If there is still event in the queue, then we need to check again.
133 if (event) { 162 if (event) {
134 base::MessageLoop::current()->PostTask( 163 base::MessageLoop::current()->PostTask(
135 FROM_HERE, 164 FROM_HERE,
136 base::Bind(&EventQueueWatcher, task)); 165 base::Bind(&EventQueueWatcher, task));
137 } else { 166 } else {
(...skipping 28 matching lines...) Expand all
166 return window; 195 return window;
167 } 196 }
168 197
169 // Note that -[NSApplication orderedWindows] won't include NSPanels. If a test 198 // Note that -[NSApplication orderedWindows] won't include NSPanels. If a test
170 // uses those, it will need to handle that itself. 199 // uses those, it will need to handle that itself.
171 return nil; 200 return nil;
172 } 201 }
173 202
174 } // namespace 203 } // namespace
175 204
205 // Since CGEvents take some time to reach -[NSApplication sendEvent:] we use
206 // this class to wait for the events to start being processed before sending
207 // finish notifications.
208 class EventMonitor {
209 public:
210 void NotifyWhenEventIsProcessed(NSEvent* event, const base::Closure& task) {
211 if (g_use_cgevents) {
212 CHECK([[NSApplication sharedApplication] isActive])
213 << "If we generate CGEvents and the application is not active, we'll "
214 "deadlock waiting for NSMouseMoved events. Use "
215 "ui_test_utils::BringBrowserWindowToFront() to activate the "
216 "browser window prior to generating CGEvents.";
217 }
218
219 base::AutoLock auto_lock(lock_);
220 tasks_.emplace_back(Task(event, task));
221 }
222
223 void ProcessingEvent(NSEvent* event) {
224 base::AutoLock auto_lock(lock_);
225 auto it = std::find_if(
226 tasks_.begin(), tasks_.end(),
227 [&event](const Task& task) { return task.MatchesEvent(event); });
228 if (it != tasks_.end()) {
229 it->Run();
230 tasks_.erase(it);
231 }
232 }
233
234 static EventMonitor* Instance() {
235 static EventMonitor* monitor = nullptr;
236 if (!monitor) {
237 monitor = new EventMonitor();
238 }
239 return monitor;
240 }
241
242 private:
243 class Task {
244 public:
245 Task(NSEvent* event, const base::Closure& task)
246 : task_runner_(base::ThreadTaskRunnerHandle::Get()),
247 event_([event retain]),
248 finish_closure_(task) {}
249
250 bool MatchesEvent(NSEvent* event) const {
251 // When moving the window using BridgedNativeWidget::RunMoveLoop the
252 // locationInWindow can be a little inconsistent with what we expect.
253 // Seems that only comparing event type is fine.
254 return
255 [event_ type] == [event type] && [event_ subtype] == [event subtype];
256 }
257
258 void Run() {
259 // We get here before the event is actually processed. Run the
260 // EventQueueWatcher on the main thread in order to wait for all events to
261 // finish processing.
262 base::MessageLoop::current()->PostTask(
263 FROM_HERE, base::Bind(&EventQueueWatcher,
264 base::Bind(&RunTaskInTaskRunner, task_runner_,
265 finish_closure_)));
266 }
267
268 private:
269 // Events could be spawned on background threads. Be sure to invoke the
270 // |finish_closure_| on an appropriate thread.
271 scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
272 base::scoped_nsobject<NSEvent> event_;
273 base::Closure finish_closure_;
274 };
275
276 EventMonitor()
277 : send_event_swizzler_(
278 new base::mac::ScopedObjCClassSwizzler([NSApplication class],
279 @selector(sendEvent:),
280 @selector(cr_sendEvent:))) {}
281
282 std::vector<Task> tasks_;
283
284 // synchronizes access to the |tasks_| in case we spawn the events on a
285 // different thread
286 base::Lock lock_;
287
288 std::unique_ptr<base::mac::ScopedObjCClassSwizzler> send_event_swizzler_;
289
290 DISALLOW_COPY_AND_ASSIGN(EventMonitor);
291 };
292
293 // Donates testing implementations of NSApplication methods. We can't simply
294 // use -[NSEvent addLocalMonitorForEventsMatchingMask:handler:], as other event
295 // monitors could have precedence, and they could filter the events before we
296 // can see them. But since nobody swizzles -[NSApplication sendEvent:] we should
297 // be safe.
298 @interface NSApplication (TestingDonor)
299 @end
300
301 @implementation NSApplication (TestingDonor)
302 - (void)cr_sendEvent:(NSEvent*)event {
303 // Invoke the finish handler before the event is processed, since we can get
304 // stuck in BridgedNativeWidget::RunMoveLoop and would never see the event
305 // otherwise.
306 EventMonitor::Instance()->ProcessingEvent(event);
307
308 [self cr_sendEvent:event];
309 }
310 @end
311
312 // Donates testing implementations of NSEvent methods.
313 @interface FakeNSEventTestingDonor : NSObject
314 @end
315
316 @implementation FakeNSEventTestingDonor
317 + (NSPoint)mouseLocation {
318 if (g_mouse_location_override_enabled)
319 return g_mouse_location_override;
320
321 return g_mouse_location;
322 }
323
324 + (NSUInteger)pressedMouseButtons {
325 NSUInteger result = 0;
326 const int buttons[3] = {ui_controls::LEFT, ui_controls::RIGHT,
327 ui_controls::MIDDLE};
328 for (unsigned int i = 0; i < arraysize(buttons); ++i) {
329 if (g_mouse_button_down[buttons[i]])
330 result |= (1 << i);
331 }
332 return result;
333 }
334 @end
335
336 // Donates testing implementations of NSWindow methods.
337 @interface FakeNSWindowTestingDonor : NSObject
338 @end
339
340 @implementation FakeNSWindowTestingDonor
341 - (NSPoint)mouseLocationOutsideOfEventStream {
342 NSWindow* window = base::mac::ObjCCastStrict<NSWindow>(self);
343 if (g_mouse_location_override_enabled) {
344 return ui::ConvertPointFromScreenToWindow(window,
345 g_mouse_location_override);
346 }
347
348 return ui::ConvertPointFromScreenToWindow(window, g_mouse_location);
349 }
350 @end
351
352 namespace {
353 class NSEventSwizzler {
354 public:
355 static void Install() {
356 static NSEventSwizzler* swizzler = nullptr;
357 if (!swizzler) {
358 swizzler = new NSEventSwizzler();
359 }
360 }
361
362 protected:
363 NSEventSwizzler()
364 : mouse_location_swizzler_(new base::mac::ScopedObjCClassSwizzler(
365 [NSEvent class],
366 [FakeNSEventTestingDonor class],
367 @selector(mouseLocation))),
368 pressed_mouse_buttons_swizzler_(new base::mac::ScopedObjCClassSwizzler(
369 [NSEvent class],
370 [FakeNSEventTestingDonor class],
371 @selector(pressedMouseButtons))),
372 mouse_location_outside_of_event_stream_swizzler_(
373 new base::mac::ScopedObjCClassSwizzler(
374 [NSWindow class],
375 [FakeNSWindowTestingDonor class],
376 @selector(mouseLocationOutsideOfEventStream))) {}
377
378 private:
379 std::unique_ptr<base::mac::ScopedObjCClassSwizzler> mouse_location_swizzler_;
380 std::unique_ptr<base::mac::ScopedObjCClassSwizzler>
381 pressed_mouse_buttons_swizzler_;
382 std::unique_ptr<base::mac::ScopedObjCClassSwizzler>
383 mouse_location_outside_of_event_stream_swizzler_;
384 };
385 } // namespace
386
176 namespace ui_controls { 387 namespace ui_controls {
177 388
178 void EnableUIControls() { 389 void EnableUIControls() {
179 g_ui_controls_enabled = true; 390 g_ui_controls_enabled = true;
180 } 391 }
181 392
182 bool IsUIControlsEnabled() { 393 bool IsUIControlsEnabled() {
183 return g_ui_controls_enabled; 394 return g_ui_controls_enabled;
184 } 395 }
185 396
(...skipping 11 matching lines...) Expand all
197 408
198 // Win and Linux implement a SendKeyPress() this as a 409 // Win and Linux implement a SendKeyPress() this as a
199 // SendKeyPressAndRelease(), so we should as well (despite the name). 410 // SendKeyPressAndRelease(), so we should as well (despite the name).
200 bool SendKeyPressNotifyWhenDone(gfx::NativeWindow window, 411 bool SendKeyPressNotifyWhenDone(gfx::NativeWindow window,
201 ui::KeyboardCode key, 412 ui::KeyboardCode key,
202 bool control, 413 bool control,
203 bool shift, 414 bool shift,
204 bool alt, 415 bool alt,
205 bool command, 416 bool command,
206 const base::Closure& task) { 417 const base::Closure& task) {
418 DCHECK(!g_use_cgevents) << "Not implemented";
207 CHECK(g_ui_controls_enabled); 419 CHECK(g_ui_controls_enabled);
208 DCHECK(base::MessageLoopForUI::IsCurrent()); 420 DCHECK(base::MessageLoopForUI::IsCurrent());
209 421
210 std::vector<NSEvent*> events; 422 std::vector<NSEvent*> events;
211 SynthesizeKeyEventsSequence( 423 SynthesizeKeyEventsSequence(
212 window, key, control, shift, alt, command, &events); 424 window, key, control, shift, alt, command, &events);
213 425
214 // TODO(suzhe): Using [NSApplication postEvent:atStart:] here causes 426 // TODO(suzhe): Using [NSApplication postEvent:atStart:] here causes
215 // BrowserKeyEventsTest.CommandKeyEvents to fail. See http://crbug.com/49270 427 // BrowserKeyEventsTest.CommandKeyEvents to fail. See http://crbug.com/49270
216 // But using [NSApplication sendEvent:] should be safe for keyboard events, 428 // But using [NSApplication sendEvent:] should be safe for keyboard events,
(...skipping 15 matching lines...) Expand all
232 CHECK(g_ui_controls_enabled); 444 CHECK(g_ui_controls_enabled);
233 return SendMouseMoveNotifyWhenDone(x, y, base::Closure()); 445 return SendMouseMoveNotifyWhenDone(x, y, base::Closure());
234 } 446 }
235 447
236 // Input position is in screen coordinates. However, NSMouseMoved 448 // Input position is in screen coordinates. However, NSMouseMoved
237 // events require them window-relative, so we adjust. We *DO* flip 449 // events require them window-relative, so we adjust. We *DO* flip
238 // the coordinate space, so input events can be the same for all 450 // the coordinate space, so input events can be the same for all
239 // platforms. E.g. (0,0) is upper-left. 451 // platforms. E.g. (0,0) is upper-left.
240 bool SendMouseMoveNotifyWhenDone(long x, long y, const base::Closure& task) { 452 bool SendMouseMoveNotifyWhenDone(long x, long y, const base::Closure& task) {
241 CHECK(g_ui_controls_enabled); 453 CHECK(g_ui_controls_enabled);
242 CGFloat screenHeight = 454 g_mouse_location = gfx::ScreenPointToNSPoint(gfx::Point(x, y)); // flip!
243 [[[NSScreen screens] firstObject] frame].size.height; 455 NSEventSwizzler::Install();
244 g_mouse_location = NSMakePoint(x, screenHeight - y); // flip!
245 456
246 NSWindow* window = WindowAtCurrentMouseLocation(); 457 NSWindow* window = WindowAtCurrentMouseLocation();
247 458
248 NSPoint pointInWindow = g_mouse_location; 459 NSPoint pointInWindow = g_mouse_location;
249 if (window) 460 if (window)
250 pointInWindow = ui::ConvertPointFromScreenToWindow(window, pointInWindow); 461 pointInWindow = ui::ConvertPointFromScreenToWindow(window, pointInWindow);
251 NSTimeInterval timestamp = TimeIntervalSinceSystemStartup(); 462 NSTimeInterval timestamp = TimeIntervalSinceSystemStartup();
252 463
464 NSEventType event_type = NSMouseMoved;
465 if (g_mouse_button_down[LEFT]) {
466 event_type = NSLeftMouseDragged;
467 } else if (g_mouse_button_down[RIGHT]) {
468 event_type = NSRightMouseDragged;
469 } else if (g_mouse_button_down[MIDDLE]) {
470 event_type = NSOtherMouseDragged;
471 }
472
253 NSEvent* event = 473 NSEvent* event =
254 [NSEvent mouseEventWithType:NSMouseMoved 474 [NSEvent mouseEventWithType:event_type
255 location:pointInWindow 475 location:pointInWindow
256 modifierFlags:0 476 modifierFlags:0
257 timestamp:timestamp 477 timestamp:timestamp
258 windowNumber:[window windowNumber] 478 windowNumber:[window windowNumber]
259 context:nil 479 context:nil
260 eventNumber:0 480 eventNumber:0
261 clickCount:0 481 clickCount:(event_type == NSMouseMoved ? 0 : 1)
262 pressure:0.0]; 482 pressure:(event_type == NSMouseMoved ? 0.0 : 1.0)];
263 [[NSApplication sharedApplication] postEvent:event atStart:NO];
264 483
265 if (!task.is_null()) { 484 if (!task.is_null()) {
266 base::MessageLoop::current()->PostTask( 485 EventMonitor::Instance()->NotifyWhenEventIsProcessed(event, task);
267 FROM_HERE, base::Bind(&EventQueueWatcher, task)); 486 }
487
488 gfx::Point gp = gfx::ScreenPointFromNSPoint(g_mouse_location);
489 CGWarpMouseCursorPosition(CGPointMake(gp.x(), gp.y()));
490
491 if (g_use_cgevents) {
492 CGEventPost(kCGSessionEventTap, [event CGEvent]);
493 } else {
494 [[NSApplication sharedApplication] postEvent:event atStart:NO];
268 } 495 }
269 496
270 return true; 497 return true;
271 } 498 }
272 499
273 bool SendMouseEvents(MouseButton type, int state) { 500 bool SendMouseEvents(MouseButton type, int state) {
274 CHECK(g_ui_controls_enabled); 501 CHECK(g_ui_controls_enabled);
275 return SendMouseEventsNotifyWhenDone(type, state, base::Closure()); 502 return SendMouseEventsNotifyWhenDone(type, state, base::Closure());
276 } 503 }
277 504
278 bool SendMouseEventsNotifyWhenDone(MouseButton type, int state, 505 bool SendMouseEventsNotifyWhenDone(MouseButton type, int state,
279 const base::Closure& task) { 506 const base::Closure& task) {
280 CHECK(g_ui_controls_enabled); 507 CHECK(g_ui_controls_enabled);
281 // On windows it appears state can be (UP|DOWN). It is unclear if 508 // On windows it appears state can be (UP|DOWN). It is unclear if
282 // that'll happen here but prepare for it just in case. 509 // that'll happen here but prepare for it just in case.
283 if (state == (UP|DOWN)) { 510 if (state == (UP|DOWN)) {
284 return (SendMouseEventsNotifyWhenDone(type, DOWN, base::Closure()) && 511 return (SendMouseEventsNotifyWhenDone(type, DOWN, base::Closure()) &&
285 SendMouseEventsNotifyWhenDone(type, UP, task)); 512 SendMouseEventsNotifyWhenDone(type, UP, task));
286 } 513 }
287 NSEventType etype = NSLeftMouseDown; 514 NSEventType event_type = NSLeftMouseDown;
288 if (type == LEFT) { 515 if (type == LEFT) {
289 if (state == UP) { 516 if (state == UP) {
290 etype = NSLeftMouseUp; 517 event_type = NSLeftMouseUp;
291 } else { 518 } else {
292 etype = NSLeftMouseDown; 519 event_type = NSLeftMouseDown;
293 } 520 }
294 } else if (type == MIDDLE) { 521 } else if (type == MIDDLE) {
295 if (state == UP) { 522 if (state == UP) {
296 etype = NSOtherMouseUp; 523 event_type = NSOtherMouseUp;
297 } else { 524 } else {
298 etype = NSOtherMouseDown; 525 event_type = NSOtherMouseDown;
299 } 526 }
300 } else if (type == RIGHT) { 527 } else if (type == RIGHT) {
301 if (state == UP) { 528 if (state == UP) {
302 etype = NSRightMouseUp; 529 event_type = NSRightMouseUp;
303 } else { 530 } else {
304 etype = NSRightMouseDown; 531 event_type = NSRightMouseDown;
305 } 532 }
306 } else { 533 } else {
534 NOTREACHED();
307 return false; 535 return false;
308 } 536 }
537 g_mouse_button_down[type] = state == DOWN;
538
309 NSWindow* window = WindowAtCurrentMouseLocation(); 539 NSWindow* window = WindowAtCurrentMouseLocation();
310 NSPoint pointInWindow = g_mouse_location; 540 NSPoint pointInWindow = g_mouse_location;
311 if (window) 541 if (window)
312 pointInWindow = ui::ConvertPointFromScreenToWindow(window, pointInWindow); 542 pointInWindow = ui::ConvertPointFromScreenToWindow(window, pointInWindow);
313 543
314 NSEvent* event = 544 NSEventSwizzler::Install();
315 [NSEvent mouseEventWithType:etype 545
316 location:pointInWindow 546 NSEvent* event = [NSEvent mouseEventWithType:event_type
317 modifierFlags:0 547 location:pointInWindow
318 timestamp:TimeIntervalSinceSystemStartup() 548 modifierFlags:0
319 windowNumber:[window windowNumber] 549 timestamp:TimeIntervalSinceSystemStartup()
320 context:nil 550 windowNumber:[window windowNumber]
321 eventNumber:0 551 context:nil
322 clickCount:1 552 eventNumber:0
323 pressure:(state == DOWN ? 1.0 : 0.0 )]; 553 clickCount:1
324 [[NSApplication sharedApplication] postEvent:event atStart:NO]; 554 pressure:(state == DOWN ? 1.0 : 0.0)];
325 555
326 if (!task.is_null()) { 556 if (!task.is_null()) {
327 base::MessageLoop::current()->PostTask( 557 EventMonitor::Instance()->NotifyWhenEventIsProcessed(event, task);
328 FROM_HERE, base::Bind(&EventQueueWatcher, task)); 558 }
559
560 if (g_use_cgevents) {
561 CGEventPost(kCGSessionEventTap, [event CGEvent]);
562 } else {
563 [[NSApplication sharedApplication] postEvent:event atStart:NO];
329 } 564 }
330 565
331 return true; 566 return true;
332 } 567 }
333 568
334 bool SendMouseClick(MouseButton type) { 569 bool SendMouseClick(MouseButton type) {
335 CHECK(g_ui_controls_enabled); 570 CHECK(g_ui_controls_enabled);
336 return SendMouseEventsNotifyWhenDone(type, UP|DOWN, base::Closure()); 571 return SendMouseEventsNotifyWhenDone(type, UP|DOWN, base::Closure());
337 } 572 }
338 573
339 void RunClosureAfterAllPendingUIEvents(const base::Closure& closure) { 574 void RunClosureAfterAllPendingUIEvents(const base::Closure& closure) {
340 base::MessageLoop::current()->PostTask( 575 base::MessageLoop::current()->PostTask(
341 FROM_HERE, base::Bind(&EventQueueWatcher, closure)); 576 FROM_HERE, base::Bind(&EventQueueWatcher, closure));
342 } 577 }
343 578
344 bool IsFullKeyboardAccessEnabled() { 579 bool IsFullKeyboardAccessEnabled() {
345 return [NSApp isFullKeyboardAccessEnabled]; 580 return [NSApp isFullKeyboardAccessEnabled];
346 } 581 }
347 582
583 void SetSendMouseEventsAsCGEvents(bool enable_cgevents) {
584 g_use_cgevents = enable_cgevents;
585 }
586
587 bool SendMouseEventsAsCGEvents() {
588 return g_use_cgevents;
589 }
590
591 void NotifyWhenEventIsProcessed(NSEvent* event, const base::Closure& task) {
592 EventMonitor::Instance()->NotifyWhenEventIsProcessed(event, task);
593 }
594
595 void SetMousePositionOverride(bool enable_override, const gfx::Point& p) {
596 g_mouse_location_override_enabled = enable_override;
597 g_mouse_location_override = gfx::ScreenPointToNSPoint(p); // flip!
598 }
599
348 } // namespace ui_controls 600 } // namespace ui_controls
OLDNEW
« no previous file with comments | « ui/base/test/ui_controls.h ('k') | ui/gfx/geometry/rect.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698