| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #import "chrome/browser/ui/cocoa/fullscreen_controller.h" | |
| 6 | |
| 7 #include <algorithm> | |
| 8 | |
| 9 #import "base/mac/mac_util.h" | |
| 10 #import "chrome/browser/ui/cocoa/browser_window_controller.h" | |
| 11 #import "third_party/GTM/AppKit/GTMNSAnimation+Duration.h" | |
| 12 | |
| 13 NSString* const kWillEnterFullscreenNotification = | |
| 14 @"WillEnterFullscreenNotification"; | |
| 15 NSString* const kWillLeaveFullscreenNotification = | |
| 16 @"WillLeaveFullscreenNotification"; | |
| 17 | |
| 18 namespace { | |
| 19 // The activation zone for the main menu is 4 pixels high; if we make it any | |
| 20 // smaller, then the menu can be made to appear without the bar sliding down. | |
| 21 const CGFloat kDropdownActivationZoneHeight = 4; | |
| 22 const NSTimeInterval kDropdownAnimationDuration = 0.12; | |
| 23 const NSTimeInterval kMouseExitCheckDelay = 0.1; | |
| 24 // This show delay attempts to match the delay for the main menu. | |
| 25 const NSTimeInterval kDropdownShowDelay = 0.3; | |
| 26 const NSTimeInterval kDropdownHideDelay = 0.2; | |
| 27 | |
| 28 // The amount by which the floating bar is offset downwards (to avoid the menu) | |
| 29 // in fullscreen mode. (We can't use |-[NSMenu menuBarHeight]| since it returns | |
| 30 // 0 when the menu bar is hidden.) | |
| 31 const CGFloat kFloatingBarVerticalOffset = 22; | |
| 32 | |
| 33 } // end namespace | |
| 34 | |
| 35 | |
| 36 // Helper class to manage animations for the fullscreen dropdown bar. Calls | |
| 37 // [FullscreenController changeFloatingBarShownFraction] once per animation | |
| 38 // step. | |
| 39 @interface DropdownAnimation : NSAnimation { | |
| 40 @private | |
| 41 FullscreenController* controller_; | |
| 42 CGFloat startFraction_; | |
| 43 CGFloat endFraction_; | |
| 44 } | |
| 45 | |
| 46 @property(readonly, nonatomic) CGFloat startFraction; | |
| 47 @property(readonly, nonatomic) CGFloat endFraction; | |
| 48 | |
| 49 // Designated initializer. Asks |controller| for the current shown fraction, so | |
| 50 // if the bar is already partially shown or partially hidden, the animation | |
| 51 // duration may be less than |fullDuration|. | |
| 52 - (id)initWithFraction:(CGFloat)fromFraction | |
| 53 fullDuration:(CGFloat)fullDuration | |
| 54 animationCurve:(NSInteger)animationCurve | |
| 55 controller:(FullscreenController*)controller; | |
| 56 | |
| 57 @end | |
| 58 | |
| 59 @implementation DropdownAnimation | |
| 60 | |
| 61 @synthesize startFraction = startFraction_; | |
| 62 @synthesize endFraction = endFraction_; | |
| 63 | |
| 64 - (id)initWithFraction:(CGFloat)toFraction | |
| 65 fullDuration:(CGFloat)fullDuration | |
| 66 animationCurve:(NSInteger)animationCurve | |
| 67 controller:(FullscreenController*)controller { | |
| 68 // Calculate the effective duration, based on the current shown fraction. | |
| 69 DCHECK(controller); | |
| 70 CGFloat fromFraction = [controller floatingBarShownFraction]; | |
| 71 CGFloat effectiveDuration = fabs(fullDuration * (fromFraction - toFraction)); | |
| 72 | |
| 73 if ((self = [super gtm_initWithDuration:effectiveDuration | |
| 74 eventMask:NSLeftMouseDownMask | |
| 75 animationCurve:animationCurve])) { | |
| 76 startFraction_ = fromFraction; | |
| 77 endFraction_ = toFraction; | |
| 78 controller_ = controller; | |
| 79 } | |
| 80 return self; | |
| 81 } | |
| 82 | |
| 83 // Called once per animation step. Overridden to change the floating bar's | |
| 84 // position based on the animation's progress. | |
| 85 - (void)setCurrentProgress:(NSAnimationProgress)progress { | |
| 86 CGFloat fraction = | |
| 87 startFraction_ + (progress * (endFraction_ - startFraction_)); | |
| 88 [controller_ changeFloatingBarShownFraction:fraction]; | |
| 89 } | |
| 90 | |
| 91 @end | |
| 92 | |
| 93 | |
| 94 @interface FullscreenController (PrivateMethods) | |
| 95 | |
| 96 // Returns YES if the fullscreen window is on the primary screen. | |
| 97 - (BOOL)isWindowOnPrimaryScreen; | |
| 98 | |
| 99 // Returns YES if it is ok to show and hide the menu bar in response to the | |
| 100 // overlay opening and closing. Will return NO if the window is not main or not | |
| 101 // on the primary monitor. | |
| 102 - (BOOL)shouldToggleMenuBar; | |
| 103 | |
| 104 // Returns |kFullScreenModeHideAll| when the overlay is hidden and | |
| 105 // |kFullScreenModeHideDock| when the overlay is shown. | |
| 106 - (base::mac::FullScreenMode)desiredFullscreenMode; | |
| 107 | |
| 108 // Change the overlay to the given fraction, with or without animation. Only | |
| 109 // guaranteed to work properly with |fraction == 0| or |fraction == 1|. This | |
| 110 // performs the show/hide (animation) immediately. It does not touch the timers. | |
| 111 - (void)changeOverlayToFraction:(CGFloat)fraction | |
| 112 withAnimation:(BOOL)animate; | |
| 113 | |
| 114 // Schedule the floating bar to be shown/hidden because of mouse position. | |
| 115 - (void)scheduleShowForMouse; | |
| 116 - (void)scheduleHideForMouse; | |
| 117 | |
| 118 // Set up the tracking area used to activate the sliding bar or keep it active | |
| 119 // using with the rectangle in |trackingAreaBounds_|, or remove the tracking | |
| 120 // area if one was previously set up. | |
| 121 - (void)setupTrackingArea; | |
| 122 - (void)removeTrackingAreaIfNecessary; | |
| 123 | |
| 124 // Returns YES if the mouse is currently in any current tracking rectangle, NO | |
| 125 // otherwise. | |
| 126 - (BOOL)mouseInsideTrackingRect; | |
| 127 | |
| 128 // The tracking area can "falsely" report exits when the menu slides down over | |
| 129 // it. In that case, we have to monitor for a "real" mouse exit on a timer. | |
| 130 // |-setupMouseExitCheck| schedules a check; |-cancelMouseExitCheck| cancels any | |
| 131 // scheduled check. | |
| 132 - (void)setupMouseExitCheck; | |
| 133 - (void)cancelMouseExitCheck; | |
| 134 | |
| 135 // Called (after a delay) by |-setupMouseExitCheck|, to check whether the mouse | |
| 136 // has exited or not; if it hasn't, it will schedule another check. | |
| 137 - (void)checkForMouseExit; | |
| 138 | |
| 139 // Start timers for showing/hiding the floating bar. | |
| 140 - (void)startShowTimer; | |
| 141 - (void)startHideTimer; | |
| 142 - (void)cancelShowTimer; | |
| 143 - (void)cancelHideTimer; | |
| 144 - (void)cancelAllTimers; | |
| 145 | |
| 146 // Methods called when the show/hide timers fire. Do not call directly. | |
| 147 - (void)showTimerFire:(NSTimer*)timer; | |
| 148 - (void)hideTimerFire:(NSTimer*)timer; | |
| 149 | |
| 150 // Stops any running animations, removes tracking areas, etc. | |
| 151 - (void)cleanup; | |
| 152 | |
| 153 // Shows and hides the UI associated with this window being active (having main | |
| 154 // status). This includes hiding the menu bar and displaying the "Exit | |
| 155 // Fullscreen" button. These functions are called when the window gains or | |
| 156 // loses main status as well as in |-cleanup|. | |
| 157 - (void)showActiveWindowUI; | |
| 158 - (void)hideActiveWindowUI; | |
| 159 | |
| 160 @end | |
| 161 | |
| 162 | |
| 163 @implementation FullscreenController | |
| 164 | |
| 165 @synthesize isFullscreen = isFullscreen_; | |
| 166 | |
| 167 - (id)initWithBrowserController:(BrowserWindowController*)controller { | |
| 168 if ((self = [super init])) { | |
| 169 browserController_ = controller; | |
| 170 currentFullscreenMode_ = base::mac::kFullScreenModeNormal; | |
| 171 } | |
| 172 | |
| 173 // Let the world know what we're up to. | |
| 174 [[NSNotificationCenter defaultCenter] | |
| 175 postNotificationName:kWillEnterFullscreenNotification | |
| 176 object:nil]; | |
| 177 | |
| 178 return self; | |
| 179 } | |
| 180 | |
| 181 - (void)dealloc { | |
| 182 DCHECK(!isFullscreen_); | |
| 183 DCHECK(!trackingArea_); | |
| 184 [super dealloc]; | |
| 185 } | |
| 186 | |
| 187 - (void)enterFullscreenForContentView:(NSView*)contentView | |
| 188 showDropdown:(BOOL)showDropdown { | |
| 189 DCHECK(!isFullscreen_); | |
| 190 isFullscreen_ = YES; | |
| 191 contentView_ = contentView; | |
| 192 [self changeFloatingBarShownFraction:(showDropdown ? 1 : 0)]; | |
| 193 | |
| 194 // Register for notifications. Self is removed as an observer in |-cleanup|. | |
| 195 NSNotificationCenter* nc = [NSNotificationCenter defaultCenter]; | |
| 196 NSWindow* window = [browserController_ window]; | |
| 197 [nc addObserver:self | |
| 198 selector:@selector(windowDidChangeScreen:) | |
| 199 name:NSWindowDidChangeScreenNotification | |
| 200 object:window]; | |
| 201 | |
| 202 [nc addObserver:self | |
| 203 selector:@selector(windowDidMove:) | |
| 204 name:NSWindowDidMoveNotification | |
| 205 object:window]; | |
| 206 | |
| 207 [nc addObserver:self | |
| 208 selector:@selector(windowDidBecomeMain:) | |
| 209 name:NSWindowDidBecomeMainNotification | |
| 210 object:window]; | |
| 211 | |
| 212 [nc addObserver:self | |
| 213 selector:@selector(windowDidResignMain:) | |
| 214 name:NSWindowDidResignMainNotification | |
| 215 object:window]; | |
| 216 } | |
| 217 | |
| 218 - (void)exitFullscreen { | |
| 219 [[NSNotificationCenter defaultCenter] | |
| 220 postNotificationName:kWillLeaveFullscreenNotification | |
| 221 object:nil]; | |
| 222 DCHECK(isFullscreen_); | |
| 223 [self cleanup]; | |
| 224 isFullscreen_ = NO; | |
| 225 } | |
| 226 | |
| 227 - (void)windowDidChangeScreen:(NSNotification*)notification { | |
| 228 [browserController_ resizeFullscreenWindow]; | |
| 229 } | |
| 230 | |
| 231 - (void)windowDidMove:(NSNotification*)notification { | |
| 232 [browserController_ resizeFullscreenWindow]; | |
| 233 } | |
| 234 | |
| 235 - (void)windowDidBecomeMain:(NSNotification*)notification { | |
| 236 [self showActiveWindowUI]; | |
| 237 } | |
| 238 | |
| 239 - (void)windowDidResignMain:(NSNotification*)notification { | |
| 240 [self hideActiveWindowUI]; | |
| 241 } | |
| 242 | |
| 243 - (CGFloat)floatingBarVerticalOffset { | |
| 244 return [self isWindowOnPrimaryScreen] ? kFloatingBarVerticalOffset : 0; | |
| 245 } | |
| 246 | |
| 247 - (void)overlayFrameChanged:(NSRect)frame { | |
| 248 if (!isFullscreen_) | |
| 249 return; | |
| 250 | |
| 251 // Make sure |trackingAreaBounds_| always reflects either the tracking area or | |
| 252 // the desired tracking area. | |
| 253 trackingAreaBounds_ = frame; | |
| 254 // The tracking area should always be at least the height of activation zone. | |
| 255 NSRect contentBounds = [contentView_ bounds]; | |
| 256 trackingAreaBounds_.origin.y = | |
| 257 std::min(trackingAreaBounds_.origin.y, | |
| 258 NSMaxY(contentBounds) - kDropdownActivationZoneHeight); | |
| 259 trackingAreaBounds_.size.height = | |
| 260 NSMaxY(contentBounds) - trackingAreaBounds_.origin.y + 1; | |
| 261 | |
| 262 // If an animation is currently running, do not set up a tracking area now. | |
| 263 // Instead, leave it to be created it in |-animationDidEnd:|. | |
| 264 if (currentAnimation_) | |
| 265 return; | |
| 266 | |
| 267 [self setupTrackingArea]; | |
| 268 } | |
| 269 | |
| 270 - (void)ensureOverlayShownWithAnimation:(BOOL)animate delay:(BOOL)delay { | |
| 271 if (!isFullscreen_) | |
| 272 return; | |
| 273 | |
| 274 if (animate) { | |
| 275 if (delay) { | |
| 276 [self startShowTimer]; | |
| 277 } else { | |
| 278 [self cancelAllTimers]; | |
| 279 [self changeOverlayToFraction:1 withAnimation:YES]; | |
| 280 } | |
| 281 } else { | |
| 282 DCHECK(!delay); | |
| 283 [self cancelAllTimers]; | |
| 284 [self changeOverlayToFraction:1 withAnimation:NO]; | |
| 285 } | |
| 286 } | |
| 287 | |
| 288 - (void)ensureOverlayHiddenWithAnimation:(BOOL)animate delay:(BOOL)delay { | |
| 289 if (!isFullscreen_) | |
| 290 return; | |
| 291 | |
| 292 if (animate) { | |
| 293 if (delay) { | |
| 294 [self startHideTimer]; | |
| 295 } else { | |
| 296 [self cancelAllTimers]; | |
| 297 [self changeOverlayToFraction:0 withAnimation:YES]; | |
| 298 } | |
| 299 } else { | |
| 300 DCHECK(!delay); | |
| 301 [self cancelAllTimers]; | |
| 302 [self changeOverlayToFraction:0 withAnimation:NO]; | |
| 303 } | |
| 304 } | |
| 305 | |
| 306 - (void)cancelAnimationAndTimers { | |
| 307 [self cancelAllTimers]; | |
| 308 [currentAnimation_ stopAnimation]; | |
| 309 currentAnimation_.reset(); | |
| 310 } | |
| 311 | |
| 312 - (CGFloat)floatingBarShownFraction { | |
| 313 return [browserController_ floatingBarShownFraction]; | |
| 314 } | |
| 315 | |
| 316 - (void)changeFloatingBarShownFraction:(CGFloat)fraction { | |
| 317 [browserController_ setFloatingBarShownFraction:fraction]; | |
| 318 | |
| 319 base::mac::FullScreenMode desiredMode = [self desiredFullscreenMode]; | |
| 320 if (desiredMode != currentFullscreenMode_ && [self shouldToggleMenuBar]) { | |
| 321 if (currentFullscreenMode_ == base::mac::kFullScreenModeNormal) | |
| 322 base::mac::RequestFullScreen(desiredMode); | |
| 323 else | |
| 324 base::mac::SwitchFullScreenModes(currentFullscreenMode_, desiredMode); | |
| 325 currentFullscreenMode_ = desiredMode; | |
| 326 } | |
| 327 } | |
| 328 | |
| 329 // Used to activate the floating bar in fullscreen mode. | |
| 330 - (void)mouseEntered:(NSEvent*)event { | |
| 331 DCHECK(isFullscreen_); | |
| 332 | |
| 333 // Having gotten a mouse entered, we no longer need to do exit checks. | |
| 334 [self cancelMouseExitCheck]; | |
| 335 | |
| 336 NSTrackingArea* trackingArea = [event trackingArea]; | |
| 337 if (trackingArea == trackingArea_) { | |
| 338 // The tracking area shouldn't be active during animation. | |
| 339 DCHECK(!currentAnimation_); | |
| 340 [self scheduleShowForMouse]; | |
| 341 } | |
| 342 } | |
| 343 | |
| 344 // Used to deactivate the floating bar in fullscreen mode. | |
| 345 - (void)mouseExited:(NSEvent*)event { | |
| 346 DCHECK(isFullscreen_); | |
| 347 | |
| 348 NSTrackingArea* trackingArea = [event trackingArea]; | |
| 349 if (trackingArea == trackingArea_) { | |
| 350 // The tracking area shouldn't be active during animation. | |
| 351 DCHECK(!currentAnimation_); | |
| 352 | |
| 353 // We can get a false mouse exit when the menu slides down, so if the mouse | |
| 354 // is still actually over the tracking area, we ignore the mouse exit, but | |
| 355 // we set up to check the mouse position again after a delay. | |
| 356 if ([self mouseInsideTrackingRect]) { | |
| 357 [self setupMouseExitCheck]; | |
| 358 return; | |
| 359 } | |
| 360 | |
| 361 [self scheduleHideForMouse]; | |
| 362 } | |
| 363 } | |
| 364 | |
| 365 - (void)animationDidStop:(NSAnimation*)animation { | |
| 366 // Reset the |currentAnimation_| pointer now that the animation is over. | |
| 367 currentAnimation_.reset(); | |
| 368 | |
| 369 // Invariant says that the tracking area is not installed while animations are | |
| 370 // in progress. Ensure this is true. | |
| 371 DCHECK(!trackingArea_); | |
| 372 [self removeTrackingAreaIfNecessary]; // For paranoia. | |
| 373 | |
| 374 // Don't automatically set up a new tracking area. When explicitly stopped, | |
| 375 // either another animation is going to start immediately or the state will be | |
| 376 // changed immediately. | |
| 377 } | |
| 378 | |
| 379 - (void)animationDidEnd:(NSAnimation*)animation { | |
| 380 [self animationDidStop:animation]; | |
| 381 | |
| 382 // |trackingAreaBounds_| contains the correct tracking area bounds, including | |
| 383 // |any updates that may have come while the animation was running. Install a | |
| 384 // new tracking area with these bounds. | |
| 385 [self setupTrackingArea]; | |
| 386 | |
| 387 // TODO(viettrungluu): Better would be to check during the animation; doing it | |
| 388 // here means that the timing is slightly off. | |
| 389 if (![self mouseInsideTrackingRect]) | |
| 390 [self scheduleHideForMouse]; | |
| 391 } | |
| 392 | |
| 393 @end | |
| 394 | |
| 395 | |
| 396 @implementation FullscreenController (PrivateMethods) | |
| 397 | |
| 398 - (BOOL)isWindowOnPrimaryScreen { | |
| 399 NSScreen* screen = [[browserController_ window] screen]; | |
| 400 NSScreen* primaryScreen = [[NSScreen screens] objectAtIndex:0]; | |
| 401 return (screen == primaryScreen); | |
| 402 } | |
| 403 | |
| 404 - (BOOL)shouldToggleMenuBar { | |
| 405 return [self isWindowOnPrimaryScreen] && | |
| 406 [[browserController_ window] isMainWindow]; | |
| 407 } | |
| 408 | |
| 409 - (base::mac::FullScreenMode)desiredFullscreenMode { | |
| 410 if ([browserController_ floatingBarShownFraction] >= 1.0) | |
| 411 return base::mac::kFullScreenModeHideDock; | |
| 412 return base::mac::kFullScreenModeHideAll; | |
| 413 } | |
| 414 | |
| 415 - (void)changeOverlayToFraction:(CGFloat)fraction | |
| 416 withAnimation:(BOOL)animate { | |
| 417 // The non-animated case is really simple, so do it and return. | |
| 418 if (!animate) { | |
| 419 [currentAnimation_ stopAnimation]; | |
| 420 [self changeFloatingBarShownFraction:fraction]; | |
| 421 return; | |
| 422 } | |
| 423 | |
| 424 // If we're already animating to the given fraction, then there's nothing more | |
| 425 // to do. | |
| 426 if (currentAnimation_ && [currentAnimation_ endFraction] == fraction) | |
| 427 return; | |
| 428 | |
| 429 // In all other cases, we want to cancel any running animation (which may be | |
| 430 // to show or to hide). | |
| 431 [currentAnimation_ stopAnimation]; | |
| 432 | |
| 433 // Now, if it happens to already be in the right state, there's nothing more | |
| 434 // to do. | |
| 435 if ([browserController_ floatingBarShownFraction] == fraction) | |
| 436 return; | |
| 437 | |
| 438 // Create the animation and set it up. | |
| 439 currentAnimation_.reset( | |
| 440 [[DropdownAnimation alloc] initWithFraction:fraction | |
| 441 fullDuration:kDropdownAnimationDuration | |
| 442 animationCurve:NSAnimationEaseOut | |
| 443 controller:self]); | |
| 444 DCHECK(currentAnimation_); | |
| 445 [currentAnimation_ setAnimationBlockingMode:NSAnimationNonblocking]; | |
| 446 [currentAnimation_ setDelegate:self]; | |
| 447 | |
| 448 // If there is an existing tracking area, remove it. We do not track mouse | |
| 449 // movements during animations (see class comment in the header file). | |
| 450 [self removeTrackingAreaIfNecessary]; | |
| 451 | |
| 452 [currentAnimation_ startAnimation]; | |
| 453 } | |
| 454 | |
| 455 - (void)scheduleShowForMouse { | |
| 456 [browserController_ lockBarVisibilityForOwner:self | |
| 457 withAnimation:YES | |
| 458 delay:YES]; | |
| 459 } | |
| 460 | |
| 461 - (void)scheduleHideForMouse { | |
| 462 [browserController_ releaseBarVisibilityForOwner:self | |
| 463 withAnimation:YES | |
| 464 delay:YES]; | |
| 465 } | |
| 466 | |
| 467 - (void)setupTrackingArea { | |
| 468 if (trackingArea_) { | |
| 469 // If the tracking rectangle is already |trackingAreaBounds_|, quit early. | |
| 470 NSRect oldRect = [trackingArea_ rect]; | |
| 471 if (NSEqualRects(trackingAreaBounds_, oldRect)) | |
| 472 return; | |
| 473 | |
| 474 // Otherwise, remove it. | |
| 475 [self removeTrackingAreaIfNecessary]; | |
| 476 } | |
| 477 | |
| 478 // Create and add a new tracking area for |frame|. | |
| 479 trackingArea_.reset( | |
| 480 [[NSTrackingArea alloc] initWithRect:trackingAreaBounds_ | |
| 481 options:NSTrackingMouseEnteredAndExited | | |
| 482 NSTrackingActiveInKeyWindow | |
| 483 owner:self | |
| 484 userInfo:nil]); | |
| 485 DCHECK(contentView_); | |
| 486 [contentView_ addTrackingArea:trackingArea_]; | |
| 487 } | |
| 488 | |
| 489 - (void)removeTrackingAreaIfNecessary { | |
| 490 if (trackingArea_) { | |
| 491 DCHECK(contentView_); // |contentView_| better be valid. | |
| 492 [contentView_ removeTrackingArea:trackingArea_]; | |
| 493 trackingArea_.reset(); | |
| 494 } | |
| 495 } | |
| 496 | |
| 497 - (BOOL)mouseInsideTrackingRect { | |
| 498 NSWindow* window = [browserController_ window]; | |
| 499 NSPoint mouseLoc = [window mouseLocationOutsideOfEventStream]; | |
| 500 NSPoint mousePos = [contentView_ convertPoint:mouseLoc fromView:nil]; | |
| 501 return NSMouseInRect(mousePos, trackingAreaBounds_, [contentView_ isFlipped]); | |
| 502 } | |
| 503 | |
| 504 - (void)setupMouseExitCheck { | |
| 505 [self performSelector:@selector(checkForMouseExit) | |
| 506 withObject:nil | |
| 507 afterDelay:kMouseExitCheckDelay]; | |
| 508 } | |
| 509 | |
| 510 - (void)cancelMouseExitCheck { | |
| 511 [NSObject cancelPreviousPerformRequestsWithTarget:self | |
| 512 selector:@selector(checkForMouseExit) object:nil]; | |
| 513 } | |
| 514 | |
| 515 - (void)checkForMouseExit { | |
| 516 if ([self mouseInsideTrackingRect]) | |
| 517 [self setupMouseExitCheck]; | |
| 518 else | |
| 519 [self scheduleHideForMouse]; | |
| 520 } | |
| 521 | |
| 522 - (void)startShowTimer { | |
| 523 // If there's already a show timer going, just keep it. | |
| 524 if (showTimer_) { | |
| 525 DCHECK([showTimer_ isValid]); | |
| 526 DCHECK(!hideTimer_); | |
| 527 return; | |
| 528 } | |
| 529 | |
| 530 // Cancel the hide timer (if necessary) and set up the new show timer. | |
| 531 [self cancelHideTimer]; | |
| 532 showTimer_.reset( | |
| 533 [[NSTimer scheduledTimerWithTimeInterval:kDropdownShowDelay | |
| 534 target:self | |
| 535 selector:@selector(showTimerFire:) | |
| 536 userInfo:nil | |
| 537 repeats:NO] retain]); | |
| 538 DCHECK([showTimer_ isValid]); // This also checks that |showTimer_ != nil|. | |
| 539 } | |
| 540 | |
| 541 - (void)startHideTimer { | |
| 542 // If there's already a hide timer going, just keep it. | |
| 543 if (hideTimer_) { | |
| 544 DCHECK([hideTimer_ isValid]); | |
| 545 DCHECK(!showTimer_); | |
| 546 return; | |
| 547 } | |
| 548 | |
| 549 // Cancel the show timer (if necessary) and set up the new hide timer. | |
| 550 [self cancelShowTimer]; | |
| 551 hideTimer_.reset( | |
| 552 [[NSTimer scheduledTimerWithTimeInterval:kDropdownHideDelay | |
| 553 target:self | |
| 554 selector:@selector(hideTimerFire:) | |
| 555 userInfo:nil | |
| 556 repeats:NO] retain]); | |
| 557 DCHECK([hideTimer_ isValid]); // This also checks that |hideTimer_ != nil|. | |
| 558 } | |
| 559 | |
| 560 - (void)cancelShowTimer { | |
| 561 [showTimer_ invalidate]; | |
| 562 showTimer_.reset(); | |
| 563 } | |
| 564 | |
| 565 - (void)cancelHideTimer { | |
| 566 [hideTimer_ invalidate]; | |
| 567 hideTimer_.reset(); | |
| 568 } | |
| 569 | |
| 570 - (void)cancelAllTimers { | |
| 571 [self cancelShowTimer]; | |
| 572 [self cancelHideTimer]; | |
| 573 } | |
| 574 | |
| 575 - (void)showTimerFire:(NSTimer*)timer { | |
| 576 DCHECK_EQ(showTimer_, timer); // This better be our show timer. | |
| 577 [showTimer_ invalidate]; // Make sure it doesn't repeat. | |
| 578 showTimer_.reset(); // And get rid of it. | |
| 579 [self changeOverlayToFraction:1 withAnimation:YES]; | |
| 580 } | |
| 581 | |
| 582 - (void)hideTimerFire:(NSTimer*)timer { | |
| 583 DCHECK_EQ(hideTimer_, timer); // This better be our hide timer. | |
| 584 [hideTimer_ invalidate]; // Make sure it doesn't repeat. | |
| 585 hideTimer_.reset(); // And get rid of it. | |
| 586 [self changeOverlayToFraction:0 withAnimation:YES]; | |
| 587 } | |
| 588 | |
| 589 - (void)cleanup { | |
| 590 [self cancelMouseExitCheck]; | |
| 591 [self cancelAnimationAndTimers]; | |
| 592 [[NSNotificationCenter defaultCenter] removeObserver:self]; | |
| 593 | |
| 594 [self removeTrackingAreaIfNecessary]; | |
| 595 contentView_ = nil; | |
| 596 | |
| 597 // This isn't tracked when not in fullscreen mode. | |
| 598 [browserController_ releaseBarVisibilityForOwner:self | |
| 599 withAnimation:NO | |
| 600 delay:NO]; | |
| 601 | |
| 602 // Call the main status resignation code to perform the associated cleanup, | |
| 603 // since we will no longer be receiving actual status resignation | |
| 604 // notifications. | |
| 605 [self hideActiveWindowUI]; | |
| 606 | |
| 607 // No more calls back up to the BWC. | |
| 608 browserController_ = nil; | |
| 609 } | |
| 610 | |
| 611 - (void)showActiveWindowUI { | |
| 612 DCHECK_EQ(currentFullscreenMode_, base::mac::kFullScreenModeNormal); | |
| 613 if (currentFullscreenMode_ != base::mac::kFullScreenModeNormal) | |
| 614 return; | |
| 615 | |
| 616 if ([self shouldToggleMenuBar]) { | |
| 617 base::mac::FullScreenMode desiredMode = [self desiredFullscreenMode]; | |
| 618 base::mac::RequestFullScreen(desiredMode); | |
| 619 currentFullscreenMode_ = desiredMode; | |
| 620 } | |
| 621 | |
| 622 // TODO(rohitrao): Insert the Exit Fullscreen button. http://crbug.com/35956 | |
| 623 } | |
| 624 | |
| 625 - (void)hideActiveWindowUI { | |
| 626 if (currentFullscreenMode_ != base::mac::kFullScreenModeNormal) { | |
| 627 base::mac::ReleaseFullScreen(currentFullscreenMode_); | |
| 628 currentFullscreenMode_ = base::mac::kFullScreenModeNormal; | |
| 629 } | |
| 630 | |
| 631 // TODO(rohitrao): Remove the Exit Fullscreen button. http://crbug.com/35956 | |
| 632 } | |
| 633 | |
| 634 @end | |
| OLD | NEW |