diff options
-rw-r--r-- | chrome/browser/cocoa/browser_theme_provider_init.h | 19 | ||||
-rw-r--r-- | chrome/browser/cocoa/browser_theme_provider_init.mm | 178 | ||||
-rw-r--r-- | chrome/browser/cocoa/browser_window_controller.h | 117 | ||||
-rw-r--r-- | chrome/browser/cocoa/browser_window_controller.mm | 991 | ||||
-rw-r--r-- | chrome/browser/cocoa/browser_window_controller_private.h | 108 | ||||
-rw-r--r-- | chrome/browser/cocoa/browser_window_controller_private.mm | 440 | ||||
-rwxr-xr-x | chrome/chrome_browser.gypi | 4 |
7 files changed, 990 insertions, 867 deletions
diff --git a/chrome/browser/cocoa/browser_theme_provider_init.h b/chrome/browser/cocoa/browser_theme_provider_init.h new file mode 100644 index 0000000..0959e9c --- /dev/null +++ b/chrome/browser/cocoa/browser_theme_provider_init.h @@ -0,0 +1,19 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_COCOA_BROWSER_THEME_PROVIDER_INIT_H_ +#define CHROME_BROWSER_COCOA_BROWSER_THEME_PROVIDER_INIT_H_ + +#import "third_party/GTM/AppKit/GTMTheme.h" + +class BrowserThemeProvider; + +// Provides a routine to initialize GTMTheme with data from a provided +// |BrowserThemeProvider|. +@interface GTMTheme(BrowserThemeProviderInitialization) ++ (GTMTheme*)themeWithBrowserThemeProvider:(BrowserThemeProvider*)provider + isOffTheRecord:(BOOL)offTheRecord; +@end + +#endif // CHROME_BROWSER_COCOA_BROWSER_THEME_PROVIDER_INIT_H_ diff --git a/chrome/browser/cocoa/browser_theme_provider_init.mm b/chrome/browser/cocoa/browser_theme_provider_init.mm new file mode 100644 index 0000000..baf5226 --- /dev/null +++ b/chrome/browser/cocoa/browser_theme_provider_init.mm @@ -0,0 +1,178 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "chrome/browser/cocoa/browser_theme_provider_init.h" + +#import <Cocoa/Cocoa.h> + +#include <map> +#include <string> +#include <utility> + +#import "base/scoped_nsobject.h" +#include "chrome/browser/browser_theme_provider.h" +#include "grit/generated_resources.h" +#include "grit/locale_settings.h" +#include "grit/theme_resources.h" + + +@implementation GTMTheme(BrowserThemeProviderInitialization) + ++ (GTMTheme*)themeWithBrowserThemeProvider:(BrowserThemeProvider*)provider + isOffTheRecord:(BOOL)isOffTheRecord { + // First check if it's in the cache. + typedef std::pair<std::string, BOOL> ThemeKey; + static std::map<ThemeKey, GTMTheme*> cache; + ThemeKey key(provider->GetThemeID(), isOffTheRecord); + GTMTheme* theme = cache[key]; + if (theme) + return theme; + + theme = [[GTMTheme alloc] init]; // "Leak" it in the cache. + cache[key] = theme; + + // TODO(pinkerton): Need to be able to theme the entire incognito window + // http://crbug.com/18568 The hardcoding of the colors here will need to be + // removed when that bug is addressed, but are here in order for things to be + // usable in the meantime. + if (isOffTheRecord) { + NSColor* incognitoColor = [NSColor colorWithCalibratedRed:83/255.0 + green:108.0/255.0 + blue:140/255.0 + alpha:1.0]; + [theme setBackgroundColor:incognitoColor]; + [theme setValue:[NSColor blackColor] + forAttribute:@"textColor" + style:GTMThemeStyleTabBarSelected + state:GTMThemeStateActiveWindow]; + [theme setValue:[NSColor blackColor] + forAttribute:@"textColor" + style:GTMThemeStyleTabBarDeselected + state:GTMThemeStateActiveWindow]; + [theme setValue:[NSColor blackColor] + forAttribute:@"textColor" + style:GTMThemeStyleBookmarksBarButton + state:GTMThemeStateActiveWindow]; + [theme setValue:[NSColor blackColor] + forAttribute:@"iconColor" + style:GTMThemeStyleToolBarButton + state:GTMThemeStateActiveWindow]; + return theme; + } + + NSImage* frameImage = provider->GetNSImageNamed(IDR_THEME_FRAME); + NSImage* frameInactiveImage = + provider->GetNSImageNamed(IDR_THEME_FRAME_INACTIVE); + + [theme setValue:frameImage + forAttribute:@"backgroundImage" + style:GTMThemeStyleWindow + state:GTMThemeStateActiveWindow]; + + NSColor* tabTextColor = + provider->GetNSColor(BrowserThemeProvider::COLOR_TAB_TEXT); + [theme setValue:tabTextColor + forAttribute:@"textColor" + style:GTMThemeStyleTabBarSelected + state:GTMThemeStateActiveWindow]; + + NSColor* tabInactiveTextColor = + provider->GetNSColor(BrowserThemeProvider::COLOR_BACKGROUND_TAB_TEXT); + [theme setValue:tabInactiveTextColor + forAttribute:@"textColor" + style:GTMThemeStyleTabBarDeselected + state:GTMThemeStateActiveWindow]; + + NSColor* bookmarkBarTextColor = + provider->GetNSColor(BrowserThemeProvider::COLOR_BOOKMARK_TEXT); + [theme setValue:bookmarkBarTextColor + forAttribute:@"textColor" + style:GTMThemeStyleBookmarksBarButton + state:GTMThemeStateActiveWindow]; + + [theme setValue:frameInactiveImage + forAttribute:@"backgroundImage" + style:GTMThemeStyleWindow + state:0]; + + NSImage* toolbarImage = provider->GetNSImageNamed(IDR_THEME_TOOLBAR); + [theme setValue:toolbarImage + forAttribute:@"backgroundImage" + style:GTMThemeStyleToolBar + state:GTMThemeStateActiveWindow]; + NSImage* toolbarBackgroundImage = + provider->GetNSImageNamed(IDR_THEME_TAB_BACKGROUND); + [theme setValue:toolbarBackgroundImage + forAttribute:@"backgroundImage" + style:GTMThemeStyleTabBarDeselected + state:GTMThemeStateActiveWindow]; + + NSImage* toolbarButtonImage = + provider->GetNSImageNamed(IDR_THEME_BUTTON_BACKGROUND); + if (toolbarButtonImage) { + [theme setValue:toolbarButtonImage + forAttribute:@"backgroundImage" + style:GTMThemeStyleToolBarButton + state:GTMThemeStateActiveWindow]; + } else { + NSColor* startColor = [NSColor colorWithCalibratedWhite:1.0 alpha:0.0]; + NSColor* endColor = [NSColor colorWithCalibratedWhite:1.0 alpha:0.3]; + scoped_nsobject<NSGradient> gradient([[NSGradient alloc] + initWithStartingColor:startColor + endingColor:endColor]); + + [theme setValue:gradient + forAttribute:@"gradient" + style:GTMThemeStyleToolBarButton + state:GTMThemeStateActiveWindow]; + + [theme setValue:gradient + forAttribute:@"gradient" + style:GTMThemeStyleToolBarButton + state:GTMThemeStateActiveWindow]; + } + + NSColor* toolbarButtonIconColor = + provider->GetNSColorTint(BrowserThemeProvider::TINT_BUTTONS); + [theme setValue:toolbarButtonIconColor + forAttribute:@"iconColor" + style:GTMThemeStyleToolBarButton + state:GTMThemeStateActiveWindow]; + + NSColor* toolbarButtonBorderColor = toolbarButtonIconColor; + [theme setValue:toolbarButtonBorderColor + forAttribute:@"borderColor" + style:GTMThemeStyleToolBar + state:GTMThemeStateActiveWindow]; + + NSColor* toolbarBackgroundColor = + provider->GetNSColor(BrowserThemeProvider::COLOR_TOOLBAR); + [theme setValue:toolbarBackgroundColor + forAttribute:@"backgroundColor" + style:GTMThemeStyleToolBar + state:GTMThemeStateActiveWindow]; + + NSImage* frameOverlayImage = + provider->GetNSImageNamed(IDR_THEME_FRAME_OVERLAY); + if (frameOverlayImage) { + [theme setValue:frameOverlayImage + forAttribute:@"overlay" + style:GTMThemeStyleWindow + state:GTMThemeStateActiveWindow]; + } + + NSImage* frameOverlayInactiveImage = + provider->GetNSImageNamed(IDR_THEME_FRAME_OVERLAY_INACTIVE); + if (frameOverlayInactiveImage) { + [theme setValue:frameOverlayInactiveImage + forAttribute:@"overlay" + style:GTMThemeStyleWindow + state:GTMThemeStateInactiveWindow]; + } + + return theme; +} + + +@end // @implementation GTMTheme(BrowserThemeProviderInitialization) diff --git a/chrome/browser/cocoa/browser_window_controller.h b/chrome/browser/cocoa/browser_window_controller.h index db0364f..ad38462 100644 --- a/chrome/browser/cocoa/browser_window_controller.h +++ b/chrome/browser/cocoa/browser_window_controller.h @@ -23,6 +23,7 @@ #include "chrome/browser/sync/sync_ui_util.h" #import "third_party/GTM/AppKit/GTMTheme.h" + class Browser; class BrowserWindow; class BrowserWindowCocoa; @@ -42,6 +43,7 @@ class TabStripModelObserverBridge; @class ToolbarController; @class TitlebarController; + @interface BrowserWindowController : TabWindowController<NSUserInterfaceValidations, BookmarkBarControllerDelegate, @@ -130,12 +132,18 @@ class TabStripModelObserverBridge; // Access the C++ bridge between the NSWindow and the rest of Chromium. - (BrowserWindow*)browserWindow; -// Access the C++ bridge object representing the location bar. -- (LocationBar*)locationBarBridge; +// Return a weak pointer to the toolbar controller. +- (ToolbarController*)toolbarController; + +// Return a weak pointer to the tab strip controller. +- (TabStripController*)tabStripController; // Access the C++ bridge object representing the status bubble for the window. - (StatusBubbleMac*)statusBubble; +// Access the C++ bridge object representing the location bar. +- (LocationBar*)locationBarBridge; + // Updates the toolbar (and transitively the location bar) with the states of // the specified |tab|. If |shouldRestore| is true, we're switching // (back?) to this tab and should restore any previous location bar state @@ -164,6 +172,57 @@ class TabStripModelObserverBridge; // coordinates (origin in bottom-left). - (NSRect)regularWindowFrame; +- (BOOL)isBookmarkBarVisible; + +// Called after bookmark bar visibility changes (due to pref change or change in +// tab/tab contents). +- (void)updateBookmarkBarVisibilityWithAnimation:(BOOL)animate; + +- (BOOL)isDownloadShelfVisible; + +// Lazily creates the download shelf in visible state if it doesn't exist yet. +- (DownloadShelfController*)downloadShelf; + +// Retains the given FindBarCocoaController and adds its view to this +// browser window. Must only be called once per +// BrowserWindowController. +- (void)addFindBar:(FindBarCocoaController*)findBarCocoaController; + +// The user changed the theme. +- (void)userChangedTheme; + +// Executes the command in the context of the current browser. +// |command| is an integer value containing one of the constants defined in the +// "chrome/app/chrome_dll_resource.h" file. +- (void)executeCommand:(int)command; + +// Delegate method for the status bubble to query about its vertical offset. +- (float)verticalOffsetForStatusBubble; + +// Show the bookmark bubble (e.g. user just clicked on the STAR) +- (void)showBookmarkBubbleForURL:(const GURL&)url + alreadyBookmarked:(BOOL)alreadyBookmarked; + +// Returns the (lazily created) window sheet controller of this window. Used +// for the per-tab sheets. +- (GTMWindowSheetController*)sheetController; + +// Requests that |window| is opened as a per-tab sheet to the current tab. +- (void)attachConstrainedWindow:(ConstrainedWindowMac*)window; +// Closes the tab sheet |window| and potentially shows the next sheet in the +// tab's sheet queue. +- (void)removeConstrainedWindow:(ConstrainedWindowMac*)window; + +// Shows or hides the docked web inspector depending on |contents|'s state. +- (void)updateDevToolsForContents:(TabContents*)contents; + +@end // @interface BrowserWindowController + + +// Methods having to do with the window type (normal/popup/app, and whether the +// window has various features; fullscreen methods are separate). +@interface BrowserWindowController(WindowType) + // Determines whether this controller's window supports a given feature (i.e., // whether a given feature is or can be shown in the window). // TODO(viettrungluu): |feature| is really should be |Browser::Feature|, but I @@ -191,27 +250,11 @@ class TabStripModelObserverBridge; // pop-up window). Returns YES if it is, NO otherwise. - (BOOL)isNormalWindow; -- (BOOL)isBookmarkBarVisible; +@end // @interface BrowserWindowController(WindowType) -// Called after bookmark bar visibility changes (due to pref change or change in -// tab/tab contents). -- (void)updateBookmarkBarVisibilityWithAnimation:(BOOL)animate; -// Return a weak pointer to the tab strip controller. -- (TabStripController*)tabStripController; - -// Return a weak pointer to the toolbar controller. -- (ToolbarController*)toolbarController; - -- (BOOL)isDownloadShelfVisible; - -// Lazily creates the download shelf in visible state if it doesn't exist yet. -- (DownloadShelfController*)downloadShelf; - -// Retains the given FindBarCocoaController and adds its view to this -// browser window. Must only be called once per -// BrowserWindowController. -- (void)addFindBar:(FindBarCocoaController*)findBarCocoaController; +// Methods having to do with fullscreen mode. +@interface BrowserWindowController(Fullscreen) // Enters (or exits) fullscreen mode. - (void)setFullscreen:(BOOL)fullscreen; @@ -245,35 +288,8 @@ class TabStripModelObserverBridge; // Returns YES if any of the views in the floating bar currently has focus. - (BOOL)floatingBarHasFocus; -// The user changed the theme. -- (void)userChangedTheme; +@end // @interface BrowserWindowController(Fullscreen) -// Executes the command in the context of the current browser. -// |command| is an integer value containing one of the constants defined in the -// "chrome/app/chrome_dll_resource.h" file. -- (void)executeCommand:(int)command; - -// Delegate method for the status bubble to query about its vertical offset. -- (float)verticalOffsetForStatusBubble; - -// Show the bookmark bubble (e.g. user just clicked on the STAR) -- (void)showBookmarkBubbleForURL:(const GURL&)url - alreadyBookmarked:(BOOL)alreadyBookmarked; - -// Returns the (lazily created) window sheet controller of this window. Used -// for the per-tab sheets. -- (GTMWindowSheetController*)sheetController; - -// Requests that |window| is opened as a per-tab sheet to the current tab. -- (void)attachConstrainedWindow:(ConstrainedWindowMac*)window; -// Closes the tab sheet |window| and potentially shows the next sheet in the -// tab's sheet queue. -- (void)removeConstrainedWindow:(ConstrainedWindowMac*)window; - -// Shows or hides the docked web inspector depending on |contents|'s state. -- (void)updateDevToolsForContents:(TabContents*)contents; - -@end // Methods which are either only for testing, or only public for testing. @interface BrowserWindowController(TestingAPI) @@ -305,6 +321,7 @@ class TabStripModelObserverBridge; // or the download shelf), so that future shrinking will occur from the bottom. - (void)resetWindowGrowthState; -@end // BrowserWindowController(TestingAPI) +@end // @interface BrowserWindowController(TestingAPI) + #endif // CHROME_BROWSER_COCOA_BROWSER_WINDOW_CONTROLLER_H_ diff --git a/chrome/browser/cocoa/browser_window_controller.mm b/chrome/browser/cocoa/browser_window_controller.mm index c646528..4818b52 100644 --- a/chrome/browser/cocoa/browser_window_controller.mm +++ b/chrome/browser/cocoa/browser_window_controller.mm @@ -12,32 +12,25 @@ #import "base/scoped_nsobject.h" #include "base/sys_string_conversions.h" #include "chrome/app/chrome_dll_resource.h" // IDC_* -#include "chrome/browser/bookmarks/bookmark_editor.h" #include "chrome/browser/browser.h" #include "chrome/browser/browser_list.h" -#include "chrome/browser/browser_process.h" -#include "chrome/browser/browser_theme_provider.h" #include "chrome/browser/dock_info.h" #include "chrome/browser/encoding_menu_controller.h" #include "chrome/browser/location_bar.h" #include "chrome/browser/profile.h" #include "chrome/browser/window_sizer.h" -#include "chrome/browser/renderer_host/render_widget_host_view.h" -#include "chrome/browser/tab_contents/tab_contents.h" -#include "chrome/browser/tab_contents/tab_contents_view.h" -#include "chrome/browser/tabs/tab_strip_model.h" +#include "chrome/browser/bookmarks/bookmark_editor.h" #import "chrome/browser/cocoa/autocomplete_text_field_editor.h" #import "chrome/browser/cocoa/background_gradient_view.h" #import "chrome/browser/cocoa/bookmark_bar_controller.h" #import "chrome/browser/cocoa/bookmark_editor_controller.h" #import "chrome/browser/cocoa/browser_window_cocoa.h" -#import "chrome/browser/cocoa/chrome_browser_window.h" +#import "chrome/browser/cocoa/browser_window_controller_private.h" #import "chrome/browser/cocoa/download_shelf_controller.h" #import "chrome/browser/cocoa/event_utils.h" #import "chrome/browser/cocoa/fast_resize_view.h" #import "chrome/browser/cocoa/find_bar_cocoa_controller.h" -#include "chrome/browser/cocoa/find_bar_bridge.h" -#import "chrome/browser/cocoa/floating_bar_backing_view.h" +#import "chrome/browser/cocoa/find_bar_bridge.h" #import "chrome/browser/cocoa/focus_tracker.h" #import "chrome/browser/cocoa/fullscreen_controller.h" #import "chrome/browser/cocoa/fullscreen_window.h" @@ -46,37 +39,51 @@ #import "chrome/browser/cocoa/status_bubble_mac.h" #import "chrome/browser/cocoa/tab_contents_controller.h" #import "chrome/browser/cocoa/tab_strip_model_observer_bridge.h" -#import "chrome/browser/cocoa/tab_strip_view.h" #import "chrome/browser/cocoa/tab_strip_controller.h" +#import "chrome/browser/cocoa/tab_strip_view.h" #import "chrome/browser/cocoa/tab_view.h" #import "chrome/browser/cocoa/toolbar_controller.h" +#include "chrome/browser/renderer_host/render_widget_host_view.h" #include "chrome/browser/sync/profile_sync_service.h" #include "chrome/browser/sync/sync_ui_util_mac.h" -#include "chrome/common/pref_names.h" -#include "chrome/common/pref_service.h" -#include "grit/generated_resources.h" +#include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/tab_contents/tab_contents_view.h" +#include "chrome/browser/tabs/tab_strip_model.h" #include "grit/locale_settings.h" -#include "grit/theme_resources.h" -#import "third_party/GTM/AppKit/GTMTheme.h" + // ORGANIZATION: This is a big file. It is (in principle) organized as follows // (in order): -// 1. Interfaces, including for our private methods. Very short, one-time-use -// classes may include an implementation immediately after their interface. +// 1. Interfaces. Very short, one-time-use classes may include an implementation +// immediately after their interface. // 2. The general implementation section, ordered as follows: // i. Public methods and overrides. // ii. Overrides/implementations of undocumented methods. // iii. Delegate methods for various protocols, formal and informal, to which // |BrowserWindowController| conforms. -// 3. The private implementation section (|BrowserWindowController (Private)|). -// 4. Implementation for |GTMTheme (BrowserThemeProviderInitialization)|. +// 3. (temporary) Implementation sections for various categories. +// +// Private methods are defined and implemented separately in +// browser_window_controller_private.{h,mm}. // // Not all of the above guidelines are followed and more (re-)organization is // needed. BUT PLEASE TRY TO KEEP THIS FILE ORGANIZED. I'd rather re-organize as // little as possible, since doing so messes up the file's history. // -// TODO(viettrungluu): (re-)organize some more, possibly split into separate -// files? +// TODO(viettrungluu): [crbug.com/35543] on-going re-organization, splitting +// things into multiple files -- the plan is as follows: +// - in general, everything stays in browser_window_controller.h, but is split +// off into categories (see below) +// - core stuff stays in browser_window_controller.mm +// - ... overrides also stay (without going into a category, in particular) +// - private stuff which everyone needs goes into +// browser_window_controller_private.{h,mm}; if no one else needs them, they +// can go in individual files (see below) +// - area/task-specific stuff go in browser_window_controller_<area>.mm +// - ... in categories called "(<Area>)" or "(<PrivateArea>)" +// Plan of action: +// - first re-organize into categories +// - then split into files // Notes on self-inflicted (not user-inflicted) window resizing and moving: // @@ -119,25 +126,8 @@ // longer indicate that the window is shrinking from an apparent zoomed state) // and if it's set we continue to constrain the resize. -namespace { -// Insets for the location bar, used when the full toolbar is hidden. -// TODO(viettrungluu): We can argue about the "correct" insetting; I like the -// following best, though arguably 0 inset is better/more correct. -const CGFloat kLocBarLeftRightInset = 1; -const CGFloat kLocBarTopInset = 0; -const CGFloat kLocBarBottomInset = 1; - -// The amount by which the floating bar is offset downwards (to avoid the menu) -// in fullscreen mode. -const CGFloat kFullscreenVerticalBarOffset = 14; -} // end namespace - -@interface GTMTheme (BrowserThemeProviderInitialization) -+ (GTMTheme*)themeWithBrowserThemeProvider:(BrowserThemeProvider*)provider - isOffTheRecord:(BOOL)offTheRecord; -@end -@interface NSWindow (NSPrivateApis) +@interface NSWindow(NSPrivateApis) // Note: These functions are private, use -[NSObject respondsToSelector:] // before calling them. @@ -147,95 +137,6 @@ const CGFloat kFullscreenVerticalBarOffset = 14; @end -@interface BrowserWindowController(Private) - -// Saves the window's position in the local state preferences. -- (void)saveWindowPositionIfNeeded; - -// Saves the window's position to the given pref service. -- (void)saveWindowPositionToPrefs:(PrefService*)prefs; - -// We need to adjust where sheets come out of the window, as by default they -// erupt from the omnibox, which is rather weird. -- (NSRect)window:(NSWindow*)window -willPositionSheet:(NSWindow*)sheet - usingRect:(NSRect)defaultSheetRect; - -// Assign a theme to the window. -- (void)setTheme; - -// Repositions the window's subviews. From the top down: toolbar, normal -// bookmark bar (if shown), infobar, NTP detached bookmark bar (if shown), -// content area, download shelf (if any). -- (void)layoutSubviews; - -// Find the total height of the floating bar (in fullscreen mode). Safe to call -// even when not in fullscreen mode. -- (CGFloat)floatingBarHeight; - -// Lays out the tab strip at the given maximum y-coordinate, with the given -// width, possibly for fullscreen mode; returns the new maximum y (below the tab -// strip). This is safe to call even when there is no tab strip. -- (CGFloat)layoutTabStripAtMaxY:(CGFloat)maxY - width:(CGFloat)width - fullscreen:(BOOL)fullscreen; - -// Lays out the toolbar (or just location bar for popups) at the given maximum -// y-coordinate, with the given width; returns the new maximum y (below the -// toolbar). -- (CGFloat)layoutToolbarAtMaxY:(CGFloat)maxY width:(CGFloat)width; - -// Returns YES if the bookmark bar should be placed below the infobar, NO -// otherwise. -- (BOOL)placeBookmarkBarBelowInfoBar; - -// Lays out the bookmark bar at the given maximum y-coordinate, with the given -// width; returns the new maximum y (below the bookmark bar). Note that one must -// call it with the appropriate |maxY| which depends on whether or not the -// bookmark bar is shown as the NTP bubble or not (use -// |-placeBookmarkBarBelowInfoBar|). -- (CGFloat)layoutBookmarkBarAtMaxY:(CGFloat)maxY width:(CGFloat)width; - -// Lay out the view which draws the background for the floating bar when in -// fullscreen mode, with the given (minimum) y-coordinate, width, height, and -// fullscreen-mode-status. Should be called even when not in fullscreen mode to -// hide the backing view. -- (void)layoutFloatingBarBackingViewAtY:(CGFloat)y - width:(CGFloat)width - height:(CGFloat)height - fullscreen:(BOOL)fullscreen; - -// Lays out the infobar at the given maximum y-coordinate, with the given width; -// returns the new maximum y (below the infobar). -- (CGFloat)layoutInfoBarAtMaxY:(CGFloat)maxY width:(CGFloat)width; - -// Lays out the download shelf, if there is one, at the given minimum -// y-coordinate, with the given width; returns the new minimum y (above the -// download shelf). This is safe to call even if there is no download shelf. -- (CGFloat)layoutDownloadShelfAtMinY:(CGFloat)minY width:(CGFloat)width; - -// Lays out the tab content area between the given minimum and maximum -// y-coordinates, with the given width. -- (void)layoutTabContentAreaAtMinY:(CGFloat)minY - maxY:(CGFloat)maxY - width:(CGFloat)width; - -// Should we show the normal bookmark bar? -- (BOOL)shouldShowBookmarkBar; - -// Is the current page one for which the bookmark should be shown detached *if* -// 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; - -// Adjust the UI when entering or leaving fullscreen mode. -- (void)adjustUIForFullscreen:(BOOL)fullscreen; - -@end // IncognitoImageView subclasses NSImageView to allow mouse events to pass // through it so you can drag the window by dragging on the spy guy @@ -248,6 +149,7 @@ willPositionSheet:(NSWindow*)sheet } @end + @implementation BrowserWindowController + (BrowserWindowController*)browserWindowControllerForView:(NSView*)view { @@ -264,7 +166,7 @@ willPositionSheet:(NSWindow*)sheet return [self initWithBrowser:browser takeOwnership:YES]; } -// Private (TestingAPI) init routine with testing options. +// Private(TestingAPI) init routine with testing options. - (id)initWithBrowser:(Browser*)browser takeOwnership:(BOOL)ownIt { // Use initWithWindowNibPath:: instead of initWithWindowNibName: so we // can override it in a unit test. @@ -413,11 +315,26 @@ willPositionSheet:(NSWindow*)sheet [super dealloc]; } -// Access the C++ bridge between the NSWindow and the rest of Chromium - (BrowserWindow*)browserWindow { return windowShim_.get(); } +- (ToolbarController*)toolbarController { + return toolbarController_.get(); +} + +- (TabStripController*)tabStripController { + return tabStripController_.get(); +} + +- (StatusBubbleMac*)statusBubble { + return statusBubble_; +} + +- (LocationBar*)locationBarBridge { + return [toolbarController_ locationBarBridge]; +} + - (void)destroyBrowser { [NSApp removeWindowsItem:[self window]]; @@ -1038,14 +955,6 @@ willPositionSheet:(NSWindow*)sheet return [tabStripController_ sheetController]; } -- (LocationBar*)locationBarBridge { - return [toolbarController_ locationBarBridge]; -} - -- (StatusBubbleMac*)statusBubble { - return statusBubble_; -} - - (void)updateToolbarWithContents:(TabContents*)tab shouldRestoreState:(BOOL)shouldRestore { [toolbarController_ updateToolbarWithContents:tab @@ -1162,14 +1071,6 @@ willPositionSheet:(NSWindow*)sheet return [tabStripController_ selectedTabView]; } -- (TabStripController*)tabStripController { - return tabStripController_.get(); -} - -- (ToolbarController*)toolbarController { - return toolbarController_.get(); -} - - (void)setIsLoading:(BOOL)isLoading { [toolbarController_ setIsLoading:isLoading]; } @@ -1320,146 +1221,6 @@ willPositionSheet:(NSWindow*)sheet autorelease]; } -- (void)setFullscreen:(BOOL)fullscreen { - // The logic in this function is a bit complicated and very carefully - // arranged. See the below comments for more details. - - if (fullscreen == [self isFullscreen]) - return; - - if (![self supportsFullscreen]) - return; - - // Save the current first responder so we can restore after views are moved. - NSWindow* window = [self window]; - scoped_nsobject<FocusTracker> focusTracker( - [[FocusTracker alloc] initWithWindow:window]); - BOOL showDropdown = [self floatingBarHasFocus]; - - // If we're entering fullscreen, create the fullscreen controller. If we're - // exiting fullscreen, kill the controller. - if (fullscreen) { - fullscreenController_.reset([[FullscreenController alloc] - initWithBrowserController:self]); - } else { - [fullscreenController_ exitFullscreen]; - fullscreenController_.reset(nil); - } - - // Retain the tab strip view while we remove it from its superview. - scoped_nsobject<NSView> tabStripView; - if ([self hasTabStrip]) { - tabStripView.reset([[self tabStripView] retain]); - [tabStripView removeFromSuperview]; - } - - // Ditto for the content view. - scoped_nsobject<NSView> contentView([[window contentView] retain]); - // Disable autoresizing of subviews while we move views around. This prevents - // spurious renderer resizes. - [contentView setAutoresizesSubviews:NO]; - [contentView removeFromSuperview]; - - NSWindow* destWindow = nil; - if (fullscreen) { - DCHECK(!savedRegularWindow_); - savedRegularWindow_ = [window retain]; - destWindow = [self createFullscreenWindow]; - } else { - DCHECK(savedRegularWindow_); - destWindow = [savedRegularWindow_ autorelease]; - savedRegularWindow_ = nil; - } - DCHECK(destWindow); - - // Have to do this here, otherwise later calls can crash because the window - // has no delegate. - [window setDelegate:nil]; - [destWindow setDelegate:self]; - - // With this call, valgrind complains that a "Conditional jump or move depends - // on uninitialised value(s)". The error happens in -[NSThemeFrame - // drawOverlayRect:]. I'm pretty convinced this is an Apple bug, but there is - // no visual impact. I have been unable to tickle it away with other window - // or view manipulation Cocoa calls. Stack added to suppressions_mac.txt. - [contentView setAutoresizesSubviews:YES]; - [destWindow setContentView:contentView]; - - // Add the tabstrip after setting the content view, so that the tab strip will - // be on top (in the z-order). - if ([self hasTabStrip]) - [[[destWindow contentView] superview] addSubview:tabStripView]; - - [window setWindowController:nil]; - [self setWindow:destWindow]; - [destWindow setWindowController:self]; - [self adjustUIForFullscreen:fullscreen]; - - // When entering fullscreen mode, the controller forces a layout for us. When - // exiting, we need to call layoutSubviews manually. - if (fullscreen) { - [fullscreenController_ enterFullscreenForContentView:contentView - showDropdown:showDropdown]; - } else { - [self layoutSubviews]; - } - - // The window needs to be onscreen before we can set its first responder. - [destWindow makeKeyAndOrderFront:self]; - [focusTracker restoreFocusInWindow:destWindow]; - [window orderOut:self]; -} - -- (BOOL)isFullscreen { - return savedRegularWindow_ != nil; -} - -- (CGFloat)floatingBarShownFraction { - return floatingBarShownFraction_; -} - -- (void)setFloatingBarShownFraction:(CGFloat)fraction { - floatingBarShownFraction_ = fraction; - [self layoutSubviews]; -} - -- (BOOL)isBarVisibilityLockedForOwner:(id)owner { - DCHECK(owner); - DCHECK(barVisibilityLocks_); - return [barVisibilityLocks_ containsObject:owner]; -} - -- (void)lockBarVisibilityForOwner:(id)owner - withAnimation:(BOOL)animate - delay:(BOOL)delay { - if (![self isBarVisibilityLockedForOwner:owner]) { - [barVisibilityLocks_ addObject:owner]; - - // Show the overlay if necessary (and if in fullscreen mode). - [fullscreenController_ ensureOverlayShownWithAnimation:animate - delay:delay]; - } -} - -- (void)releaseBarVisibilityForOwner:(id)owner - withAnimation:(BOOL)animate - delay:(BOOL)delay { - if ([self isBarVisibilityLockedForOwner:owner]) { - [barVisibilityLocks_ removeObject:owner]; - - // Hide the overlay if necessary (and if in fullscreen mode). - if (![barVisibilityLocks_ count]) { - [fullscreenController_ ensureOverlayHiddenWithAnimation:animate - delay:delay]; - } - } -} - -- (BOOL)floatingBarHasFocus { - NSResponder* focused = [[self window] firstResponder]; - return [focused isKindOfClass:[AutocompleteTextFieldEditor class]]; -} - - (NSInteger)numberOfTabs { return browser_->tabstrip_model()->count(); } @@ -1469,11 +1230,6 @@ willPositionSheet:(NSWindow*)sheet return base::SysUTF16ToNSString(contents->GetTitle()); } -- (BOOL)supportsWindowFeature:(int)feature { - return browser_->SupportsWindowFeature( - static_cast<Browser::WindowFeature>(feature)); -} - - (NSRect)regularWindowFrame { return [self isFullscreen] ? [savedRegularWindow_ frame] : [[self window] frame]; @@ -1484,26 +1240,6 @@ willPositionSheet:(NSWindow*)sheet return [self supportsWindowFeature:Browser::FEATURE_TABSTRIP]; } -- (BOOL)hasTitleBar { - return [self supportsWindowFeature:Browser::FEATURE_TITLEBAR]; -} - -- (BOOL)hasToolbar { - return [self supportsWindowFeature:Browser::FEATURE_TOOLBAR]; -} - -- (BOOL)hasLocationBar { - return [self supportsWindowFeature:Browser::FEATURE_LOCATIONBAR]; -} - -- (BOOL)supportsBookmarkBar { - return [self supportsWindowFeature:Browser::FEATURE_BOOKMARKBAR]; -} - -- (BOOL)isNormalWindow { - return browser_->type() == Browser::TYPE_NORMAL; -} - - (void)selectTabWithContents:(TabContents*)newContents previousContents:(TabContents*)oldContents atIndex:(NSInteger)index @@ -1844,558 +1580,179 @@ willAnimateFromState:(bookmarks::VisualState)oldState isShrinkingFromZoomed_ = NO; } -@end +@end // @implementation BrowserWindowController -@implementation BrowserWindowController (Private) -- (void)saveWindowPositionIfNeeded { - if (browser_ != BrowserList::GetLastActive()) - return; +@implementation BrowserWindowController(Fullscreen) + +- (void)setFullscreen:(BOOL)fullscreen { + // The logic in this function is a bit complicated and very carefully + // arranged. See the below comments for more details. - if (!g_browser_process || !g_browser_process->local_state() || - !browser_->ShouldSaveWindowPlacement()) + if (fullscreen == [self isFullscreen]) return; - [self saveWindowPositionToPrefs:g_browser_process->local_state()]; -} - -- (void)saveWindowPositionToPrefs:(PrefService*)prefs { - // If we're in fullscreen mode, save the position of the regular window - // instead. - NSWindow* window = [self isFullscreen] ? savedRegularWindow_ : [self window]; - - // Window positions are stored relative to the origin of the primary monitor. - NSRect monitorFrame = [[[NSScreen screens] objectAtIndex:0] frame]; - - // Start with the window's frame, which is in virtual coordinates. - // Do some y twiddling to flip the coordinate system. - gfx::Rect bounds(NSRectToCGRect([window frame])); - bounds.set_y(monitorFrame.size.height - bounds.y() - bounds.height()); - - // We also need to save the current work area, in flipped coordinates. - gfx::Rect workArea(NSRectToCGRect([[window screen] visibleFrame])); - workArea.set_y(monitorFrame.size.height - workArea.y() - workArea.height()); - - DictionaryValue* windowPreferences = prefs->GetMutableDictionary( - browser_->GetWindowPlacementKey().c_str()); - windowPreferences->SetInteger(L"left", bounds.x()); - windowPreferences->SetInteger(L"top", bounds.y()); - windowPreferences->SetInteger(L"right", bounds.right()); - windowPreferences->SetInteger(L"bottom", bounds.bottom()); - windowPreferences->SetBoolean(L"maximized", false); - windowPreferences->SetBoolean(L"always_on_top", false); - windowPreferences->SetInteger(L"work_area_left", workArea.x()); - windowPreferences->SetInteger(L"work_area_top", workArea.y()); - windowPreferences->SetInteger(L"work_area_right", workArea.right()); - windowPreferences->SetInteger(L"work_area_bottom", workArea.bottom()); -} - -- (NSRect)window:(NSWindow*)window -willPositionSheet:(NSWindow*)sheet - usingRect:(NSRect)defaultSheetRect { - // Position the sheet as follows: - // - If the bookmark bar is hidden or shown as a bubble (on the NTP when the - // bookmark bar is disabled), position the sheet immediately below the - // normal toolbar. - // - If the bookmark bar is shown (attached to the normal toolbar), position - // the sheet below the bookmark bar. - // - If the bookmark bar is currently animating, position the sheet according - // to where the bar will be when the animation ends. - switch ([bookmarkBarController_ visualState]) { - case bookmarks::kShowingState: { - NSRect bookmarkBarFrame = [[bookmarkBarController_ view] frame]; - defaultSheetRect.origin.y = bookmarkBarFrame.origin.y; - break; - } - case bookmarks::kHiddenState: - case bookmarks::kDetachedState: { - NSRect toolbarFrame = [[toolbarController_ view] frame]; - defaultSheetRect.origin.y = toolbarFrame.origin.y; - break; - } - case bookmarks::kInvalidState: - default: - NOTREACHED(); - } - return defaultSheetRect; -} - -- (void)setTheme { - ThemeProvider* theme_provider = browser_->profile()->GetThemeProvider(); - BrowserThemeProvider* browser_theme_provider = - static_cast<BrowserThemeProvider*>(theme_provider); - if (browser_theme_provider) { - bool offtheRecord = browser_->profile()->IsOffTheRecord(); - GTMTheme* theme = - [GTMTheme themeWithBrowserThemeProvider:browser_theme_provider - isOffTheRecord:offtheRecord]; - theme_.reset([theme retain]); - } -} + if (![self supportsFullscreen]) + return; -- (void)layoutSubviews { - // With the exception of the tab strip, the subviews which we lay out are - // subviews of the content view, so we mainly work in the content view's - // coordinate system. Note, however, that the content view's coordinate system - // and the window's base coordinate system should coincide. + // Save the current first responder so we can restore after views are moved. NSWindow* window = [self window]; - NSView* contentView = [window contentView]; - NSRect contentBounds = [contentView bounds]; - CGFloat minY = NSMinY(contentBounds); - CGFloat width = NSWidth(contentBounds); - - // Suppress title drawing if necessary. - if ([window respondsToSelector:@selector(setShouldHideTitle:)]) - [(id)window setShouldHideTitle:![self hasTitleBar]]; + scoped_nsobject<FocusTracker> focusTracker( + [[FocusTracker alloc] initWithWindow:window]); + BOOL showDropdown = [self floatingBarHasFocus]; - BOOL isFullscreen = [self isFullscreen]; - CGFloat floatingBarHeight = [self floatingBarHeight]; - CGFloat yOffset = floor( - isFullscreen ? (1 - floatingBarShownFraction_) * floatingBarHeight : 0); - CGFloat maxY = NSMaxY(contentBounds) + yOffset; - CGFloat startMaxY = maxY; + // If we're entering fullscreen, create the fullscreen controller. If we're + // exiting fullscreen, kill the controller. + if (fullscreen) { + fullscreenController_.reset([[FullscreenController alloc] + initWithBrowserController:self]); + } else { + [fullscreenController_ exitFullscreen]; + fullscreenController_.reset(nil); + } + // Retain the tab strip view while we remove it from its superview. + scoped_nsobject<NSView> tabStripView; if ([self hasTabStrip]) { - // If we need to lay out the tab strip, replace |maxY| and |startMaxY| with - // higher values, and then lay out the tab strip. - startMaxY = maxY = NSHeight([window frame]) + yOffset; - maxY = [self layoutTabStripAtMaxY:maxY width:width fullscreen:isFullscreen]; + tabStripView.reset([[self tabStripView] retain]); + [tabStripView removeFromSuperview]; } - // Sanity-check |maxY|. - DCHECK_GE(maxY, minY); - DCHECK_LE(maxY, NSMaxY(contentBounds) + yOffset); - - // Place the toolbar at the top of the reserved area. - maxY = [self layoutToolbarAtMaxY:maxY width:width]; - - // If we're not displaying the bookmark bar below the infobar, then it goes - // immediately below the toolbar. - BOOL placeBookmarkBarBelowInfoBar = [self placeBookmarkBarBelowInfoBar]; - if (!placeBookmarkBarBelowInfoBar) - maxY = [self layoutBookmarkBarAtMaxY:maxY width:width]; - - // The floating bar backing view doesn't actually add any height. - [self layoutFloatingBarBackingViewAtY:maxY - width:width - height:floatingBarHeight - fullscreen:isFullscreen]; + // Ditto for the content view. + scoped_nsobject<NSView> contentView([[window contentView] retain]); + // Disable autoresizing of subviews while we move views around. This prevents + // spurious renderer resizes. + [contentView setAutoresizesSubviews:NO]; + [contentView removeFromSuperview]; - [fullscreenController_ overlayFrameChanged:[floatingBarBackingView_ frame]]; + NSWindow* destWindow = nil; + if (fullscreen) { + DCHECK(!savedRegularWindow_); + savedRegularWindow_ = [window retain]; + destWindow = [self createFullscreenWindow]; + } else { + DCHECK(savedRegularWindow_); + destWindow = [savedRegularWindow_ autorelease]; + savedRegularWindow_ = nil; + } + DCHECK(destWindow); - // Place the find bar immediately below the toolbar/attached bookmark bar. In - // fullscreen mode, it hangs off the top of the screen when the bar is hidden. - [findBarCocoaController_ positionFindBarViewAtMaxY:maxY maxWidth:width]; + // Have to do this here, otherwise later calls can crash because the window + // has no delegate. + [window setDelegate:nil]; + [destWindow setDelegate:self]; - // If in fullscreen mode, reset |maxY| to top of screen, so that the floating - // bar slides over the things which appear to be in the content area. - if (isFullscreen) - maxY = NSMaxY(contentBounds); + // With this call, valgrind complains that a "Conditional jump or move depends + // on uninitialised value(s)". The error happens in -[NSThemeFrame + // drawOverlayRect:]. I'm pretty convinced this is an Apple bug, but there is + // no visual impact. I have been unable to tickle it away with other window + // or view manipulation Cocoa calls. Stack added to suppressions_mac.txt. + [contentView setAutoresizesSubviews:YES]; + [destWindow setContentView:contentView]; - // Also place the infobar container immediate below the toolbar, except in - // fullscreen mode in which case it's at the top of the visual content area. - maxY = [self layoutInfoBarAtMaxY:maxY width:width]; + // Add the tabstrip after setting the content view, so that the tab strip will + // be on top (in the z-order). + if ([self hasTabStrip]) + [[[destWindow contentView] superview] addSubview:tabStripView]; - // If the bookmark bar is detached, place it next in the visual content area. - if (placeBookmarkBarBelowInfoBar) - maxY = [self layoutBookmarkBarAtMaxY:maxY width:width]; + [window setWindowController:nil]; + [self setWindow:destWindow]; + [destWindow setWindowController:self]; + [self adjustUIForFullscreen:fullscreen]; - // Place the download shelf, if any, at the bottom of the view. - minY = [self layoutDownloadShelfAtMinY:minY width:width]; + // When entering fullscreen mode, the controller forces a layout for us. When + // exiting, we need to call layoutSubviews manually. + if (fullscreen) { + [fullscreenController_ enterFullscreenForContentView:contentView + showDropdown:showDropdown]; + } else { + [self layoutSubviews]; + } - // Finally, the content area takes up all of the remaining space. - [self layoutTabContentAreaAtMinY:minY maxY:maxY width:width]; + // The window needs to be onscreen before we can set its first responder. + [destWindow makeKeyAndOrderFront:self]; + [focusTracker restoreFocusInWindow:destWindow]; + [window orderOut:self]; +} - // Place the status bubble at the bottom of the content area. - verticalOffsetForStatusBubble_ = minY; +- (BOOL)isFullscreen { + return savedRegularWindow_ != nil; +} - // Normally, we don't need to tell the toolbar whether or not to show the - // divider, but things break down during animation. - [toolbarController_ - setDividerOpacity:[bookmarkBarController_ toolbarDividerOpacity]]; +- (CGFloat)floatingBarShownFraction { + return floatingBarShownFraction_; } -- (CGFloat)floatingBarHeight { - if (![self isFullscreen]) - return 0; +- (void)setFloatingBarShownFraction:(CGFloat)fraction { + floatingBarShownFraction_ = fraction; + [self layoutSubviews]; +} - CGFloat totalHeight = kFullscreenVerticalBarOffset; +- (BOOL)isBarVisibilityLockedForOwner:(id)owner { + DCHECK(owner); + DCHECK(barVisibilityLocks_); + return [barVisibilityLocks_ containsObject:owner]; +} - if ([self hasTabStrip]) - totalHeight += NSHeight([[self tabStripView] frame]); +- (void)lockBarVisibilityForOwner:(id)owner + withAnimation:(BOOL)animate + delay:(BOOL)delay { + if (![self isBarVisibilityLockedForOwner:owner]) { + [barVisibilityLocks_ addObject:owner]; - if ([self hasToolbar]) { - totalHeight += NSHeight([[toolbarController_ view] frame]); - } else if ([self hasLocationBar]) { - totalHeight += NSHeight([[toolbarController_ view] frame]) + - kLocBarTopInset + kLocBarBottomInset; + // Show the overlay if necessary (and if in fullscreen mode). + [fullscreenController_ ensureOverlayShownWithAnimation:animate + delay:delay]; } - - if (![self placeBookmarkBarBelowInfoBar]) - totalHeight += NSHeight([[bookmarkBarController_ view] frame]); - - return totalHeight; } -- (CGFloat)layoutTabStripAtMaxY:(CGFloat)maxY - width:(CGFloat)width - fullscreen:(BOOL)fullscreen { - // Nothing to do if no tab strip. - if (![self hasTabStrip]) - return maxY; - - NSView* tabStripView = [self tabStripView]; - CGFloat tabStripHeight = NSHeight([tabStripView frame]); - // In fullscreen mode, push the tab strip down so that the main menu (which - // also slides down) doesn't run it over. - if (fullscreen) - maxY -= kFullscreenVerticalBarOffset; - maxY -= tabStripHeight; - [tabStripView setFrame:NSMakeRect(0, maxY, width, tabStripHeight)]; - - // Set indentation. - [tabStripController_ setIndentForControls:(fullscreen ? 0 : - [[tabStripController_ class] defaultIndentForControls])]; - - // TODO(viettrungluu): Seems kind of bad -- shouldn't |-layoutSubviews| do - // this? Moreover, |-layoutTabs| will try to animate.... - [tabStripController_ layoutTabs]; - - return maxY; -} +- (void)releaseBarVisibilityForOwner:(id)owner + withAnimation:(BOOL)animate + delay:(BOOL)delay { + if ([self isBarVisibilityLockedForOwner:owner]) { + [barVisibilityLocks_ removeObject:owner]; -- (CGFloat)layoutToolbarAtMaxY:(CGFloat)maxY width:(CGFloat)width { - NSView* toolbarView = [toolbarController_ view]; - NSRect toolbarFrame = [toolbarView frame]; - if ([self hasToolbar]) { - // The toolbar is present in the window, so we make room for it. - DCHECK(![toolbarView isHidden]); - toolbarFrame.origin.x = 0; - toolbarFrame.origin.y = maxY - NSHeight(toolbarFrame); - toolbarFrame.size.width = width; - maxY -= NSHeight(toolbarFrame); - } else { - if ([self hasLocationBar]) { - // Location bar is present with no toolbar. Put a border of - // |kLocBar...Inset| pixels around the location bar. - // TODO(viettrungluu): This is moderately ridiculous. The toolbar should - // really be aware of what its height should be (the way the toolbar - // compression stuff is currently set up messes things up). - DCHECK(![toolbarView isHidden]); - toolbarFrame.origin.x = kLocBarLeftRightInset; - toolbarFrame.origin.y = maxY - NSHeight(toolbarFrame) - kLocBarTopInset; - toolbarFrame.size.width = width - 2 * kLocBarLeftRightInset; - maxY -= kLocBarTopInset + NSHeight(toolbarFrame) + kLocBarBottomInset; - } else { - DCHECK([toolbarView isHidden]); - } - } - [toolbarView setFrame:toolbarFrame]; - return maxY; -} - -- (BOOL)placeBookmarkBarBelowInfoBar { - // If we are currently displaying the NTP detached bookmark bar or animating - // to/from it (from/to anything else), we display the bookmark bar below the - // infobar. - return [bookmarkBarController_ isInState:bookmarks::kDetachedState] || - [bookmarkBarController_ isAnimatingToState:bookmarks::kDetachedState] || - [bookmarkBarController_ isAnimatingFromState:bookmarks::kDetachedState]; -} - -- (CGFloat)layoutBookmarkBarAtMaxY:(CGFloat)maxY width:(CGFloat)width { - NSView* bookmarkBarView = [bookmarkBarController_ view]; - NSRect bookmarkBarFrame = [bookmarkBarView frame]; - BOOL oldHidden = [bookmarkBarView isHidden]; - BOOL newHidden = ![self isBookmarkBarVisible]; - if (oldHidden != newHidden) - [bookmarkBarView setHidden:newHidden]; - bookmarkBarFrame.origin.y = maxY - NSHeight(bookmarkBarFrame); - bookmarkBarFrame.size.width = width; - [bookmarkBarView setFrame:bookmarkBarFrame]; - maxY -= NSHeight(bookmarkBarFrame); - - // TODO(viettrungluu): Does this really belong here? Calling it shouldn't be - // necessary in the non-NTP case. - [bookmarkBarController_ layoutSubviews]; - - return maxY; -} - -- (void)layoutFloatingBarBackingViewAtY:(CGFloat)y - width:(CGFloat)width - height:(CGFloat)height - fullscreen:(BOOL)fullscreen { - // Only display when in fullscreen mode. - if (fullscreen) { - DCHECK(floatingBarBackingView_.get()); - BOOL aboveBookmarkBar = [self placeBookmarkBarBelowInfoBar]; - - // Insert it into the view hierarchy if necessary. - if (![floatingBarBackingView_ superview] || - aboveBookmarkBar != floatingBarAboveBookmarkBar_) { - NSView* contentView = [[self window] contentView]; - // z-order gets messed up unless we explicitly remove the floatingbar view - // and re-add it. - [floatingBarBackingView_ removeFromSuperview]; - [contentView addSubview:floatingBarBackingView_ - positioned:(aboveBookmarkBar ? - NSWindowAbove : NSWindowBelow) - relativeTo:[bookmarkBarController_ view]]; - floatingBarAboveBookmarkBar_ = aboveBookmarkBar; + // Hide the overlay if necessary (and if in fullscreen mode). + if (![barVisibilityLocks_ count]) { + [fullscreenController_ ensureOverlayHiddenWithAnimation:animate + delay:delay]; } - - // Set its frame. - [floatingBarBackingView_ setFrame:NSMakeRect(0, y, width, height)]; - } else { - // Okay to call even if |floatingBarBackingView_| is nil. - if ([floatingBarBackingView_ superview]) - [floatingBarBackingView_ removeFromSuperview]; } } -- (CGFloat)layoutInfoBarAtMaxY:(CGFloat)maxY width:(CGFloat)width { - NSView* infoBarView = [infoBarContainerController_ view]; - NSRect infoBarFrame = [infoBarView frame]; - infoBarFrame.origin.y = maxY - NSHeight(infoBarFrame); - infoBarFrame.size.width = width; - [infoBarView setFrame:infoBarFrame]; - maxY -= NSHeight(infoBarFrame); - return maxY; -} - -- (CGFloat)layoutDownloadShelfAtMinY:(CGFloat)minY width:(CGFloat)width { - if (downloadShelfController_.get()) { - NSView* downloadView = [downloadShelfController_ view]; - NSRect downloadFrame = [downloadView frame]; - downloadFrame.origin.y = minY; - downloadFrame.size.width = width; - [downloadView setFrame:downloadFrame]; - minY += NSHeight(downloadFrame); - } - return minY; +- (BOOL)floatingBarHasFocus { + NSResponder* focused = [[self window] firstResponder]; + return [focused isKindOfClass:[AutocompleteTextFieldEditor class]]; } -- (void)layoutTabContentAreaAtMinY:(CGFloat)minY - maxY:(CGFloat)maxY - width:(CGFloat)width { - NSView* tabContentView = [self tabContentArea]; - NSRect tabContentFrame = [tabContentView frame]; +@end // @implementation BrowserWindowController(Fullscreen) - bool contentShifted = NSMaxY(tabContentFrame) != maxY; - tabContentFrame.origin.y = minY; - tabContentFrame.size.height = maxY - minY; - tabContentFrame.size.width = width; - [tabContentView setFrame:tabContentFrame]; +@implementation BrowserWindowController(WindowType) - // If the relayout shifts the content area up or down, let the renderer know. - if (contentShifted) { - if (TabContents* contents = browser_->GetSelectedTabContents()) { - if (RenderWidgetHostView* rwhv = contents->GetRenderWidgetHostView()) - rwhv->WindowFrameChanged(); - } - } +- (BOOL)supportsWindowFeature:(int)feature { + return browser_->SupportsWindowFeature( + static_cast<Browser::WindowFeature>(feature)); } -- (BOOL)shouldShowBookmarkBar { - DCHECK(browser_.get()); - return browser_->profile()->GetPrefs()->GetBoolean(prefs::kShowBookmarkBar) ? - YES : NO; +- (BOOL)hasTitleBar { + return [self supportsWindowFeature:Browser::FEATURE_TITLEBAR]; } -- (BOOL)shouldShowDetachedBookmarkBar { - DCHECK(browser_.get()); - TabContents* contents = browser_->GetSelectedTabContents(); - return (contents && contents->ShouldShowBookmarkBar()) ? YES : NO; +- (BOOL)hasToolbar { + return [self supportsWindowFeature:Browser::FEATURE_TOOLBAR]; } -- (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]; +- (BOOL)hasLocationBar { + return [self supportsWindowFeature:Browser::FEATURE_LOCATIONBAR]; } -- (void)adjustUIForFullscreen:(BOOL)fullscreen { - if (fullscreen) { - mac_util::RequestFullScreen(); - - // Create the floating bar backing view if necessary. - if (!floatingBarBackingView_.get()) { - floatingBarBackingView_.reset( - [[FloatingBarBackingView alloc] initWithFrame:NSZeroRect]); - } - } else { - mac_util::ReleaseFullScreen(); - } +- (BOOL)supportsBookmarkBar { + return [self supportsWindowFeature:Browser::FEATURE_BOOKMARKBAR]; } -@end // @implementation BrowserWindowController (Private) - -@implementation GTMTheme (BrowserThemeProviderInitialization) -+ (GTMTheme*)themeWithBrowserThemeProvider:(BrowserThemeProvider*)provider - isOffTheRecord:(BOOL)isOffTheRecord { - // First check if it's in the cache. - typedef std::pair<std::string, BOOL> ThemeKey; - static std::map<ThemeKey, GTMTheme*> cache; - ThemeKey key(provider->GetThemeID(), isOffTheRecord); - GTMTheme* theme = cache[key]; - if (theme) - return theme; - - theme = [[GTMTheme alloc] init]; // "Leak" it in the cache. - cache[key] = theme; - - // TODO(pinkerton): Need to be able to theme the entire incognito window - // http://crbug.com/18568 The hardcoding of the colors here will need to be - // removed when that bug is addressed, but are here in order for things to be - // usable in the meantime. - if (isOffTheRecord) { - NSColor* incognitoColor = [NSColor colorWithCalibratedRed:83/255.0 - green:108.0/255.0 - blue:140/255.0 - alpha:1.0]; - [theme setBackgroundColor:incognitoColor]; - [theme setValue:[NSColor blackColor] - forAttribute:@"textColor" - style:GTMThemeStyleTabBarSelected - state:GTMThemeStateActiveWindow]; - [theme setValue:[NSColor blackColor] - forAttribute:@"textColor" - style:GTMThemeStyleTabBarDeselected - state:GTMThemeStateActiveWindow]; - [theme setValue:[NSColor blackColor] - forAttribute:@"textColor" - style:GTMThemeStyleBookmarksBarButton - state:GTMThemeStateActiveWindow]; - [theme setValue:[NSColor blackColor] - forAttribute:@"iconColor" - style:GTMThemeStyleToolBarButton - state:GTMThemeStateActiveWindow]; - return theme; - } - - NSImage* frameImage = provider->GetNSImageNamed(IDR_THEME_FRAME); - NSImage* frameInactiveImage = - provider->GetNSImageNamed(IDR_THEME_FRAME_INACTIVE); - - [theme setValue:frameImage - forAttribute:@"backgroundImage" - style:GTMThemeStyleWindow - state:GTMThemeStateActiveWindow]; - - NSColor* tabTextColor = - provider->GetNSColor(BrowserThemeProvider::COLOR_TAB_TEXT); - [theme setValue:tabTextColor - forAttribute:@"textColor" - style:GTMThemeStyleTabBarSelected - state:GTMThemeStateActiveWindow]; - - NSColor* tabInactiveTextColor = - provider->GetNSColor(BrowserThemeProvider::COLOR_BACKGROUND_TAB_TEXT); - [theme setValue:tabInactiveTextColor - forAttribute:@"textColor" - style:GTMThemeStyleTabBarDeselected - state:GTMThemeStateActiveWindow]; - - NSColor* bookmarkBarTextColor = - provider->GetNSColor(BrowserThemeProvider::COLOR_BOOKMARK_TEXT); - [theme setValue:bookmarkBarTextColor - forAttribute:@"textColor" - style:GTMThemeStyleBookmarksBarButton - state:GTMThemeStateActiveWindow]; - - [theme setValue:frameInactiveImage - forAttribute:@"backgroundImage" - style:GTMThemeStyleWindow - state:0]; - - NSImage* toolbarImage = provider->GetNSImageNamed(IDR_THEME_TOOLBAR); - [theme setValue:toolbarImage - forAttribute:@"backgroundImage" - style:GTMThemeStyleToolBar - state:GTMThemeStateActiveWindow]; - NSImage* toolbarBackgroundImage = - provider->GetNSImageNamed(IDR_THEME_TAB_BACKGROUND); - [theme setValue:toolbarBackgroundImage - forAttribute:@"backgroundImage" - style:GTMThemeStyleTabBarDeselected - state:GTMThemeStateActiveWindow]; - - NSImage* toolbarButtonImage = - provider->GetNSImageNamed(IDR_THEME_BUTTON_BACKGROUND); - if (toolbarButtonImage) { - [theme setValue:toolbarButtonImage - forAttribute:@"backgroundImage" - style:GTMThemeStyleToolBarButton - state:GTMThemeStateActiveWindow]; - } else { - NSColor* startColor = [NSColor colorWithCalibratedWhite:1.0 alpha:0.0]; - NSColor* endColor = [NSColor colorWithCalibratedWhite:1.0 alpha:0.3]; - scoped_nsobject<NSGradient> gradient([[NSGradient alloc] - initWithStartingColor:startColor - endingColor:endColor]); - - [theme setValue:gradient - forAttribute:@"gradient" - style:GTMThemeStyleToolBarButton - state:GTMThemeStateActiveWindow]; - - [theme setValue:gradient - forAttribute:@"gradient" - style:GTMThemeStyleToolBarButton - state:GTMThemeStateActiveWindow]; - } - - NSColor* toolbarButtonIconColor = - provider->GetNSColorTint(BrowserThemeProvider::TINT_BUTTONS); - [theme setValue:toolbarButtonIconColor - forAttribute:@"iconColor" - style:GTMThemeStyleToolBarButton - state:GTMThemeStateActiveWindow]; - - NSColor* toolbarButtonBorderColor = toolbarButtonIconColor; - [theme setValue:toolbarButtonBorderColor - forAttribute:@"borderColor" - style:GTMThemeStyleToolBar - state:GTMThemeStateActiveWindow]; - - NSColor* toolbarBackgroundColor = - provider->GetNSColor(BrowserThemeProvider::COLOR_TOOLBAR); - [theme setValue:toolbarBackgroundColor - forAttribute:@"backgroundColor" - style:GTMThemeStyleToolBar - state:GTMThemeStateActiveWindow]; - - NSImage* frameOverlayImage = - provider->GetNSImageNamed(IDR_THEME_FRAME_OVERLAY); - if (frameOverlayImage) { - [theme setValue:frameOverlayImage - forAttribute:@"overlay" - style:GTMThemeStyleWindow - state:GTMThemeStateActiveWindow]; - } - - NSImage* frameOverlayInactiveImage = - provider->GetNSImageNamed(IDR_THEME_FRAME_OVERLAY_INACTIVE); - if (frameOverlayInactiveImage) { - [theme setValue:frameOverlayInactiveImage - forAttribute:@"overlay" - style:GTMThemeStyleWindow - state:GTMThemeStateInactiveWindow]; - } - - return theme; +- (BOOL)isNormalWindow { + return browser_->type() == Browser::TYPE_NORMAL; } -@end + +@end // @implementation BrowserWindowController(WindowType) diff --git a/chrome/browser/cocoa/browser_window_controller_private.h b/chrome/browser/cocoa/browser_window_controller_private.h new file mode 100644 index 0000000..3ae054a --- /dev/null +++ b/chrome/browser/cocoa/browser_window_controller_private.h @@ -0,0 +1,108 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_COCOA_BROWSER_WINDOW_CONTROLLER_PRIVATE_H_ +#define CHROME_BROWSER_COCOA_BROWSER_WINDOW_CONTROLLER_PRIVATE_H_ + +#import "chrome/browser/cocoa/browser_window_controller.h" + + +// Private methods for the |BrowserWindowController|. This category should +// contain the private methods used by different parts of the BWC; private +// methods used only by single parts should be declared in their own file. +// TODO(viettrungluu): [crbug.com/35543] work on splitting out stuff from the +// BWC, and figuring out which methods belong here (need to unravel +// "dependencies"). +@interface BrowserWindowController(Private) + +// Saves the window's position in the local state preferences. +- (void)saveWindowPositionIfNeeded; + +// Saves the window's position to the given pref service. +- (void)saveWindowPositionToPrefs:(PrefService*)prefs; + +// We need to adjust where sheets come out of the window, as by default they +// erupt from the omnibox, which is rather weird. +- (NSRect)window:(NSWindow*)window + willPositionSheet:(NSWindow*)sheet + usingRect:(NSRect)defaultSheetRect; + +// Assign a theme to the window. +- (void)setTheme; + +// Repositions the window's subviews. From the top down: toolbar, normal +// bookmark bar (if shown), infobar, NTP detached bookmark bar (if shown), +// content area, download shelf (if any). +- (void)layoutSubviews; + +// Find the total height of the floating bar (in fullscreen mode). Safe to call +// even when not in fullscreen mode. +- (CGFloat)floatingBarHeight; + +// Lays out the tab strip at the given maximum y-coordinate, with the given +// width, possibly for fullscreen mode; returns the new maximum y (below the tab +// strip). This is safe to call even when there is no tab strip. +- (CGFloat)layoutTabStripAtMaxY:(CGFloat)maxY + width:(CGFloat)width + fullscreen:(BOOL)fullscreen; + +// Lays out the toolbar (or just location bar for popups) at the given maximum +// y-coordinate, with the given width; returns the new maximum y (below the +// toolbar). +- (CGFloat)layoutToolbarAtMaxY:(CGFloat)maxY width:(CGFloat)width; + +// Returns YES if the bookmark bar should be placed below the infobar, NO +// otherwise. +- (BOOL)placeBookmarkBarBelowInfoBar; + +// Lays out the bookmark bar at the given maximum y-coordinate, with the given +// width; returns the new maximum y (below the bookmark bar). Note that one must +// call it with the appropriate |maxY| which depends on whether or not the +// bookmark bar is shown as the NTP bubble or not (use +// |-placeBookmarkBarBelowInfoBar|). +- (CGFloat)layoutBookmarkBarAtMaxY:(CGFloat)maxY width:(CGFloat)width; + +// Lay out the view which draws the background for the floating bar when in +// fullscreen mode, with the given (minimum) y-coordinate, width, height, and +// fullscreen-mode-status. Should be called even when not in fullscreen mode to +// hide the backing view. +- (void)layoutFloatingBarBackingViewAtY:(CGFloat)y + width:(CGFloat)width + height:(CGFloat)height + fullscreen:(BOOL)fullscreen; + +// Lays out the infobar at the given maximum y-coordinate, with the given width; +// returns the new maximum y (below the infobar). +- (CGFloat)layoutInfoBarAtMaxY:(CGFloat)maxY width:(CGFloat)width; + +// Lays out the download shelf, if there is one, at the given minimum +// y-coordinate, with the given width; returns the new minimum y (above the +// download shelf). This is safe to call even if there is no download shelf. +- (CGFloat)layoutDownloadShelfAtMinY:(CGFloat)minY width:(CGFloat)width; + +// Lays out the tab content area between the given minimum and maximum +// y-coordinates, with the given width. +- (void)layoutTabContentAreaAtMinY:(CGFloat)minY + maxY:(CGFloat)maxY + width:(CGFloat)width; + +// Should we show the normal bookmark bar? +- (BOOL)shouldShowBookmarkBar; + +// Is the current page one for which the bookmark should be shown detached *if* +// 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; + +// Adjust the UI when entering or leaving fullscreen mode. +- (void)adjustUIForFullscreen:(BOOL)fullscreen; + +@end // @interface BrowserWindowController(Private) + + +#endif // CHROME_BROWSER_COCOA_BROWSER_WINDOW_CONTROLLER_PRIVATE_H_ diff --git a/chrome/browser/cocoa/browser_window_controller_private.mm b/chrome/browser/cocoa/browser_window_controller_private.mm new file mode 100644 index 0000000..45da0bf --- /dev/null +++ b/chrome/browser/cocoa/browser_window_controller_private.mm @@ -0,0 +1,440 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "chrome/browser/cocoa/browser_window_controller_private.h" + +#include "base/mac_util.h" +#import "base/scoped_nsobject.h" +#include "chrome/browser/browser.h" +#include "chrome/browser/browser_list.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/browser_theme_provider.h" +#import "chrome/browser/cocoa/browser_theme_provider_init.h" +#import "chrome/browser/cocoa/chrome_browser_window.h" +#import "chrome/browser/cocoa/fast_resize_view.h" +#import "chrome/browser/cocoa/find_bar_cocoa_controller.h" +#import "chrome/browser/cocoa/floating_bar_backing_view.h" +#import "chrome/browser/cocoa/fullscreen_controller.h" +#import "chrome/browser/cocoa/tab_strip_controller.h" +#import "chrome/browser/cocoa/tab_strip_view.h" +#import "chrome/browser/cocoa/toolbar_controller.h" +#include "chrome/browser/renderer_host/render_widget_host_view.h" +#include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/tab_contents/tab_contents_view.h" +#include "chrome/common/pref_names.h" +#include "chrome/common/pref_service.h" + + +namespace { + +// Insets for the location bar, used when the full toolbar is hidden. +// TODO(viettrungluu): We can argue about the "correct" insetting; I like the +// following best, though arguably 0 inset is better/more correct. +const CGFloat kLocBarLeftRightInset = 1; +const CGFloat kLocBarTopInset = 0; +const CGFloat kLocBarBottomInset = 1; + +// The amount by which the floating bar is offset downwards (to avoid the menu) +// in fullscreen mode. +const CGFloat kFullscreenVerticalBarOffset = 14; + +} // end namespace + + +@implementation BrowserWindowController(Private) + +- (void)saveWindowPositionIfNeeded { + if (browser_ != BrowserList::GetLastActive()) + return; + + if (!g_browser_process || !g_browser_process->local_state() || + !browser_->ShouldSaveWindowPlacement()) + return; + + [self saveWindowPositionToPrefs:g_browser_process->local_state()]; +} + +- (void)saveWindowPositionToPrefs:(PrefService*)prefs { + // If we're in fullscreen mode, save the position of the regular window + // instead. + NSWindow* window = [self isFullscreen] ? savedRegularWindow_ : [self window]; + + // Window positions are stored relative to the origin of the primary monitor. + NSRect monitorFrame = [[[NSScreen screens] objectAtIndex:0] frame]; + + // Start with the window's frame, which is in virtual coordinates. + // Do some y twiddling to flip the coordinate system. + gfx::Rect bounds(NSRectToCGRect([window frame])); + bounds.set_y(monitorFrame.size.height - bounds.y() - bounds.height()); + + // We also need to save the current work area, in flipped coordinates. + gfx::Rect workArea(NSRectToCGRect([[window screen] visibleFrame])); + workArea.set_y(monitorFrame.size.height - workArea.y() - workArea.height()); + + DictionaryValue* windowPreferences = prefs->GetMutableDictionary( + browser_->GetWindowPlacementKey().c_str()); + windowPreferences->SetInteger(L"left", bounds.x()); + windowPreferences->SetInteger(L"top", bounds.y()); + windowPreferences->SetInteger(L"right", bounds.right()); + windowPreferences->SetInteger(L"bottom", bounds.bottom()); + windowPreferences->SetBoolean(L"maximized", false); + windowPreferences->SetBoolean(L"always_on_top", false); + windowPreferences->SetInteger(L"work_area_left", workArea.x()); + windowPreferences->SetInteger(L"work_area_top", workArea.y()); + windowPreferences->SetInteger(L"work_area_right", workArea.right()); + windowPreferences->SetInteger(L"work_area_bottom", workArea.bottom()); +} + +- (NSRect)window:(NSWindow*)window +willPositionSheet:(NSWindow*)sheet + usingRect:(NSRect)defaultSheetRect { + // Position the sheet as follows: + // - If the bookmark bar is hidden or shown as a bubble (on the NTP when the + // bookmark bar is disabled), position the sheet immediately below the + // normal toolbar. + // - If the bookmark bar is shown (attached to the normal toolbar), position + // the sheet below the bookmark bar. + // - If the bookmark bar is currently animating, position the sheet according + // to where the bar will be when the animation ends. + switch ([bookmarkBarController_ visualState]) { + case bookmarks::kShowingState: { + NSRect bookmarkBarFrame = [[bookmarkBarController_ view] frame]; + defaultSheetRect.origin.y = bookmarkBarFrame.origin.y; + break; + } + case bookmarks::kHiddenState: + case bookmarks::kDetachedState: { + NSRect toolbarFrame = [[toolbarController_ view] frame]; + defaultSheetRect.origin.y = toolbarFrame.origin.y; + break; + } + case bookmarks::kInvalidState: + default: + NOTREACHED(); + } + return defaultSheetRect; +} + +- (void)setTheme { + ThemeProvider* theme_provider = browser_->profile()->GetThemeProvider(); + BrowserThemeProvider* browser_theme_provider = + static_cast<BrowserThemeProvider*>(theme_provider); + if (browser_theme_provider) { + bool offtheRecord = browser_->profile()->IsOffTheRecord(); + GTMTheme* theme = + [GTMTheme themeWithBrowserThemeProvider:browser_theme_provider + isOffTheRecord:offtheRecord]; + theme_.reset([theme retain]); + } +} + +- (void)layoutSubviews { + // With the exception of the tab strip, the subviews which we lay out are + // subviews of the content view, so we mainly work in the content view's + // coordinate system. Note, however, that the content view's coordinate system + // and the window's base coordinate system should coincide. + NSWindow* window = [self window]; + NSView* contentView = [window contentView]; + NSRect contentBounds = [contentView bounds]; + CGFloat minY = NSMinY(contentBounds); + CGFloat width = NSWidth(contentBounds); + + // Suppress title drawing if necessary. + if ([window respondsToSelector:@selector(setShouldHideTitle:)]) + [(id)window setShouldHideTitle:![self hasTitleBar]]; + + BOOL isFullscreen = [self isFullscreen]; + CGFloat floatingBarHeight = [self floatingBarHeight]; + CGFloat yOffset = floor( + isFullscreen ? (1 - floatingBarShownFraction_) * floatingBarHeight : 0); + CGFloat maxY = NSMaxY(contentBounds) + yOffset; + CGFloat startMaxY = maxY; + + if ([self hasTabStrip]) { + // If we need to lay out the tab strip, replace |maxY| and |startMaxY| with + // higher values, and then lay out the tab strip. + startMaxY = maxY = NSHeight([window frame]) + yOffset; + maxY = [self layoutTabStripAtMaxY:maxY width:width fullscreen:isFullscreen]; + } + + // Sanity-check |maxY|. + DCHECK_GE(maxY, minY); + DCHECK_LE(maxY, NSMaxY(contentBounds) + yOffset); + + // Place the toolbar at the top of the reserved area. + maxY = [self layoutToolbarAtMaxY:maxY width:width]; + + // If we're not displaying the bookmark bar below the infobar, then it goes + // immediately below the toolbar. + BOOL placeBookmarkBarBelowInfoBar = [self placeBookmarkBarBelowInfoBar]; + if (!placeBookmarkBarBelowInfoBar) + maxY = [self layoutBookmarkBarAtMaxY:maxY width:width]; + + // The floating bar backing view doesn't actually add any height. + [self layoutFloatingBarBackingViewAtY:maxY + width:width + height:floatingBarHeight + fullscreen:isFullscreen]; + + [fullscreenController_ overlayFrameChanged:[floatingBarBackingView_ frame]]; + + // Place the find bar immediately below the toolbar/attached bookmark bar. In + // fullscreen mode, it hangs off the top of the screen when the bar is hidden. + [findBarCocoaController_ positionFindBarViewAtMaxY:maxY maxWidth:width]; + + // If in fullscreen mode, reset |maxY| to top of screen, so that the floating + // bar slides over the things which appear to be in the content area. + if (isFullscreen) + maxY = NSMaxY(contentBounds); + + // Also place the infobar container immediate below the toolbar, except in + // fullscreen mode in which case it's at the top of the visual content area. + maxY = [self layoutInfoBarAtMaxY:maxY width:width]; + + // If the bookmark bar is detached, place it next in the visual content area. + if (placeBookmarkBarBelowInfoBar) + maxY = [self layoutBookmarkBarAtMaxY:maxY width:width]; + + // Place the download shelf, if any, at the bottom of the view. + minY = [self layoutDownloadShelfAtMinY:minY width:width]; + + // Finally, the content area takes up all of the remaining space. + [self layoutTabContentAreaAtMinY:minY maxY:maxY width:width]; + + // Place the status bubble at the bottom of the content area. + verticalOffsetForStatusBubble_ = minY; + + // Normally, we don't need to tell the toolbar whether or not to show the + // divider, but things break down during animation. + [toolbarController_ + setDividerOpacity:[bookmarkBarController_ toolbarDividerOpacity]]; +} + +- (CGFloat)floatingBarHeight { + if (![self isFullscreen]) + return 0; + + CGFloat totalHeight = kFullscreenVerticalBarOffset; + + if ([self hasTabStrip]) + totalHeight += NSHeight([[self tabStripView] frame]); + + if ([self hasToolbar]) { + totalHeight += NSHeight([[toolbarController_ view] frame]); + } else if ([self hasLocationBar]) { + totalHeight += NSHeight([[toolbarController_ view] frame]) + + kLocBarTopInset + kLocBarBottomInset; + } + + if (![self placeBookmarkBarBelowInfoBar]) + totalHeight += NSHeight([[bookmarkBarController_ view] frame]); + + return totalHeight; +} + +- (CGFloat)layoutTabStripAtMaxY:(CGFloat)maxY + width:(CGFloat)width + fullscreen:(BOOL)fullscreen { + // Nothing to do if no tab strip. + if (![self hasTabStrip]) + return maxY; + + NSView* tabStripView = [self tabStripView]; + CGFloat tabStripHeight = NSHeight([tabStripView frame]); + // In fullscreen mode, push the tab strip down so that the main menu (which + // also slides down) doesn't run it over. + if (fullscreen) + maxY -= kFullscreenVerticalBarOffset; + maxY -= tabStripHeight; + [tabStripView setFrame:NSMakeRect(0, maxY, width, tabStripHeight)]; + + // Set indentation. + [tabStripController_ setIndentForControls:(fullscreen ? 0 : + [[tabStripController_ class] defaultIndentForControls])]; + + // TODO(viettrungluu): Seems kind of bad -- shouldn't |-layoutSubviews| do + // this? Moreover, |-layoutTabs| will try to animate.... + [tabStripController_ layoutTabs]; + + return maxY; +} + +- (CGFloat)layoutToolbarAtMaxY:(CGFloat)maxY width:(CGFloat)width { + NSView* toolbarView = [toolbarController_ view]; + NSRect toolbarFrame = [toolbarView frame]; + if ([self hasToolbar]) { + // The toolbar is present in the window, so we make room for it. + DCHECK(![toolbarView isHidden]); + toolbarFrame.origin.x = 0; + toolbarFrame.origin.y = maxY - NSHeight(toolbarFrame); + toolbarFrame.size.width = width; + maxY -= NSHeight(toolbarFrame); + } else { + if ([self hasLocationBar]) { + // Location bar is present with no toolbar. Put a border of + // |kLocBar...Inset| pixels around the location bar. + // TODO(viettrungluu): This is moderately ridiculous. The toolbar should + // really be aware of what its height should be (the way the toolbar + // compression stuff is currently set up messes things up). + DCHECK(![toolbarView isHidden]); + toolbarFrame.origin.x = kLocBarLeftRightInset; + toolbarFrame.origin.y = maxY - NSHeight(toolbarFrame) - kLocBarTopInset; + toolbarFrame.size.width = width - 2 * kLocBarLeftRightInset; + maxY -= kLocBarTopInset + NSHeight(toolbarFrame) + kLocBarBottomInset; + } else { + DCHECK([toolbarView isHidden]); + } + } + [toolbarView setFrame:toolbarFrame]; + return maxY; +} + +- (BOOL)placeBookmarkBarBelowInfoBar { + // If we are currently displaying the NTP detached bookmark bar or animating + // to/from it (from/to anything else), we display the bookmark bar below the + // infobar. + return [bookmarkBarController_ isInState:bookmarks::kDetachedState] || + [bookmarkBarController_ isAnimatingToState:bookmarks::kDetachedState] || + [bookmarkBarController_ isAnimatingFromState:bookmarks::kDetachedState]; +} + +- (CGFloat)layoutBookmarkBarAtMaxY:(CGFloat)maxY width:(CGFloat)width { + NSView* bookmarkBarView = [bookmarkBarController_ view]; + NSRect bookmarkBarFrame = [bookmarkBarView frame]; + BOOL oldHidden = [bookmarkBarView isHidden]; + BOOL newHidden = ![self isBookmarkBarVisible]; + if (oldHidden != newHidden) + [bookmarkBarView setHidden:newHidden]; + bookmarkBarFrame.origin.y = maxY - NSHeight(bookmarkBarFrame); + bookmarkBarFrame.size.width = width; + [bookmarkBarView setFrame:bookmarkBarFrame]; + maxY -= NSHeight(bookmarkBarFrame); + + // TODO(viettrungluu): Does this really belong here? Calling it shouldn't be + // necessary in the non-NTP case. + [bookmarkBarController_ layoutSubviews]; + + return maxY; +} + +- (void)layoutFloatingBarBackingViewAtY:(CGFloat)y + width:(CGFloat)width + height:(CGFloat)height + fullscreen:(BOOL)fullscreen { + // Only display when in fullscreen mode. + if (fullscreen) { + DCHECK(floatingBarBackingView_.get()); + BOOL aboveBookmarkBar = [self placeBookmarkBarBelowInfoBar]; + + // Insert it into the view hierarchy if necessary. + if (![floatingBarBackingView_ superview] || + aboveBookmarkBar != floatingBarAboveBookmarkBar_) { + NSView* contentView = [[self window] contentView]; + // z-order gets messed up unless we explicitly remove the floatingbar view + // and re-add it. + [floatingBarBackingView_ removeFromSuperview]; + [contentView addSubview:floatingBarBackingView_ + positioned:(aboveBookmarkBar ? + NSWindowAbove : NSWindowBelow) + relativeTo:[bookmarkBarController_ view]]; + floatingBarAboveBookmarkBar_ = aboveBookmarkBar; + } + + // Set its frame. + [floatingBarBackingView_ setFrame:NSMakeRect(0, y, width, height)]; + } else { + // Okay to call even if |floatingBarBackingView_| is nil. + if ([floatingBarBackingView_ superview]) + [floatingBarBackingView_ removeFromSuperview]; + } +} + +- (CGFloat)layoutInfoBarAtMaxY:(CGFloat)maxY width:(CGFloat)width { + NSView* infoBarView = [infoBarContainerController_ view]; + NSRect infoBarFrame = [infoBarView frame]; + infoBarFrame.origin.y = maxY - NSHeight(infoBarFrame); + infoBarFrame.size.width = width; + [infoBarView setFrame:infoBarFrame]; + maxY -= NSHeight(infoBarFrame); + return maxY; +} + +- (CGFloat)layoutDownloadShelfAtMinY:(CGFloat)minY width:(CGFloat)width { + if (downloadShelfController_.get()) { + NSView* downloadView = [downloadShelfController_ view]; + NSRect downloadFrame = [downloadView frame]; + downloadFrame.origin.y = minY; + downloadFrame.size.width = width; + [downloadView setFrame:downloadFrame]; + minY += NSHeight(downloadFrame); + } + return minY; +} + +- (void)layoutTabContentAreaAtMinY:(CGFloat)minY + maxY:(CGFloat)maxY + width:(CGFloat)width { + NSView* tabContentView = [self tabContentArea]; + NSRect tabContentFrame = [tabContentView frame]; + + bool contentShifted = NSMaxY(tabContentFrame) != maxY; + + tabContentFrame.origin.y = minY; + tabContentFrame.size.height = maxY - minY; + tabContentFrame.size.width = width; + [tabContentView setFrame:tabContentFrame]; + + // If the relayout shifts the content area up or down, let the renderer know. + if (contentShifted) { + if (TabContents* contents = browser_->GetSelectedTabContents()) { + if (RenderWidgetHostView* rwhv = contents->GetRenderWidgetHostView()) + rwhv->WindowFrameChanged(); + } + } +} + +- (BOOL)shouldShowBookmarkBar { + DCHECK(browser_.get()); + return browser_->profile()->GetPrefs()->GetBoolean(prefs::kShowBookmarkBar) ? + YES : NO; +} + +- (BOOL)shouldShowDetachedBookmarkBar { + DCHECK(browser_.get()); + TabContents* contents = browser_->GetSelectedTabContents(); + 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]; +} + +- (void)adjustUIForFullscreen:(BOOL)fullscreen { + if (fullscreen) { + mac_util::RequestFullScreen(); + + // Create the floating bar backing view if necessary. + if (!floatingBarBackingView_.get()) { + floatingBarBackingView_.reset( + [[FloatingBarBackingView alloc] initWithFrame:NSZeroRect]); + } + } else { + mac_util::ReleaseFullScreen(); + } +} + +@end // @implementation BrowserWindowController(Private) diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index 109b503..54fa4fe9 100755 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -437,10 +437,14 @@ 'browser/cocoa/browser_command_executor.h', 'browser/cocoa/browser_frame_view.h', 'browser/cocoa/browser_frame_view.mm', + 'browser/cocoa/browser_theme_provider_init.h', + 'browser/cocoa/browser_theme_provider_init.mm', 'browser/cocoa/browser_window_cocoa.h', 'browser/cocoa/browser_window_cocoa.mm', 'browser/cocoa/browser_window_controller.h', 'browser/cocoa/browser_window_controller.mm', + 'browser/cocoa/browser_window_controller_private.h', + 'browser/cocoa/browser_window_controller_private.mm', 'browser/cocoa/bubble_view.h', 'browser/cocoa/bubble_view.mm', 'browser/cocoa/bug_report_window_controller.h', |