| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 "chrome/browser/ui/cocoa/hover_button.h" | 5 #import "chrome/browser/ui/cocoa/hover_button.h" |
| 6 #import "chrome/browser/ui/cocoa/tracking_area.h" |
| 6 | 7 |
| 7 @implementation HoverButton | 8 @implementation HoverButton |
| 8 | 9 |
| 10 @synthesize hoverState = hoverState_; |
| 11 |
| 9 - (id)initWithFrame:(NSRect)frameRect { | 12 - (id)initWithFrame:(NSRect)frameRect { |
| 10 if ((self = [super initWithFrame:frameRect])) { | 13 if ((self = [super initWithFrame:frameRect])) { |
| 11 [self setTrackingEnabled:YES]; | 14 [self setTrackingEnabled:YES]; |
| 12 hoverState_ = kHoverStateNone; | 15 hoverState_ = kHoverStateNone; |
| 13 [self updateTrackingAreas]; | 16 [self updateTrackingAreas]; |
| 14 } | 17 } |
| 15 return self; | 18 return self; |
| 16 } | 19 } |
| 17 | 20 |
| 18 - (void)awakeFromNib { | 21 - (void)awakeFromNib { |
| 19 [self setTrackingEnabled:YES]; | 22 [self setTrackingEnabled:YES]; |
| 20 hoverState_ = kHoverStateNone; | 23 self.hoverState = kHoverStateNone; |
| 21 [self updateTrackingAreas]; | 24 [self updateTrackingAreas]; |
| 22 } | 25 } |
| 23 | 26 |
| 24 - (void)dealloc { | 27 - (void)dealloc { |
| 25 [self setTrackingEnabled:NO]; | 28 [self setTrackingEnabled:NO]; |
| 26 [super dealloc]; | 29 [super dealloc]; |
| 27 } | 30 } |
| 28 | 31 |
| 29 - (void)mouseEntered:(NSEvent*)theEvent { | 32 - (void)mouseEntered:(NSEvent*)theEvent { |
| 30 hoverState_ = kHoverStateMouseOver; | 33 self.hoverState = kHoverStateMouseOver; |
| 31 [self setNeedsDisplay:YES]; | |
| 32 } | 34 } |
| 33 | 35 |
| 34 - (void)mouseExited:(NSEvent*)theEvent { | 36 - (void)mouseExited:(NSEvent*)theEvent { |
| 35 hoverState_ = kHoverStateNone; | 37 self.hoverState = kHoverStateNone; |
| 36 [self setNeedsDisplay:YES]; | |
| 37 } | 38 } |
| 38 | 39 |
| 39 - (void)mouseDown:(NSEvent*)theEvent { | 40 - (void)mouseDown:(NSEvent*)theEvent { |
| 40 hoverState_ = kHoverStateMouseDown; | 41 self.hoverState = kHoverStateMouseDown; |
| 41 [self setNeedsDisplay:YES]; | |
| 42 // The hover button needs to hold onto itself here for a bit. Otherwise, | 42 // The hover button needs to hold onto itself here for a bit. Otherwise, |
| 43 // it can be freed while |super mouseDown:| is in it's loop, and the | 43 // it can be freed while |super mouseDown:| is in it's loop, and the |
| 44 // |checkImageState| call will crash. | 44 // |checkImageState| call will crash. |
| 45 // http://crbug.com/28220 | 45 // http://crbug.com/28220 |
| 46 scoped_nsobject<HoverButton> myself([self retain]); | 46 scoped_nsobject<HoverButton> myself([self retain]); |
| 47 | 47 |
| 48 [super mouseDown:theEvent]; | 48 [super mouseDown:theEvent]; |
| 49 // We need to check the image state after the mouseDown event loop finishes. | 49 // We need to check the image state after the mouseDown event loop finishes. |
| 50 // It's possible that we won't get a mouseExited event if the button was | 50 // It's possible that we won't get a mouseExited event if the button was |
| 51 // moved under the mouse during tab resize, instead of the mouse moving over | 51 // moved under the mouse during tab resize, instead of the mouse moving over |
| 52 // the button. | 52 // the button. |
| 53 // http://crbug.com/31279 | 53 // http://crbug.com/31279 |
| 54 [self checkImageState]; | 54 [self checkImageState]; |
| 55 } | 55 } |
| 56 | 56 |
| 57 - (void)setTrackingEnabled:(BOOL)enabled { | 57 - (void)setTrackingEnabled:(BOOL)enabled { |
| 58 if (enabled) { | 58 if (enabled) { |
| 59 trackingArea_.reset( | 59 trackingArea_.reset( |
| 60 [[NSTrackingArea alloc] initWithRect:[self bounds] | 60 [[CrTrackingArea alloc] initWithRect:[self bounds] |
| 61 options:NSTrackingMouseEnteredAndExited | | 61 options:NSTrackingMouseEnteredAndExited | |
| 62 NSTrackingActiveAlways | 62 NSTrackingActiveAlways |
| 63 owner:self | 63 proxiedOwner:self |
| 64 userInfo:nil]); | 64 userInfo:nil]); |
| 65 [self addTrackingArea:trackingArea_.get()]; | 65 [self addTrackingArea:trackingArea_.get()]; |
| 66 | 66 |
| 67 // If you have a separate window that overlaps the close button, and you | 67 // If you have a separate window that overlaps the close button, and you |
| 68 // move the mouse directly over the close button without entering another | 68 // move the mouse directly over the close button without entering another |
| 69 // part of the tab strip, we don't get any mouseEntered event since the | 69 // part of the tab strip, we don't get any mouseEntered event since the |
| 70 // tracking area was disabled when we entered. | 70 // tracking area was disabled when we entered. |
| 71 [self checkImageState]; | 71 // Done with a delay of 0 because sometimes an event appears to be missed |
| 72 // between the activation of the tracking area and the call to |
| 73 // checkImageState resulting in the button state being incorrect. |
| 74 [self performSelector:@selector(checkImageState) |
| 75 withObject:nil |
| 76 afterDelay:0]; |
| 72 } else { | 77 } else { |
| 73 if (trackingArea_.get()) { | 78 if (trackingArea_.get()) { |
| 74 [self removeTrackingArea:trackingArea_.get()]; | 79 [self removeTrackingArea:trackingArea_.get()]; |
| 75 trackingArea_.reset(nil); | 80 trackingArea_.reset(nil); |
| 76 } | 81 } |
| 77 } | 82 } |
| 78 } | 83 } |
| 79 | 84 |
| 80 - (void)updateTrackingAreas { | 85 - (void)updateTrackingAreas { |
| 81 [super updateTrackingAreas]; | 86 [super updateTrackingAreas]; |
| 82 [self checkImageState]; | 87 [self checkImageState]; |
| 83 } | 88 } |
| 84 | 89 |
| 85 - (void)checkImageState { | 90 - (void)checkImageState { |
| 86 if (!trackingArea_.get()) | 91 if (!trackingArea_.get()) |
| 87 return; | 92 return; |
| 88 | 93 |
| 89 // Update the button's state if the button has moved. | 94 // Update the button's state if the button has moved. |
| 90 NSPoint mouseLoc = [[self window] mouseLocationOutsideOfEventStream]; | 95 NSPoint mouseLoc = [[self window] mouseLocationOutsideOfEventStream]; |
| 91 mouseLoc = [self convertPoint:mouseLoc fromView:nil]; | 96 mouseLoc = [self convertPoint:mouseLoc fromView:nil]; |
| 92 hoverState_ = NSPointInRect(mouseLoc, [self bounds]) ? | 97 self.hoverState = NSPointInRect(mouseLoc, [self bounds]) ? |
| 93 kHoverStateMouseOver : kHoverStateNone; | 98 kHoverStateMouseOver : kHoverStateNone; |
| 99 } |
| 100 |
| 101 - (void)setHoverState:(HoverState)state { |
| 102 hoverState_ = state; |
| 94 [self setNeedsDisplay:YES]; | 103 [self setNeedsDisplay:YES]; |
| 95 } | 104 } |
| 96 | 105 |
| 97 @end | 106 @end |
| OLD | NEW |