blob: 996a5ca4182cdf9492b937479f3c97fd2b90973d (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
|
// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "chrome/browser/cocoa/hover_close_button.h"
#include "app/l10n_util.h"
#include "base/nsimage_cache_mac.h"
#include "grit/generated_resources.h"
namespace {
const NSString* kNormalImageString = @"close_bar.pdf";
const NSString* kHoverImageString = @"close_bar_h.pdf";
const NSString* kPressedImageString = @"close_bar_p.pdf";
}
@implementation HoverCloseButton
- (id)initWithFrame:(NSRect)frameRect {
if ((self = [super initWithFrame:frameRect])) {
[self commonInit];
}
return self;
}
- (void)awakeFromNib {
[self commonInit];
}
- (void)commonInit {
[self setTrackingEnabled:YES];
NSImage* alternateImage = nsimage_cache::ImageNamed(kPressedImageString);
[self setAlternateImage:alternateImage];
[self updateTrackingAreas];
// Set accessibility description.
NSString* description = l10n_util::GetNSStringWithFixup(IDS_ACCNAME_CLOSE);
[[self cell]
accessibilitySetOverrideValue:description
forAttribute:NSAccessibilityDescriptionAttribute];
}
- (void)dealloc {
[self setTrackingEnabled:NO];
[super dealloc];
}
- (void)mouseEntered:(NSEvent*)theEvent {
[self setImage:nsimage_cache::ImageNamed(kHoverImageString)];
}
- (void)mouseExited:(NSEvent*)theEvent {
[self setImage:nsimage_cache::ImageNamed(kNormalImageString)];
}
- (void)mouseDown:(NSEvent*)theEvent {
// The hover button needs to hold onto itself here for a bit. Otherwise,
// it can be freed while |super mouseDown:| is in it's loop, and the
// |checkImageState| call will crash.
// http://crbug.com/28220
scoped_nsobject<HoverCloseButton> myself([self retain]);
[super mouseDown:theEvent];
// We need to check the image state after the mouseDown event loop finishes.
// It's possible that we won't get a mouseExited event if the button was
// moved under the mouse during tab resize, instead of the mouse moving over
// the button.
// http://crbug.com/31279
[self checkImageState];
}
- (void)setTrackingEnabled:(BOOL)enabled {
if (enabled) {
closeTrackingArea_.reset(
[[NSTrackingArea alloc] initWithRect:[self bounds]
options:NSTrackingMouseEnteredAndExited |
NSTrackingActiveAlways
owner:self
userInfo:nil]);
[self addTrackingArea:closeTrackingArea_.get()];
// If you have a separate window that overlaps the close button, and you
// move the mouse directly over the close button without entering another
// part of the tab strip, we don't get any mouseEntered event since the
// tracking area was disabled when we entered.
[self checkImageState];
} else {
if (closeTrackingArea_.get()) {
[self removeTrackingArea:closeTrackingArea_.get()];
closeTrackingArea_.reset(nil);
}
}
}
- (void)updateTrackingAreas {
[super updateTrackingAreas];
[self checkImageState];
}
- (void)checkImageState {
if (closeTrackingArea_.get()) {
// Update the close buttons if the tab has moved.
NSPoint mouseLoc = [[self window] mouseLocationOutsideOfEventStream];
mouseLoc = [self convertPoint:mouseLoc fromView:nil];
NSString* name = NSPointInRect(mouseLoc, [self bounds]) ?
kHoverImageString : kNormalImageString;
NSImage* newImage = nsimage_cache::ImageNamed(name);
NSImage* buttonImage = [self image];
if (![buttonImage isEqual:newImage]) {
[self setImage:newImage];
}
}
}
@end
|