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

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

Issue 1137653005: MacViews: Implement Tooltips (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: respond to comments Created 5 years, 7 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/views/cocoa/tooltip_manager_mac.mm ('k') | ui/views/views.gyp » ('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 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.
21 ui::test::EventGenerator* g_active_generator = NULL;
22
23 // Set (and always cleared) in EmulateSendEvent() to provide an answer for 20 // Set (and always cleared) in EmulateSendEvent() to provide an answer for
24 // [NSApp currentEvent]. 21 // [NSApp currentEvent].
25 NSEvent* g_current_event = nil; 22 NSEvent* g_current_event = nil;
26 23
27 } // namespace 24 } // namespace
28 25
29 @interface NSEventDonor : NSObject 26 @interface NSEventDonor : NSObject
30 @end 27 @end
31 28
32 @interface NSApplicationDonor : NSObject 29 @interface NSApplicationDonor : NSObject
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
227 public ui::test::EventGeneratorDelegate { 224 public ui::test::EventGeneratorDelegate {
228 public: 225 public:
229 static EventGeneratorDelegateMac* GetInstance() { 226 static EventGeneratorDelegateMac* GetInstance() {
230 return Singleton<EventGeneratorDelegateMac>::get(); 227 return Singleton<EventGeneratorDelegateMac>::get();
231 } 228 }
232 229
233 IMP CurrentEventMethod() { 230 IMP CurrentEventMethod() {
234 return swizzle_current_event_->GetOriginalImplementation(); 231 return swizzle_current_event_->GetOriginalImplementation();
235 } 232 }
236 233
234 NSWindow* window() { return window_.get(); }
235 ui::test::EventGenerator* owner() { return owner_; }
236
237 // Overridden from ui::EventTarget: 237 // Overridden from ui::EventTarget:
238 bool CanAcceptEvent(const ui::Event& event) override { return true; } 238 bool CanAcceptEvent(const ui::Event& event) override { return true; }
239 ui::EventTarget* GetParentTarget() override { return NULL; } 239 ui::EventTarget* GetParentTarget() override { return NULL; }
240 scoped_ptr<ui::EventTargetIterator> GetChildIterator() const override; 240 scoped_ptr<ui::EventTargetIterator> GetChildIterator() const override;
241 ui::EventTargeter* GetEventTargeter() override { return this; } 241 ui::EventTargeter* GetEventTargeter() override { return this; }
242 242
243 // Overridden from ui::EventHandler (via ui::EventTarget): 243 // Overridden from ui::EventHandler (via ui::EventTarget):
244 void OnMouseEvent(ui::MouseEvent* event) override; 244 void OnMouseEvent(ui::MouseEvent* event) override;
245 void OnKeyEvent(ui::KeyEvent* event) override; 245 void OnKeyEvent(ui::KeyEvent* event) override;
246 void OnTouchEvent(ui::TouchEvent* event) override; 246 void OnTouchEvent(ui::TouchEvent* event) override;
(...skipping 29 matching lines...) Expand all
276 276
277 private: 277 private:
278 friend struct DefaultSingletonTraits<EventGeneratorDelegateMac>; 278 friend struct DefaultSingletonTraits<EventGeneratorDelegateMac>;
279 279
280 EventGeneratorDelegateMac(); 280 EventGeneratorDelegateMac();
281 ~EventGeneratorDelegateMac() override; 281 ~EventGeneratorDelegateMac() override;
282 282
283 ui::test::EventGenerator* owner_; 283 ui::test::EventGenerator* owner_;
284 base::scoped_nsobject<NSWindow> window_; 284 base::scoped_nsobject<NSWindow> window_;
285 scoped_ptr<base::mac::ScopedObjCClassSwizzler> swizzle_pressed_; 285 scoped_ptr<base::mac::ScopedObjCClassSwizzler> swizzle_pressed_;
286 scoped_ptr<base::mac::ScopedObjCClassSwizzler> swizzle_location_;
286 scoped_ptr<base::mac::ScopedObjCClassSwizzler> swizzle_current_event_; 287 scoped_ptr<base::mac::ScopedObjCClassSwizzler> swizzle_current_event_;
287 base::scoped_nsobject<NSMenu> fake_menu_; 288 base::scoped_nsobject<NSMenu> fake_menu_;
288 289
289 DISALLOW_COPY_AND_ASSIGN(EventGeneratorDelegateMac); 290 DISALLOW_COPY_AND_ASSIGN(EventGeneratorDelegateMac);
290 }; 291 };
291 292
292 EventGeneratorDelegateMac::EventGeneratorDelegateMac() : owner_(NULL) { 293 EventGeneratorDelegateMac::EventGeneratorDelegateMac() : owner_(NULL) {
293 DCHECK(!ui::test::EventGenerator::default_delegate); 294 DCHECK(!ui::test::EventGenerator::default_delegate);
294 ui::test::EventGenerator::default_delegate = this; 295 ui::test::EventGenerator::default_delegate = this;
295 // Install a fake "edit" menu. This is normally provided by Chrome's 296 // Install a fake "edit" menu. This is normally provided by Chrome's
(...skipping 24 matching lines...) Expand all
320 ui::test::EventGenerator::default_delegate = NULL; 321 ui::test::EventGenerator::default_delegate = NULL;
321 } 322 }
322 323
323 scoped_ptr<ui::EventTargetIterator> 324 scoped_ptr<ui::EventTargetIterator>
324 EventGeneratorDelegateMac::GetChildIterator() const { 325 EventGeneratorDelegateMac::GetChildIterator() const {
325 // Return NULL to dispatch all events to the result of GetRootTarget(). 326 // Return NULL to dispatch all events to the result of GetRootTarget().
326 return nullptr; 327 return nullptr;
327 } 328 }
328 329
329 void EventGeneratorDelegateMac::OnMouseEvent(ui::MouseEvent* event) { 330 void EventGeneratorDelegateMac::OnMouseEvent(ui::MouseEvent* event) {
330 // For mouse drag events, ensure the swizzled methods return the right flags.
331 base::AutoReset<ui::test::EventGenerator*> reset(&g_active_generator, owner_);
332 NSEvent* ns_event = CreateMouseEventInWindow(window_, 331 NSEvent* ns_event = CreateMouseEventInWindow(window_,
333 event->type(), 332 event->type(),
334 event->location(), 333 event->location(),
335 event->changed_button_flags()); 334 event->changed_button_flags());
336 if (owner_->targeting_application()) 335 if (owner_->targeting_application())
337 [NSApp sendEvent:ns_event]; 336 [NSApp sendEvent:ns_event];
338 else 337 else
339 EmulateSendEvent(window_, ns_event); 338 EmulateSendEvent(window_, ns_event);
340 } 339 }
341 340
(...skipping 14 matching lines...) Expand all
356 } 355 }
357 356
358 void EventGeneratorDelegateMac::OnTouchEvent(ui::TouchEvent* event) { 357 void EventGeneratorDelegateMac::OnTouchEvent(ui::TouchEvent* event) {
359 NOTREACHED() << "Touchscreen events not supported on Chrome Mac."; 358 NOTREACHED() << "Touchscreen events not supported on Chrome Mac.";
360 } 359 }
361 360
362 void EventGeneratorDelegateMac::SetContext(ui::test::EventGenerator* owner, 361 void EventGeneratorDelegateMac::SetContext(ui::test::EventGenerator* owner,
363 gfx::NativeWindow root_window, 362 gfx::NativeWindow root_window,
364 gfx::NativeWindow window) { 363 gfx::NativeWindow window) {
365 swizzle_pressed_.reset(); 364 swizzle_pressed_.reset();
365 swizzle_location_.reset();
366 swizzle_current_event_.reset(); 366 swizzle_current_event_.reset();
367 owner_ = owner; 367 owner_ = owner;
368 368
369 // Retain the NSWindow (note it can be nil). This matches Cocoa's tendency to 369 // Retain the NSWindow (note it can be nil). This matches Cocoa's tendency to
370 // have autoreleased objects, or objects still in the event queue, that 370 // have autoreleased objects, or objects still in the event queue, that
371 // reference the NSWindow. 371 // reference the NSWindow.
372 window_.reset([window retain]); 372 window_.reset([window retain]);
373 373
374 // Normally, edit menu items have a `nil` target. This results in -[NSMenu 374 // Normally, edit menu items have a `nil` target. This results in -[NSMenu
375 // performKeyEquivalent:] relying on -[NSApplication targetForAction:to:from:] 375 // performKeyEquivalent:] relying on -[NSApplication targetForAction:to:from:]
376 // to find a target starting at the first responder of the key window. Since 376 // 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 377 // non-interactive tests have no key window, that won't work. So set (or
378 // clear) the target explicitly on all menu items. 378 // clear) the target explicitly on all menu items.
379 [[fake_menu_ itemArray] makeObjectsPerformSelector:@selector(setTarget:) 379 [[fake_menu_ itemArray] makeObjectsPerformSelector:@selector(setTarget:)
380 withObject:[window firstResponder]]; 380 withObject:[window firstResponder]];
381 381
382 if (owner_) { 382 if (owner_) {
383 swizzle_pressed_.reset(new base::mac::ScopedObjCClassSwizzler( 383 swizzle_pressed_.reset(new base::mac::ScopedObjCClassSwizzler(
384 [NSEvent class], 384 [NSEvent class],
385 [NSEventDonor class], 385 [NSEventDonor class],
386 @selector(pressedMouseButtons))); 386 @selector(pressedMouseButtons)));
387 swizzle_location_.reset(new base::mac::ScopedObjCClassSwizzler(
388 [NSEvent class], [NSEventDonor class], @selector(mouseLocation)));
387 swizzle_current_event_.reset(new base::mac::ScopedObjCClassSwizzler( 389 swizzle_current_event_.reset(new base::mac::ScopedObjCClassSwizzler(
388 [NSApplication class], 390 [NSApplication class],
389 [NSApplicationDonor class], 391 [NSApplicationDonor class],
390 @selector(currentEvent))); 392 @selector(currentEvent)));
391 } 393 }
392 } 394 }
393 395
394 gfx::Point EventGeneratorDelegateMac::CenterOfTarget( 396 gfx::Point EventGeneratorDelegateMac::CenterOfTarget(
395 const ui::EventTarget* target) const { 397 const ui::EventTarget* target) const {
396 DCHECK_EQ(target, this); 398 DCHECK_EQ(target, this);
397 return CenterOfWindow(window_); 399 return CenterOfWindow(window_);
398 } 400 }
399 401
400 gfx::Point EventGeneratorDelegateMac::CenterOfWindow( 402 gfx::Point EventGeneratorDelegateMac::CenterOfWindow(
401 gfx::NativeWindow window) const { 403 gfx::NativeWindow window) const {
402 DCHECK_EQ(window, window_); 404 DCHECK_EQ(window, window_);
403 return gfx::ScreenRectFromNSRect([window frame]).CenterPoint(); 405 return gfx::ScreenRectFromNSRect([window frame]).CenterPoint();
404 } 406 }
405 407
408 // Return the current owner of the EventGeneratorDelegate. May be null.
409 ui::test::EventGenerator* GetActiveGenerator() {
410 return EventGeneratorDelegateMac::GetInstance()->owner();
411 }
412
406 } // namespace 413 } // namespace
407 414
408 namespace views { 415 namespace views {
409 namespace test { 416 namespace test {
410 417
411 void InitializeMacEventGeneratorDelegate() { 418 void InitializeMacEventGeneratorDelegate() {
412 EventGeneratorDelegateMac::GetInstance(); 419 EventGeneratorDelegateMac::GetInstance();
413 } 420 }
414 421
415 } // namespace test 422 } // namespace test
416 } // namespace views 423 } // namespace views
417 424
418 @implementation NSEventDonor 425 @implementation NSEventDonor
419 426
420 // Donate +[NSEvent pressedMouseButtons] by retrieving the flags from the 427 // Donate +[NSEvent pressedMouseButtons] by retrieving the flags from the
421 // active generator. 428 // active generator.
422 + (NSUInteger)pressedMouseButtons { 429 + (NSUInteger)pressedMouseButtons {
423 if (!g_active_generator) 430 ui::test::EventGenerator* generator = GetActiveGenerator();
431 if (!generator)
424 return [NSEventDonor pressedMouseButtons]; // Call original implementation. 432 return [NSEventDonor pressedMouseButtons]; // Call original implementation.
425 433
426 int flags = g_active_generator->flags(); 434 int flags = generator->flags();
427 NSUInteger bitmask = 0; 435 NSUInteger bitmask = 0;
428 if (flags & ui::EF_LEFT_MOUSE_BUTTON) 436 if (flags & ui::EF_LEFT_MOUSE_BUTTON)
429 bitmask |= 1; 437 bitmask |= 1;
430 if (flags & ui::EF_RIGHT_MOUSE_BUTTON) 438 if (flags & ui::EF_RIGHT_MOUSE_BUTTON)
431 bitmask |= 1 << 1; 439 bitmask |= 1 << 1;
432 if (flags & ui::EF_MIDDLE_MOUSE_BUTTON) 440 if (flags & ui::EF_MIDDLE_MOUSE_BUTTON)
433 bitmask |= 1 << 2; 441 bitmask |= 1 << 2;
434 return bitmask; 442 return bitmask;
435 } 443 }
436 444
445 // Donate +[NSEvent mouseLocation] by retrieving the current position on screen.
446 + (NSPoint)mouseLocation {
447 ui::test::EventGenerator* generator = GetActiveGenerator();
448 if (!generator)
449 return [NSEventDonor mouseLocation]; // Call original implementation.
450
451 // The location is the point in the root window which, for desktop widgets, is
452 // the widget itself.
453 gfx::Point point_in_root = generator->current_location();
454 NSWindow* window = EventGeneratorDelegateMac::GetInstance()->window();
455 NSPoint point_in_window = ConvertRootPointToTarget(window, point_in_root);
456 return [window convertBaseToScreen:point_in_window];
457 }
458
437 @end 459 @end
438 460
439 @implementation NSApplicationDonor 461 @implementation NSApplicationDonor
440 462
441 - (NSEvent*)currentEvent { 463 - (NSEvent*)currentEvent {
442 if (g_current_event) 464 if (g_current_event)
443 return g_current_event; 465 return g_current_event;
444 466
445 // Find the original implementation and invoke it. 467 // Find the original implementation and invoke it.
446 IMP original = EventGeneratorDelegateMac::GetInstance()->CurrentEventMethod(); 468 IMP original = EventGeneratorDelegateMac::GetInstance()->CurrentEventMethod();
447 return original(self, _cmd); 469 return original(self, _cmd);
448 } 470 }
449 471
450 @end 472 @end
OLDNEW
« no previous file with comments | « ui/views/cocoa/tooltip_manager_mac.mm ('k') | ui/views/views.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698