Chromium Code Reviews| 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 #include "chrome/common/chrome_switches.h" | 13 #include "chrome/common/chrome_switches.h" |
| 14 #import "third_party/google_toolbox_for_mac/src/AppKit/GTMNSAnimation+Duration.h " | 14 #import "third_party/google_toolbox_for_mac/src/AppKit/GTMNSAnimation+Duration.h " |
| 15 #import "ui/base/cocoa/nsview_additions.h" | 15 #import "ui/base/cocoa/nsview_additions.h" |
| 16 #import "ui/base/cocoa/tracking_area.h" | |
| 17 | 16 |
| 18 namespace { | 17 namespace { |
| 19 | 18 |
| 20 // The activation zone for the main menu is 4 pixels high; if we make it any | 19 // The activation zone for the main menu is 4 pixels high; if we make it any |
| 21 // smaller, then the menu can be made to appear without the bar sliding down. | 20 // smaller, then the menu can be made to appear without the bar sliding down. |
| 22 const CGFloat kDropdownActivationZoneHeight = 4; | |
| 23 const NSTimeInterval kDropdownAnimationDuration = 0.12; | 21 const NSTimeInterval kDropdownAnimationDuration = 0.12; |
| 24 const NSTimeInterval kMouseExitCheckDelay = 0.1; | |
| 25 // This show delay attempts to match the delay for the main menu. | |
| 26 const NSTimeInterval kDropdownShowDelay = 0.3; | |
| 27 const NSTimeInterval kDropdownHideDelay = 0.2; | |
| 28 | 22 |
| 29 // The duration the toolbar is revealed for tab strip changes. | 23 // The duration the toolbar is revealed for tab strip changes. |
| 30 const NSTimeInterval kDropdownForTabStripChangesDuration = 0.75; | 24 const NSTimeInterval kDropdownForTabStripChangesDuration = 0.75; |
| 31 | 25 |
| 32 // The event kind value for a undocumented menubar show/hide Carbon event. | 26 // The event kind value for a undocumented menubar show/hide Carbon event. |
| 33 const CGFloat kMenuBarRevealEventKind = 2004; | 27 const CGFloat kMenuBarRevealEventKind = 2004; |
| 34 | 28 |
| 35 // The amount by which the floating bar is offset downwards (to avoid the menu) | 29 // The amount by which the floating bar is offset downwards (to avoid the menu) |
| 36 // when the toolbar is hidden. (We can't use |-[NSMenu menuBarHeight]| since it | 30 // when the toolbar is hidden. (We can't use |-[NSMenu menuBarHeight]| since it |
| 37 // returns 0 when the menu bar is hidden.) | 31 // returns 0 when the menu bar is hidden.) |
| 38 const CGFloat kFloatingBarVerticalOffset = 22; | 32 const CGFloat kFloatingBarVerticalOffset = 22; |
| 39 | 33 |
| 40 OSStatus MenuBarRevealHandler(EventHandlerCallRef handler, | 34 OSStatus MenuBarRevealHandler(EventHandlerCallRef handler, |
| 41 EventRef event, | 35 EventRef event, |
| 42 void* context) { | 36 void* context) { |
| 43 FullscreenToolbarController* self = | 37 FullscreenToolbarController* self = |
| 44 static_cast<FullscreenToolbarController*>(context); | 38 static_cast<FullscreenToolbarController*>(context); |
| 45 | 39 |
| 46 // If Chrome has multiple fullscreen windows in their own space, the Handler | 40 // If Chrome has multiple fullscreen windows in their own space, the Handler |
| 47 // becomes flaky and might start receiving kMenuBarRevealEventKind events | 41 // becomes flaky and might start receiving kMenuBarRevealEventKind events |
| 48 // from another space. Since the menubar in the another space is in either a | 42 // from another space. Since the menubar in the another space is in either a |
| 49 // shown or hidden state, it will give us a reveal fraction of 0.0 or 1.0. | 43 // shown or hidden state, it will give us a reveal fraction of 0.0 or 1.0. |
| 50 // As such, we should ignore the kMenuBarRevealEventKind event if it gives | 44 // As such, we should ignore the kMenuBarRevealEventKind event if it gives |
| 51 // us a fraction of 0.0 or 1.0, and rely on kEventMenuBarShown and | 45 // us a fraction of 0.0 or 1.0, and rely on kEventMenuBarShown and |
| 52 // kEventMenuBarHidden to set these values. | 46 // kEventMenuBarHidden to set these values. |
| 53 if ([self isMainWindow] && ![self isFullscreenTransitionInProgress]) { | 47 if (![self isFullscreenTransitionInProgress]) { |
| 54 if (GetEventKind(event) == kMenuBarRevealEventKind) { | 48 if (GetEventKind(event) == kMenuBarRevealEventKind) { |
| 55 CGFloat revealFraction = 0; | 49 CGFloat revealFraction = 0; |
| 56 GetEventParameter(event, FOUR_CHAR_CODE('rvlf'), typeCGFloat, NULL, | 50 GetEventParameter(event, FOUR_CHAR_CODE('rvlf'), typeCGFloat, NULL, |
| 57 sizeof(CGFloat), NULL, &revealFraction); | 51 sizeof(CGFloat), NULL, &revealFraction); |
| 58 if (revealFraction > 0.0 && revealFraction < 1.0) | 52 if (revealFraction > 0.0 && revealFraction < 1.0) |
| 59 [self setMenuBarRevealProgress:revealFraction]; | 53 [self setMenuBarRevealProgress:revealFraction]; |
| 60 } else if (GetEventKind(event) == kEventMenuBarShown) { | 54 } else if (GetEventKind(event) == kEventMenuBarShown) { |
| 61 [self setMenuBarRevealProgress:1.0]; | 55 [self setMenuBarRevealProgress:1.0]; |
| 62 } else { | 56 } else { |
| 63 [self setMenuBarRevealProgress:0.0]; | 57 [self setMenuBarRevealProgress:0.0]; |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 140 | 134 |
| 141 // Returns |kFullScreenModeHideAll| when the overlay is hidden and | 135 // Returns |kFullScreenModeHideAll| when the overlay is hidden and |
| 142 // |kFullScreenModeHideDock| when the overlay is shown. | 136 // |kFullScreenModeHideDock| when the overlay is shown. |
| 143 - (base::mac::FullScreenMode)desiredSystemFullscreenMode; | 137 - (base::mac::FullScreenMode)desiredSystemFullscreenMode; |
| 144 | 138 |
| 145 // Change the overlay to the given fraction, with or without animation. Only | 139 // Change the overlay to the given fraction, with or without animation. Only |
| 146 // guaranteed to work properly with |fraction == 0| or |fraction == 1|. This | 140 // guaranteed to work properly with |fraction == 0| or |fraction == 1|. This |
| 147 // performs the show/hide (animation) immediately. It does not touch the timers. | 141 // performs the show/hide (animation) immediately. It does not touch the timers. |
| 148 - (void)changeOverlayToFraction:(CGFloat)fraction withAnimation:(BOOL)animate; | 142 - (void)changeOverlayToFraction:(CGFloat)fraction withAnimation:(BOOL)animate; |
| 149 | 143 |
| 150 // Schedule the floating bar to be shown/hidden because of mouse position. | 144 // Cancels the timer for hiding the floating bar. |
| 151 - (void)scheduleShowForMouse; | 145 - (void)cancelHideTimer; |
| 152 - (void)scheduleHideForMouse; | |
| 153 | 146 |
| 154 // Set up the tracking area used to activate the sliding bar or keep it active | 147 // Methods called when the hide timers fire. Do not call directly. |
| 155 // using with the rectangle in |trackingAreaBounds_|, or remove the tracking | |
| 156 // area if one was previously set up. | |
| 157 - (void)setupTrackingArea; | |
| 158 - (void)removeTrackingAreaIfNecessary; | |
| 159 | |
| 160 // Returns YES if the mouse is currently in any current tracking rectangle, NO | |
| 161 // otherwise. | |
| 162 - (BOOL)mouseInsideTrackingRect; | |
| 163 | |
| 164 // The tracking area can "falsely" report exits when the menu slides down over | |
| 165 // it. In that case, we have to monitor for a "real" mouse exit on a timer. | |
| 166 // |-setupMouseExitCheck| schedules a check; |-cancelMouseExitCheck| cancels any | |
| 167 // scheduled check. | |
| 168 - (void)setupMouseExitCheck; | |
| 169 - (void)cancelMouseExitCheck; | |
| 170 | |
| 171 // Called (after a delay) by |-setupMouseExitCheck|, to check whether the mouse | |
| 172 // has exited or not; if it hasn't, it will schedule another check. | |
| 173 - (void)checkForMouseExit; | |
| 174 | |
| 175 // Start timers for showing/hiding the floating bar. | |
| 176 - (void)startShowTimer; | |
| 177 - (void)startHideTimer; | |
| 178 - (void)cancelShowTimer; | |
| 179 - (void)cancelHideTimer; | |
| 180 - (void)cancelAllTimers; | |
| 181 | |
| 182 // Methods called when the show/hide timers fire. Do not call directly. | |
| 183 - (void)showTimerFire:(NSTimer*)timer; | |
| 184 - (void)hideTimerFire:(NSTimer*)timer; | 148 - (void)hideTimerFire:(NSTimer*)timer; |
| 185 | 149 |
| 186 // Stops any running animations, removes tracking areas, etc. | 150 // Stops any running animations, etc. |
| 187 - (void)cleanup; | 151 - (void)cleanup; |
| 188 | 152 |
| 189 // Shows and hides the UI associated with this window being active (having main | 153 // Shows and hides the UI associated with this window being active (having main |
| 190 // status). This includes hiding the menu bar. These functions are called when | 154 // status). This includes hiding the menu bar. These functions are called when |
| 191 // the window gains or loses main status as well as in |-cleanup|. | 155 // the window gains or loses main status as well as in |-cleanup|. |
| 192 - (void)showActiveWindowUI; | 156 - (void)showActiveWindowUI; |
| 193 - (void)hideActiveWindowUI; | 157 - (void)hideActiveWindowUI; |
| 194 | 158 |
| 195 // Whether the menu bar should be shown in immersive fullscreen for the screen | 159 // Whether the menu bar should be shown in immersive fullscreen for the screen |
| 196 // that contains the window. | 160 // that contains the window. |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 226 | 190 |
| 227 InstallApplicationEventHandler(NewEventHandlerUPP(&MenuBarRevealHandler), 3, | 191 InstallApplicationEventHandler(NewEventHandlerUPP(&MenuBarRevealHandler), 3, |
| 228 eventSpecs, self, &menuBarTrackingHandler_); | 192 eventSpecs, self, &menuBarTrackingHandler_); |
| 229 | 193 |
| 230 return self; | 194 return self; |
| 231 } | 195 } |
| 232 | 196 |
| 233 - (void)dealloc { | 197 - (void)dealloc { |
| 234 RemoveEventHandler(menuBarTrackingHandler_); | 198 RemoveEventHandler(menuBarTrackingHandler_); |
| 235 DCHECK(!inFullscreenMode_); | 199 DCHECK(!inFullscreenMode_); |
| 236 DCHECK(!trackingArea_); | |
| 237 [super dealloc]; | 200 [super dealloc]; |
| 238 } | 201 } |
| 239 | 202 |
| 240 - (void)setupFullscreenToolbarForContentView:(NSView*)contentView | 203 - (void)setupFullscreenToolbarWithDropdown:(BOOL)showDropdown { |
| 241 showDropdown:(BOOL)showDropdown { | |
| 242 DCHECK(!inFullscreenMode_); | 204 DCHECK(!inFullscreenMode_); |
| 243 settingUp_ = YES; | |
| 244 inFullscreenMode_ = YES; | 205 inFullscreenMode_ = YES; |
| 245 contentView_ = contentView; | |
| 246 [self changeToolbarFraction:(showDropdown ? 1 : 0)]; | 206 [self changeToolbarFraction:(showDropdown ? 1 : 0)]; |
| 247 [self updateMenuBarAndDockVisibility]; | 207 [self updateMenuBarAndDockVisibility]; |
| 248 | 208 |
| 249 // Register for notifications. Self is removed as an observer in |-cleanup|. | 209 // Register for notifications. Self is removed as an observer in |-cleanup|. |
| 250 NSNotificationCenter* nc = [NSNotificationCenter defaultCenter]; | 210 NSNotificationCenter* nc = [NSNotificationCenter defaultCenter]; |
| 251 NSWindow* window = [browserController_ window]; | 211 NSWindow* window = [browserController_ window]; |
| 252 | 212 |
| 253 [nc addObserver:self | 213 [nc addObserver:self |
| 254 selector:@selector(windowDidBecomeMain:) | 214 selector:@selector(windowDidBecomeMain:) |
| 255 name:NSWindowDidBecomeMainNotification | 215 name:NSWindowDidBecomeMainNotification |
| 256 object:window]; | 216 object:window]; |
| 257 | 217 |
| 258 [nc addObserver:self | 218 [nc addObserver:self |
| 259 selector:@selector(windowDidResignMain:) | 219 selector:@selector(windowDidResignMain:) |
| 260 name:NSWindowDidResignMainNotification | 220 name:NSWindowDidResignMainNotification |
| 261 object:window]; | 221 object:window]; |
| 262 | |
| 263 settingUp_ = NO; | |
| 264 } | 222 } |
| 265 | 223 |
| 266 - (void)exitFullscreenMode { | 224 - (void)exitFullscreenMode { |
| 267 DCHECK(inFullscreenMode_); | 225 DCHECK(inFullscreenMode_); |
| 268 inFullscreenMode_ = NO; | 226 inFullscreenMode_ = NO; |
| 269 | 227 |
| 270 [self cleanup]; | 228 [self cleanup]; |
| 271 } | 229 } |
| 272 | 230 |
| 273 - (void)windowDidChangeScreen:(NSNotification*)notification { | 231 - (void)windowDidChangeScreen:(NSNotification*)notification { |
| 274 [browserController_ resizeFullscreenWindow]; | 232 [browserController_ resizeFullscreenWindow]; |
| 275 } | 233 } |
| 276 | 234 |
| 277 - (void)windowDidMove:(NSNotification*)notification { | 235 - (void)windowDidMove:(NSNotification*)notification { |
| 278 [browserController_ resizeFullscreenWindow]; | 236 [browserController_ resizeFullscreenWindow]; |
| 279 } | 237 } |
| 280 | 238 |
| 281 - (void)windowDidBecomeMain:(NSNotification*)notification { | 239 - (void)windowDidBecomeMain:(NSNotification*)notification { |
| 282 [self showActiveWindowUI]; | 240 [self showActiveWindowUI]; |
| 283 } | 241 } |
| 284 | 242 |
| 285 - (void)windowDidResignMain:(NSNotification*)notification { | 243 - (void)windowDidResignMain:(NSNotification*)notification { |
| 286 [self hideActiveWindowUI]; | 244 [self hideActiveWindowUI]; |
| 287 } | 245 } |
| 288 | 246 |
| 289 // On OSX 10.8+, the menu bar shows on the secondary screen in fullscreen. | |
| 290 - (CGFloat)floatingBarVerticalOffset { | 247 - (CGFloat)floatingBarVerticalOffset { |
| 291 return kFloatingBarVerticalOffset; | 248 return kFloatingBarVerticalOffset; |
| 292 } | 249 } |
| 293 | 250 |
| 294 - (void)overlayFrameChanged:(NSRect)frame { | 251 - (void)ensureOverlayShownWithAnimation:(BOOL)animate { |
| 295 if (!inFullscreenMode_) | 252 if (!inFullscreenMode_) |
| 296 return; | 253 return; |
| 297 | 254 |
| 298 // Make sure |trackingAreaBounds_| always reflects either the tracking area or | |
| 299 // the desired tracking area. | |
| 300 trackingAreaBounds_ = frame; | |
| 301 // The tracking area should always be at least the height of activation zone. | |
| 302 NSRect contentBounds = [contentView_ bounds]; | |
| 303 trackingAreaBounds_.origin.y = | |
| 304 std::min(trackingAreaBounds_.origin.y, | |
| 305 NSMaxY(contentBounds) - kDropdownActivationZoneHeight); | |
| 306 trackingAreaBounds_.size.height = | |
| 307 NSMaxY(contentBounds) - trackingAreaBounds_.origin.y + 1; | |
| 308 | |
| 309 // If an animation is currently running, do not set up a tracking area now. | |
| 310 // Instead, leave it to be created it in |-animationDidEnd:|. | |
| 311 if (currentAnimation_) | |
| 312 return; | |
| 313 | |
| 314 // If this is part of the initial setup, lock bar visibility if the mouse is | |
| 315 // within the tracking area bounds. | |
| 316 if (settingUp_ && [self mouseInsideTrackingRect]) | |
| 317 [browserController_ lockBarVisibilityForOwner:self | |
| 318 withAnimation:NO | |
| 319 delay:NO]; | |
| 320 [self setupTrackingArea]; | |
| 321 } | |
| 322 | |
| 323 - (void)ensureOverlayShownWithAnimation:(BOOL)animate delay:(BOOL)delay { | |
| 324 if (!inFullscreenMode_) | |
| 325 return; | |
| 326 | |
| 327 if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kKioskMode)) | 255 if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kKioskMode)) |
| 328 return; | 256 return; |
| 329 | 257 |
| 330 if (self.slidingStyle == fullscreen_mac::OMNIBOX_TABS_PRESENT) | 258 if (self.slidingStyle == fullscreen_mac::OMNIBOX_TABS_PRESENT) |
| 331 return; | 259 return; |
| 332 | 260 |
| 333 if (animate) { | 261 [self cancelHideTimer]; |
| 334 if (delay) { | 262 if (animate) |
| 335 [self startShowTimer]; | 263 [self changeOverlayToFraction:1 withAnimation:YES]; |
|
erikchen
2016/08/18 19:33:47
maybe just [self changeOverlayToFraction:1 withAni
spqchan
2016/08/18 19:55:58
Done.
| |
| 336 } else { | 264 else |
| 337 [self cancelAllTimers]; | |
| 338 [self changeOverlayToFraction:1 withAnimation:YES]; | |
| 339 } | |
| 340 } else { | |
| 341 DCHECK(!delay); | |
| 342 [self cancelAllTimers]; | |
| 343 [self changeOverlayToFraction:1 withAnimation:NO]; | 265 [self changeOverlayToFraction:1 withAnimation:NO]; |
| 344 } | |
| 345 } | 266 } |
| 346 | 267 |
| 347 - (void)ensureOverlayHiddenWithAnimation:(BOOL)animate delay:(BOOL)delay { | 268 - (void)ensureOverlayHiddenWithAnimation:(BOOL)animate { |
| 348 if (!inFullscreenMode_) | 269 if (!inFullscreenMode_) |
| 349 return; | 270 return; |
| 350 | 271 |
| 351 if (self.slidingStyle == fullscreen_mac::OMNIBOX_TABS_PRESENT) | 272 if (self.slidingStyle == fullscreen_mac::OMNIBOX_TABS_PRESENT) |
| 352 return; | 273 return; |
| 353 | 274 |
| 354 if (animate) { | 275 [self cancelHideTimer]; |
| 355 if (delay) { | 276 if (animate) |
| 356 [self startHideTimer]; | 277 [self changeOverlayToFraction:0 withAnimation:YES]; |
| 357 } else { | 278 else |
| 358 [self cancelAllTimers]; | |
| 359 [self changeOverlayToFraction:0 withAnimation:YES]; | |
| 360 } | |
| 361 } else { | |
| 362 DCHECK(!delay); | |
| 363 [self cancelAllTimers]; | |
| 364 [self changeOverlayToFraction:0 withAnimation:NO]; | 279 [self changeOverlayToFraction:0 withAnimation:NO]; |
| 365 } | |
| 366 } | 280 } |
| 367 | 281 |
| 368 - (void)cancelAnimationAndTimers { | 282 - (void)cancelAnimationAndTimer { |
| 369 [self cancelAllTimers]; | 283 [self cancelHideTimer]; |
| 370 [currentAnimation_ stopAnimation]; | 284 [currentAnimation_ stopAnimation]; |
| 371 currentAnimation_.reset(); | 285 currentAnimation_.reset(); |
| 372 } | 286 } |
| 373 | 287 |
| 374 - (void)revealToolbarForTabStripChanges { | 288 - (void)revealToolbarForTabStripChanges { |
| 375 if (!base::CommandLine::ForCurrentProcess()->HasSwitch( | 289 if (!base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 376 switches::kEnableFullscreenToolbarReveal)) { | 290 switches::kEnableFullscreenToolbarReveal)) { |
| 377 return; | 291 return; |
| 378 } | 292 } |
| 379 | 293 |
| 380 revealToolbarForTabStripChanges_ = YES; | 294 revealToolbarForTabStripChanges_ = YES; |
| 381 [self ensureOverlayShownWithAnimation:YES delay:NO]; | 295 [self ensureOverlayShownWithAnimation:YES]; |
| 382 } | 296 } |
| 383 | 297 |
| 384 - (void)setSystemFullscreenModeTo:(base::mac::FullScreenMode)mode { | 298 - (void)setSystemFullscreenModeTo:(base::mac::FullScreenMode)mode { |
| 385 if (mode == systemFullscreenMode_) | 299 if (mode == systemFullscreenMode_) |
| 386 return; | 300 return; |
| 387 if (systemFullscreenMode_ == base::mac::kFullScreenModeNormal) | 301 if (systemFullscreenMode_ == base::mac::kFullScreenModeNormal) |
| 388 base::mac::RequestFullScreen(mode); | 302 base::mac::RequestFullScreen(mode); |
| 389 else if (mode == base::mac::kFullScreenModeNormal) | 303 else if (mode == base::mac::kFullScreenModeNormal) |
| 390 base::mac::ReleaseFullScreen(systemFullscreenMode_); | 304 base::mac::ReleaseFullScreen(systemFullscreenMode_); |
| 391 else | 305 else |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 420 | 334 |
| 421 return [self shouldShowMenubarInImmersiveFullscreen] | 335 return [self shouldShowMenubarInImmersiveFullscreen] |
| 422 ? -[self floatingBarVerticalOffset] | 336 ? -[self floatingBarVerticalOffset] |
| 423 : 0; | 337 : 0; |
| 424 } | 338 } |
| 425 | 339 |
| 426 - (BOOL)isFullscreenTransitionInProgress { | 340 - (BOOL)isFullscreenTransitionInProgress { |
| 427 return [browserController_ isFullscreenTransitionInProgress]; | 341 return [browserController_ isFullscreenTransitionInProgress]; |
| 428 } | 342 } |
| 429 | 343 |
| 430 - (BOOL)isMainWindow { | 344 - (BOOL)isMouseOnScreen { |
| 431 return [browserController_ window].isMainWindow; | 345 return NSMouseInRect([NSEvent mouseLocation], |
| 432 } | 346 [[browserController_ window] screen].frame, false); |
| 433 | |
| 434 // Used to activate the floating bar if the toolbar is hidden. | |
| 435 - (void)mouseEntered:(NSEvent*)event { | |
| 436 DCHECK(inFullscreenMode_); | |
| 437 | |
| 438 // Having gotten a mouse entered, we no longer need to do exit checks. | |
| 439 [self cancelMouseExitCheck]; | |
| 440 | |
| 441 if ([event trackingArea] == trackingArea_.get()) { | |
| 442 // The tracking area shouldn't be active during animation. | |
| 443 DCHECK(!currentAnimation_); | |
| 444 | |
| 445 // Don't show anything if the style is set to OMNIBOX_TABS_NONE. | |
| 446 if (self.slidingStyle != fullscreen_mac::OMNIBOX_TABS_NONE) | |
| 447 [self scheduleShowForMouse]; | |
| 448 } | |
| 449 } | |
| 450 | |
| 451 // Used to deactivate the floating bar if the toolbar is hidden. | |
| 452 - (void)mouseExited:(NSEvent*)event { | |
| 453 DCHECK(inFullscreenMode_); | |
| 454 | |
| 455 if ([event trackingArea] == trackingArea_.get()) { | |
| 456 // The tracking area shouldn't be active during animation. | |
| 457 DCHECK(!currentAnimation_); | |
| 458 | |
| 459 // We can get a false mouse exit when the menu slides down, so if the mouse | |
| 460 // is still actually over the tracking area, we ignore the mouse exit, but | |
| 461 // we set up to check the mouse position again after a delay. | |
| 462 if ([self mouseInsideTrackingRect]) { | |
| 463 [self setupMouseExitCheck]; | |
| 464 return; | |
| 465 } | |
| 466 | |
| 467 if (self.slidingStyle != fullscreen_mac::OMNIBOX_TABS_NONE) | |
| 468 [self scheduleHideForMouse]; | |
| 469 } | |
| 470 } | 347 } |
| 471 | 348 |
| 472 - (void)animationDidStop:(NSAnimation*)animation { | 349 - (void)animationDidStop:(NSAnimation*)animation { |
| 473 // Reset the |currentAnimation_| pointer now that the animation is over. | 350 // Reset the |currentAnimation_| pointer now that the animation is over. |
| 474 currentAnimation_.reset(); | 351 currentAnimation_.reset(); |
| 475 | 352 |
| 476 // Invariant says that the tracking area is not installed while animations are | |
| 477 // in progress. Ensure this is true. | |
| 478 DCHECK(!trackingArea_); | |
| 479 [self removeTrackingAreaIfNecessary]; // For paranoia. | |
| 480 | |
| 481 // Don't automatically set up a new tracking area. When explicitly stopped, | |
| 482 // either another animation is going to start immediately or the state will be | |
| 483 // changed immediately. | |
| 484 if (revealToolbarForTabStripChanges_) { | 353 if (revealToolbarForTabStripChanges_) { |
| 485 if (toolbarFraction_ > 0.0) { | 354 if (toolbarFraction_ > 0.0) { |
| 486 // Set the timer to hide the toolbar. | 355 // Set the timer to hide the toolbar. |
| 487 [hideTimer_ invalidate]; | 356 [hideTimer_ invalidate]; |
| 488 hideTimer_.reset([[NSTimer | 357 hideTimer_.reset([[NSTimer |
| 489 scheduledTimerWithTimeInterval:kDropdownForTabStripChangesDuration | 358 scheduledTimerWithTimeInterval:kDropdownForTabStripChangesDuration |
| 490 target:self | 359 target:self |
| 491 selector:@selector(hideTimerFire:) | 360 selector:@selector(hideTimerFire:) |
| 492 userInfo:nil | 361 userInfo:nil |
| 493 repeats:NO] retain]); | 362 repeats:NO] retain]); |
| 494 } else { | 363 } else { |
| 495 revealToolbarForTabStripChanges_ = NO; | 364 revealToolbarForTabStripChanges_ = NO; |
| 496 } | 365 } |
| 497 } | 366 } |
| 498 } | 367 } |
| 499 | 368 |
| 500 - (void)animationDidEnd:(NSAnimation*)animation { | 369 - (void)animationDidEnd:(NSAnimation*)animation { |
| 501 [self animationDidStop:animation]; | 370 [self animationDidStop:animation]; |
| 502 | |
| 503 // |trackingAreaBounds_| contains the correct tracking area bounds, including | |
| 504 // |any updates that may have come while the animation was running. Install a | |
| 505 // new tracking area with these bounds. | |
| 506 [self setupTrackingArea]; | |
| 507 | |
| 508 // TODO(viettrungluu): Better would be to check during the animation; doing it | |
| 509 // here means that the timing is slightly off. | |
| 510 if (![self mouseInsideTrackingRect]) | |
| 511 [self scheduleHideForMouse]; | |
| 512 } | 371 } |
| 513 | 372 |
| 514 - (void)setMenuBarRevealProgress:(CGFloat)progress { | 373 - (void)setMenuBarRevealProgress:(CGFloat)progress { |
| 374 // If the menubarFraction increases, check if we are in the right screen | |
| 375 // so that the toolbar is not revealed on the wrong screen. | |
| 376 if (![self isMouseOnScreen] && progress > menubarFraction_) | |
| 377 return; | |
| 378 | |
| 515 menubarFraction_ = progress; | 379 menubarFraction_ = progress; |
| 516 | 380 |
| 517 // If an animation is not running, then -layoutSubviews will not be called | 381 // If an animation is not running, then -layoutSubviews will not be called |
| 518 // for each tick of the menu bar reveal. Do that manually. | 382 // for each tick of the menu bar reveal. Do that manually. |
| 519 // TODO(erikchen): The animation is janky. layoutSubviews need a refactor so | 383 // TODO(erikchen): The animation is janky. layoutSubviews need a refactor so |
| 520 // that it calls setFrameOffset: instead of setFrame: if the frame's size has | 384 // that it calls setFrameOffset: instead of setFrame: if the frame's size has |
| 521 // not changed. | 385 // not changed. |
| 522 if (!currentAnimation_.get()) | 386 if (!currentAnimation_.get()) { |
| 387 if (self.slidingStyle != fullscreen_mac::OMNIBOX_TABS_NONE) | |
| 388 toolbarFraction_ = progress; | |
|
erikchen
2016/08/18 19:33:47
I don't understand why we didn't need this before.
spqchan
2016/08/18 19:55:58
Yeah, it was pretty confusing. |toolbarFraction_|
| |
| 523 [browserController_ layoutSubviews]; | 389 [browserController_ layoutSubviews]; |
| 390 } | |
| 524 } | 391 } |
| 525 | 392 |
| 526 @end | 393 @end |
| 527 | 394 |
| 528 @implementation FullscreenToolbarController (PrivateMethods) | 395 @implementation FullscreenToolbarController (PrivateMethods) |
| 529 | 396 |
| 530 - (void)updateMenuBarAndDockVisibility { | 397 - (void)updateMenuBarAndDockVisibility { |
| 531 if (![self isMainWindow] || ![browserController_ isInImmersiveFullscreen]) { | 398 if (![self isMouseOnScreen] || |
| 399 ![browserController_ isInImmersiveFullscreen]) { | |
| 532 [self setSystemFullscreenModeTo:base::mac::kFullScreenModeNormal]; | 400 [self setSystemFullscreenModeTo:base::mac::kFullScreenModeNormal]; |
| 533 return; | 401 return; |
| 534 } | 402 } |
| 535 | 403 |
| 536 // The screen does not have a menu bar, so there's no need to hide it. | 404 // The screen does not have a menu bar, so there's no need to hide it. |
| 537 if (![self doesScreenHaveMenuBar]) { | 405 if (![self doesScreenHaveMenuBar]) { |
| 538 [self setSystemFullscreenModeTo:base::mac::kFullScreenModeHideDock]; | 406 [self setSystemFullscreenModeTo:base::mac::kFullScreenModeHideDock]; |
| 539 return; | 407 return; |
| 540 } | 408 } |
| 541 | 409 |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 583 // Create the animation and set it up. | 451 // Create the animation and set it up. |
| 584 currentAnimation_.reset([[DropdownAnimation alloc] | 452 currentAnimation_.reset([[DropdownAnimation alloc] |
| 585 initWithFraction:fraction | 453 initWithFraction:fraction |
| 586 fullDuration:kDropdownAnimationDuration | 454 fullDuration:kDropdownAnimationDuration |
| 587 animationCurve:NSAnimationEaseOut | 455 animationCurve:NSAnimationEaseOut |
| 588 controller:self]); | 456 controller:self]); |
| 589 DCHECK(currentAnimation_); | 457 DCHECK(currentAnimation_); |
| 590 [currentAnimation_ setAnimationBlockingMode:NSAnimationNonblocking]; | 458 [currentAnimation_ setAnimationBlockingMode:NSAnimationNonblocking]; |
| 591 [currentAnimation_ setDelegate:self]; | 459 [currentAnimation_ setDelegate:self]; |
| 592 | 460 |
| 593 // If there is an existing tracking area, remove it. We do not track mouse | |
| 594 // movements during animations (see class comment in the header file). | |
| 595 [self removeTrackingAreaIfNecessary]; | |
| 596 | |
| 597 [currentAnimation_ startAnimation]; | 461 [currentAnimation_ startAnimation]; |
| 598 } | 462 } |
| 599 | 463 |
| 600 - (void)scheduleShowForMouse { | |
| 601 [browserController_ lockBarVisibilityForOwner:self | |
| 602 withAnimation:YES | |
| 603 delay:YES]; | |
| 604 } | |
| 605 | |
| 606 - (void)scheduleHideForMouse { | |
| 607 [browserController_ releaseBarVisibilityForOwner:self | |
| 608 withAnimation:YES | |
| 609 delay:YES]; | |
| 610 } | |
| 611 | |
| 612 - (void)setupTrackingArea { | |
| 613 if (trackingArea_) { | |
| 614 // If the tracking rectangle is already |trackingAreaBounds_|, quit early. | |
| 615 NSRect oldRect = [trackingArea_ rect]; | |
| 616 if (NSEqualRects(trackingAreaBounds_, oldRect)) | |
| 617 return; | |
| 618 | |
| 619 // Otherwise, remove it. | |
| 620 [self removeTrackingAreaIfNecessary]; | |
| 621 } | |
| 622 | |
| 623 // Create and add a new tracking area for |frame|. | |
| 624 trackingArea_.reset([[CrTrackingArea alloc] | |
| 625 initWithRect:trackingAreaBounds_ | |
| 626 options:NSTrackingMouseEnteredAndExited | NSTrackingActiveInKeyWindow | |
| 627 owner:self | |
| 628 userInfo:nil]); | |
| 629 DCHECK(contentView_); | |
| 630 [contentView_ addTrackingArea:trackingArea_]; | |
| 631 } | |
| 632 | |
| 633 - (void)removeTrackingAreaIfNecessary { | |
| 634 if (trackingArea_) { | |
| 635 DCHECK(contentView_); // |contentView_| better be valid. | |
| 636 [contentView_ removeTrackingArea:trackingArea_]; | |
| 637 trackingArea_.reset(); | |
| 638 } | |
| 639 } | |
| 640 | |
| 641 - (BOOL)mouseInsideTrackingRect { | |
| 642 NSWindow* window = [browserController_ window]; | |
| 643 NSPoint mouseLoc = [window mouseLocationOutsideOfEventStream]; | |
| 644 NSPoint mousePos = [contentView_ convertPoint:mouseLoc fromView:nil]; | |
| 645 return NSMouseInRect(mousePos, trackingAreaBounds_, [contentView_ isFlipped]); | |
| 646 } | |
| 647 | |
| 648 - (void)setupMouseExitCheck { | |
| 649 [self performSelector:@selector(checkForMouseExit) | |
| 650 withObject:nil | |
| 651 afterDelay:kMouseExitCheckDelay]; | |
| 652 } | |
| 653 | |
| 654 - (void)cancelMouseExitCheck { | |
| 655 [NSObject cancelPreviousPerformRequestsWithTarget:self | |
| 656 selector:@selector(checkForMouseExit) | |
| 657 object:nil]; | |
| 658 } | |
| 659 | |
| 660 - (void)checkForMouseExit { | |
| 661 if ([self mouseInsideTrackingRect]) | |
| 662 [self setupMouseExitCheck]; | |
| 663 else | |
| 664 [self scheduleHideForMouse]; | |
| 665 } | |
| 666 | |
| 667 - (void)startShowTimer { | |
| 668 // If there's already a show timer going, just keep it. | |
| 669 if (showTimer_) { | |
| 670 DCHECK([showTimer_ isValid]); | |
| 671 DCHECK(!hideTimer_); | |
| 672 return; | |
| 673 } | |
| 674 | |
| 675 // Cancel the hide timer (if necessary) and set up the new show timer. | |
| 676 [self cancelHideTimer]; | |
| 677 showTimer_.reset( | |
| 678 [[NSTimer scheduledTimerWithTimeInterval:kDropdownShowDelay | |
| 679 target:self | |
| 680 selector:@selector(showTimerFire:) | |
| 681 userInfo:nil | |
| 682 repeats:NO] retain]); | |
| 683 DCHECK([showTimer_ isValid]); // This also checks that |showTimer_ != nil|. | |
| 684 } | |
| 685 | |
| 686 - (void)startHideTimer { | |
| 687 // If there's already a hide timer going, just keep it. | |
| 688 if (hideTimer_) { | |
| 689 DCHECK([hideTimer_ isValid]); | |
| 690 DCHECK(!showTimer_); | |
| 691 return; | |
| 692 } | |
| 693 | |
| 694 // Cancel the show timer (if necessary) and set up the new hide timer. | |
| 695 [self cancelShowTimer]; | |
| 696 hideTimer_.reset( | |
| 697 [[NSTimer scheduledTimerWithTimeInterval:kDropdownHideDelay | |
| 698 target:self | |
| 699 selector:@selector(hideTimerFire:) | |
| 700 userInfo:nil | |
| 701 repeats:NO] retain]); | |
| 702 DCHECK([hideTimer_ isValid]); // This also checks that |hideTimer_ != nil|. | |
| 703 } | |
| 704 | |
| 705 - (void)cancelShowTimer { | |
| 706 [showTimer_ invalidate]; | |
| 707 showTimer_.reset(); | |
| 708 } | |
| 709 | |
| 710 - (void)cancelHideTimer { | 464 - (void)cancelHideTimer { |
| 711 [hideTimer_ invalidate]; | 465 [hideTimer_ invalidate]; |
| 712 hideTimer_.reset(); | 466 hideTimer_.reset(); |
| 713 } | 467 } |
| 714 | 468 |
| 715 - (void)cancelAllTimers { | |
| 716 [self cancelShowTimer]; | |
| 717 [self cancelHideTimer]; | |
| 718 } | |
| 719 | |
| 720 - (void)showTimerFire:(NSTimer*)timer { | |
| 721 DCHECK_EQ(showTimer_, timer); // This better be our show timer. | |
| 722 [showTimer_ invalidate]; // Make sure it doesn't repeat. | |
| 723 showTimer_.reset(); // And get rid of it. | |
| 724 [self changeOverlayToFraction:1 withAnimation:YES]; | |
| 725 } | |
| 726 | |
| 727 - (void)hideTimerFire:(NSTimer*)timer { | 469 - (void)hideTimerFire:(NSTimer*)timer { |
| 728 DCHECK_EQ(hideTimer_, timer); // This better be our hide timer. | 470 DCHECK_EQ(hideTimer_, timer); // This better be our hide timer. |
| 729 [hideTimer_ invalidate]; // Make sure it doesn't repeat. | 471 [hideTimer_ invalidate]; // Make sure it doesn't repeat. |
| 730 hideTimer_.reset(); // And get rid of it. | 472 hideTimer_.reset(); // And get rid of it. |
| 731 [self changeOverlayToFraction:0 withAnimation:YES]; | 473 [self changeOverlayToFraction:0 withAnimation:YES]; |
| 732 } | 474 } |
| 733 | 475 |
| 734 - (void)cleanup { | 476 - (void)cleanup { |
| 735 [self cancelMouseExitCheck]; | 477 [self cancelAnimationAndTimer]; |
| 736 [self cancelAnimationAndTimers]; | |
| 737 [[NSNotificationCenter defaultCenter] removeObserver:self]; | 478 [[NSNotificationCenter defaultCenter] removeObserver:self]; |
| 738 | 479 |
| 739 [self removeTrackingAreaIfNecessary]; | |
| 740 contentView_ = nil; | |
| 741 | |
| 742 // This isn't tracked when not in fullscreen mode. | 480 // This isn't tracked when not in fullscreen mode. |
| 743 [browserController_ releaseBarVisibilityForOwner:self | 481 [browserController_ releaseBarVisibilityForOwner:self withAnimation:NO]; |
| 744 withAnimation:NO | |
| 745 delay:NO]; | |
| 746 | 482 |
| 747 // Call the main status resignation code to perform the associated cleanup, | 483 // Call the main status resignation code to perform the associated cleanup, |
| 748 // since we will no longer be receiving actual status resignation | 484 // since we will no longer be receiving actual status resignation |
| 749 // notifications. | 485 // notifications. |
| 750 [self setSystemFullscreenModeTo:base::mac::kFullScreenModeNormal]; | 486 [self setSystemFullscreenModeTo:base::mac::kFullScreenModeNormal]; |
| 751 | 487 |
| 752 // No more calls back up to the BWC. | 488 // No more calls back up to the BWC. |
| 753 browserController_ = nil; | 489 browserController_ = nil; |
| 754 } | 490 } |
| 755 | 491 |
| 756 - (void)showActiveWindowUI { | 492 - (void)showActiveWindowUI { |
| 757 [self updateMenuBarAndDockVisibility]; | 493 [self updateMenuBarAndDockVisibility]; |
| 758 | |
| 759 // TODO(rohitrao): Insert the Exit Fullscreen button. http://crbug.com/35956 | |
| 760 } | 494 } |
| 761 | 495 |
| 762 - (void)hideActiveWindowUI { | 496 - (void)hideActiveWindowUI { |
| 763 [self updateMenuBarAndDockVisibility]; | 497 [self updateMenuBarAndDockVisibility]; |
| 764 | |
| 765 // TODO(rohitrao): Remove the Exit Fullscreen button. http://crbug.com/35956 | |
| 766 } | 498 } |
| 767 | 499 |
| 768 - (BOOL)shouldShowMenubarInImmersiveFullscreen { | 500 - (BOOL)shouldShowMenubarInImmersiveFullscreen { |
| 769 return [self doesScreenHaveMenuBar] && toolbarFraction_ > 0.99; | 501 return [self doesScreenHaveMenuBar] && toolbarFraction_ > 0.99; |
| 770 } | 502 } |
| 771 | 503 |
| 772 @end | 504 @end |
| OLD | NEW |