Chromium Code Reviews| Index: ui/base/cocoa/base_view.mm |
| diff --git a/ui/base/cocoa/base_view.mm b/ui/base/cocoa/base_view.mm |
| index b37b6789435d8a6da2698e72d63b1779adba2957..4d2b6025d3b9e0f211c7fa9f4e3895919bafd626 100644 |
| --- a/ui/base/cocoa/base_view.mm |
| +++ b/ui/base/cocoa/base_view.mm |
| @@ -8,20 +8,83 @@ NSString* kViewDidBecomeFirstResponder = |
| @"Chromium.kViewDidBecomeFirstResponder"; |
| NSString* kSelectionDirection = @"Chromium.kSelectionDirection"; |
| -const int kTrackingOptions = NSTrackingMouseMoved | |
| - NSTrackingMouseEnteredAndExited | |
| - NSTrackingActiveAlways; |
| - |
| @implementation BaseView |
| +- (instancetype)initWithFrame:(NSRect)frame |
| + wantsReliableMouseEvents:(BOOL)wantsReliableMouseEvents { |
| + if ((self = [super initWithFrame:frame])) { |
| + [self initBaseViewUsingEventTap:wantsReliableMouseEvents]; |
| + } |
| + return self; |
| +} |
| + |
| +- (instancetype)initWithFrame:(NSRect)frame { |
| + if ((self = [super initWithFrame:frame])) { |
| + [self initBaseViewUsingEventTap:NO]; |
| + } |
| + return self; |
| +} |
| + |
| +- (instancetype)initWithCoder:(NSCoder*)decoder { |
| + if ((self = [super initWithCoder:decoder])) { |
| + [self initBaseViewUsingEventTap:NO]; |
| + } |
| + return self; |
| +} |
| + |
| +- (void)initBaseViewUsingEventTap:(BOOL)wantsReliableMouseEvents { |
|
Scott Hess - ex-Googler
2015/02/27 17:56:11
IMHO this should not be called -init*, since the c
|
| + NSTrackingAreaOptions trackingOptions = NSTrackingMouseEnteredAndExited | |
| + NSTrackingActiveAlways | |
| + NSTrackingInVisibleRect; |
| + if (!wantsReliableMouseEvents) |
| + trackingOptions |= NSTrackingMouseMoved; |
|
Scott Hess - ex-Googler
2015/02/27 17:56:11
If this approach is sufficiently performant to use
|
| + trackingArea_.reset([[CrTrackingArea alloc] initWithRect:NSZeroRect |
| + options:trackingOptions |
| + owner:self |
| + userInfo:nil]); |
| + [self addTrackingArea:trackingArea_.get()]; |
| + |
| + if (wantsReliableMouseEvents) { |
| + // Workaround for http://crbug.com/176725 |
| + // Check if the mouse moved over us. |
| + // Don't do it if we are firstResponder to avoid processing the event twice. |
| + eventTap_ = [NSEvent addLocalMonitorForEventsMatchingMask:NSMouseMovedMask |
| + handler:^NSEvent*(NSEvent* event) { |
| + NSWindow* window = [self window]; |
| + if (window && window == [event window] && |
| + [window firstResponder] != self) { |
| + NSPoint location = |
| + [[self superview] convertPoint:[event locationInWindow] |
| + fromView:nil]; |
| + if ([self hitTest:location]) |
| + [self mouseMoved:event]; |
| + } |
| + return event; |
| + }]; |
| + } |
| +} |
| + |
| - (void)dealloc { |
| if (trackingArea_.get()) |
| [self removeTrackingArea:trackingArea_.get()]; |
| trackingArea_.reset(nil); |
| + if (eventTap_) |
| + [NSEvent removeMonitor:eventTap_]; |
| + |
| [super dealloc]; |
| } |
| +- (void)viewDidMoveToWindow { |
| + [super viewDidMoveToWindow]; |
| + |
| + // Ensure our event tap gets mouse moved events. The mouse moved events are |
| + // normally sent to the window's firstResponder (like key events, unlike |
| + // other mouse events). |
| + if (eventTap_) |
| + [[self window] setAcceptsMouseMovedEvents:YES]; |
| +} |
| + |
| - (void)mouseEvent:(NSEvent*)theEvent { |
| // This method left intentionally blank. |
| } |
| @@ -138,19 +201,4 @@ const int kTrackingOptions = NSTrackingMouseMoved | |
| return new_rect; |
| } |
| -- (void)updateTrackingAreas { |
| - [super updateTrackingAreas]; |
| - |
| - // NSTrackingInVisibleRect doesn't work correctly with Lion's window resizing, |
| - // http://crbug.com/176725 / http://openradar.appspot.com/radar?id=2773401 . |
| - // Tear down old tracking area and create a new one as workaround. |
| - if (trackingArea_.get()) |
| - [self removeTrackingArea:trackingArea_.get()]; |
| - trackingArea_.reset([[CrTrackingArea alloc] initWithRect:[self bounds] |
| - options:kTrackingOptions |
| - owner:self |
| - userInfo:nil]); |
| - [self addTrackingArea:trackingArea_.get()]; |
| -} |
| - |
| @end |