| OLD | NEW |
| 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 <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| 11 #include "base/callback.h" | 11 #include "base/callback.h" |
| 12 #import "base/mac/foundation_util.h" | 12 #import "base/mac/foundation_util.h" |
| 13 #import "base/mac/scoped_objc_class_swizzler.h" | 13 #import "base/mac/scoped_objc_class_swizzler.h" |
| 14 #include "base/message_loop/message_loop.h" | 14 #include "base/message_loop/message_loop.h" |
| 15 #include "base/threading/thread_task_runner_handle.h" |
| 15 #include "ui/base/cocoa/cocoa_base_utils.h" | 16 #include "ui/base/cocoa/cocoa_base_utils.h" |
| 16 #include "ui/events/keycodes/keyboard_code_conversion_mac.h" | 17 #include "ui/events/keycodes/keyboard_code_conversion_mac.h" |
| 17 #import "ui/events/test/cocoa_test_event_utils.h" | 18 #import "ui/events/test/cocoa_test_event_utils.h" |
| 18 #include "ui/gfx/geometry/point.h" | 19 #include "ui/gfx/geometry/point.h" |
| 19 #import "ui/gfx/mac/coordinate_conversion.h" | 20 #import "ui/gfx/mac/coordinate_conversion.h" |
| 20 | 21 |
| 21 // Implementation details: We use [NSApplication sendEvent:] instead | 22 // Implementation details: We use [NSApplication sendEvent:] instead |
| 22 // of [NSApplication postEvent:atStart:] so that the event gets sent | 23 // of [NSApplication postEvent:atStart:] so that the event gets sent |
| 23 // immediately. This lets us run the post-event task right | 24 // immediately. This lets us run the post-event task right |
| 24 // immediately as well. Unfortunately I cannot subclass NSEvent (it's | 25 // immediately as well. Unfortunately I cannot subclass NSEvent (it's |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 132 | 133 |
| 133 // A helper function to watch for the event queue. The specific task will be | 134 // A helper function to watch for the event queue. The specific task will be |
| 134 // fired when there is no more event in the queue. | 135 // fired when there is no more event in the queue. |
| 135 void EventQueueWatcher(const base::Closure& task) { | 136 void EventQueueWatcher(const base::Closure& task) { |
| 136 NSEvent* event = [NSApp nextEventMatchingMask:NSAnyEventMask | 137 NSEvent* event = [NSApp nextEventMatchingMask:NSAnyEventMask |
| 137 untilDate:nil | 138 untilDate:nil |
| 138 inMode:NSDefaultRunLoopMode | 139 inMode:NSDefaultRunLoopMode |
| 139 dequeue:NO]; | 140 dequeue:NO]; |
| 140 // If there is still event in the queue, then we need to check again. | 141 // If there is still event in the queue, then we need to check again. |
| 141 if (event) { | 142 if (event) { |
| 142 base::MessageLoop::current()->PostTask( | 143 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 143 FROM_HERE, | 144 FROM_HERE, base::Bind(&EventQueueWatcher, task)); |
| 144 base::Bind(&EventQueueWatcher, task)); | |
| 145 } else { | 145 } else { |
| 146 base::MessageLoop::current()->PostTask(FROM_HERE, task); | 146 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, task); |
| 147 } | 147 } |
| 148 } | 148 } |
| 149 | 149 |
| 150 // Returns the NSWindow located at |g_mouse_location|. NULL if there is no | 150 // Returns the NSWindow located at |g_mouse_location|. NULL if there is no |
| 151 // window there, or if the window located there is not owned by the application. | 151 // window there, or if the window located there is not owned by the application. |
| 152 // On Mac, unless dragging, mouse events are sent to the window under the | 152 // On Mac, unless dragging, mouse events are sent to the window under the |
| 153 // cursor. Note that the OS will ignore transparent windows and windows that | 153 // cursor. Note that the OS will ignore transparent windows and windows that |
| 154 // explicitly ignore mouse events. | 154 // explicitly ignore mouse events. |
| 155 NSWindow* WindowAtCurrentMouseLocation() { | 155 NSWindow* WindowAtCurrentMouseLocation() { |
| 156 NSInteger window_number = [NSWindow windowNumberAtPoint:g_mouse_location | 156 NSInteger window_number = [NSWindow windowNumberAtPoint:g_mouse_location |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 275 // TODO(suzhe): Using [NSApplication postEvent:atStart:] here causes | 275 // TODO(suzhe): Using [NSApplication postEvent:atStart:] here causes |
| 276 // BrowserKeyEventsTest.CommandKeyEvents to fail. See http://crbug.com/49270 | 276 // BrowserKeyEventsTest.CommandKeyEvents to fail. See http://crbug.com/49270 |
| 277 // But using [NSApplication sendEvent:] should be safe for keyboard events, | 277 // But using [NSApplication sendEvent:] should be safe for keyboard events, |
| 278 // because until now, no code wants to retrieve the next event when handling | 278 // because until now, no code wants to retrieve the next event when handling |
| 279 // a keyboard event. | 279 // a keyboard event. |
| 280 for (std::vector<NSEvent*>::iterator iter = events.begin(); | 280 for (std::vector<NSEvent*>::iterator iter = events.begin(); |
| 281 iter != events.end(); ++iter) | 281 iter != events.end(); ++iter) |
| 282 [[NSApplication sharedApplication] sendEvent:*iter]; | 282 [[NSApplication sharedApplication] sendEvent:*iter]; |
| 283 | 283 |
| 284 if (!task.is_null()) { | 284 if (!task.is_null()) { |
| 285 base::MessageLoop::current()->PostTask( | 285 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 286 FROM_HERE, base::Bind(&EventQueueWatcher, task)); | 286 FROM_HERE, base::Bind(&EventQueueWatcher, task)); |
| 287 } | 287 } |
| 288 | 288 |
| 289 return true; | 289 return true; |
| 290 } | 290 } |
| 291 | 291 |
| 292 bool SendMouseMove(long x, long y) { | 292 bool SendMouseMove(long x, long y) { |
| 293 CHECK(g_ui_controls_enabled); | 293 CHECK(g_ui_controls_enabled); |
| 294 return SendMouseMoveNotifyWhenDone(x, y, base::Closure()); | 294 return SendMouseMoveNotifyWhenDone(x, y, base::Closure()); |
| 295 } | 295 } |
| (...skipping 28 matching lines...) Expand all Loading... |
| 324 modifierFlags:0 | 324 modifierFlags:0 |
| 325 timestamp:timestamp | 325 timestamp:timestamp |
| 326 windowNumber:[window windowNumber] | 326 windowNumber:[window windowNumber] |
| 327 context:nil | 327 context:nil |
| 328 eventNumber:0 | 328 eventNumber:0 |
| 329 clickCount:event_type == NSMouseMoved ? 0 : 1 | 329 clickCount:event_type == NSMouseMoved ? 0 : 1 |
| 330 pressure:event_type == NSMouseMoved ? 0.0 : 1.0]; | 330 pressure:event_type == NSMouseMoved ? 0.0 : 1.0]; |
| 331 [[NSApplication sharedApplication] postEvent:event atStart:NO]; | 331 [[NSApplication sharedApplication] postEvent:event atStart:NO]; |
| 332 | 332 |
| 333 if (!task.is_null()) { | 333 if (!task.is_null()) { |
| 334 base::MessageLoop::current()->PostTask( | 334 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 335 FROM_HERE, base::Bind(&EventQueueWatcher, task)); | 335 FROM_HERE, base::Bind(&EventQueueWatcher, task)); |
| 336 } | 336 } |
| 337 | 337 |
| 338 return true; | 338 return true; |
| 339 } | 339 } |
| 340 | 340 |
| 341 bool SendMouseEvents(MouseButton type, int state) { | 341 bool SendMouseEvents(MouseButton type, int state) { |
| 342 CHECK(g_ui_controls_enabled); | 342 CHECK(g_ui_controls_enabled); |
| 343 return SendMouseEventsNotifyWhenDone(type, state, base::Closure()); | 343 return SendMouseEventsNotifyWhenDone(type, state, base::Closure()); |
| 344 } | 344 } |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 388 modifierFlags:0 | 388 modifierFlags:0 |
| 389 timestamp:TimeIntervalSinceSystemStartup() | 389 timestamp:TimeIntervalSinceSystemStartup() |
| 390 windowNumber:[window windowNumber] | 390 windowNumber:[window windowNumber] |
| 391 context:nil | 391 context:nil |
| 392 eventNumber:0 | 392 eventNumber:0 |
| 393 clickCount:1 | 393 clickCount:1 |
| 394 pressure:state == DOWN ? 1.0 : 0.0]; | 394 pressure:state == DOWN ? 1.0 : 0.0]; |
| 395 [[NSApplication sharedApplication] postEvent:event atStart:NO]; | 395 [[NSApplication sharedApplication] postEvent:event atStart:NO]; |
| 396 | 396 |
| 397 if (!task.is_null()) { | 397 if (!task.is_null()) { |
| 398 base::MessageLoop::current()->PostTask( | 398 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 399 FROM_HERE, base::Bind(&EventQueueWatcher, task)); | 399 FROM_HERE, base::Bind(&EventQueueWatcher, task)); |
| 400 } | 400 } |
| 401 | 401 |
| 402 return true; | 402 return true; |
| 403 } | 403 } |
| 404 | 404 |
| 405 bool SendMouseClick(MouseButton type) { | 405 bool SendMouseClick(MouseButton type) { |
| 406 CHECK(g_ui_controls_enabled); | 406 CHECK(g_ui_controls_enabled); |
| 407 return SendMouseEventsNotifyWhenDone(type, UP|DOWN, base::Closure()); | 407 return SendMouseEventsNotifyWhenDone(type, UP|DOWN, base::Closure()); |
| 408 } | 408 } |
| 409 | 409 |
| 410 void RunClosureAfterAllPendingUIEvents(const base::Closure& closure) { | 410 void RunClosureAfterAllPendingUIEvents(const base::Closure& closure) { |
| 411 base::MessageLoop::current()->PostTask( | 411 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 412 FROM_HERE, base::Bind(&EventQueueWatcher, closure)); | 412 FROM_HERE, base::Bind(&EventQueueWatcher, closure)); |
| 413 } | 413 } |
| 414 | 414 |
| 415 bool IsFullKeyboardAccessEnabled() { | 415 bool IsFullKeyboardAccessEnabled() { |
| 416 return [NSApp isFullKeyboardAccessEnabled]; | 416 return [NSApp isFullKeyboardAccessEnabled]; |
| 417 } | 417 } |
| 418 | 418 |
| 419 } // namespace ui_controls | 419 } // namespace ui_controls |
| OLD | NEW |