summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordmaclach@chromium.org <dmaclach@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-11-13 22:11:50 +0000
committerdmaclach@chromium.org <dmaclach@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-11-13 22:11:50 +0000
commit108a96fe15de05d91fe9a0a2eb39c3edd287c123 (patch)
tree13bc4245b37371b75d7b64cdeb4c30b070bddc25
parentf30a566d7fcc4c56004f40e9db160906bdf9ac8c (diff)
downloadchromium_src-108a96fe15de05d91fe9a0a2eb39c3edd287c123.zip
chromium_src-108a96fe15de05d91fe9a0a2eb39c3edd287c123.tar.gz
chromium_src-108a96fe15de05d91fe9a0a2eb39c3edd287c123.tar.bz2
Attempt to get a fix and performance back.
Originally submitted as: http://codereview.chromium.org/386021 Reverted with: http://codereview.chromium.org/384100 This new version only creates the tracking regions (and the associated notifications) if the mouse is actually in the tab strip. Hoping this should improve our startup performance. BUG=27458, 13208, 21448 TEST=Create a pile of tabs. Select a middle one. Put your cursor in some other tab. Hit cmd-w a couple of times Watch to make sure highlights occur correctly in both the tabs and the close buttons. Review URL: http://codereview.chromium.org/385102 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@31956 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/cocoa/tab_strip_controller.h3
-rw-r--r--chrome/browser/cocoa/tab_strip_controller.mm68
-rw-r--r--chrome/browser/cocoa/tab_view.h8
-rw-r--r--chrome/browser/cocoa/tab_view.mm60
4 files changed, 117 insertions, 22 deletions
diff --git a/chrome/browser/cocoa/tab_strip_controller.h b/chrome/browser/cocoa/tab_strip_controller.h
index fae7831..a3b4048 100644
--- a/chrome/browser/cocoa/tab_strip_controller.h
+++ b/chrome/browser/cocoa/tab_strip_controller.h
@@ -100,6 +100,9 @@ class ToolbarModel;
// Manages per-tab sheets.
scoped_nsobject<GTMWindowSheetController> sheetController_;
+ // Is the mouse currently inside the strip;
+ BOOL mouseInside_;
+
// GTMWindowSheetController supports only one per-tab sheet at a time.
// Thus, keep a queue of sheets for every tab. The first element in the queue
// is the currently visible sheet, and when this sheet is closed, the next
diff --git a/chrome/browser/cocoa/tab_strip_controller.mm b/chrome/browser/cocoa/tab_strip_controller.mm
index a971808..4dd2148 100644
--- a/chrome/browser/cocoa/tab_strip_controller.mm
+++ b/chrome/browser/cocoa/tab_strip_controller.mm
@@ -95,7 +95,7 @@ private:
} // namespace
-@interface TabStripController(Private)
+@interface TabStripController (Private)
- (void)installTrackingArea;
- (void)addSubviewToPermanentList:(NSView*)aView;
- (void)regenerateSubviewList;
@@ -107,6 +107,8 @@ private:
- (void)animationDidStopForController:(TabController*)controller
finished:(BOOL)finished;
- (NSInteger)indexFromModelIndex:(NSInteger)index;
+- (void)mouseMoved:(NSEvent*)event;
+- (void)setTabTrackingAreasEnabled:(BOOL)enabled;
@end
// A simple view class that prevents the Window Server from dragging the area
@@ -1185,6 +1187,28 @@ private:
[self layoutTabsWithAnimation:NO regenerateSubviews:NO];
}
+// Called when the tracking areas for any given tab are updated. This allows
+// the individual tabs to update their hover states correctly.
+// Only generates the event if the cursor is in the tab strip.
+- (void)tabUpdateTracking:(NSNotification*)notification {
+ DCHECK([[notification object] isKindOfClass:[TabView class]]);
+ DCHECK(mouseInside_);
+ NSWindow* window = [tabView_ window];
+ NSPoint location = [window mouseLocationOutsideOfEventStream];
+ if (NSPointInRect(location, [tabView_ frame])) {
+ NSEvent* mouseEvent = [NSEvent mouseEventWithType:NSMouseMoved
+ location:location
+ modifierFlags:0
+ timestamp:0
+ windowNumber:[window windowNumber]
+ context:nil
+ eventNumber:0
+ clickCount:0
+ pressure:0];
+ [self mouseMoved:mouseEvent];
+ }
+}
+
- (BOOL)inRapidClosureMode {
return availableResizeWidth_ != kUseFullAvailableWidth;
}
@@ -1217,6 +1241,8 @@ private:
- (void)mouseEntered:(NSEvent*)event {
NSTrackingArea* area = [event trackingArea];
if ([area isEqual:trackingArea_]) {
+ mouseInside_ = YES;
+ [self setTabTrackingAreasEnabled:YES];
[self mouseMoved:event];
} else if ([area isEqual:newTabTrackingArea_]) {
[newTabButton_ setImage:nsimage_cache::ImageNamed(@"newtab_h.pdf")];
@@ -1229,8 +1255,9 @@ private:
- (void)mouseExited:(NSEvent*)event {
NSTrackingArea* area = [event trackingArea];
if ([area isEqual:trackingArea_]) {
+ mouseInside_ = NO;
+ [self setTabTrackingAreasEnabled:NO];
availableResizeWidth_ = kUseFullAvailableWidth;
-
[hoveredTab_ mouseExited:event];
hoveredTab_ = nil;
[self layoutTabs];
@@ -1239,6 +1266,27 @@ private:
}
}
+// Enable/Disable the tracking areas for the tabs. They are only enabled
+// when the mouse is in the tabstrip.
+- (void)setTabTrackingAreasEnabled:(BOOL)enabled {
+ NSNotificationCenter* defaultCenter = [NSNotificationCenter defaultCenter];
+ for (TabController* controller in tabArray_.get()) {
+ TabView* tabView = [controller tabView];
+ if (enabled) {
+ // Set self up to observe tabs so hover states will be correct.
+ [defaultCenter addObserver:self
+ selector:@selector(tabUpdateTracking:)
+ name:NSViewDidUpdateTrackingAreasNotification
+ object:tabView];
+ } else {
+ [defaultCenter removeObserver:self
+ name:NSViewDidUpdateTrackingAreasNotification
+ object:tabView];
+ }
+ [tabView setTrackingEnabled:enabled];
+ }
+}
+
// Adds the given subview to (the end of) the list of permanent subviews
// (specified from bottom up). These subviews will always be below the
// transitory subviews (tabs). |-regenerateSubviewList| must be called to
@@ -1254,24 +1302,30 @@ private:
// should call |-addSubviewToPermanentList:| (or better yet, call that and then
// |-regenerateSubviewList| to actually add it).
- (void)regenerateSubviewList {
+ // Remove self as an observer from all the old tabs before a new set of
+ // potentially different tabs is put in place.
+ [self setTabTrackingAreasEnabled:NO];
+
// Subviews to put in (in bottom-to-top order), beginning with the permanent
// ones.
NSMutableArray* subviews = [NSMutableArray arrayWithArray:permanentSubviews_];
NSView* selectedTabView = nil;
// Go through tabs in reverse order, since |subviews| is bottom-to-top.
- for (TabController* tab in [tabArray_.get() reverseObjectEnumerator]) {
+ for (TabController* tab in [tabArray_ reverseObjectEnumerator]) {
+ NSView* tabView = [tab view];
if ([tab selected]) {
DCHECK(!selectedTabView);
- selectedTabView = [tab view];
+ selectedTabView = tabView;
} else {
- [subviews addObject:[tab view]];
+ [subviews addObject:tabView];
}
}
- if (selectedTabView)
+ if (selectedTabView) {
[subviews addObject:selectedTabView];
-
+ }
[tabView_ setSubviews:subviews];
+ [self setTabTrackingAreasEnabled:mouseInside_];
}
- (GTMWindowSheetController*)sheetController {
diff --git a/chrome/browser/cocoa/tab_view.h b/chrome/browser/cocoa/tab_view.h
index f36512e..249f1e3 100644
--- a/chrome/browser/cocoa/tab_view.h
+++ b/chrome/browser/cocoa/tab_view.h
@@ -56,11 +56,15 @@
NSCellStateValue state_;
}
@property(assign) NSCellStateValue state;
-@property(assign, nonatomic)CGFloat hoverAlpha;
+@property(assign, nonatomic) CGFloat hoverAlpha;
// Determines if the tab is in the process of animating closed. It may still
// be visible on-screen, but should not respond to/initiate any events.
-@property(assign, nonatomic)BOOL isClosing;
+@property(assign, nonatomic) BOOL isClosing;
+
+// Enables/Disables tracking regions for the tab.
+- (void)setTrackingEnabled:(BOOL)enabled;
+
@end
#endif // CHROME_BROWSER_COCOA_TAB_VIEW_H_
diff --git a/chrome/browser/cocoa/tab_view.mm b/chrome/browser/cocoa/tab_view.mm
index 6ad5a05..50e333c 100644
--- a/chrome/browser/cocoa/tab_view.mm
+++ b/chrome/browser/cocoa/tab_view.mm
@@ -35,24 +35,12 @@ static const NSTimeInterval kAnimationHideDuration = 0.4;
- (void)awakeFromNib {
[self setShowsDivider:NO];
- // Set up the tracking rect for the close button mouseover. Add it
- // to the |closeButton_| view, but we'll handle the message ourself.
- // The mouseover is always enabled, because the close button works
- // regardless of key/main/active status.
- closeTrackingArea_.reset(
- [[NSTrackingArea alloc] initWithRect:[closeButton_ bounds]
- options:NSTrackingMouseEnteredAndExited |
- NSTrackingActiveAlways
- owner:self
- userInfo:nil]);
- [closeButton_ addTrackingArea:closeTrackingArea_.get()];
}
- (void)dealloc {
// Cancel any delayed requests that may still be pending (drags or hover).
[NSObject cancelPreviousPerformRequestsWithTarget:self];
- // [self gtm_unregisterForThemeNotifications];
- [closeButton_ removeTrackingArea:closeTrackingArea_.get()];
+ [self setTrackingEnabled:NO];
[super dealloc];
}
@@ -116,6 +104,52 @@ static const NSTimeInterval kAnimationHideDuration = 0.4;
}
}
+// Enable/Disable tracking for the closeButton.
+- (void)setTrackingEnabled:(BOOL)enabled {
+ if (enabled) {
+ // Set up the tracking rect for the close button mouseover. Add it
+ // to the |closeButton_| view, but |self| will handle the messages.
+ // The mouseover is always enabled, because the close button works
+ // regardless of key/main/active status.
+ DCHECK(closeTrackingArea_.get() == nil);
+ closeTrackingArea_.reset(
+ [[NSTrackingArea alloc] initWithRect:[closeButton_ bounds]
+ options:NSTrackingMouseEnteredAndExited |
+ NSTrackingActiveAlways
+ owner:self
+ userInfo:nil]);
+ [closeButton_ addTrackingArea:closeTrackingArea_.get()];
+ } else {
+ if (closeTrackingArea_.get()) {
+ [closeButton_ removeTrackingArea:closeTrackingArea_.get()];
+ closeTrackingArea_.reset(nil);
+ }
+ }
+}
+
+// The tracking areas have been moved. Make sure that the close button is
+// highlighting correctly with respect to the cursor position with the new
+// tracking area locations.
+- (void)updateTrackingAreas {
+ [super updateTrackingAreas];
+ if (closeTrackingArea_.get()) {
+ // Update the close buttons if the tab has moved.
+ NSPoint mouseLoc = [[self window] mouseLocationOutsideOfEventStream];
+ mouseLoc = [self convertPointFromBase:mouseLoc];
+ NSString* name = nil;
+ if (NSPointInRect(mouseLoc, [closeButton_ frame])) {
+ name = @"close_bar_h.pdf";
+ } else {
+ name = @"close_bar.pdf";
+ }
+ NSImage* newImage = nsimage_cache::ImageNamed(name);
+ NSImage* buttonImage = [closeButton_ image];
+ if (![buttonImage isEqual:newImage]) {
+ [closeButton_ setImage:newImage];
+ }
+ }
+}
+
// Determines which view a click in our frame actually hit. It's either this
// view or our child close button.
- (NSView*)hitTest:(NSPoint)aPoint {