| Index: chrome/browser/cocoa/tab_strip_controller.mm
|
| diff --git a/chrome/browser/cocoa/tab_strip_controller.mm b/chrome/browser/cocoa/tab_strip_controller.mm
|
| index 029bdb7ee90a18afdd6435eb463cb4d70c068c04..46834b24d96445dd05cd9b3a0f69d440771183ec 100644
|
| --- a/chrome/browser/cocoa/tab_strip_controller.mm
|
| +++ b/chrome/browser/cocoa/tab_strip_controller.mm
|
| @@ -576,16 +576,32 @@ private:
|
| if (!isClosingLastTab) {
|
| // Limit the width available for laying out tabs so that tabs are not
|
| // resized until a later time (when the mouse leaves the tab strip).
|
| - // TODO(pinkerton): re-visit when handling tab overflow.
|
| - // http://crbug.com/188
|
| NSView* penultimateTab = [self viewAtIndex:numberOfOpenTabs - 2];
|
| availableResizeWidth_ = NSMaxX([penultimateTab frame]);
|
| } else {
|
| // If the rightmost tab is closed, change the available width so that
|
| // another tab's close button lands below the cursor (assuming the tabs
|
| - // are currently below their maximum width and can grow).
|
| + // are currently below their maximum width and can grow) if possible.
|
| NSView* lastTab = [self viewAtIndex:numberOfOpenTabs - 1];
|
| availableResizeWidth_ = NSMaxX([lastTab frame]);
|
| +
|
| + // Since close buttons are on the left, this is a bit tricky. To make this
|
| + // at all possible, the rightmost tab keeps its narrow pre-close width
|
| + // and the other tabs expand to push it over.
|
| + // Only do this if the other tabs can be pushed far enough, though.
|
| + lastClosedTabWidth_.reset();
|
| + const CGFloat kPinnedTabWidth = [TabController pinnedTabWidth];
|
| + const CGFloat pinnedWidth =
|
| + [self numberOfOpenPinnedTabs] * (kPinnedTabWidth - kTabOverlap);
|
| + const CGFloat kMaxTabWidth = [TabController maxTabWidth];
|
| + const CGFloat unpinnedWidth = // 1 tab is candidate for being shorter
|
| + ([self numberOfOpenUnpinnedTabs] - 1) * (kMaxTabWidth - kTabOverlap);
|
| + CGFloat candidateWidth = NSWidth([lastTab frame]);
|
| + // Technically, it should be
|
| + // |pinnedWidth + unpinnedWidth + widthOfPartOfLastTabThatContainsClose|,
|
| + // but that's complicated _and_ makes the last tab look very thin.
|
| + if (pinnedWidth + unpinnedWidth >= availableResizeWidth_)
|
| + lastClosedTabWidth_.reset(new CGFloat(candidateWidth));
|
| }
|
| tabStripModel_->CloseTabContentsAt(index);
|
| } else {
|
| @@ -667,6 +683,8 @@ private:
|
| CGFloat availableWidth = 0;
|
| if ([self inRapidClosureMode]) {
|
| availableWidth = availableResizeWidth_;
|
| + if (lastClosedTabWidth_.get())
|
| + availableWidth -= *lastClosedTabWidth_.get();
|
| } else {
|
| availableWidth = NSWidth([tabStripView_ frame]);
|
| availableWidth -= NSWidth([newTabButton_ frame]) + kNewTabButtonOffset;
|
| @@ -681,10 +699,13 @@ private:
|
| // Initialize |unpinnedTabWidth| in case there aren't any unpinned tabs; this
|
| // value shouldn't actually be used.
|
| CGFloat unpinnedTabWidth = kMaxTabWidth;
|
| - const NSInteger numberOfOpenUnpinnedTabs = [self numberOfOpenUnpinnedTabs];
|
| + const NSInteger numberOfOpenUnpinnedTabs = [self numberOfOpenUnpinnedTabs]
|
| + - (lastClosedTabWidth_.get() ? 1 : 0);
|
| if (numberOfOpenUnpinnedTabs) { // Find the width of an unpinned tab.
|
| // Add in the amount we "get back" from the tabs overlapping.
|
| availableWidthForUnpinned += (numberOfOpenUnpinnedTabs - 1) * kTabOverlap;
|
| + if (lastClosedTabWidth_.get())
|
| + availableWidthForUnpinned += kTabOverlap;
|
|
|
| // Divide up the space between the unpinned tabs.
|
| unpinnedTabWidth = availableWidthForUnpinned / numberOfOpenUnpinnedTabs;
|
| @@ -697,13 +718,14 @@ private:
|
| BOOL visible = [[tabStripView_ window] isVisible];
|
|
|
| CGFloat offset = [self indentForControls];
|
| - NSUInteger i = 0;
|
| bool hasPlaceholderGap = false;
|
| + int openTabCount = 0;
|
| for (TabController* tab in tabArray_.get()) {
|
| // Ignore a tab that is going through a close animation.
|
| if ([closingControllers_ containsObject:tab])
|
| continue;
|
|
|
| + ++openTabCount;
|
| BOOL isPlaceholder = [[tab view] isEqual:placeholderTab_];
|
| NSRect tabFrame = [[tab view] frame];
|
| tabFrame.size.height = [[self class] defaultTabHeight] + 1;
|
| @@ -750,6 +772,12 @@ private:
|
| if ([tab selected])
|
| tabFrame.size.width = MAX(tabFrame.size.width, kMinSelectedTabWidth);
|
|
|
| + // When in rapid-closure mode, treat the width of the last tab in a way
|
| + // that its close button ends up below the cursor.
|
| + BOOL isLastOpenTab = tabStripModel_->count() == openTabCount;
|
| + if (isLastOpenTab && lastClosedTabWidth_.get())
|
| + tabFrame.size.width = *lastClosedTabWidth_.get();
|
| +
|
| // Animate a new tab in by putting it below the horizon unless told to put
|
| // it in a specific location (i.e., from a drop).
|
| if (newTab && visible && animate) {
|
| @@ -776,7 +804,6 @@ private:
|
|
|
| offset += NSWidth(tabFrame);
|
| offset -= kTabOverlap;
|
| - i++;
|
| }
|
|
|
| // Hide the new tab button if we're explicitly told to. It may already
|
| @@ -891,6 +918,7 @@ private:
|
| // If a tab is being inserted, we can again use the entire tab strip width
|
| // for layout.
|
| availableResizeWidth_ = kUseFullAvailableWidth;
|
| + lastClosedTabWidth_.reset();
|
|
|
| // We don't need to call |-layoutTabs| if the tab will be in the foreground
|
| // because it will get called when the new tab is selected by the tab model.
|
| @@ -1409,6 +1437,7 @@ private:
|
| mouseInside_ = NO;
|
| [self setTabTrackingAreasEnabled:NO];
|
| availableResizeWidth_ = kUseFullAvailableWidth;
|
| + lastClosedTabWidth_.reset();
|
| [hoveredTab_ mouseExited:event];
|
| hoveredTab_ = nil;
|
| [self layoutTabs];
|
|
|