| Index: chrome/browser/ui/cocoa/fullscreen/immersive_fullscreen_controller.mm
|
| diff --git a/chrome/browser/ui/cocoa/fullscreen/immersive_fullscreen_controller.mm b/chrome/browser/ui/cocoa/fullscreen/immersive_fullscreen_controller.mm
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..766fbff0c2939fe803d33eaf12b2d804bd748b82
|
| --- /dev/null
|
| +++ b/chrome/browser/ui/cocoa/fullscreen/immersive_fullscreen_controller.mm
|
| @@ -0,0 +1,196 @@
|
| +// Copyright 2016 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/ui/cocoa/fullscreen/immersive_fullscreen_controller.h"
|
| +
|
| +#include "base/mac/sdk_forward_declarations.h"
|
| +#import "chrome/browser/ui/cocoa/browser_window_controller.h"
|
| +#import "chrome/browser/ui/cocoa/fullscreen/fullscreen_toolbar_layout_manager.h"
|
| +#import "ui/base/cocoa/tracking_area.h"
|
| +
|
| +namespace {
|
| +
|
| +// The height from the top of the screen that will show the menubar.
|
| +const CGFloat kMenubarShowZoneHeight = 4;
|
| +
|
| +// The height from the top of the screen that will hide the menubar.
|
| +// The height must be greater than the menubar's height.
|
| +const CGFloat kMenubarHideZoneHeight = 28;
|
| +
|
| +} // namespace
|
| +
|
| +@interface ImmersiveFullscreenController () {
|
| + BrowserWindowController* browserController_; // weak
|
| +
|
| + // Used to track the mouse movements to show/hide the menu.
|
| + base::scoped_nsobject<CrTrackingArea> trackingArea_;
|
| +
|
| + // The content view for the window.
|
| + NSView* contentView_; // weak
|
| +
|
| + // Tracks the currently requested system fullscreen mode, used to show or
|
| + // hide the menubar. Its value is as follows:
|
| + // + |kFullScreenModeNormal| - when the window is not main or not fullscreen,
|
| + // + |kFullScreenModeHideDock| - when the user interacts with the top of the
|
| + // screen
|
| + // + |kFullScreenModeHideAll| - when the conditions don't meet the first two
|
| + // modes.
|
| + base::mac::FullScreenMode systemFullscreenMode_;
|
| +
|
| + // True if the menubar should be shown on the screen.
|
| + BOOL shouldShowMenubar_;
|
| +}
|
| +
|
| +// Whether the current screen is expected to have a menu bar, regardless of
|
| +// current visibility of the menu bar.
|
| +- (BOOL)doesScreenHaveMenuBar;
|
| +
|
| +// Returns |kFullScreenModeHideAll| when the menubar is hidden and
|
| +// |kFullScreenModeHideDock| when the menubar is shown.
|
| +- (base::mac::FullScreenMode)desiredSystemFullscreenMode;
|
| +
|
| +// Adjusts the AppKit Fullscreen options of the application.
|
| +- (void)setSystemFullscreenModeTo:(base::mac::FullScreenMode)mode;
|
| +
|
| +// Methods that update and remove the tracking area.
|
| +- (void)updateTrackingArea;
|
| +- (void)removeTrackingArea;
|
| +
|
| +@end
|
| +
|
| +@implementation ImmersiveFullscreenController
|
| +
|
| +- (id)initWithBrowserController:(BrowserWindowController*)bwc {
|
| + if ((self = [super init])) {
|
| + browserController_ = bwc;
|
| + systemFullscreenMode_ = base::mac::kFullScreenModeNormal;
|
| + contentView_ = [[bwc window] contentView];
|
| +
|
| + NSNotificationCenter* nc = [NSNotificationCenter defaultCenter];
|
| + NSWindow* window = [browserController_ window];
|
| +
|
| + [nc addObserver:self
|
| + selector:@selector(windowDidBecomeMain:)
|
| + name:NSWindowDidBecomeMainNotification
|
| + object:window];
|
| +
|
| + [nc addObserver:self
|
| + selector:@selector(windowDidResignMain:)
|
| + name:NSWindowDidResignMainNotification
|
| + object:window];
|
| +
|
| + [self updateTrackingArea];
|
| + }
|
| +
|
| + return self;
|
| +}
|
| +
|
| +- (void)dealloc {
|
| + [[NSNotificationCenter defaultCenter] removeObserver:self];
|
| +
|
| + [self removeTrackingArea];
|
| + [self setSystemFullscreenModeTo:base::mac::kFullScreenModeNormal];
|
| +
|
| + [super dealloc];
|
| +}
|
| +
|
| +- (void)updateMenuBarAndDockVisibility {
|
| + BOOL isMouseOnScreen =
|
| + NSMouseInRect([NSEvent mouseLocation],
|
| + [[browserController_ window] screen].frame, false);
|
| +
|
| + if (isMouseOnScreen || ![browserController_ isInImmersiveFullscreen])
|
| + [self setSystemFullscreenModeTo:base::mac::kFullScreenModeNormal];
|
| + else if (![self doesScreenHaveMenuBar])
|
| + [self setSystemFullscreenModeTo:base::mac::kFullScreenModeHideDock];
|
| + else
|
| + [self setSystemFullscreenModeTo:[self desiredSystemFullscreenMode]];
|
| +}
|
| +
|
| +- (BOOL)shouldShowMenubar {
|
| + return [self doesScreenHaveMenuBar] && shouldShowMenubar_;
|
| +}
|
| +
|
| +- (void)windowDidBecomeMain:(NSNotification*)notification {
|
| + [self updateMenuBarAndDockVisibility];
|
| +}
|
| +
|
| +- (void)windowDidResignMain:(NSNotification*)notification {
|
| + [self updateMenuBarAndDockVisibility];
|
| +}
|
| +
|
| +- (base::mac::FullScreenMode)desiredSystemFullscreenMode {
|
| + return [self shouldShowMenubar] ? base::mac::kFullScreenModeHideDock
|
| + : base::mac::kFullScreenModeHideAll;
|
| +}
|
| +
|
| +- (BOOL)doesScreenHaveMenuBar {
|
| + NSScreen* screen = [[browserController_ window] screen];
|
| + NSScreen* primaryScreen = [[NSScreen screens] firstObject];
|
| + BOOL isWindowOnPrimaryScreen = screen == primaryScreen;
|
| +
|
| + BOOL eachScreenShouldHaveMenuBar = [NSScreen screensHaveSeparateSpaces];
|
| + return eachScreenShouldHaveMenuBar ?: isWindowOnPrimaryScreen;
|
| +}
|
| +
|
| +- (void)setSystemFullscreenModeTo:(base::mac::FullScreenMode)mode {
|
| + if (mode == systemFullscreenMode_)
|
| + return;
|
| +
|
| + if (systemFullscreenMode_ == base::mac::kFullScreenModeNormal)
|
| + base::mac::RequestFullScreen(mode);
|
| + else if (mode == base::mac::kFullScreenModeNormal)
|
| + base::mac::ReleaseFullScreen(systemFullscreenMode_);
|
| + else
|
| + base::mac::SwitchFullScreenModes(systemFullscreenMode_, mode);
|
| +
|
| + systemFullscreenMode_ = mode;
|
| +}
|
| +
|
| +- (void)updateTrackingArea {
|
| + if (trackingArea_)
|
| + [self removeTrackingArea];
|
| +
|
| + CGFloat trackingHeight =
|
| + shouldShowMenubar_ ? kMenubarHideZoneHeight : kMenubarShowZoneHeight;
|
| + NSRect trackingFrame = [contentView_ bounds];
|
| + trackingFrame.origin.y = NSMaxY(trackingFrame) - trackingHeight;
|
| + trackingFrame.size.height = trackingHeight;
|
| +
|
| + // Create and add a new tracking area for |frame|.
|
| + trackingArea_.reset([[CrTrackingArea alloc]
|
| + initWithRect:trackingFrame
|
| + options:NSTrackingMouseEnteredAndExited | NSTrackingActiveInKeyWindow
|
| + owner:self
|
| + userInfo:nil]);
|
| + DCHECK(contentView_);
|
| + [contentView_ addTrackingArea:trackingArea_];
|
| +}
|
| +
|
| +- (void)removeTrackingArea {
|
| + if (trackingArea_) {
|
| + DCHECK(contentView_); // |contentView_| better be valid.
|
| + [contentView_ removeTrackingArea:trackingArea_];
|
| + trackingArea_.reset();
|
| + }
|
| +}
|
| +
|
| +- (void)mouseEntered:(NSEvent*)event {
|
| + if (shouldShowMenubar_)
|
| + return;
|
| +
|
| + shouldShowMenubar_ = YES;
|
| + [self updateTrackingArea];
|
| + [self updateMenuBarAndDockVisibility];
|
| +}
|
| +
|
| +- (void)mouseExited:(NSEvent*)event {
|
| + DCHECK_EQ([event trackingArea], trackingArea_.get());
|
| +
|
| + shouldShowMenubar_ = NO;
|
| + [self updateTrackingArea];
|
| + [self updateMenuBarAndDockVisibility];
|
| +}
|
| +
|
| +@end
|
|
|