Chromium Code Reviews| 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 #include "base/message_loop/message_loop.h" | 12 #include "base/message_loop/message_loop.h" |
| 13 #include "ui/base/cocoa/cocoa_base_utils.h" | 13 #include "ui/base/cocoa/cocoa_base_utils.h" |
| 14 #include "ui/events/keycodes/keyboard_code_conversion_mac.h" | 14 #include "ui/events/keycodes/keyboard_code_conversion_mac.h" |
| 15 #import "ui/events/test/cocoa_test_event_utils.h" | 15 #import "ui/events/test/cocoa_test_event_utils.h" |
| 16 | 16 |
| 17 // Implementation details: We use [NSApplication sendEvent:] instead | 17 // [NSApplication sendEvent:] causes a problem when sending mouse click |
| 18 // of [NSApplication postEvent:atStart:] so that the event gets sent | |
| 19 // immediately. This lets us run the post-event task right | |
|
tapted
2016/06/06 04:44:05
So, sadly we will need to land the change that con
karandeepb
2016/06/06 11:21:09
Done. See crrev.com/2035393002.
| |
| 20 // immediately as well. Unfortunately I cannot subclass NSEvent (it's | |
| 21 // 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 | |
| 23 // dealloc routine (which necessarily happens after the event is | |
| 24 // dispatched). Unlike Linux, Mac does not have message loop | |
| 25 // observer/notification. Unlike windows, I cannot post non-events | |
|
tapted
2016/06/06 04:44:05
Should we keep some of these notes?
karandeepb
2016/06/06 11:21:09
These notes are explaining why [NSApp sendEvent] i
| |
| 26 // into the event queue. (I can post other kinds of tasks but can't | |
| 27 // guarantee their order with regards to events). | |
| 28 | |
| 29 // But [NSApplication sendEvent:] causes a problem when sending mouse click | |
| 30 // events. Because in order to handle mouse drag, when processing a mouse | 18 // events. Because in order to handle mouse drag, when processing a mouse |
| 31 // click event, the application may want to retrieve the next event | 19 // click event, the application may want to retrieve the next event |
| 32 // synchronously by calling NSApplication's nextEventMatchingMask method. | 20 // synchronously by calling NSApplication's nextEventMatchingMask method. |
| 33 // In this case, [NSApplication sendEvent:] causes deadlock. | 21 // In this case, [NSApplication sendEvent:] causes deadlock. |
| 34 // So we need to use [NSApplication postEvent:atStart:] for mouse click | 22 // Also since events sent using [NSApp sendEvent] are not added to the event |
| 35 // events. In order to notify the caller correctly after all events has been | 23 // queue but instead are invoked directly from the main event loop, |
| 24 // [NSApp currentEvent] does not report the correct event for it. | |
| 25 // So we need to use [NSApplication postEvent:atStart:]. | |
| 26 // In order to notify the caller correctly after all events has been | |
|
tapted
2016/06/06 04:44:05
has -> have
karandeepb
2016/06/06 11:21:09
Done.
| |
| 36 // processed, we setup a task to watch for the event queue time to time and | 27 // processed, we setup a task to watch for the event queue time to time and |
| 37 // notify the caller as soon as there is no event in the queue. | 28 // notify the caller as soon as there is no event in the queue. |
| 38 // | 29 // |
| 39 // TODO(suzhe): | 30 // TODO(suzhe): |
| 40 // 1. Investigate why using [NSApplication postEvent:atStart:] for keyboard | 31 // 1. Investigate why using [NSApplication postEvent:atStart:] for keyboard |
| 41 // events causes BrowserKeyEventsTest.CommandKeyEvents to fail. | 32 // events causes BrowserKeyEventsTest.CommandKeyEvents to fail. |
| 42 // See http://crbug.com/49270 | 33 // See http://crbug.com/49270 |
| 43 // 2. On OSX 10.6, [NSEvent addLocalMonitorForEventsMatchingMask:handler:] may | 34 // 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. | 35 // be used, so that we don't need to poll the event queue time to time. |
| 45 | 36 |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 204 bool alt, | 195 bool alt, |
| 205 bool command, | 196 bool command, |
| 206 const base::Closure& task) { | 197 const base::Closure& task) { |
| 207 CHECK(g_ui_controls_enabled); | 198 CHECK(g_ui_controls_enabled); |
| 208 DCHECK(base::MessageLoopForUI::IsCurrent()); | 199 DCHECK(base::MessageLoopForUI::IsCurrent()); |
| 209 | 200 |
| 210 std::vector<NSEvent*> events; | 201 std::vector<NSEvent*> events; |
| 211 SynthesizeKeyEventsSequence( | 202 SynthesizeKeyEventsSequence( |
| 212 window, key, control, shift, alt, command, &events); | 203 window, key, control, shift, alt, command, &events); |
| 213 | 204 |
| 214 // TODO(suzhe): Using [NSApplication postEvent:atStart:] here causes | |
| 215 // BrowserKeyEventsTest.CommandKeyEvents to fail. See http://crbug.com/49270 | |
| 216 // But using [NSApplication sendEvent:] should be safe for keyboard events, | |
| 217 // because until now, no code wants to retrieve the next event when handling | |
| 218 // a keyboard event. | |
| 219 for (std::vector<NSEvent*>::iterator iter = events.begin(); | 205 for (std::vector<NSEvent*>::iterator iter = events.begin(); |
| 220 iter != events.end(); ++iter) | 206 iter != events.end(); ++iter) |
| 221 [[NSApplication sharedApplication] sendEvent:*iter]; | 207 [[NSApplication sharedApplication] postEvent:*iter atStart:NO]; |
| 222 | 208 |
| 223 if (!task.is_null()) { | 209 if (!task.is_null()) { |
| 224 base::MessageLoop::current()->PostTask( | 210 base::MessageLoop::current()->PostTask( |
| 225 FROM_HERE, base::Bind(&EventQueueWatcher, task)); | 211 FROM_HERE, base::Bind(&EventQueueWatcher, task)); |
| 226 } | 212 } |
| 227 | 213 |
| 228 return true; | 214 return true; |
| 229 } | 215 } |
| 230 | 216 |
| 231 bool SendMouseMove(long x, long y) { | 217 bool SendMouseMove(long x, long y) { |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 339 void RunClosureAfterAllPendingUIEvents(const base::Closure& closure) { | 325 void RunClosureAfterAllPendingUIEvents(const base::Closure& closure) { |
| 340 base::MessageLoop::current()->PostTask( | 326 base::MessageLoop::current()->PostTask( |
| 341 FROM_HERE, base::Bind(&EventQueueWatcher, closure)); | 327 FROM_HERE, base::Bind(&EventQueueWatcher, closure)); |
| 342 } | 328 } |
| 343 | 329 |
| 344 bool IsFullKeyboardAccessEnabled() { | 330 bool IsFullKeyboardAccessEnabled() { |
| 345 return [NSApp isFullKeyboardAccessEnabled]; | 331 return [NSApp isFullKeyboardAccessEnabled]; |
| 346 } | 332 } |
| 347 | 333 |
| 348 } // namespace ui_controls | 334 } // namespace ui_controls |
| OLD | NEW |