| 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 #import "chrome/browser/ui/cocoa/browser_window_controller.h" | 12 #import "chrome/browser/ui/cocoa/browser_window_controller.h" |
| 13 #import "chrome/browser/ui/cocoa/fullscreen/fullscreen_menubar_tracker.h" | 13 #import "chrome/browser/ui/cocoa/fullscreen/fullscreen_menubar_tracker.h" |
| 14 #import "chrome/browser/ui/cocoa/fullscreen/fullscreen_toolbar_animation_control
ler.h" | 14 #import "chrome/browser/ui/cocoa/fullscreen/fullscreen_toolbar_animation_control
ler.h" |
| 15 #import "chrome/browser/ui/cocoa/fullscreen/fullscreen_toolbar_mouse_tracker.h" |
| 15 #include "chrome/common/chrome_switches.h" | 16 #include "chrome/common/chrome_switches.h" |
| 16 #include "ui/base/cocoa/appkit_utils.h" | 17 #include "ui/base/cocoa/appkit_utils.h" |
| 17 #import "ui/base/cocoa/nsview_additions.h" | 18 #import "ui/base/cocoa/nsview_additions.h" |
| 18 #import "ui/base/cocoa/tracking_area.h" | 19 #import "ui/base/cocoa/tracking_area.h" |
| 19 | 20 |
| 20 namespace { | 21 namespace { |
| 21 | 22 |
| 22 // Additional height threshold added at the toolbar's bottom. This is to mimic | |
| 23 // threshold the mouse position needs to be at before the menubar automatically | |
| 24 // hides. | |
| 25 const CGFloat kTrackingAreaAdditionalThreshold = 20; | |
| 26 | |
| 27 // Visibility fractions for the menubar and toolbar. | 23 // Visibility fractions for the menubar and toolbar. |
| 28 const CGFloat kHideFraction = 0.0; | 24 const CGFloat kHideFraction = 0.0; |
| 29 const CGFloat kShowFraction = 1.0; | 25 const CGFloat kShowFraction = 1.0; |
| 30 | 26 |
| 31 // The amount by which the toolbar is offset downwards (to avoid the menu) | 27 // The amount by which the toolbar is offset downwards (to avoid the menu) |
| 32 // when the toolbar style is OMNIBOX_TABS_HIDDEN. (We can't use | 28 // when the toolbar style is OMNIBOX_TABS_HIDDEN. (We can't use |
| 33 // |-[NSMenu menuBarHeight]| since it returns 0 when the menu bar is hidden.) | 29 // |-[NSMenu menuBarHeight]| since it returns 0 when the menu bar is hidden.) |
| 34 const CGFloat kToolbarVerticalOffset = 22; | 30 const CGFloat kToolbarVerticalOffset = 22; |
| 35 | 31 |
| 36 } // end namespace | 32 } // end namespace |
| 37 | 33 |
| 38 @interface FullscreenToolbarController (PrivateMethods) | 34 @interface FullscreenToolbarController (PrivateMethods) |
| 39 | 35 |
| 40 // Updates the visibility of the menu bar and the dock. | 36 // Updates the visibility of the menu bar and the dock. |
| 41 - (void)updateMenuBarAndDockVisibility; | 37 - (void)updateMenuBarAndDockVisibility; |
| 42 | 38 |
| 43 // Methods to set up or remove the tracking area. | |
| 44 - (void)updateTrackingArea; | |
| 45 - (void)removeTrackingAreaIfNecessary; | |
| 46 | |
| 47 // Returns YES if the mouse is inside the tracking area. | |
| 48 - (BOOL)mouseInsideTrackingArea; | |
| 49 | |
| 50 // Whether the current screen is expected to have a menu bar, regardless of | 39 // Whether the current screen is expected to have a menu bar, regardless of |
| 51 // current visibility of the menu bar. | 40 // current visibility of the menu bar. |
| 52 - (BOOL)doesScreenHaveMenuBar; | 41 - (BOOL)doesScreenHaveMenuBar; |
| 53 | 42 |
| 54 // Returns YES if the window is on the primary screen. | 43 // Returns YES if the window is on the primary screen. |
| 55 - (BOOL)isWindowOnPrimaryScreen; | 44 - (BOOL)isWindowOnPrimaryScreen; |
| 56 | 45 |
| 57 // Returns |kFullScreenModeHideAll| when the overlay is hidden and | 46 // Returns |kFullScreenModeHideAll| when the overlay is hidden and |
| 58 // |kFullScreenModeHideDock| when the overlay is shown. | 47 // |kFullScreenModeHideDock| when the overlay is shown. |
| 59 - (base::mac::FullScreenMode)desiredSystemFullscreenMode; | 48 - (base::mac::FullScreenMode)desiredSystemFullscreenMode; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 81 } | 70 } |
| 82 | 71 |
| 83 return self; | 72 return self; |
| 84 } | 73 } |
| 85 | 74 |
| 86 - (void)dealloc { | 75 - (void)dealloc { |
| 87 DCHECK(!inFullscreenMode_); | 76 DCHECK(!inFullscreenMode_); |
| 88 [super dealloc]; | 77 [super dealloc]; |
| 89 } | 78 } |
| 90 | 79 |
| 91 - (void)setupFullscreenToolbarForContentView:(NSView*)contentView { | 80 - (void)enterFullscreenMode { |
| 92 DCHECK(!inFullscreenMode_); | 81 DCHECK(!inFullscreenMode_); |
| 93 contentView_ = contentView; | |
| 94 inFullscreenMode_ = YES; | 82 inFullscreenMode_ = YES; |
| 95 | 83 |
| 96 menubarTracker_.reset([[FullscreenMenubarTracker alloc] | 84 menubarTracker_.reset([[FullscreenMenubarTracker alloc] |
| 97 initWithFullscreenToolbarController:self]); | 85 initWithFullscreenToolbarController:self]); |
| 86 mouseTracker_.reset([[FullscreenToolbarMouseTracker alloc] |
| 87 initWithFullscreenToolbarController:self |
| 88 animationController:animationController_.get()]); |
| 98 | 89 |
| 99 [self updateMenuBarAndDockVisibility]; | 90 [self updateMenuBarAndDockVisibility]; |
| 100 | 91 |
| 101 // Register for notifications. Self is removed as an observer in |-cleanup|. | 92 // Register for notifications. Self is removed as an observer in |-cleanup|. |
| 102 NSNotificationCenter* nc = [NSNotificationCenter defaultCenter]; | 93 NSNotificationCenter* nc = [NSNotificationCenter defaultCenter]; |
| 103 NSWindow* window = [browserController_ window]; | 94 NSWindow* window = [browserController_ window]; |
| 104 | 95 |
| 105 [nc addObserver:self | 96 [nc addObserver:self |
| 106 selector:@selector(windowDidBecomeMain:) | 97 selector:@selector(windowDidBecomeMain:) |
| 107 name:NSWindowDidBecomeMainNotification | 98 name:NSWindowDidBecomeMainNotification |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 163 return; | 154 return; |
| 164 if (systemFullscreenMode_ == base::mac::kFullScreenModeNormal) | 155 if (systemFullscreenMode_ == base::mac::kFullScreenModeNormal) |
| 165 base::mac::RequestFullScreen(mode); | 156 base::mac::RequestFullScreen(mode); |
| 166 else if (mode == base::mac::kFullScreenModeNormal) | 157 else if (mode == base::mac::kFullScreenModeNormal) |
| 167 base::mac::ReleaseFullScreen(systemFullscreenMode_); | 158 base::mac::ReleaseFullScreen(systemFullscreenMode_); |
| 168 else | 159 else |
| 169 base::mac::SwitchFullScreenModes(systemFullscreenMode_, mode); | 160 base::mac::SwitchFullScreenModes(systemFullscreenMode_, mode); |
| 170 systemFullscreenMode_ = mode; | 161 systemFullscreenMode_ = mode; |
| 171 } | 162 } |
| 172 | 163 |
| 173 - (void)mouseEntered:(NSEvent*)event { | |
| 174 // Empty implementation. Required for CrTrackingArea. | |
| 175 } | |
| 176 | |
| 177 - (void)mouseExited:(NSEvent*)event { | |
| 178 DCHECK(inFullscreenMode_); | |
| 179 DCHECK_EQ([event trackingArea], trackingArea_.get()); | |
| 180 | |
| 181 if ([browserController_ isBarVisibilityLockedForOwner:nil]) | |
| 182 return; | |
| 183 | |
| 184 // If the menubar is gone, animate the toolbar out. | |
| 185 if ([menubarTracker_ state] == FullscreenMenubarState::HIDDEN) | |
| 186 [self ensureOverlayHiddenWithAnimation:YES]; | |
| 187 | |
| 188 [self removeTrackingAreaIfNecessary]; | |
| 189 } | |
| 190 | |
| 191 - (void)updateToolbar { | 164 - (void)updateToolbar { |
| 192 [browserController_ layoutSubviews]; | 165 [browserController_ layoutSubviews]; |
| 193 [self updateTrackingArea]; | |
| 194 animationController_->ToolbarDidUpdate(); | 166 animationController_->ToolbarDidUpdate(); |
| 167 [mouseTracker_ updateTrackingArea]; |
| 195 | 168 |
| 196 // In AppKit fullscreen, moving the mouse to the top of the screen toggles | 169 // In AppKit fullscreen, moving the mouse to the top of the screen toggles |
| 197 // menu visibility. Replicate the same effect for immersive fullscreen. | 170 // menu visibility. Replicate the same effect for immersive fullscreen. |
| 198 if ([browserController_ isInImmersiveFullscreen]) | 171 if ([browserController_ isInImmersiveFullscreen]) |
| 199 [self updateMenuBarAndDockVisibility]; | 172 [self updateMenuBarAndDockVisibility]; |
| 200 } | 173 } |
| 201 | 174 |
| 202 - (BrowserWindowController*)browserWindowController { | 175 - (BrowserWindowController*)browserWindowController { |
| 203 return browserController_; | 176 return browserController_; |
| 204 } | 177 } |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 249 return NO; | 222 return NO; |
| 250 | 223 |
| 251 if (slidingStyle_ == FullscreenSlidingStyle::OMNIBOX_TABS_PRESENT) | 224 if (slidingStyle_ == FullscreenSlidingStyle::OMNIBOX_TABS_PRESENT) |
| 252 return YES; | 225 return YES; |
| 253 | 226 |
| 254 if (slidingStyle_ == FullscreenSlidingStyle::OMNIBOX_TABS_NONE) | 227 if (slidingStyle_ == FullscreenSlidingStyle::OMNIBOX_TABS_NONE) |
| 255 return NO; | 228 return NO; |
| 256 | 229 |
| 257 FullscreenMenubarState menubarState = [menubarTracker_ state]; | 230 FullscreenMenubarState menubarState = [menubarTracker_ state]; |
| 258 return menubarState == FullscreenMenubarState::SHOWN || | 231 return menubarState == FullscreenMenubarState::SHOWN || |
| 259 [self mouseInsideTrackingArea] || | 232 [mouseTracker_ mouseInsideTrackingArea] || |
| 260 [browserController_ isBarVisibilityLockedForOwner:nil]; | 233 [browserController_ isBarVisibilityLockedForOwner:nil]; |
| 261 } | 234 } |
| 262 | 235 |
| 263 - (BOOL)isFullscreenTransitionInProgress { | 236 - (BOOL)isFullscreenTransitionInProgress { |
| 264 return [browserController_ isFullscreenTransitionInProgress]; | 237 return [browserController_ isFullscreenTransitionInProgress]; |
| 265 } | 238 } |
| 266 | 239 |
| 267 - (BOOL)isInFullscreen { | 240 - (BOOL)isInFullscreen { |
| 268 return inFullscreenMode_; | 241 return inFullscreenMode_; |
| 269 } | 242 } |
| 270 | 243 |
| 271 - (BOOL)isMouseOnScreen { | 244 - (BOOL)isMouseOnScreen { |
| 272 return NSMouseInRect([NSEvent mouseLocation], | 245 return NSMouseInRect([NSEvent mouseLocation], |
| 273 [[browserController_ window] screen].frame, false); | 246 [[browserController_ window] screen].frame, false); |
| 274 } | 247 } |
| 275 | 248 |
| 276 - (void)setTrackingAreaFromOverlayFrame:(NSRect)frame { | 249 - (void)updateToolbarFrame:(NSRect)frame { |
| 277 NSRect contentBounds = [contentView_ bounds]; | 250 if (mouseTracker_.get()) |
| 278 trackingAreaFrame_ = frame; | 251 [mouseTracker_ updateToolbarFrame:frame]; |
| 279 trackingAreaFrame_.origin.y -= kTrackingAreaAdditionalThreshold; | |
| 280 trackingAreaFrame_.size.height = | |
| 281 NSMaxY(contentBounds) - trackingAreaFrame_.origin.y; | |
| 282 } | 252 } |
| 283 | 253 |
| 284 @end | 254 @end |
| 285 | 255 |
| 286 @implementation FullscreenToolbarController (PrivateMethods) | 256 @implementation FullscreenToolbarController (PrivateMethods) |
| 287 | 257 |
| 288 - (void)updateMenuBarAndDockVisibility { | 258 - (void)updateMenuBarAndDockVisibility { |
| 289 if (![self isMouseOnScreen] || | 259 if (![self isMouseOnScreen] || |
| 290 ![browserController_ isInImmersiveFullscreen]) { | 260 ![browserController_ isInImmersiveFullscreen]) { |
| 291 [self setSystemFullscreenModeTo:base::mac::kFullScreenModeNormal]; | 261 [self setSystemFullscreenModeTo:base::mac::kFullScreenModeNormal]; |
| 292 return; | 262 return; |
| 293 } | 263 } |
| 294 | 264 |
| 295 // The screen does not have a menu bar, so there's no need to hide it. | 265 // The screen does not have a menu bar, so there's no need to hide it. |
| 296 if (![self doesScreenHaveMenuBar]) { | 266 if (![self doesScreenHaveMenuBar]) { |
| 297 [self setSystemFullscreenModeTo:base::mac::kFullScreenModeHideDock]; | 267 [self setSystemFullscreenModeTo:base::mac::kFullScreenModeHideDock]; |
| 298 return; | 268 return; |
| 299 } | 269 } |
| 300 | 270 |
| 301 [self setSystemFullscreenModeTo:[self desiredSystemFullscreenMode]]; | 271 [self setSystemFullscreenModeTo:[self desiredSystemFullscreenMode]]; |
| 302 } | 272 } |
| 303 | 273 |
| 304 - (void)updateTrackingArea { | |
| 305 // Remove the tracking area if the toolbar isn't fully shown. | |
| 306 if (!ui::IsCGFloatEqual([self toolbarFraction], kShowFraction)) { | |
| 307 [self removeTrackingAreaIfNecessary]; | |
| 308 return; | |
| 309 } | |
| 310 | |
| 311 if (trackingArea_) { | |
| 312 // If the tracking rectangle is already |trackingAreaBounds_|, quit early. | |
| 313 NSRect oldRect = [trackingArea_ rect]; | |
| 314 if (NSEqualRects(trackingAreaFrame_, oldRect)) | |
| 315 return; | |
| 316 | |
| 317 // Otherwise, remove it. | |
| 318 [self removeTrackingAreaIfNecessary]; | |
| 319 } | |
| 320 | |
| 321 // Create and add a new tracking area for |frame|. | |
| 322 trackingArea_.reset([[CrTrackingArea alloc] | |
| 323 initWithRect:trackingAreaFrame_ | |
| 324 options:NSTrackingMouseEnteredAndExited | NSTrackingActiveInKeyWindow | |
| 325 owner:self | |
| 326 userInfo:nil]); | |
| 327 DCHECK(contentView_); | |
| 328 [contentView_ addTrackingArea:trackingArea_]; | |
| 329 } | |
| 330 | |
| 331 - (void)removeTrackingAreaIfNecessary { | |
| 332 if (trackingArea_) { | |
| 333 DCHECK(contentView_); // |contentView_| better be valid. | |
| 334 [contentView_ removeTrackingArea:trackingArea_]; | |
| 335 trackingArea_.reset(); | |
| 336 } | |
| 337 } | |
| 338 | |
| 339 - (BOOL)mouseInsideTrackingArea { | |
| 340 if (!trackingArea_) | |
| 341 return NO; | |
| 342 | |
| 343 NSWindow* window = [browserController_ window]; | |
| 344 NSPoint mouseLoc = [window mouseLocationOutsideOfEventStream]; | |
| 345 NSPoint mousePos = [contentView_ convertPoint:mouseLoc fromView:nil]; | |
| 346 return NSMouseInRect(mousePos, trackingAreaFrame_, [contentView_ isFlipped]); | |
| 347 } | |
| 348 | |
| 349 - (BOOL)doesScreenHaveMenuBar { | 274 - (BOOL)doesScreenHaveMenuBar { |
| 350 if (![[NSScreen class] | 275 if (![[NSScreen class] |
| 351 respondsToSelector:@selector(screensHaveSeparateSpaces)]) | 276 respondsToSelector:@selector(screensHaveSeparateSpaces)]) |
| 352 return [self isWindowOnPrimaryScreen]; | 277 return [self isWindowOnPrimaryScreen]; |
| 353 | 278 |
| 354 BOOL eachScreenShouldHaveMenuBar = [NSScreen screensHaveSeparateSpaces]; | 279 BOOL eachScreenShouldHaveMenuBar = [NSScreen screensHaveSeparateSpaces]; |
| 355 return eachScreenShouldHaveMenuBar ?: [self isWindowOnPrimaryScreen]; | 280 return eachScreenShouldHaveMenuBar ?: [self isWindowOnPrimaryScreen]; |
| 356 } | 281 } |
| 357 | 282 |
| 358 - (BOOL)isWindowOnPrimaryScreen { | 283 - (BOOL)isWindowOnPrimaryScreen { |
| 359 NSScreen* screen = [[browserController_ window] screen]; | 284 NSScreen* screen = [[browserController_ window] screen]; |
| 360 NSScreen* primaryScreen = [[NSScreen screens] firstObject]; | 285 NSScreen* primaryScreen = [[NSScreen screens] firstObject]; |
| 361 return (screen == primaryScreen); | 286 return (screen == primaryScreen); |
| 362 } | 287 } |
| 363 | 288 |
| 364 - (base::mac::FullScreenMode)desiredSystemFullscreenMode { | 289 - (base::mac::FullScreenMode)desiredSystemFullscreenMode { |
| 365 if ([self shouldShowMenubarInImmersiveFullscreen]) | 290 if ([self shouldShowMenubarInImmersiveFullscreen]) |
| 366 return base::mac::kFullScreenModeHideDock; | 291 return base::mac::kFullScreenModeHideDock; |
| 367 return base::mac::kFullScreenModeHideAll; | 292 return base::mac::kFullScreenModeHideAll; |
| 368 } | 293 } |
| 369 | 294 |
| 370 - (void)cleanup { | 295 - (void)cleanup { |
| 371 animationController_->StopAnimationAndTimer(); | 296 animationController_->StopAnimationAndTimer(); |
| 372 [[NSNotificationCenter defaultCenter] removeObserver:self]; | 297 [[NSNotificationCenter defaultCenter] removeObserver:self]; |
| 373 | 298 |
| 374 [self removeTrackingAreaIfNecessary]; | |
| 375 | |
| 376 // Call the main status resignation code to perform the associated cleanup, | 299 // Call the main status resignation code to perform the associated cleanup, |
| 377 // since we will no longer be receiving actual status resignation | 300 // since we will no longer be receiving actual status resignation |
| 378 // notifications. | 301 // notifications. |
| 379 [self setSystemFullscreenModeTo:base::mac::kFullScreenModeNormal]; | 302 [self setSystemFullscreenModeTo:base::mac::kFullScreenModeNormal]; |
| 380 | 303 |
| 381 menubarTracker_.reset(); | 304 menubarTracker_.reset(); |
| 305 mouseTracker_.reset(); |
| 382 | 306 |
| 383 // No more calls back up to the BWC. | 307 // No more calls back up to the BWC. |
| 384 browserController_ = nil; | 308 browserController_ = nil; |
| 385 } | 309 } |
| 386 | 310 |
| 387 - (BOOL)shouldShowMenubarInImmersiveFullscreen { | 311 - (BOOL)shouldShowMenubarInImmersiveFullscreen { |
| 388 return [self doesScreenHaveMenuBar] && [self toolbarFraction] > 0.99; | 312 return [self doesScreenHaveMenuBar] && [self toolbarFraction] > 0.99; |
| 389 } | 313 } |
| 390 | 314 |
| 391 @end | 315 @end |
| OLD | NEW |