| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #import "chrome/browser/ui/cocoa/fullscreen_toolbar_controller.h" | 5 #import "chrome/browser/ui/cocoa/fullscreen_toolbar_controller.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
| 10 #import "base/mac/mac_util.h" | 10 #import "base/mac/mac_util.h" |
| 11 #include "base/mac/sdk_forward_declarations.h" | 11 #include "base/mac/sdk_forward_declarations.h" |
| 12 #include "chrome/browser/profiles/profile.h" | 12 #include "chrome/browser/profiles/profile.h" |
| 13 #import "chrome/browser/ui/cocoa/browser_window_controller.h" | 13 #import "chrome/browser/ui/cocoa/browser_window_controller.h" |
| 14 #import "chrome/browser/ui/cocoa/fullscreen/fullscreen_menubar_tracker.h" | 14 #import "chrome/browser/ui/cocoa/fullscreen/fullscreen_menubar_tracker.h" |
| 15 #import "chrome/browser/ui/cocoa/fullscreen/fullscreen_toolbar_animation_control
ler.h" | 15 #import "chrome/browser/ui/cocoa/fullscreen/fullscreen_toolbar_animation_control
ler.h" |
| 16 #import "chrome/browser/ui/cocoa/fullscreen/fullscreen_toolbar_mouse_tracker.h" | 16 #import "chrome/browser/ui/cocoa/fullscreen/fullscreen_toolbar_mouse_tracker.h" |
| 17 #import "chrome/browser/ui/cocoa/fullscreen/fullscreen_toolbar_visibility_lock_c
ontroller.h" | 17 #import "chrome/browser/ui/cocoa/fullscreen/fullscreen_toolbar_visibility_lock_c
ontroller.h" |
| 18 #import "chrome/browser/ui/cocoa/fullscreen/immersive_fullscreen_controller.h" |
| 18 #include "chrome/common/chrome_switches.h" | 19 #include "chrome/common/chrome_switches.h" |
| 19 #include "chrome/common/pref_names.h" | 20 #include "chrome/common/pref_names.h" |
| 20 #include "ui/base/cocoa/appkit_utils.h" | 21 #include "ui/base/cocoa/appkit_utils.h" |
| 21 #import "ui/base/cocoa/nsview_additions.h" | 22 #import "ui/base/cocoa/nsview_additions.h" |
| 22 | 23 |
| 23 namespace { | 24 namespace { |
| 24 | 25 |
| 25 // Visibility fractions for the menubar and toolbar. | 26 // Visibility fractions for the menubar and toolbar. |
| 26 const CGFloat kHideFraction = 0.0; | 27 const CGFloat kHideFraction = 0.0; |
| 27 const CGFloat kShowFraction = 1.0; | 28 const CGFloat kShowFraction = 1.0; |
| 28 | 29 |
| 29 // The amount by which the toolbar is offset downwards (to avoid the menu) | 30 // The amount by which the toolbar is offset downwards (to avoid the menu) |
| 30 // when the toolbar style is TOOLBAR_HIDDEN. (We can't use | 31 // when the toolbar style is TOOLBAR_HIDDEN. (We can't use |
| 31 // |-[NSMenu menuBarHeight]| since it returns 0 when the menu bar is hidden.) | 32 // |-[NSMenu menuBarHeight]| since it returns 0 when the menu bar is hidden.) |
| 32 const CGFloat kToolbarVerticalOffset = 22; | 33 const CGFloat kToolbarVerticalOffset = 22; |
| 33 | 34 |
| 34 } // end namespace | 35 } // end namespace |
| 35 | 36 |
| 36 @interface FullscreenToolbarController (PrivateMethods) | |
| 37 | |
| 38 // Updates the visibility of the menu bar and the dock. | |
| 39 - (void)updateMenuBarAndDockVisibility; | |
| 40 | |
| 41 // Whether the current screen is expected to have a menu bar, regardless of | |
| 42 // current visibility of the menu bar. | |
| 43 - (BOOL)doesScreenHaveMenuBar; | |
| 44 | |
| 45 // Returns YES if the window is on the primary screen. | |
| 46 - (BOOL)isWindowOnPrimaryScreen; | |
| 47 | |
| 48 // Returns |kFullScreenModeHideAll| when the overlay is hidden and | |
| 49 // |kFullScreenModeHideDock| when the overlay is shown. | |
| 50 - (base::mac::FullScreenMode)desiredSystemFullscreenMode; | |
| 51 | |
| 52 // Stops any running animations, etc. | |
| 53 - (void)cleanup; | |
| 54 | |
| 55 // Whether the menu bar should be shown in immersive fullscreen for the screen | |
| 56 // that contains the window. | |
| 57 - (BOOL)shouldShowMenubarInImmersiveFullscreen; | |
| 58 | |
| 59 @end | |
| 60 | |
| 61 @implementation FullscreenToolbarController | 37 @implementation FullscreenToolbarController |
| 62 | 38 |
| 63 @synthesize toolbarStyle = toolbarStyle_; | 39 @synthesize toolbarStyle = toolbarStyle_; |
| 64 | 40 |
| 65 - (id)initWithBrowserController:(BrowserWindowController*)controller { | 41 - (id)initWithBrowserController:(BrowserWindowController*)controller { |
| 66 if ((self = [super init])) { | 42 if ((self = [super init])) { |
| 67 browserController_ = controller; | 43 browserController_ = controller; |
| 68 systemFullscreenMode_ = base::mac::kFullScreenModeNormal; | |
| 69 animationController_.reset(new FullscreenToolbarAnimationController(self)); | 44 animationController_.reset(new FullscreenToolbarAnimationController(self)); |
| 70 visibilityLockController_.reset( | 45 visibilityLockController_.reset( |
| 71 [[FullscreenToolbarVisibilityLockController alloc] | 46 [[FullscreenToolbarVisibilityLockController alloc] |
| 72 initWithFullscreenToolbarController:self | 47 initWithFullscreenToolbarController:self |
| 73 animationController:animationController_.get()]); | 48 animationController:animationController_.get()]); |
| 74 } | 49 } |
| 75 | 50 |
| 76 return self; | 51 return self; |
| 77 } | 52 } |
| 78 | 53 |
| 79 - (void)dealloc { | 54 - (void)dealloc { |
| 80 DCHECK(!inFullscreenMode_); | 55 DCHECK(!inFullscreenMode_); |
| 81 [super dealloc]; | 56 [super dealloc]; |
| 82 } | 57 } |
| 83 | 58 |
| 84 - (void)enterFullscreenMode { | 59 - (void)enterFullscreenMode { |
| 85 DCHECK(!inFullscreenMode_); | 60 DCHECK(!inFullscreenMode_); |
| 86 inFullscreenMode_ = YES; | 61 inFullscreenMode_ = YES; |
| 87 | 62 |
| 88 [self updateToolbarStyle]; | 63 [self updateToolbarStyle]; |
| 89 | 64 |
| 90 menubarTracker_.reset([[FullscreenMenubarTracker alloc] | 65 if ([browserController_ isInImmersiveFullscreen]) { |
| 91 initWithFullscreenToolbarController:self]); | 66 immersiveFullscreenController_.reset([[ImmersiveFullscreenController alloc] |
| 92 mouseTracker_.reset([[FullscreenToolbarMouseTracker alloc] | 67 initWithBrowserController:browserController_]); |
| 93 initWithFullscreenToolbarController:self | 68 [immersiveFullscreenController_ updateMenuBarAndDockVisibility]; |
| 94 animationController:animationController_.get()]); | 69 } else { |
| 95 | 70 menubarTracker_.reset([[FullscreenMenubarTracker alloc] |
| 96 [self updateMenuBarAndDockVisibility]; | 71 initWithFullscreenToolbarController:self]); |
| 97 | 72 mouseTracker_.reset([[FullscreenToolbarMouseTracker alloc] |
| 98 // Register for notifications. Self is removed as an observer in |-cleanup|. | 73 initWithFullscreenToolbarController:self |
| 99 NSNotificationCenter* nc = [NSNotificationCenter defaultCenter]; | 74 animationController:animationController_.get()]); |
| 100 NSWindow* window = [browserController_ window]; | 75 } |
| 101 | |
| 102 [nc addObserver:self | |
| 103 selector:@selector(windowDidBecomeMain:) | |
| 104 name:NSWindowDidBecomeMainNotification | |
| 105 object:window]; | |
| 106 | |
| 107 [nc addObserver:self | |
| 108 selector:@selector(windowDidResignMain:) | |
| 109 name:NSWindowDidResignMainNotification | |
| 110 object:window]; | |
| 111 } | 76 } |
| 112 | 77 |
| 113 - (void)exitFullscreenMode { | 78 - (void)exitFullscreenMode { |
| 114 DCHECK(inFullscreenMode_); | 79 DCHECK(inFullscreenMode_); |
| 115 inFullscreenMode_ = NO; | 80 inFullscreenMode_ = NO; |
| 116 [self cleanup]; | |
| 117 } | |
| 118 | 81 |
| 119 - (void)windowDidChangeScreen:(NSNotification*)notification { | 82 animationController_->StopAnimationAndTimer(); |
| 120 [browserController_ resizeFullscreenWindow]; | 83 [[NSNotificationCenter defaultCenter] removeObserver:self]; |
| 121 } | |
| 122 | 84 |
| 123 - (void)windowDidMove:(NSNotification*)notification { | 85 menubarTracker_.reset(); |
| 124 [browserController_ resizeFullscreenWindow]; | 86 mouseTracker_.reset(); |
| 125 } | 87 immersiveFullscreenController_.reset(); |
| 126 | 88 |
| 127 - (void)windowDidBecomeMain:(NSNotification*)notification { | 89 // No more calls back up to the BWC. |
| 128 [self updateMenuBarAndDockVisibility]; | 90 browserController_ = nil; |
| 129 } | |
| 130 | |
| 131 - (void)windowDidResignMain:(NSNotification*)notification { | |
| 132 [self updateMenuBarAndDockVisibility]; | |
| 133 } | 91 } |
| 134 | 92 |
| 135 // Cancels any running animation and timers. | 93 // Cancels any running animation and timers. |
| 136 - (void)cancelAnimationAndTimer { | 94 - (void)cancelAnimationAndTimer { |
| 137 animationController_->StopAnimationAndTimer(); | 95 animationController_->StopAnimationAndTimer(); |
| 138 } | 96 } |
| 139 | 97 |
| 140 - (void)revealToolbarForTabStripChanges { | 98 - (void)revealToolbarForTabStripChanges { |
| 141 if (!base::CommandLine::ForCurrentProcess()->HasSwitch( | 99 if (!base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 142 switches::kEnableFullscreenToolbarReveal)) { | 100 switches::kEnableFullscreenToolbarReveal)) { |
| 143 return; | 101 return; |
| 144 } | 102 } |
| 145 | 103 |
| 146 animationController_->AnimateToolbarForTabstripChanges(); | 104 animationController_->AnimateToolbarForTabstripChanges(); |
| 147 } | 105 } |
| 148 | 106 |
| 149 - (void)setSystemFullscreenModeTo:(base::mac::FullScreenMode)mode { | |
| 150 if (mode == systemFullscreenMode_) | |
| 151 return; | |
| 152 if (systemFullscreenMode_ == base::mac::kFullScreenModeNormal) | |
| 153 base::mac::RequestFullScreen(mode); | |
| 154 else if (mode == base::mac::kFullScreenModeNormal) | |
| 155 base::mac::ReleaseFullScreen(systemFullscreenMode_); | |
| 156 else | |
| 157 base::mac::SwitchFullScreenModes(systemFullscreenMode_, mode); | |
| 158 systemFullscreenMode_ = mode; | |
| 159 } | |
| 160 | |
| 161 - (void)updateToolbarStyle { | 107 - (void)updateToolbarStyle { |
| 162 FullscreenToolbarStyle oldStyle = toolbarStyle_; | 108 FullscreenToolbarStyle oldStyle = toolbarStyle_; |
| 163 | 109 |
| 164 if ([browserController_ isFullscreenForTabContentOrExtension]) { | 110 if ([browserController_ isFullscreenForTabContentOrExtension]) { |
| 165 toolbarStyle_ = FullscreenToolbarStyle::TOOLBAR_NONE; | 111 toolbarStyle_ = FullscreenToolbarStyle::TOOLBAR_NONE; |
| 166 } else { | 112 } else { |
| 167 PrefService* prefs = [browserController_ profile]->GetPrefs(); | 113 PrefService* prefs = [browserController_ profile]->GetPrefs(); |
| 168 toolbarStyle_ = prefs->GetBoolean(prefs::kShowFullscreenToolbar) | 114 toolbarStyle_ = prefs->GetBoolean(prefs::kShowFullscreenToolbar) |
| 169 ? FullscreenToolbarStyle::TOOLBAR_PRESENT | 115 ? FullscreenToolbarStyle::TOOLBAR_PRESENT |
| 170 : FullscreenToolbarStyle::TOOLBAR_HIDDEN; | 116 : FullscreenToolbarStyle::TOOLBAR_HIDDEN; |
| 171 } | 117 } |
| 172 | 118 |
| 173 if (oldStyle != toolbarStyle_) | 119 if (oldStyle != toolbarStyle_) |
| 174 [self updateToolbar]; | 120 [self updateToolbar]; |
| 175 } | 121 } |
| 176 | 122 |
| 177 - (void)updateToolbar { | 123 - (void)updateToolbar { |
| 178 [browserController_ layoutSubviews]; | 124 [browserController_ layoutSubviews]; |
| 179 animationController_->ToolbarDidUpdate(); | 125 animationController_->ToolbarDidUpdate(); |
| 180 [mouseTracker_ updateTrackingArea]; | 126 [mouseTracker_ updateTrackingArea]; |
| 181 | |
| 182 // In AppKit fullscreen, moving the mouse to the top of the screen toggles | |
| 183 // menu visibility. Replicate the same effect for immersive fullscreen. | |
| 184 if ([browserController_ isInImmersiveFullscreen]) | |
| 185 [self updateMenuBarAndDockVisibility]; | |
| 186 } | 127 } |
| 187 | 128 |
| 188 - (BrowserWindowController*)browserWindowController { | 129 - (BrowserWindowController*)browserWindowController { |
| 189 return browserController_; | 130 return browserController_; |
| 190 } | 131 } |
| 191 | 132 |
| 192 - (FullscreenToolbarVisibilityLockController*)visibilityLockController { | 133 - (FullscreenToolbarVisibilityLockController*)visibilityLockController { |
| 193 return visibilityLockController_.get(); | 134 return visibilityLockController_.get(); |
| 194 } | 135 } |
| 195 | 136 |
| 196 // This method works, but is fragile. | 137 // This method works, but is fragile. |
| 197 // | 138 // |
| 198 // It gets used during view layout, which sometimes needs to be done at the | 139 // It gets used during view layout, which sometimes needs to be done at the |
| 199 // beginning of an animation. As such, this method needs to reflect the | 140 // beginning of an animation. As such, this method needs to reflect the |
| 200 // menubarOffset expected at the end of the animation. This information is not | 141 // menubarOffset expected at the end of the animation. This information is not |
| 201 // readily available. (The layout logic needs a refactor). | 142 // readily available. (The layout logic needs a refactor). |
| 202 // | 143 // |
| 203 // For AppKit Fullscreen, the menubar always starts hidden, and | 144 // For AppKit Fullscreen, the menubar always starts hidden, and |
| 204 // menubarFraction_ always starts at 0, so the logic happens to work. For | 145 // menubarFraction_ always starts at 0, so the logic happens to work. For |
| 205 // Immersive Fullscreen, this class controls the visibility of the menu bar, so | 146 // Immersive Fullscreen, this class controls the visibility of the menu bar, so |
| 206 // the logic is correct and not fragile. | 147 // the logic is correct and not fragile. |
| 207 - (CGFloat)menubarOffset { | 148 - (CGFloat)menubarOffset { |
| 208 if ([browserController_ isInAppKitFullscreen]) { | 149 if ([browserController_ isInAppKitFullscreen]) { |
| 209 return -std::floor([menubarTracker_ menubarFraction] * | 150 return -std::floor([menubarTracker_ menubarFraction] * |
| 210 kToolbarVerticalOffset); | 151 kToolbarVerticalOffset); |
| 211 } | 152 } |
| 212 | 153 |
| 213 return [self shouldShowMenubarInImmersiveFullscreen] ? -kToolbarVerticalOffset | 154 return [immersiveFullscreenController_ shouldShowMenubar] |
| 214 : 0; | 155 ? -kToolbarVerticalOffset |
| 156 : 0; |
| 215 } | 157 } |
| 216 | 158 |
| 217 - (CGFloat)toolbarFraction { | 159 - (CGFloat)toolbarFraction { |
| 218 if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kKioskMode)) | 160 if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kKioskMode)) |
| 219 return kHideFraction; | 161 return kHideFraction; |
| 220 | 162 |
| 221 switch (toolbarStyle_) { | 163 switch (toolbarStyle_) { |
| 222 case FullscreenToolbarStyle::TOOLBAR_PRESENT: | 164 case FullscreenToolbarStyle::TOOLBAR_PRESENT: |
| 223 return kShowFraction; | 165 return kShowFraction; |
| 224 case FullscreenToolbarStyle::TOOLBAR_NONE: | 166 case FullscreenToolbarStyle::TOOLBAR_NONE: |
| (...skipping 18 matching lines...) Expand all Loading... |
| 243 | 185 |
| 244 if (toolbarStyle_ == FullscreenToolbarStyle::TOOLBAR_NONE) | 186 if (toolbarStyle_ == FullscreenToolbarStyle::TOOLBAR_NONE) |
| 245 return NO; | 187 return NO; |
| 246 | 188 |
| 247 FullscreenMenubarState menubarState = [menubarTracker_ state]; | 189 FullscreenMenubarState menubarState = [menubarTracker_ state]; |
| 248 return menubarState == FullscreenMenubarState::SHOWN || | 190 return menubarState == FullscreenMenubarState::SHOWN || |
| 249 [mouseTracker_ mouseInsideTrackingArea] || | 191 [mouseTracker_ mouseInsideTrackingArea] || |
| 250 [visibilityLockController_ isToolbarVisibilityLocked]; | 192 [visibilityLockController_ isToolbarVisibilityLocked]; |
| 251 } | 193 } |
| 252 | 194 |
| 253 - (BOOL)isFullscreenTransitionInProgress { | |
| 254 return [browserController_ isFullscreenTransitionInProgress]; | |
| 255 } | |
| 256 | |
| 257 - (BOOL)isInFullscreen { | 195 - (BOOL)isInFullscreen { |
| 258 return inFullscreenMode_; | 196 return inFullscreenMode_; |
| 259 } | 197 } |
| 260 | 198 |
| 261 - (BOOL)isMouseOnScreen { | |
| 262 return NSMouseInRect([NSEvent mouseLocation], | |
| 263 [[browserController_ window] screen].frame, false); | |
| 264 } | |
| 265 | |
| 266 - (void)updateToolbarFrame:(NSRect)frame { | 199 - (void)updateToolbarFrame:(NSRect)frame { |
| 267 if (mouseTracker_.get()) | 200 if (mouseTracker_.get()) |
| 268 [mouseTracker_ updateToolbarFrame:frame]; | 201 [mouseTracker_ updateToolbarFrame:frame]; |
| 269 } | 202 } |
| 270 | 203 |
| 271 @end | 204 @end |
| 272 | 205 |
| 273 @implementation FullscreenToolbarController (PrivateMethods) | |
| 274 | |
| 275 - (void)updateMenuBarAndDockVisibility { | |
| 276 if (![self isMouseOnScreen] || | |
| 277 ![browserController_ isInImmersiveFullscreen]) { | |
| 278 [self setSystemFullscreenModeTo:base::mac::kFullScreenModeNormal]; | |
| 279 return; | |
| 280 } | |
| 281 | |
| 282 // The screen does not have a menu bar, so there's no need to hide it. | |
| 283 if (![self doesScreenHaveMenuBar]) { | |
| 284 [self setSystemFullscreenModeTo:base::mac::kFullScreenModeHideDock]; | |
| 285 return; | |
| 286 } | |
| 287 | |
| 288 [self setSystemFullscreenModeTo:[self desiredSystemFullscreenMode]]; | |
| 289 } | |
| 290 | |
| 291 - (BOOL)doesScreenHaveMenuBar { | |
| 292 if (![[NSScreen class] | |
| 293 respondsToSelector:@selector(screensHaveSeparateSpaces)]) | |
| 294 return [self isWindowOnPrimaryScreen]; | |
| 295 | |
| 296 BOOL eachScreenShouldHaveMenuBar = [NSScreen screensHaveSeparateSpaces]; | |
| 297 return eachScreenShouldHaveMenuBar ?: [self isWindowOnPrimaryScreen]; | |
| 298 } | |
| 299 | |
| 300 - (BOOL)isWindowOnPrimaryScreen { | |
| 301 NSScreen* screen = [[browserController_ window] screen]; | |
| 302 NSScreen* primaryScreen = [[NSScreen screens] firstObject]; | |
| 303 return (screen == primaryScreen); | |
| 304 } | |
| 305 | |
| 306 - (base::mac::FullScreenMode)desiredSystemFullscreenMode { | |
| 307 if ([self shouldShowMenubarInImmersiveFullscreen]) | |
| 308 return base::mac::kFullScreenModeHideDock; | |
| 309 return base::mac::kFullScreenModeHideAll; | |
| 310 } | |
| 311 | |
| 312 - (void)cleanup { | |
| 313 animationController_->StopAnimationAndTimer(); | |
| 314 [[NSNotificationCenter defaultCenter] removeObserver:self]; | |
| 315 | |
| 316 // Call the main status resignation code to perform the associated cleanup, | |
| 317 // since we will no longer be receiving actual status resignation | |
| 318 // notifications. | |
| 319 [self setSystemFullscreenModeTo:base::mac::kFullScreenModeNormal]; | |
| 320 | |
| 321 // No more calls back up to the BWC. | |
| 322 browserController_ = nil; | |
| 323 | |
| 324 menubarTracker_.reset(); | |
| 325 mouseTracker_.reset(); | |
| 326 } | |
| 327 | |
| 328 - (BOOL)shouldShowMenubarInImmersiveFullscreen { | |
| 329 return [self doesScreenHaveMenuBar] && [self toolbarFraction] > 0.99; | |
| 330 } | |
| 331 | |
| 332 @end | |
| OLD | NEW |