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

Side by Side Diff: ui/views/test/event_generator_delegate_mac.mm

Issue 951433002: MacViews: Handle Tab properly (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@20150129-MacViews-Bringup5
Patch Set: Still need insertTexT: Created 5 years, 10 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
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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 #import <Cocoa/Cocoa.h> 5 #import <Cocoa/Cocoa.h>
6 6
7 #import "base/mac/scoped_nsobject.h" 7 #import "base/mac/scoped_nsobject.h"
8 #import "base/mac/scoped_objc_class_swizzler.h" 8 #import "base/mac/scoped_objc_class_swizzler.h"
9 #include "base/memory/singleton.h" 9 #include "base/memory/singleton.h"
10 #include "ui/events/event_processor.h" 10 #include "ui/events/event_processor.h"
11 #include "ui/events/event_target.h" 11 #include "ui/events/event_target.h"
12 #include "ui/events/event_target_iterator.h" 12 #include "ui/events/event_target_iterator.h"
13 #include "ui/events/event_targeter.h" 13 #include "ui/events/event_targeter.h"
14 #import "ui/events/test/cocoa_test_event_utils.h" 14 #import "ui/events/test/cocoa_test_event_utils.h"
15 #include "ui/events/test/event_generator.h" 15 #include "ui/events/test/event_generator.h"
16 #include "ui/gfx/mac/coordinate_conversion.h" 16 #include "ui/gfx/mac/coordinate_conversion.h"
17 17
18 namespace { 18 namespace {
19 19
20 // Singleton to provide state for swizzled Objective C methods. 20 // Singleton to provide state for swizzled Objective C methods.
21 ui::test::EventGenerator* g_active_generator = NULL; 21 ui::test::EventGenerator* g_active_generator = NULL;
22 22
23 // Set (and always cleared) in EmulateSendEvent() to provide an answer for
24 // [NSApp currentEvent].
25 NSEvent* g_current_event = nil;
26
23 } // namespace 27 } // namespace
24 28
25 @interface NSEventDonor : NSObject 29 @interface NSEventDonor : NSObject
26 @end 30 @end
27 31
28 @implementation NSEventDonor 32 @interface NSApplicationDonor : NSObject
29
30 // Donate +[NSEvent pressedMouseButtons] by retrieving the flags from the
31 // active generator.
32 + (NSUInteger)pressedMouseButtons {
33 if (!g_active_generator)
34 return [NSEventDonor pressedMouseButtons]; // Call original implementation.
35
36 int flags = g_active_generator->flags();
37 NSUInteger bitmask = 0;
38 if (flags & ui::EF_LEFT_MOUSE_BUTTON)
39 bitmask |= 1;
40 if (flags & ui::EF_RIGHT_MOUSE_BUTTON)
41 bitmask |= 1 << 1;
42 if (flags & ui::EF_MIDDLE_MOUSE_BUTTON)
43 bitmask |= 1 << 2;
44 return bitmask;
45 }
46
47 @end 33 @end
48 34
49 namespace { 35 namespace {
50 36
51 NSPoint ConvertRootPointToTarget(NSWindow* target, 37 NSPoint ConvertRootPointToTarget(NSWindow* target,
52 const gfx::Point& point_in_root) { 38 const gfx::Point& point_in_root) {
53 // Normally this would do [NSWindow convertScreenToBase:]. However, Cocoa can 39 // Normally this would do [NSWindow convertScreenToBase:]. However, Cocoa can
54 // reposition the window on screen and make things flaky. Initially, just 40 // reposition the window on screen and make things flaky. Initially, just
55 // assume that the contentRect of |target| is at the top-left corner of the 41 // assume that the contentRect of |target| is at the top-left corner of the
56 // screen. 42 // screen.
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
126 default: 112 default:
127 NOTREACHED(); 113 NOTREACHED();
128 return 0; 114 return 0;
129 } 115 }
130 } 116 }
131 117
132 // Emulate the dispatching that would be performed by -[NSWindow sendEvent:]. 118 // Emulate the dispatching that would be performed by -[NSWindow sendEvent:].
133 // sendEvent is a black box which (among other things) will try to peek at the 119 // sendEvent is a black box which (among other things) will try to peek at the
134 // event queue and can block indefinitely. 120 // event queue and can block indefinitely.
135 void EmulateSendEvent(NSWindow* window, NSEvent* event) { 121 void EmulateSendEvent(NSWindow* window, NSEvent* event) {
122 base::AutoReset<NSEvent*> reset(&g_current_event, event);
136 NSResponder* responder = [window firstResponder]; 123 NSResponder* responder = [window firstResponder];
137 switch ([event type]) { 124 switch ([event type]) {
138 case NSKeyDown: 125 case NSKeyDown:
139 [responder keyDown:event]; 126 [responder keyDown:event];
140 return; 127 return;
141 case NSKeyUp: 128 case NSKeyUp:
142 [responder keyUp:event]; 129 [responder keyUp:event];
143 return; 130 return;
144 } 131 }
145 132
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
236 class EventGeneratorDelegateMac : public ui::EventTarget, 223 class EventGeneratorDelegateMac : public ui::EventTarget,
237 public ui::EventSource, 224 public ui::EventSource,
238 public ui::EventProcessor, 225 public ui::EventProcessor,
239 public ui::EventTargeter, 226 public ui::EventTargeter,
240 public ui::test::EventGeneratorDelegate { 227 public ui::test::EventGeneratorDelegate {
241 public: 228 public:
242 static EventGeneratorDelegateMac* GetInstance() { 229 static EventGeneratorDelegateMac* GetInstance() {
243 return Singleton<EventGeneratorDelegateMac>::get(); 230 return Singleton<EventGeneratorDelegateMac>::get();
244 } 231 }
245 232
233 IMP CurrentEventMethod() {
234 return swizzle_current_event_->GetOriginalImplementation();
235 }
236
246 // Overridden from ui::EventTarget: 237 // Overridden from ui::EventTarget:
247 bool CanAcceptEvent(const ui::Event& event) override { return true; } 238 bool CanAcceptEvent(const ui::Event& event) override { return true; }
248 ui::EventTarget* GetParentTarget() override { return NULL; } 239 ui::EventTarget* GetParentTarget() override { return NULL; }
249 scoped_ptr<ui::EventTargetIterator> GetChildIterator() const override; 240 scoped_ptr<ui::EventTargetIterator> GetChildIterator() const override;
250 ui::EventTargeter* GetEventTargeter() override { return this; } 241 ui::EventTargeter* GetEventTargeter() override { return this; }
251 242
252 // Overridden from ui::EventHandler (via ui::EventTarget): 243 // Overridden from ui::EventHandler (via ui::EventTarget):
253 void OnMouseEvent(ui::MouseEvent* event) override; 244 void OnMouseEvent(ui::MouseEvent* event) override;
254 void OnKeyEvent(ui::KeyEvent* event) override; 245 void OnKeyEvent(ui::KeyEvent* event) override;
255 246
(...skipping 28 matching lines...) Expand all
284 275
285 private: 276 private:
286 friend struct DefaultSingletonTraits<EventGeneratorDelegateMac>; 277 friend struct DefaultSingletonTraits<EventGeneratorDelegateMac>;
287 278
288 EventGeneratorDelegateMac(); 279 EventGeneratorDelegateMac();
289 ~EventGeneratorDelegateMac() override; 280 ~EventGeneratorDelegateMac() override;
290 281
291 ui::test::EventGenerator* owner_; 282 ui::test::EventGenerator* owner_;
292 NSWindow* window_; 283 NSWindow* window_;
293 scoped_ptr<base::mac::ScopedObjCClassSwizzler> swizzle_pressed_; 284 scoped_ptr<base::mac::ScopedObjCClassSwizzler> swizzle_pressed_;
285 scoped_ptr<base::mac::ScopedObjCClassSwizzler> swizzle_current_event_;
294 base::scoped_nsobject<NSMenu> fake_menu_; 286 base::scoped_nsobject<NSMenu> fake_menu_;
295 287
296 DISALLOW_COPY_AND_ASSIGN(EventGeneratorDelegateMac); 288 DISALLOW_COPY_AND_ASSIGN(EventGeneratorDelegateMac);
297 }; 289 };
298 290
299 EventGeneratorDelegateMac::EventGeneratorDelegateMac() 291 EventGeneratorDelegateMac::EventGeneratorDelegateMac()
300 : owner_(NULL), 292 : owner_(NULL),
301 window_(NULL) { 293 window_(NULL) {
302 DCHECK(!ui::test::EventGenerator::default_delegate); 294 DCHECK(!ui::test::EventGenerator::default_delegate);
303 ui::test::EventGenerator::default_delegate = this; 295 ui::test::EventGenerator::default_delegate = this;
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
361 if ([fake_menu_ performKeyEquivalent:ns_event]) 353 if ([fake_menu_ performKeyEquivalent:ns_event])
362 return; 354 return;
363 355
364 EmulateSendEvent(window_, ns_event); 356 EmulateSendEvent(window_, ns_event);
365 } 357 }
366 358
367 void EventGeneratorDelegateMac::SetContext(ui::test::EventGenerator* owner, 359 void EventGeneratorDelegateMac::SetContext(ui::test::EventGenerator* owner,
368 gfx::NativeWindow root_window, 360 gfx::NativeWindow root_window,
369 gfx::NativeWindow window) { 361 gfx::NativeWindow window) {
370 swizzle_pressed_.reset(); 362 swizzle_pressed_.reset();
363 swizzle_current_event_.reset();
371 owner_ = owner; 364 owner_ = owner;
372 window_ = window; 365 window_ = window;
373 366
374 // Normally, edit menu items have a `nil` target. This results in -[NSMenu 367 // Normally, edit menu items have a `nil` target. This results in -[NSMenu
375 // performKeyEquivalent:] relying on -[NSApplication targetForAction:to:from:] 368 // performKeyEquivalent:] relying on -[NSApplication targetForAction:to:from:]
376 // to find a target starting at the first responder of the key window. Since 369 // to find a target starting at the first responder of the key window. Since
377 // non-interactive tests have no key window, that won't work. So set (or 370 // non-interactive tests have no key window, that won't work. So set (or
378 // clear) the target explicitly on all menu items. 371 // clear) the target explicitly on all menu items.
379 [[fake_menu_ itemArray] makeObjectsPerformSelector:@selector(setTarget:) 372 [[fake_menu_ itemArray] makeObjectsPerformSelector:@selector(setTarget:)
380 withObject:[window firstResponder]]; 373 withObject:[window firstResponder]];
381 374
382 if (owner_) { 375 if (owner_) {
383 swizzle_pressed_.reset(new base::mac::ScopedObjCClassSwizzler( 376 swizzle_pressed_.reset(new base::mac::ScopedObjCClassSwizzler(
384 [NSEvent class], 377 [NSEvent class],
385 [NSEventDonor class], 378 [NSEventDonor class],
386 @selector(pressedMouseButtons))); 379 @selector(pressedMouseButtons)));
380 swizzle_current_event_.reset(new base::mac::ScopedObjCClassSwizzler(
381 [NSApplication class],
382 [NSApplicationDonor class],
383 @selector(currentEvent)));
387 } 384 }
388 } 385 }
389 386
390 gfx::Point EventGeneratorDelegateMac::CenterOfTarget( 387 gfx::Point EventGeneratorDelegateMac::CenterOfTarget(
391 const ui::EventTarget* target) const { 388 const ui::EventTarget* target) const {
392 DCHECK_EQ(target, this); 389 DCHECK_EQ(target, this);
393 return CenterOfWindow(window_); 390 return CenterOfWindow(window_);
394 } 391 }
395 392
396 gfx::Point EventGeneratorDelegateMac::CenterOfWindow( 393 gfx::Point EventGeneratorDelegateMac::CenterOfWindow(
397 gfx::NativeWindow window) const { 394 gfx::NativeWindow window) const {
398 DCHECK_EQ(window, window_); 395 DCHECK_EQ(window, window_);
399 return gfx::ScreenRectFromNSRect([window frame]).CenterPoint(); 396 return gfx::ScreenRectFromNSRect([window frame]).CenterPoint();
400 } 397 }
401 398
402 } // namespace 399 } // namespace
403 400
404 namespace views { 401 namespace views {
405 namespace test { 402 namespace test {
406 403
407 void InitializeMacEventGeneratorDelegate() { 404 void InitializeMacEventGeneratorDelegate() {
408 EventGeneratorDelegateMac::GetInstance(); 405 EventGeneratorDelegateMac::GetInstance();
409 } 406 }
410 407
411 } // namespace test 408 } // namespace test
412 } // namespace views 409 } // namespace views
410
411 @implementation NSEventDonor
412
413 // Donate +[NSEvent pressedMouseButtons] by retrieving the flags from the
414 // active generator.
415 + (NSUInteger)pressedMouseButtons {
416 if (!g_active_generator)
417 return [NSEventDonor pressedMouseButtons]; // Call original implementation.
418
419 int flags = g_active_generator->flags();
420 NSUInteger bitmask = 0;
421 if (flags & ui::EF_LEFT_MOUSE_BUTTON)
422 bitmask |= 1;
423 if (flags & ui::EF_RIGHT_MOUSE_BUTTON)
424 bitmask |= 1 << 1;
425 if (flags & ui::EF_MIDDLE_MOUSE_BUTTON)
426 bitmask |= 1 << 2;
427 return bitmask;
428 }
429
430 @end
431
432 @implementation NSApplicationDonor
433
434 - (NSEvent*)currentEvent {
435 if (g_current_event)
436 return g_current_event;
437
438 // Find the original implementation and invoke it.
439 IMP original = EventGeneratorDelegateMac::GetInstance()->CurrentEventMethod();
440 return original(self, _cmd);
441 }
442
443 @end
OLDNEW
« ui/views/cocoa/bridged_content_view.mm ('K') | « ui/views/controls/textfield/textfield_unittest.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698