Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(270)

Unified Diff: chrome/browser/ui/cocoa/browser_window_controller.mm

Issue 7566016: Fullscreen support for Lion. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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::IsOSSnowLeopardOrEarlier())
+ [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,106 @@
@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)])
Mark Mentovai 2011/08/04 19:18:17 Can you do this as an isKindOfClass check with a c
rohitrao (ping after 24h) 2011/08/04 19:49:17 Done. Why is this better?
Mark Mentovai 2011/08/04 19:56:53 rohitrao wrote:
+ [(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::IsOSSnowLeopardOrEarlier()) {
+ [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 lockBarVisibilityForOwner:self withAnimation:NO delay:NO];
+ [self focusTabContents];
+ [self setPresentationModeInternal:YES forceDropdown:YES];
+ [self releaseBarVisibilityForOwner:self withAnimation:YES delay: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 +2174,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 +2188,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];
}
}
}

Powered by Google App Engine
This is Rietveld 408576698