diff options
author | dmaclach@chromium.org <dmaclach@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-11-13 22:11:50 +0000 |
---|---|---|
committer | dmaclach@chromium.org <dmaclach@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-11-13 22:11:50 +0000 |
commit | 108a96fe15de05d91fe9a0a2eb39c3edd287c123 (patch) | |
tree | 13bc4245b37371b75d7b64cdeb4c30b070bddc25 | |
parent | f30a566d7fcc4c56004f40e9db160906bdf9ac8c (diff) | |
download | chromium_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.h | 3 | ||||
-rw-r--r-- | chrome/browser/cocoa/tab_strip_controller.mm | 68 | ||||
-rw-r--r-- | chrome/browser/cocoa/tab_view.h | 8 | ||||
-rw-r--r-- | chrome/browser/cocoa/tab_view.mm | 60 |
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 { |