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

Unified Diff: chrome/browser/ui/cocoa/fullscreen/immersive_fullscreen_controller.mm

Issue 2484973004: [Mac] Refactor Immersive Fullscreen Logic (Closed)
Patch Set: fix for rsesek Created 4 years, 1 month 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/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..23c42c35287ed236b21251d66b36ce7ba7d2f25b
--- /dev/null
+++ b/chrome/browser/ui/cocoa/fullscreen/immersive_fullscreen_controller.mm
@@ -0,0 +1,205 @@
+// 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"
+
+#import "base/mac/mac_util.h"
+#include "base/mac/sdk_forward_declarations.h"
+#import "chrome/browser/ui/cocoa/browser_window_controller.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 value must be greater than the menubar's height of 22px.
+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 isMenubarVisible_;
+}
+
+// Whether the current screen is expected to have a menubar, regardless of
+// current visibility of the menubar.
+- (BOOL)doesScreenHaveMenubar;
+
+// Adjusts the AppKit Fullscreen options of the application.
+- (void)setSystemFullscreenModeTo:(base::mac::FullScreenMode)mode;
+
+// Sets |isMenubarVisible_|. If the value has changed, update the tracking
+// area, the dock, and the menubar
+- (void)setMenubarVisibility:(BOOL)visible;
+
+// Methods that update and remove the tracking area.
+- (void)updateTrackingArea;
+- (void)removeTrackingArea;
+
+@end
+
+@implementation ImmersiveFullscreenController
+
+- (instancetype)initWithBrowserController:(BrowserWindowController*)bwc {
+ if ((self = [super init])) {
+ browserController_ = bwc;
+ systemFullscreenMode_ = base::mac::kFullScreenModeNormal;
+
+ contentView_ = [[bwc window] contentView];
+ DCHECK(contentView_);
+
+ isMenubarVisible_ = NO;
+
+ 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 shouldShowMenubar])
+ [self setSystemFullscreenModeTo:base::mac::kFullScreenModeHideDock];
+ else
+ [self setSystemFullscreenModeTo:base::mac::kFullScreenModeHideAll];
+}
+
+- (BOOL)shouldShowMenubar {
+ return [self doesScreenHaveMenubar] && isMenubarVisible_;
+}
+
+- (void)windowDidBecomeMain:(NSNotification*)notification {
+ [self updateMenuBarAndDockVisibility];
+}
+
+- (void)windowDidResignMain:(NSNotification*)notification {
+ [self updateMenuBarAndDockVisibility];
+}
+
+- (BOOL)doesScreenHaveMenubar {
+ NSScreen* screen = [[browserController_ window] screen];
+ NSScreen* primaryScreen = [[NSScreen screens] firstObject];
+ BOOL isWindowOnPrimaryScreen = [screen isEqual: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)setMenubarVisibility:(BOOL)visible {
+ if (isMenubarVisible_ == visible)
+ return;
+
+ isMenubarVisible_ = visible;
+ [self updateTrackingArea];
+ [self updateMenuBarAndDockVisibility];
+}
+
+- (void)updateTrackingArea {
+ [self removeTrackingArea];
+
+ CGFloat trackingHeight =
+ isMenubarVisible_ ? kMenubarHideZoneHeight : kMenubarShowZoneHeight;
+ NSRect trackingFrame = [contentView_ bounds];
+ trackingFrame.origin.y = NSMaxY(trackingFrame) - trackingHeight;
+ trackingFrame.size.height = trackingHeight;
+
+ // If we replace the tracking area with a new one under the cursor, the new
+ // tracking area might not receive a |-mouseEntered:| or |-mouseExited| call.
+ // As a result, we should also track the mouse's movements so that the
+ // so the menubar won't get stuck.
+ NSTrackingAreaOptions options =
+ NSTrackingMouseEnteredAndExited | NSTrackingActiveInKeyWindow;
+ if (isMenubarVisible_)
+ options |= NSTrackingMouseMoved;
+
+ // Create and add a new tracking area for |frame|.
+ trackingArea_.reset([[CrTrackingArea alloc] initWithRect:trackingFrame
+ options:options
+ owner:self
+ userInfo:nil]);
+ [contentView_ addTrackingArea:trackingArea_];
+}
+
+- (void)removeTrackingArea {
+ if (trackingArea_) {
+ [contentView_ removeTrackingArea:trackingArea_];
+ trackingArea_.reset();
+ }
+}
+
+- (void)mouseEntered:(NSEvent*)event {
+ [self setMenubarVisibility:YES];
+}
+
+- (void)mouseExited:(NSEvent*)event {
+ [self setMenubarVisibility:NO];
+}
+
+- (void)mouseMoved:(NSEvent*)event {
+ [self setMenubarVisibility:[trackingArea_
+ mouseInsideTrackingAreaForView:contentView_]];
+}
+
+@end

Powered by Google App Engine
This is Rietveld 408576698