| Index: chrome/browser/ui/cocoa/browser_window_controller.mm
|
| ===================================================================
|
| --- chrome/browser/ui/cocoa/browser_window_controller.mm (revision 95287)
|
| +++ chrome/browser/ui/cocoa/browser_window_controller.mm (working copy)
|
| @@ -39,13 +39,13 @@
|
| #import "chrome/browser/ui/cocoa/fast_resize_view.h"
|
| #import "chrome/browser/ui/cocoa/find_bar/find_bar_bridge.h"
|
| #import "chrome/browser/ui/cocoa/find_bar/find_bar_cocoa_controller.h"
|
| -#import "chrome/browser/ui/cocoa/focus_tracker.h"
|
| -#import "chrome/browser/ui/cocoa/fullscreen_controller.h"
|
| +#import "chrome/browser/ui/cocoa/framed_browser_window.h"
|
| #import "chrome/browser/ui/cocoa/fullscreen_window.h"
|
| #import "chrome/browser/ui/cocoa/gesture_utils.h"
|
| #import "chrome/browser/ui/cocoa/image_utils.h"
|
| #import "chrome/browser/ui/cocoa/infobars/infobar_container_controller.h"
|
| #import "chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_editor.h"
|
| +#import "chrome/browser/ui/cocoa/presentation_mode_controller.h"
|
| #import "chrome/browser/ui/cocoa/sidebar_controller.h"
|
| #import "chrome/browser/ui/cocoa/status_bubble_mac.h"
|
| #import "chrome/browser/ui/cocoa/tab_contents/previewable_contents_controller.h"
|
| @@ -196,6 +196,15 @@
|
| };
|
| typedef NSInteger NSWindowAnimationBehavior;
|
|
|
| +enum {
|
| + NSWindowCollectionBehaviorFullScreenPrimary = 1 << 7,
|
| + NSWindowCollectionBehaviorFullScreenAuxiliary = 1 << 8
|
| +};
|
| +
|
| +enum {
|
| + NSFullScreenWindowMask = 1 << 14
|
| +};
|
| +
|
| @interface NSWindow (LionSDKDeclarations)
|
| - (void)setRestorable:(BOOL)flag;
|
| - (void)setAnimationBehavior:(NSWindowAnimationBehavior)newAnimationBehavior;
|
| @@ -262,6 +271,12 @@
|
| if ([window respondsToSelector:@selector(setAnimationBehavior:)])
|
| [window setAnimationBehavior:NSWindowAnimationBehaviorDocumentWindow];
|
|
|
| + // Set the window to participate in Lion Fullscreen mode. Setting this flag
|
| + // has no effect on Snow Leopard or earlier.
|
| + NSUInteger collectionBehavior = [window collectionBehavior];
|
| + collectionBehavior |= NSWindowCollectionBehaviorFullScreenPrimary;
|
| + [window setCollectionBehavior:collectionBehavior];
|
| +
|
| // Get the most appropriate size for the window, then enforce the
|
| // minimum width and height. The window shim will handle flipping
|
| // the coordinates for us so we can use it to save some code.
|
| @@ -407,8 +422,6 @@
|
| if ([self hasToolbar]) // Do not create the buttons in popups.
|
| [toolbarController_ createBrowserActionButtons];
|
|
|
| - [self setUpOSFullScreenButton];
|
| -
|
| // We are done initializing now.
|
| initializing_ = NO;
|
| }
|
| @@ -426,11 +439,11 @@
|
| browser_->CloseAllTabs();
|
| [downloadShelfController_ exiting];
|
|
|
| - // Explicitly release |fullscreenController_| here, as it may call back to
|
| - // this BWC in |-dealloc|. We are required to call |-exitFullscreen| before
|
| - // releasing the controller.
|
| - [fullscreenController_ exitFullscreen];
|
| - fullscreenController_.reset();
|
| + // Explicitly release |presentationModeController_| here, as it may call back
|
| + // to this BWC in |-dealloc|. We are required to call |-exitPresentationMode|
|
| + // before releasing the controller.
|
| + [presentationModeController_ exitPresentationMode];
|
| + presentationModeController_.reset();
|
|
|
| // Under certain testing configurations we may not actually own the browser.
|
| if (ownsBrowser_ == NO)
|
| @@ -1018,9 +1031,22 @@
|
| [self isFullscreen] ? IDS_EXIT_FULLSCREEN_MAC :
|
| IDS_ENTER_FULLSCREEN_MAC);
|
| [static_cast<NSMenuItem*>(item) setTitle:menuTitle];
|
| +
|
| + if (!base::mac::IsOSLionOrLater())
|
| + [static_cast<NSMenuItem*>(item) setHidden:YES];
|
| }
|
| break;
|
| }
|
| + case IDC_PRESENTATION_MODE: {
|
| + enable &= [self supportsFullscreen];
|
| + if ([static_cast<NSObject*>(item) isKindOfClass:[NSMenuItem class]]) {
|
| + NSString* menuTitle = l10n_util::GetNSString(
|
| + [self inPresentationMode] ? IDS_EXIT_PRESENTATION_MAC :
|
| + IDS_ENTER_PRESENTATION_MAC);
|
| + [static_cast<NSMenuItem*>(item) setTitle:menuTitle];
|
| + }
|
| + break;
|
| + }
|
| case IDC_SYNC_BOOKMARKS:
|
| enable &= browser_->profile()->IsSyncAccessible();
|
| sync_ui_util::UpdateSyncItem(item, enable, browser_->profile());
|
| @@ -1399,7 +1425,8 @@
|
| relativeTo:[infoBarContainerController_ view]];
|
|
|
| // 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.
|
| + // presentation mode, it hangs off the top of the screen when the bar is
|
| + // hidden.
|
| CGFloat maxY = [self placeBookmarkBarBelowInfoBar] ?
|
| NSMinY([[toolbarController_ view] frame]) :
|
| NSMinY([[bookmarkBarController_ view] frame]);
|
| @@ -1431,7 +1458,7 @@
|
| }
|
|
|
| - (NSRect)regularWindowFrame {
|
| - return [self isFullscreen] ? [savedRegularWindow_ frame] :
|
| + return [self isFullscreen] ? savedRegularWindowFrame_ :
|
| [[self window] frame];
|
| }
|
|
|
| @@ -2014,171 +2041,104 @@
|
|
|
| @implementation BrowserWindowController(Fullscreen)
|
|
|
| -- (IBAction)enterFullscreen:(id)sender {
|
| +- (void)handleLionToggleFullscreen {
|
| + DCHECK(base::mac::IsOSLionOrLater());
|
| browser_->ExecuteCommand(IDC_FULLSCREEN);
|
| }
|
|
|
| +// On Lion, this method is called by either the Lion fullscreen button or the
|
| +// "Enter Full Screen" menu item. On Snow Leopard, this function is never
|
| +// called by the UI directly, but it provides the implementation for
|
| +// |-setPresentationMode:|.
|
| - (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;
|
|
|
| - // Fade to black.
|
| - const CGDisplayReservationInterval kFadeDurationSeconds = 0.6;
|
| - Boolean didFadeOut = NO;
|
| - CGDisplayFadeReservationToken token;
|
| - if (CGAcquireDisplayFadeReservation(kFadeDurationSeconds, &token)
|
| - == kCGErrorSuccess) {
|
| - didFadeOut = YES;
|
| - CGDisplayFade(token, kFadeDurationSeconds / 2, kCGDisplayBlendNormal,
|
| - kCGDisplayBlendSolidColor, 0.0, 0.0, 0.0, /*synchronous=*/true);
|
| + if (base::mac::IsOSLionOrLater()) {
|
| + enteredPresentationModeFromFullscreen_ = YES;
|
| + if ([[self window] respondsToSelector:@selector(toggleSystemFullScreen)])
|
| + [(id)[self window] toggleSystemFullScreen];
|
| + return;
|
| }
|
|
|
| - // Close the bookmark bubble, if it's open. We use |-ok:| instead of
|
| - // |-cancel:| or |-close| because that matches the behavior when the bubble
|
| - // loses key status.
|
| - [bookmarkBubbleController_ ok:self];
|
| + if (fullscreen)
|
| + [self enterFullscreenForSnowLeopardOrEarlier];
|
| + else
|
| + [self exitFullscreenForSnowLeopardOrEarlier];
|
| +}
|
|
|
| - // 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];
|
| +- (BOOL)isFullscreen {
|
| + return (fullscreenWindow_.get() != nil) ||
|
| + ([[self window] styleMask] & NSFullScreenWindowMask);
|
| +}
|
|
|
| - // While we move views (and focus) around, disable any bar visibility changes.
|
| - [self disableBarVisibilityUpdates];
|
| +- (void)togglePresentationMode:(id)sender {
|
| + // Called only by the presentation mode toggle button.
|
| + DCHECK(base::mac::IsOSLionOrLater());
|
| + enteredPresentationModeFromFullscreen_ = YES;
|
| + browser_->ExecuteCommand(IDC_PRESENTATION_MODE);
|
| +}
|
|
|
| - // 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();
|
| +// On Lion, this function is called by either the presentation mode toggle
|
| +// button or the "Enter Presentation Mode" menu item. In the latter case, this
|
| +// function also triggers the Lion machinery to enter fullscreen mode as well as
|
| +// set presentation mode. On Snow Leopard, this function is called by the
|
| +// "Enter Presentation Mode" menu item, and triggering presentation mode always
|
| +// moves the user into fullscreen mode.
|
| +- (void)setPresentationMode:(BOOL)presentationMode {
|
| + // Presentation mode on Leopard and Snow Leopard maps directly to fullscreen
|
| + // mode.
|
| + if (!base::mac::IsOSLionOrLater()) {
|
| + [self setFullscreen:presentationMode];
|
| + return;
|
| }
|
|
|
| - // Destroy the tab strip's sheet controller. We will recreate it in the new
|
| - // window when needed.
|
| - [tabStripController_ destroySheetController];
|
| + if (presentationMode) {
|
| + BOOL fullscreen = [self isFullscreen];
|
| + [self setShouldUsePresentationModeWhenEnteringFullscreen:YES];
|
| + enteredPresentationModeFromFullscreen_ = fullscreen;
|
|
|
| - // Retain the tab strip view while we remove it from its superview.
|
| - scoped_nsobject<NSView> tabStripView;
|
| - if ([self hasTabStrip] && ![self useVerticalTabs]) {
|
| - 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];
|
| + if (fullscreen) {
|
| + // If already in fullscreen mode, just toggle the presentation mode
|
| + // setting. Go through an elaborate dance to force the overlay to show,
|
| + // then animate out once the mouse moves away. This helps draw attention
|
| + // to the fact that the UI is in an overlay. Focus the tab contents
|
| + // because the omnibox is the most likely source of bar visibility locks,
|
| + // and taking focus away from the omnibox releases its lock.
|
| + [self focusTabContents];
|
| + [self setPresentationModeInternal:YES forceDropdown:YES];
|
| + } else {
|
| + // If not in fullscreen mode, trigger the Lion fullscreen mode machinery.
|
| + // Presentation mode will automatically be enabled in
|
| + // |-windowWillEnterFullScreen:|.
|
| + if ([[self window] respondsToSelector:@selector(toggleSystemFullScreen)])
|
| + [(id)[self window] toggleSystemFullScreen];
|
| + }
|
| } else {
|
| - DCHECK(savedRegularWindow_);
|
| - destWindow = [savedRegularWindow_ autorelease];
|
| - savedRegularWindow_ = nil;
|
| + if (enteredPresentationModeFromFullscreen_) {
|
| + // The window is currently in fullscreen mode, but the user is choosing to
|
| + // turn presentation mode off (choosing to always show the UI). Set the
|
| + // preference to ensure that presentation mode will stay off for the next
|
| + // window that goes fullscreen.
|
| + [self setShouldUsePresentationModeWhenEnteringFullscreen:NO];
|
| + [self setPresentationModeInternal:NO forceDropdown:NO];
|
| + } else {
|
| + // The user entered presentation mode directly from non-fullscreen mode
|
| + // using the "Enter Presentation Mode" menu item and is using that same
|
| + // menu item to exit presentation mode. In this case, exit fullscreen
|
| + // mode as well (using the Lion machinery).
|
| + if ([[self window] respondsToSelector:@selector(toggleSystemFullScreen)])
|
| + [(id)[self window] toggleSystemFullScreen];
|
| + }
|
| }
|
| - 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];
|
| -
|
| - // Move the incognito badge if present.
|
| - if (avatarButton_.get()) {
|
| - [avatarButton_ removeFromSuperview];
|
| - [avatarButton_ setHidden:YES]; // Will be shown in layout.
|
| - [[[destWindow contentView] superview] addSubview:avatarButton_];
|
| - }
|
| -
|
| - // Add the tab strip after setting the content view and moving the incognito
|
| - // badge (if any), so that the tab strip will be on top (in the z-order).
|
| - if ([self hasTabStrip] && ![self useVerticalTabs])
|
| - [[[destWindow contentView] superview] addSubview:tabStripView];
|
| -
|
| - [window setWindowController:nil];
|
| - [self setWindow:destWindow];
|
| - [destWindow setWindowController:self];
|
| - [self adjustUIForFullscreen:fullscreen];
|
| -
|
| - // Adjust the infobar container. In fullscreen, it needs to be below all
|
| - // top chrome elements so it only sits atop the web contents. When in normal
|
| - // mode, it needs to draw over the bookmark bar and part of the toolbar.
|
| - [[infoBarContainerController_ view] removeFromSuperview];
|
| - NSView* infoBarDest = [[destWindow contentView] superview];
|
| - [infoBarDest addSubview:[infoBarContainerController_ view]
|
| - positioned:fullscreen ? NSWindowBelow : NSWindowAbove
|
| - relativeTo:fullscreen ? floatingBarBackingView_
|
| - : [bookmarkBarController_ view]];
|
| -
|
| - // 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];
|
| - }
|
| -
|
| - // Move the status bubble over, if we have one.
|
| - if (statusBubble_)
|
| - statusBubble_->SwitchParentWindow(destWindow);
|
| -
|
| - // Move the title over.
|
| - [destWindow setTitle:[window title]];
|
| -
|
| - // The window needs to be onscreen before we can set its first responder.
|
| - // Ordering the window to the front can change the active Space (either to
|
| - // the window's old Space or to the application's assigned Space). To prevent
|
| - // this by temporarily change the collectionBehavior.
|
| - NSWindowCollectionBehavior behavior = [window collectionBehavior];
|
| - [destWindow setCollectionBehavior:
|
| - NSWindowCollectionBehaviorMoveToActiveSpace];
|
| - [destWindow makeKeyAndOrderFront:self];
|
| - [destWindow setCollectionBehavior:behavior];
|
| -
|
| - [focusTracker restoreFocusInWindow:destWindow];
|
| - [window orderOut:self];
|
| -
|
| - // We're done moving focus, so re-enable bar visibility changes.
|
| - [self enableBarVisibilityUpdates];
|
| -
|
| - // This needs to be done when leaving full-screen mode to ensure that the
|
| - // button's action is set properly.
|
| - [self setUpOSFullScreenButton];
|
| -
|
| - // Fade back in.
|
| - if (didFadeOut) {
|
| - CGDisplayFade(token, kFadeDurationSeconds / 2, kCGDisplayBlendSolidColor,
|
| - kCGDisplayBlendNormal, 0.0, 0.0, 0.0, /*synchronous=*/false);
|
| - CGReleaseDisplayFadeReservation(token);
|
| - }
|
| }
|
|
|
| -- (BOOL)isFullscreen {
|
| - return fullscreenController_.get() && [fullscreenController_ isFullscreen];
|
| +- (BOOL)inPresentationMode {
|
| + return presentationModeController_.get() &&
|
| + [presentationModeController_ inPresentationMode];
|
| }
|
|
|
| - (void)resizeFullscreenWindow {
|
| @@ -2212,10 +2172,10 @@
|
| if (![self isBarVisibilityLockedForOwner:owner]) {
|
| [barVisibilityLocks_ addObject:owner];
|
|
|
| - // If enabled, show the overlay if necessary (and if in fullscreen mode).
|
| + // If enabled, show the overlay if necessary (and if in presentation mode).
|
| if (barVisibilityUpdatesEnabled_) {
|
| - [fullscreenController_ ensureOverlayShownWithAnimation:animate
|
| - delay:delay];
|
| + [presentationModeController_ ensureOverlayShownWithAnimation:animate
|
| + delay:delay];
|
| }
|
| }
|
| }
|
| @@ -2226,11 +2186,11 @@
|
| if ([self isBarVisibilityLockedForOwner:owner]) {
|
| [barVisibilityLocks_ removeObject:owner];
|
|
|
| - // If enabled, hide the overlay if necessary (and if in fullscreen mode).
|
| + // If enabled, hide the overlay if necessary (and if in presentation mode).
|
| if (barVisibilityUpdatesEnabled_ &&
|
| ![barVisibilityLocks_ count]) {
|
| - [fullscreenController_ ensureOverlayHiddenWithAnimation:animate
|
| - delay:delay];
|
| + [presentationModeController_ ensureOverlayHiddenWithAnimation:animate
|
| + delay:delay];
|
| }
|
| }
|
| }
|
|
|