diff options
-rw-r--r-- | chrome/browser/cocoa/bookmark_bar_controller.mm | 18 | ||||
-rw-r--r-- | chrome/browser/cocoa/browser_window_controller.h | 11 | ||||
-rw-r--r-- | chrome/browser/cocoa/browser_window_controller.mm | 98 | ||||
-rw-r--r-- | chrome/browser/cocoa/browser_window_controller_unittest.mm | 73 | ||||
-rw-r--r-- | chrome/browser/cocoa/toolbar_controller.h | 5 | ||||
-rw-r--r-- | chrome/browser/cocoa/toolbar_controller.mm | 6 | ||||
-rw-r--r-- | chrome/browser/cocoa/toolbar_controller_unittest.mm | 7 |
7 files changed, 174 insertions, 44 deletions
diff --git a/chrome/browser/cocoa/bookmark_bar_controller.mm b/chrome/browser/cocoa/bookmark_bar_controller.mm index 6f2806d..d1c9861 100644 --- a/chrome/browser/cocoa/bookmark_bar_controller.mm +++ b/chrome/browser/cocoa/bookmark_bar_controller.mm @@ -360,15 +360,6 @@ const NSTimeInterval kBookmarkBarAnimationDuration = 0.12; duration:kBookmarkBarAnimationDuration]; } else if ([self isAnimatingFromState:bookmarks::kShowingState toState:bookmarks::kHiddenState]) { - // The toolbar uncompresses immediately at the beginning (otherwise the - // slide looks wrong, since we slide into the bottom of stuff in the - // toolbar). Do this only if we're at the beginning height since we may - // enter this mid-animation. - if (NSHeight([[self view] frame]) == bookmarks::kBookmarkBarHeight) { - [resizeDelegate_ resizeView:[self view] - newHeight:(bookmarks::kBookmarkBarHeight - - kBookmarkBarOverlap)]; - } [[self backgroundGradientView] setShowsDivider:YES]; [[self view] setHidden:NO]; AnimatableView* view = [self animatableView]; @@ -376,15 +367,6 @@ const NSTimeInterval kBookmarkBarAnimationDuration = 0.12; duration:kBookmarkBarAnimationDuration]; } else if ([self isAnimatingFromState:bookmarks::kShowingState toState:bookmarks::kDetachedState]) { - // The toolbar uncompresses immediately at the beginning (otherwise the - // slide looks wrong, since we slide into the bottom of stuff in the - // toolbar). Do this only if we're at the beginning height since we may - // enter this mid-animation. - if (NSHeight([[self view] frame]) == bookmarks::kBookmarkBarHeight) { - [resizeDelegate_ resizeView:[self view] - newHeight:(bookmarks::kBookmarkBarHeight - - kBookmarkBarOverlap)]; - } [[self backgroundGradientView] setShowsDivider:YES]; [[self view] setHidden:NO]; AnimatableView* view = [self animatableView]; diff --git a/chrome/browser/cocoa/browser_window_controller.h b/chrome/browser/cocoa/browser_window_controller.h index fed8fc1..c410592 100644 --- a/chrome/browser/cocoa/browser_window_controller.h +++ b/chrome/browser/cocoa/browser_window_controller.h @@ -74,6 +74,7 @@ class TabStripModelObserverBridge; BookmarkBubbleController* bookmarkBubbleController_; // Weak. scoped_nsobject<GTMTheme> theme_; + BOOL initializing_; // YES while we are currently in initWithBrowser: BOOL ownsBrowser_; // Only ever NO when testing CGFloat verticalOffsetForStatusBubble_; } @@ -185,6 +186,16 @@ class TabStripModelObserverBridge; // Allows us to initWithBrowser withOUT taking ownership of the browser. - (id)initWithBrowser:(Browser*)browser takeOwnership:(BOOL)ownIt; +// Adjusts the window height by the given amount. If the window spans from the +// top of the current workspace to the bottom of the current workspace, the +// height is not adjusted. If growing the window by the requested amount would +// size the window to be taller than the current workspace, the window height is +// capped to be equal to the height of the current workspace. If the window is +// partially offscreen, its height is not adjusted at all. This function +// prefers to grow the window down, but will grow up if needed. Calls to this +// function should be followed by a call to |layoutSubviews|. +- (void)adjustWindowHeightBy:(CGFloat)deltaH; + // Return an autoreleased NSWindow suitable for fullscreen use. - (NSWindow*)fullscreenWindow; diff --git a/chrome/browser/cocoa/browser_window_controller.mm b/chrome/browser/cocoa/browser_window_controller.mm index ff2c441..a58ad28 100644 --- a/chrome/browser/cocoa/browser_window_controller.mm +++ b/chrome/browser/cocoa/browser_window_controller.mm @@ -92,6 +92,11 @@ willPositionSheet:(NSWindow*)sheet // the normal bookmark bar is not shown? - (BOOL)shouldShowDetachedBookmarkBar; +// Sets the toolbar's height to a value appropriate for the given compression. +// Also adjusts the bookmark bar's height by the opposite amount in order to +// keep the total height of the two views constant. +- (void)adjustToolbarAndBookmarkBarForCompression:(CGFloat)compression; + @end @@ -113,6 +118,7 @@ willPositionSheet:(NSWindow*)sheet ofType:@"nib"]; if ((self = [super initWithWindowNibPath:nibpath owner:self])) { DCHECK(browser); + initializing_ = YES; browser_.reset(browser); ownsBrowser_ = ownIt; tabObserver_.reset( @@ -219,6 +225,9 @@ willPositionSheet:(NSWindow*)sheet // Create the bridge for the status bubble. statusBubble_ = new StatusBubbleMac([self window], self); + + // We are done initializing now. + initializing_ = NO; } return self; } @@ -468,6 +477,53 @@ willPositionSheet:(NSWindow*)sheet return NO; } +// Adjusts the window height by the given amount. +- (void)adjustWindowHeightBy:(CGFloat)deltaH { + // By not adjusting the window height when initializing, we can ensure that + // the window opens with the same size that was saved on close. + if (initializing_ || [self isFullscreen] || deltaH == 0) + return; + + NSWindow* window = [self window]; + NSRect windowFrame = [window frame]; + NSRect workarea = [[window screen] visibleFrame]; + + // If the window is not already fully in the workarea, do not adjust its frame + // at all. + if (!NSContainsRect(workarea, windowFrame)) + return; + + // If the window spans the full height of the current workspace, do not adjust + // its frame at all. + if (windowFrame.origin.y == workarea.origin.y && + windowFrame.size.height == workarea.size.height) + return; + + // Resize the window down until it hits the bottom of the workarea, then if + // needed continue resizing upwards. Do not resize the window to be taller + // than the current workarea. + // Resize the window as requested, keeping the top left corner fixed. + windowFrame.origin.y -= deltaH; + windowFrame.size.height += deltaH; + + // If the bottom left corner is now outside the visible frame, move the window + // up to make it fit, but make sure not to move the top left corner out of the + // visible frame. + if (windowFrame.origin.y < workarea.origin.y) { + windowFrame.origin.y = workarea.origin.y; + windowFrame.size.height = + std::min(windowFrame.size.height, workarea.size.height); + } + + // Disable subview resizing while resizing the window, or else we will get + // unwanted renderer resizes. The calling code must call layoutSubviews to + // make things right again. + NSView* contentView = [window contentView]; + [contentView setAutoresizesSubviews:NO]; + [window setFrame:windowFrame display:NO]; + [contentView setAutoresizesSubviews:YES]; +} + // Main method to resize browser window subviews. This method should be called // when resizing any child of the content view, rather than resizing the views // directly. If the view is already the correct height, does not force a @@ -491,6 +547,23 @@ willPositionSheet:(NSWindow*)sheet if (frame.size.height == height) return; + // Grow or shrink the window by the amount of the height change. We adjust + // the window height only in two cases: + // 1) We are adjusting the height of the bookmark bar and it is currently + // animating either open or closed. + // 2) We are adjusting the height of the download shelf. + // + // We do not adjust the window height for bookmark bar changes on the NTP. + BOOL shouldAdjustBookmarkHeight = + [bookmarkBarController_ isAnimatingBetweenState:bookmarks::kHiddenState + andState:bookmarks::kShowingState]; + if ((shouldAdjustBookmarkHeight && view == [bookmarkBarController_ view]) || + view == [downloadShelfController_ view]) { + [[self window] disableScreenUpdatesUntilFlush]; + CGFloat deltaH = height - frame.size.height; + [self adjustWindowHeightBy:deltaH]; + } + frame.size.height = height; // TODO(rohitrao): Determine if calling setFrame: twice is bad. [view setFrame:frame]; @@ -1227,9 +1300,9 @@ willPositionSheet:(NSWindow*)sheet didChangeFromState:(bookmarks::VisualState)oldState toState:(bookmarks::VisualState)newState { [toolbarController_ - setHeightCompression:[controller getDesiredToolbarHeightCompression]]; - [toolbarController_ setDividerOpacity:[bookmarkBarController_ toolbarDividerOpacity]]; + [self adjustToolbarAndBookmarkBarForCompression: + [controller getDesiredToolbarHeightCompression]]; } // (Needed for |BookmarkBarControllerDelegate| protocol.) @@ -1237,9 +1310,9 @@ willPositionSheet:(NSWindow*)sheet willAnimateFromState:(bookmarks::VisualState)oldState toState:(bookmarks::VisualState)newState { [toolbarController_ - setHeightCompression:[controller getDesiredToolbarHeightCompression]]; - [toolbarController_ setDividerOpacity:[bookmarkBarController_ toolbarDividerOpacity]]; + [self adjustToolbarAndBookmarkBarForCompression: + [controller getDesiredToolbarHeightCompression]]; } @end @@ -1526,6 +1599,23 @@ willPositionSheet:(NSWindow*)sheet return (contents && contents->ShouldShowBookmarkBar()) ? YES : NO; } +- (void)adjustToolbarAndBookmarkBarForCompression:(CGFloat)compression { + CGFloat newHeight = + [toolbarController_ desiredHeightForCompression:compression]; + NSRect toolbarFrame = [[toolbarController_ view] frame]; + CGFloat deltaH = newHeight - toolbarFrame.size.height; + + if (deltaH == 0) + return; + + toolbarFrame.size.height = newHeight; + NSRect bookmarkFrame = [[bookmarkBarController_ view] frame]; + bookmarkFrame.size.height = bookmarkFrame.size.height - deltaH; + [[toolbarController_ view] setFrame:toolbarFrame]; + [[bookmarkBarController_ view] setFrame:bookmarkFrame]; + [self layoutSubviews]; +} + @end @implementation GTMTheme (BrowserThemeProviderInitialization) diff --git a/chrome/browser/cocoa/browser_window_controller_unittest.mm b/chrome/browser/cocoa/browser_window_controller_unittest.mm index 6e8fc96..81cccc9 100644 --- a/chrome/browser/cocoa/browser_window_controller_unittest.mm +++ b/chrome/browser/cocoa/browser_window_controller_unittest.mm @@ -194,6 +194,63 @@ void CheckViewPositions(BrowserWindowController* controller) { } } // end namespace +TEST_F(BrowserWindowControllerTest, TestAdjustWindowHeight) { + NSWindow* window = [controller_ window]; + NSRect workarea = [[window screen] visibleFrame]; + + // Place the window well above the bottom of the screen and try to adjust its + // height. + NSRect initialFrame = NSMakeRect(workarea.origin.x, workarea.origin.y + 100, + 200, 200); + [window setFrame:initialFrame display:YES]; + [controller_ adjustWindowHeightBy:40]; + NSRect finalFrame = [window frame]; + EXPECT_FALSE(NSEqualRects(finalFrame, initialFrame)); + EXPECT_FLOAT_EQ(NSHeight(finalFrame), NSHeight(initialFrame) + 40); + + // Place the window at the bottom of the screen and try again. Its height + // should still change, but it should not grow down below the work area. + initialFrame = NSMakeRect(workarea.origin.x, workarea.origin.y, 200, 200); + [window setFrame:initialFrame display:YES]; + [controller_ adjustWindowHeightBy:40]; + EXPECT_FALSE(NSEqualRects(finalFrame, initialFrame)); + EXPECT_GE(NSMinY(finalFrame), NSMinY(initialFrame)); + EXPECT_FLOAT_EQ(NSHeight(finalFrame), NSHeight(initialFrame) + 40); + + // Move the window slightly offscreen and try again. The height should not + // change this time. + initialFrame = NSMakeRect(workarea.origin.x - 10, 0, 200, 200); + [window setFrame:initialFrame display:YES]; + [controller_ adjustWindowHeightBy:40]; + EXPECT_TRUE(NSEqualRects([window frame], initialFrame)); + + // Make the window the same size as the workarea. Resizing both larger and + // smaller should have no effect. + [window setFrame:workarea display:YES]; + [controller_ adjustWindowHeightBy:40]; + EXPECT_TRUE(NSEqualRects([window frame], workarea)); + [controller_ adjustWindowHeightBy:-40]; + EXPECT_TRUE(NSEqualRects([window frame], workarea)); + + // Make the window smaller than the workarea and place it near the bottom of + // the workarea. The window should grow down until it hits the bottom and + // then continue to grow up. + initialFrame = NSMakeRect(workarea.origin.x, workarea.origin.y + 5, + 200, 200); + [window setFrame:initialFrame display:YES]; + [controller_ adjustWindowHeightBy:40]; + finalFrame = [window frame]; + EXPECT_EQ(NSMinY(workarea), NSMinY(finalFrame)); + EXPECT_FLOAT_EQ(NSHeight(finalFrame), NSHeight(initialFrame) + 40); + + // Inset the window slightly from the workarea. It should not grow to be + // larger than the workarea. + initialFrame = NSInsetRect(workarea, 0, 5); + [window setFrame:initialFrame display:YES]; + [controller_ adjustWindowHeightBy:40]; + EXPECT_EQ(NSHeight(workarea), NSHeight([window frame])); +} + // Test to make sure resizing and relaying-out subviews works correctly. TEST_F(BrowserWindowControllerTest, TestResizeViews) { TabStripView* tabstrip = [controller_ tabStripView]; @@ -205,9 +262,7 @@ TEST_F(BrowserWindowControllerTest, TestResizeViews) { // We need to muck with the views a bit to put us in a consistent state before // we start resizing. In particular, we need to move the tab strip to be // immediately above the content area, since we layout views to be directly - // under the tab strip. We also explicitly set the contentView's frame to be - // 800x600. - [contentView setFrame:NSMakeRect(0, 0, 800, 600)]; + // under the tab strip. NSRect tabstripFrame = [tabstrip frame]; tabstripFrame.origin.y = NSMaxY([contentView frame]); [tabstrip setFrame:tabstripFrame]; @@ -215,7 +270,9 @@ TEST_F(BrowserWindowControllerTest, TestResizeViews) { // The download shelf is created lazily. Force-create it and set its initial // height to 0. NSView* download = [[controller_ downloadShelf] view]; - [controller_ resizeView:download newHeight:0]; + NSRect downloadFrame = [download frame]; + downloadFrame.size.height = 0; + [download setFrame:downloadFrame]; // Force a layout and check each view's frame. [controller_ layoutSubviews]; @@ -259,9 +316,7 @@ TEST_F(BrowserWindowControllerTest, TestResizeViewsWithBookmarkBar) { // We need to muck with the views a bit to put us in a consistent state before // we start resizing. In particular, we need to move the tab strip to be // immediately above the content area, since we layout views to be directly - // under the tab strip. We also explicitly set the contentView's frame to be - // 800x600. - [contentView setFrame:NSMakeRect(0, 0, 800, 600)]; + // under the tab strip. NSRect tabstripFrame = [tabstrip frame]; tabstripFrame.origin.y = NSMaxY([contentView frame]); [tabstrip setFrame:tabstripFrame]; @@ -269,7 +324,9 @@ TEST_F(BrowserWindowControllerTest, TestResizeViewsWithBookmarkBar) { // The download shelf is created lazily. Force-create it and set its initial // height to 0. NSView* download = [[controller_ downloadShelf] view]; - [controller_ resizeView:download newHeight:0]; + NSRect downloadFrame = [download frame]; + downloadFrame.size.height = 0; + [download setFrame:downloadFrame]; // Force a layout and check each view's frame. [controller_ layoutSubviews]; diff --git a/chrome/browser/cocoa/toolbar_controller.h b/chrome/browser/cocoa/toolbar_controller.h index a78ae47..3801667 100644 --- a/chrome/browser/cocoa/toolbar_controller.h +++ b/chrome/browser/cocoa/toolbar_controller.h @@ -134,9 +134,8 @@ class ToolbarModel; // Somewhere near the star button seems like a good start. - (NSRect)starButtonInWindowCoordinates; -// Chop off the bottom of the toolbar by |compressByHeight|; needed when the -// bookmark bar is attached. -- (void)setHeightCompression:(CGFloat)compressByHeight; +// Returns the desired toolbar height for the given compression factor. +- (CGFloat)desiredHeightForCompression:(CGFloat)compressByHeight; // Set the opacity of the divider (the line at the bottom) *if* we have a // |ToolbarView| (0 means don't show it); no-op otherwise. diff --git a/chrome/browser/cocoa/toolbar_controller.mm b/chrome/browser/cocoa/toolbar_controller.mm index cc719dd..6617c87 100644 --- a/chrome/browser/cocoa/toolbar_controller.mm +++ b/chrome/browser/cocoa/toolbar_controller.mm @@ -517,10 +517,8 @@ class PrefObserverBridge : public NotificationObserver { fromView:starButton_]; } -- (void)setHeightCompression:(CGFloat)compressByHeight { - // Resize. - CGFloat newToolbarHeight = kBaseToolbarHeight - compressByHeight; - [resizeDelegate_ resizeView:[self view] newHeight:newToolbarHeight]; +- (CGFloat)desiredHeightForCompression:(CGFloat)compressByHeight { + return kBaseToolbarHeight - compressByHeight; } - (void)setDividerOpacity:(CGFloat)opacity { diff --git a/chrome/browser/cocoa/toolbar_controller_unittest.mm b/chrome/browser/cocoa/toolbar_controller_unittest.mm index a8be5fc..a6869c3 100644 --- a/chrome/browser/cocoa/toolbar_controller_unittest.mm +++ b/chrome/browser/cocoa/toolbar_controller_unittest.mm @@ -292,11 +292,4 @@ TEST_F(ToolbarControllerTest, PopulateEncodingMenu) { EXPECT_NE(0, [encodings numberOfItems]); } -TEST_F(ToolbarControllerTest, HeightCompression) { - for (int i = 0; i <= 10; i++) { - [bar_ setHeightCompression:static_cast<CGFloat>(i)]; - EXPECT_EQ(static_cast<CGFloat>(36 - i), [resizeDelegate_ height]); - } -} - } // namespace |