| Index: chrome/browser/cocoa/tab_controller.mm
|
| diff --git a/chrome/browser/cocoa/tab_controller.mm b/chrome/browser/cocoa/tab_controller.mm
|
| index ef0455e24d1d73cd48a45df701c900162be6b992..2dee19c0d101df2d0c04472c2828275d2c7cdfd6 100644
|
| --- a/chrome/browser/cocoa/tab_controller.mm
|
| +++ b/chrome/browser/cocoa/tab_controller.mm
|
| @@ -2,14 +2,18 @@
|
| // Use of this source code is governed by a BSD-style license that can be
|
| // found in the LICENSE file.
|
|
|
| +#import "chrome/browser/cocoa/tab_controller.h"
|
| +
|
| +#import <Cocoa/Cocoa.h>
|
| +
|
| #include "app/l10n_util_mac.h"
|
| #include "base/mac_util.h"
|
| #import "chrome/browser/browser_theme_provider.h"
|
| #import "chrome/browser/cocoa/menu_controller.h"
|
| -#import "chrome/browser/cocoa/tab_controller.h"
|
| #import "chrome/browser/cocoa/tab_controller_target.h"
|
| #import "chrome/browser/cocoa/tab_view.h"
|
| #import "chrome/browser/cocoa/themed_window.h"
|
| +#import "chrome/browser/cocoa/throbber_view.h"
|
| #include "grit/generated_resources.h"
|
|
|
| @implementation TabController
|
| @@ -75,6 +79,7 @@ class MenuDelegate : public menus::SimpleMenuModel::Delegate {
|
| + (CGFloat)pinnedTabWidth { return 53; }
|
|
|
| - (TabView*)tabView {
|
| + DCHECK([[self view] isKindOfClass:[TabView class]]);
|
| return static_cast<TabView*>([self view]);
|
| }
|
|
|
| @@ -105,8 +110,7 @@ class MenuDelegate : public menus::SimpleMenuModel::Delegate {
|
| // mark ourselves as needing a redraw.
|
| - (void)internalSetSelected:(BOOL)selected {
|
| selected_ = selected;
|
| - TabView* tabView = static_cast<TabView*>([self view]);
|
| - DCHECK([tabView isKindOfClass:[TabView class]]);
|
| + TabView* tabView = [self tabView];
|
| [tabView setState:selected];
|
| [tabView cancelAlert];
|
| [self updateVisibility];
|
| @@ -120,12 +124,13 @@ class MenuDelegate : public menus::SimpleMenuModel::Delegate {
|
| originalIconFrame_ = [iconView_ frame];
|
|
|
| // When the icon is removed, the title expands to the left to fill the space
|
| - // left by the icon. When the close button is removed, the title expands to
|
| - // the right to fill its space. These are the amounts to expand and contract
|
| - // titleView_ under those conditions.
|
| + // left by the icon. This is the amounts to expand and contracttitleView_
|
| + // under those conditions. FIXME: update comment, simplify logic
|
| NSRect titleFrame = [titleView_ frame];
|
| - iconTitleXOffset_ = NSMinX(titleFrame) - NSMinX(originalIconFrame_);
|
| - titleCloseWidthOffset_ = NSMaxX([closeButton_ frame]) - NSMaxX(titleFrame);
|
| +// iconTitleXOffset_ = NSMinX(titleFrame) - NSMinX(originalIconFrame_);
|
| + iconTitleXOffset_ = NSMinX(titleFrame) - NSMaxX(originalIconFrame_);
|
| + titleTabOffset_ = NSWidth([[self view] frame]) - NSMaxX(titleFrame);
|
| +
|
|
|
| [self internalSetSelected:selected_];
|
| }
|
| @@ -144,6 +149,25 @@ class MenuDelegate : public menus::SimpleMenuModel::Delegate {
|
| }
|
|
|
| - (IBAction)closeTab:(id)sender {
|
| + if (![self closeButtonActive]) {
|
| +
|
| + NSEvent* down = [NSApp currentEvent];
|
| + NSEvent* fakeUp = [NSEvent mouseEventWithType:NSLeftMouseUp
|
| + location:[down locationInWindow]
|
| + modifierFlags:[down modifierFlags]
|
| + timestamp:[down timestamp]
|
| + windowNumber:[down windowNumber]
|
| + context:[down context]
|
| + eventNumber:0 // FIXME
|
| + clickCount:1
|
| + pressure:0];
|
| +
|
| + [closeButton_ mouseUp:fakeUp]; // clear "pressed" state
|
| + [closeButton_ setState:NSOffState];
|
| + [[self view] mouseDown:[NSApp currentEvent]];
|
| + return;
|
| + }
|
| +
|
| if ([[self target] respondsToSelector:@selector(closeTab:)]) {
|
| [[self target] performSelector:@selector(closeTab:)
|
| withObject:[self view]];
|
| @@ -152,11 +176,8 @@ class MenuDelegate : public menus::SimpleMenuModel::Delegate {
|
|
|
| - (void)setTitle:(NSString*)title {
|
| [[self view] setToolTip:title];
|
| - if ([self pinned] && ![self selected]) {
|
| - TabView* tabView = static_cast<TabView*>([self view]);
|
| - DCHECK([tabView isKindOfClass:[TabView class]]);
|
| - [tabView startAlert];
|
| - }
|
| + if ([self pinned] && ![self selected])
|
| + [[self tabView] startAlert];
|
| [super setTitle:title];
|
| }
|
|
|
| @@ -190,86 +211,56 @@ class MenuDelegate : public menus::SimpleMenuModel::Delegate {
|
| return [[self view] toolTip];
|
| }
|
|
|
| -// Return a rough approximation of the number of icons we could fit in the
|
| -// tab. We never actually do this, but it's a helpful guide for determining
|
| -// how much space we have available.
|
| -- (int)iconCapacity {
|
| - CGFloat width = NSMaxX([closeButton_ frame]) - NSMinX(originalIconFrame_);
|
| - CGFloat iconWidth = NSWidth(originalIconFrame_);
|
| -
|
| - return width / iconWidth;
|
| -}
|
| -
|
| -// Returns YES if we should show the icon. When tabs get too small, we clip
|
| -// the favicon before the close button for selected tabs, and prefer the
|
| -// favicon for unselected tabs. The icon can also be suppressed more directly
|
| -// by clearing iconView_.
|
| -- (BOOL)shouldShowIcon {
|
| - if (!iconView_)
|
| - return NO;
|
| -
|
| - if ([self pinned])
|
| - return YES;
|
| -
|
| - int iconCapacity = [self iconCapacity];
|
| - if ([self selected])
|
| - return iconCapacity >= 2;
|
| - return iconCapacity >= 1;
|
| -}
|
| -
|
| -// Returns YES if we should be showing the close button. The selected tab
|
| -// always shows the close button.
|
| -- (BOOL)shouldShowCloseButton {
|
| - if ([self pinned])
|
| - return NO;
|
| - return ([self selected] || [self iconCapacity] >= 3);
|
| -}
|
| -
|
| - (void)updateVisibility {
|
| - // iconView_ may have been replaced or it may be nil, so [iconView_ isHidden]
|
| - // won't work. Instead, the state of the icon is tracked separately in
|
| - // isIconShowing_.
|
| - BOOL oldShowIcon = isIconShowing_ ? YES : NO;
|
| - BOOL newShowIcon = [self shouldShowIcon] ? YES : NO;
|
| -
|
| - [iconView_ setHidden:newShowIcon ? NO : YES];
|
| - isIconShowing_ = newShowIcon;
|
| -
|
| - // If the tab is pinned, hide the title.
|
| - [titleView_ setHidden:[self pinned]];
|
| -
|
| - BOOL oldShowCloseButton = [closeButton_ isHidden] ? NO : YES;
|
| - BOOL newShowCloseButton = [self shouldShowCloseButton] ? YES : NO;
|
| -
|
| - [closeButton_ setHidden:newShowCloseButton ? NO : YES];
|
| -
|
| - // Adjust the title view based on changes to the icon's and close button's
|
| - // visibility.
|
| - NSRect titleFrame = [titleView_ frame];
|
| -
|
| - if (oldShowIcon != newShowIcon) {
|
| - // Adjust the left edge of the title view according to the presence or
|
| - // absence of the icon view.
|
| -
|
| - if (newShowIcon) {
|
| - titleFrame.origin.x += iconTitleXOffset_;
|
| - titleFrame.size.width -= iconTitleXOffset_;
|
| + // Cocoa apparently gets confused if the title autoresizes too small, so
|
| + // handle this manually. FIXME: comment slightly wrong
|
| + CGFloat titleWidth = NSWidth([[self view] frame]) -
|
| + titleTabOffset_ -
|
| + NSMaxX(originalIconFrame_) -
|
| + iconTitleXOffset_;
|
| +
|
| + bool showClose = NO;
|
| + if ([[self tabView] isMouseInside]) {
|
| + if ([self selected]) {
|
| + showClose = YES;
|
| } else {
|
| - titleFrame.origin.x -= iconTitleXOffset_;
|
| - titleFrame.size.width += iconTitleXOffset_;
|
| + // To make accidental tab closure less likely, only show the close button
|
| + // on hover in background tabs if they are "wide enough".
|
| + showClose = titleWidth >= 2*NSWidth(originalIconFrame_) || !iconView_;
|
| }
|
| + } else if ([self selected]) {
|
| + // FIXME: this is a bit of a hack; use an explicit method
|
| + BOOL isLoading = [iconView_ isKindOfClass:[ThrobberView class]];
|
| + showClose = isLoading ? NO : YES;
|
| + } else {
|
| + // NTP should always show close, even if in background (it doesn't have
|
| + // an icon).
|
| + showClose = iconView_ ? NO : YES;
|
| }
|
|
|
| - if (oldShowCloseButton != newShowCloseButton) {
|
| - // Adjust the right edge of the title view according to the presence or
|
| - // absence of the close button.
|
| - if (newShowCloseButton)
|
| - titleFrame.size.width -= titleCloseWidthOffset_;
|
| - else
|
| - titleFrame.size.width += titleCloseWidthOffset_;
|
| + if (titleWidth > 0) {
|
| + NSRect titleFrame = [titleView_ frame];
|
| + titleFrame.size.width = titleWidth;
|
| + [titleView_ setHidden:NO];
|
| + [titleView_ setFrame:titleFrame];
|
| + } else {
|
| + [titleView_ setHidden:YES];
|
| }
|
|
|
| - [titleView_ setFrame:titleFrame];
|
| + // Don't show icon if tab is not active and tab is very small. The tab strip
|
| + // controller takes care to always keep the active tab wide enough for a close
|
| + // button.
|
| + if (NSWidth([[self view] frame]) >= [TabController minSelectedTabWidth]) {
|
| + if (showClose && [closeButton_ isHidden]) {
|
| + closeButtonRevealTime_ = [NSDate timeIntervalSinceReferenceDate];
|
| + }
|
| +
|
| + [closeButton_ setHidden:showClose ? NO : YES];
|
| + [iconView_ setHidden:showClose ? YES : NO];
|
| + } else {
|
| + [closeButton_ setHidden:YES];
|
| + [iconView_ setHidden:YES];
|
| + }
|
| }
|
|
|
| - (void)updateTitleColor {
|
| @@ -288,10 +279,20 @@ class MenuDelegate : public menus::SimpleMenuModel::Delegate {
|
| [titleView_ setTextColor:titleColor ? titleColor : [NSColor textColor]];
|
| }
|
|
|
| +- (BOOL)closeButtonActive {
|
| + if ([closeButton_ isHidden]) return false;
|
| + if ([self selected] || [self inRapidClosureMode]) return true;
|
| + NSTimeInterval closeButtonScreenTime =
|
| + [NSDate timeIntervalSinceReferenceDate] - closeButtonRevealTime_;
|
| +fprintf(stderr, " %f\n", closeButtonScreenTime);
|
| + return ![closeButton_ isHidden] && closeButtonScreenTime > 1.0;
|
| +
|
| +}
|
| +
|
| // Called when our view is resized. If it gets too small, start by hiding
|
| // the close button and only show it if tab is selected. Eventually, hide the
|
| // icon as well. We know that this is for our view because we only registered
|
| -// for notifications from our specific view.
|
| +// for notifications from our specific view. FIXME: update comment
|
| - (void)viewResized:(NSNotification*)info {
|
| [self updateVisibility];
|
| }
|
|
|