Commit 40f734ce authored by shrike's avatar shrike Committed by Commit Bot

[Mac] Update tab close button when user drags outside

When clicking inside a button and dragging the mouse out of the button's
bounds, a button should update its appearance to show that its action
will not fire if the user releases the mouse. This cl fixes a problem
with the tab close button where it would always show the mouse down
state, even if you clicked and dragged outside of it.

This cl also does a little refactoring, moving common init-time code to
a commonInit method (like its HoverCloseButton subclass).

R=avi@chromium.org
BUG=647757

Review-Url: https://codereview.chromium.org/2898343002
Cr-Commit-Position: refs/heads/master@{#476463}
parent 165f26ee
...@@ -59,16 +59,18 @@ const SkColor kDefaultIconColor = SkColorSetARGB(0xA0, 0x00, 0x00, 0x00); ...@@ -59,16 +59,18 @@ const SkColor kDefaultIconColor = SkColorSetARGB(0xA0, 0x00, 0x00, 0x00);
gTooltip = [l10n_util::GetNSStringWithFixup(IDS_TOOLTIP_CLOSE_TAB) copy]; gTooltip = [l10n_util::GetNSStringWithFixup(IDS_TOOLTIP_CLOSE_TAB) copy];
} }
- (id)initWithFrame:(NSRect)frameRect { - (void)commonInit {
if ((self = [super initWithFrame:frameRect])) { [super commonInit];
[self commonInit];
} [self setAccessibilityTitle:nil];
return self;
} // Add a tooltip. Using 'owner:self' means that
// -view:stringForToolTip:point:userData: will be called to provide the
// tooltip contents immediately before showing it.
[self addToolTipRect:[self bounds] owner:self userData:NULL];
- (void)awakeFromNib { previousState_ = kHoverStateNone;
[super awakeFromNib]; iconColor_ = kDefaultIconColor;
[self commonInit];
} }
- (void)removeFromSuperview { - (void)removeFromSuperview {
...@@ -198,18 +200,6 @@ const SkColor kDefaultIconColor = SkColorSetARGB(0xA0, 0x00, 0x00, 0x00); ...@@ -198,18 +200,6 @@ const SkColor kDefaultIconColor = SkColorSetARGB(0xA0, 0x00, 0x00, 0x00);
} }
} }
- (void)commonInit {
[self setAccessibilityTitle:nil];
// Add a tooltip. Using 'owner:self' means that
// -view:stringForToolTip:point:userData: will be called to provide the
// tooltip contents immediately before showing it.
[self addToolTipRect:[self bounds] owner:self userData:NULL];
previousState_ = kHoverStateNone;
iconColor_ = kDefaultIconColor;
}
// Called each time a tooltip is about to be shown. // Called each time a tooltip is about to be shown.
- (NSString*)view:(NSView*)view - (NSString*)view:(NSView*)view
stringForToolTip:(NSToolTipTag)tag stringForToolTip:(NSToolTipTag)tag
......
...@@ -27,10 +27,15 @@ UI_BASE_EXPORT ...@@ -27,10 +27,15 @@ UI_BASE_EXPORT
@private @private
// Tracking area for button mouseover states. Nil if not enabled. // Tracking area for button mouseover states. Nil if not enabled.
ui::ScopedCrTrackingArea trackingArea_; ui::ScopedCrTrackingArea trackingArea_;
BOOL mouseDown_;
} }
@property(nonatomic) HoverState hoverState; @property(nonatomic) HoverState hoverState;
// Common initialization called from initWithFrame: and awakeFromNib.
// Subclassers should call [super commonInit].
- (void)commonInit;
// Text that would be announced by screen readers. // Text that would be announced by screen readers.
- (void)setAccessibilityTitle:(NSString*)accessibilityTitle; - (void)setAccessibilityTitle:(NSString*)accessibilityTitle;
......
...@@ -10,14 +10,16 @@ ...@@ -10,14 +10,16 @@
- (id)initWithFrame:(NSRect)frameRect { - (id)initWithFrame:(NSRect)frameRect {
if ((self = [super initWithFrame:frameRect])) { if ((self = [super initWithFrame:frameRect])) {
[self setTrackingEnabled:YES]; [self commonInit];
hoverState_ = kHoverStateNone;
[self updateTrackingAreas];
} }
return self; return self;
} }
- (void)awakeFromNib { - (void)awakeFromNib {
[self commonInit];
}
- (void)commonInit {
[self setTrackingEnabled:YES]; [self setTrackingEnabled:YES];
self.hoverState = kHoverStateNone; self.hoverState = kHoverStateNone;
[self updateTrackingAreas]; [self updateTrackingAreas];
...@@ -33,30 +35,53 @@ ...@@ -33,30 +35,53 @@
self.hoverState = kHoverStateMouseOver; self.hoverState = kHoverStateMouseOver;
} }
- (void)mouseMoved:(NSEvent*)theEvent {
[self checkImageState];
}
- (void)mouseExited:(NSEvent*)theEvent { - (void)mouseExited:(NSEvent*)theEvent {
if (trackingArea_.get()) if (trackingArea_.get())
self.hoverState = kHoverStateNone; self.hoverState = kHoverStateNone;
} }
- (void)mouseMoved:(NSEvent*)theEvent {
[self checkImageState];
}
- (void)mouseDown:(NSEvent*)theEvent { - (void)mouseDown:(NSEvent*)theEvent {
mouseDown_ = YES;
self.hoverState = kHoverStateMouseDown; self.hoverState = kHoverStateMouseDown;
// The hover button needs to hold onto itself here for a bit. Otherwise, // The hover button needs to hold onto itself here for a bit. Otherwise,
// it can be freed while |super mouseDown:| is in its loop, and the // it can be freed while in the tracking loop below.
// |checkImageState| call will crash.
// http://crbug.com/28220 // http://crbug.com/28220
base::scoped_nsobject<HoverButton> myself([self retain]); base::scoped_nsobject<HoverButton> myself([self retain]);
[super mouseDown:theEvent]; // Begin tracking the mouse.
// We need to check the image state after the mouseDown event loop finishes. if ([theEvent type] == NSLeftMouseDown) {
// It's possible that we won't get a mouseExited event if the button was NSWindow* window = [self window];
// moved under the mouse during tab resize, instead of the mouse moving over NSEvent* nextEvent = nil;
// the button.
// http://crbug.com/31279 // For the tracking loop ignore key events so that they don't pile up in
[self checkImageState]; // the queue and get processed after the user releases the mouse.
const NSEventMask eventMask = (NSLeftMouseDraggedMask | NSLeftMouseUpMask |
NSKeyDownMask | NSKeyUpMask);
while ((nextEvent = [window nextEventMatchingMask:eventMask])) {
// Update the image state, which will change if the user moves the mouse
// into or out of the button.
[self checkImageState];
if ([nextEvent type] == NSLeftMouseUp) {
break;
}
}
}
// If the mouse is still over the button, it means the user clicked the
// button.
if (self.hoverState == kHoverStateMouseDown) {
[self performClick:nil];
}
// Clean up.
mouseDown_ = NO;
} }
- (void)setAccessibilityTitle:(NSString*)accessibilityTitle { - (void)setAccessibilityTitle:(NSString*)accessibilityTitle {
...@@ -108,8 +133,12 @@ ...@@ -108,8 +133,12 @@
// Update the button's state if the button has moved. // Update the button's state if the button has moved.
NSPoint mouseLoc = [[self window] mouseLocationOutsideOfEventStream]; NSPoint mouseLoc = [[self window] mouseLocationOutsideOfEventStream];
mouseLoc = [self convertPoint:mouseLoc fromView:nil]; mouseLoc = [self convertPoint:mouseLoc fromView:nil];
self.hoverState = NSPointInRect(mouseLoc, [self bounds]) ? BOOL mouseInBounds = NSPointInRect(mouseLoc, [self bounds]);
kHoverStateMouseOver : kHoverStateNone; if (mouseDown_ && mouseInBounds) {
self.hoverState = kHoverStateMouseDown;
} else {
self.hoverState = mouseInBounds ? kHoverStateMouseOver : kHoverStateNone;
}
} }
- (void)setHoverState:(HoverState)state { - (void)setHoverState:(HoverState)state {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment