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

Side by Side Diff: chrome/browser/ui/cocoa/fullscreen_toolbar_controller.mm

Issue 2256993002: [Mac] Reworked FullscreenToolbarController (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix for erikchen Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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 [self changeOverlayToFraction:1 withAnimation:animate];
335 [self startShowTimer];
336 } 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];
344 }
345 } 263 }
346 264
347 - (void)ensureOverlayHiddenWithAnimation:(BOOL)animate delay:(BOOL)delay { 265 - (void)ensureOverlayHiddenWithAnimation:(BOOL)animate {
348 if (!inFullscreenMode_) 266 if (!inFullscreenMode_)
349 return; 267 return;
350 268
351 if (self.slidingStyle == fullscreen_mac::OMNIBOX_TABS_PRESENT) 269 if (self.slidingStyle == fullscreen_mac::OMNIBOX_TABS_PRESENT)
352 return; 270 return;
353 271
354 if (animate) { 272 [self cancelHideTimer];
355 if (delay) { 273 [self changeOverlayToFraction:0 withAnimation:animate];
356 [self startHideTimer];
357 } 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];
365 }
366 } 274 }
367 275
368 - (void)cancelAnimationAndTimers { 276 - (void)cancelAnimationAndTimer {
369 [self cancelAllTimers]; 277 [self cancelHideTimer];
370 [currentAnimation_ stopAnimation]; 278 [currentAnimation_ stopAnimation];
371 currentAnimation_.reset(); 279 currentAnimation_.reset();
372 } 280 }
373 281
374 - (void)revealToolbarForTabStripChanges { 282 - (void)revealToolbarForTabStripChanges {
375 if (!base::CommandLine::ForCurrentProcess()->HasSwitch( 283 if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
376 switches::kEnableFullscreenToolbarReveal)) { 284 switches::kEnableFullscreenToolbarReveal)) {
377 return; 285 return;
378 } 286 }
379 287
380 revealToolbarForTabStripChanges_ = YES; 288 revealToolbarForTabStripChanges_ = YES;
381 [self ensureOverlayShownWithAnimation:YES delay:NO]; 289 [self ensureOverlayShownWithAnimation:YES];
382 } 290 }
383 291
384 - (void)setSystemFullscreenModeTo:(base::mac::FullScreenMode)mode { 292 - (void)setSystemFullscreenModeTo:(base::mac::FullScreenMode)mode {
385 if (mode == systemFullscreenMode_) 293 if (mode == systemFullscreenMode_)
386 return; 294 return;
387 if (systemFullscreenMode_ == base::mac::kFullScreenModeNormal) 295 if (systemFullscreenMode_ == base::mac::kFullScreenModeNormal)
388 base::mac::RequestFullScreen(mode); 296 base::mac::RequestFullScreen(mode);
389 else if (mode == base::mac::kFullScreenModeNormal) 297 else if (mode == base::mac::kFullScreenModeNormal)
390 base::mac::ReleaseFullScreen(systemFullscreenMode_); 298 base::mac::ReleaseFullScreen(systemFullscreenMode_);
391 else 299 else
(...skipping 28 matching lines...) Expand all
420 328
421 return [self shouldShowMenubarInImmersiveFullscreen] 329 return [self shouldShowMenubarInImmersiveFullscreen]
422 ? -[self floatingBarVerticalOffset] 330 ? -[self floatingBarVerticalOffset]
423 : 0; 331 : 0;
424 } 332 }
425 333
426 - (BOOL)isFullscreenTransitionInProgress { 334 - (BOOL)isFullscreenTransitionInProgress {
427 return [browserController_ isFullscreenTransitionInProgress]; 335 return [browserController_ isFullscreenTransitionInProgress];
428 } 336 }
429 337
430 - (BOOL)isMainWindow { 338 - (BOOL)isMouseOnScreen {
431 return [browserController_ window].isMainWindow; 339 return NSMouseInRect([NSEvent mouseLocation],
432 } 340 [[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 } 341 }
471 342
472 - (void)animationDidStop:(NSAnimation*)animation { 343 - (void)animationDidStop:(NSAnimation*)animation {
473 // Reset the |currentAnimation_| pointer now that the animation is over. 344 // Reset the |currentAnimation_| pointer now that the animation is over.
474 currentAnimation_.reset(); 345 currentAnimation_.reset();
475 346
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_) { 347 if (revealToolbarForTabStripChanges_) {
485 if (toolbarFraction_ > 0.0) { 348 if (toolbarFraction_ > 0.0) {
486 // Set the timer to hide the toolbar. 349 // Set the timer to hide the toolbar.
487 [hideTimer_ invalidate]; 350 [hideTimer_ invalidate];
488 hideTimer_.reset([[NSTimer 351 hideTimer_.reset([[NSTimer
489 scheduledTimerWithTimeInterval:kDropdownForTabStripChangesDuration 352 scheduledTimerWithTimeInterval:kDropdownForTabStripChangesDuration
490 target:self 353 target:self
491 selector:@selector(hideTimerFire:) 354 selector:@selector(hideTimerFire:)
492 userInfo:nil 355 userInfo:nil
493 repeats:NO] retain]); 356 repeats:NO] retain]);
494 } else { 357 } else {
495 revealToolbarForTabStripChanges_ = NO; 358 revealToolbarForTabStripChanges_ = NO;
496 } 359 }
497 } 360 }
498 } 361 }
499 362
500 - (void)animationDidEnd:(NSAnimation*)animation { 363 - (void)animationDidEnd:(NSAnimation*)animation {
501 [self animationDidStop:animation]; 364 [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 } 365 }
513 366
514 - (void)setMenuBarRevealProgress:(CGFloat)progress { 367 - (void)setMenuBarRevealProgress:(CGFloat)progress {
368 // If the menubarFraction increases, check if we are in the right screen
369 // so that the toolbar is not revealed on the wrong screen.
370 if (![self isMouseOnScreen] && progress > menubarFraction_)
371 return;
372
515 menubarFraction_ = progress; 373 menubarFraction_ = progress;
516 374
517 // If an animation is not running, then -layoutSubviews will not be called 375 // If an animation is not running, then -layoutSubviews will not be called
518 // for each tick of the menu bar reveal. Do that manually. 376 // for each tick of the menu bar reveal. Do that manually.
519 // TODO(erikchen): The animation is janky. layoutSubviews need a refactor so 377 // 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 378 // that it calls setFrameOffset: instead of setFrame: if the frame's size has
521 // not changed. 379 // not changed.
522 if (!currentAnimation_.get()) 380 if (!currentAnimation_.get()) {
381 if (self.slidingStyle != fullscreen_mac::OMNIBOX_TABS_NONE)
382 toolbarFraction_ = progress;
523 [browserController_ layoutSubviews]; 383 [browserController_ layoutSubviews];
384 }
524 } 385 }
525 386
526 @end 387 @end
527 388
528 @implementation FullscreenToolbarController (PrivateMethods) 389 @implementation FullscreenToolbarController (PrivateMethods)
529 390
530 - (void)updateMenuBarAndDockVisibility { 391 - (void)updateMenuBarAndDockVisibility {
531 if (![self isMainWindow] || ![browserController_ isInImmersiveFullscreen]) { 392 if (![self isMouseOnScreen] ||
393 ![browserController_ isInImmersiveFullscreen]) {
532 [self setSystemFullscreenModeTo:base::mac::kFullScreenModeNormal]; 394 [self setSystemFullscreenModeTo:base::mac::kFullScreenModeNormal];
533 return; 395 return;
534 } 396 }
535 397
536 // The screen does not have a menu bar, so there's no need to hide it. 398 // The screen does not have a menu bar, so there's no need to hide it.
537 if (![self doesScreenHaveMenuBar]) { 399 if (![self doesScreenHaveMenuBar]) {
538 [self setSystemFullscreenModeTo:base::mac::kFullScreenModeHideDock]; 400 [self setSystemFullscreenModeTo:base::mac::kFullScreenModeHideDock];
539 return; 401 return;
540 } 402 }
541 403
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
583 // Create the animation and set it up. 445 // Create the animation and set it up.
584 currentAnimation_.reset([[DropdownAnimation alloc] 446 currentAnimation_.reset([[DropdownAnimation alloc]
585 initWithFraction:fraction 447 initWithFraction:fraction
586 fullDuration:kDropdownAnimationDuration 448 fullDuration:kDropdownAnimationDuration
587 animationCurve:NSAnimationEaseOut 449 animationCurve:NSAnimationEaseOut
588 controller:self]); 450 controller:self]);
589 DCHECK(currentAnimation_); 451 DCHECK(currentAnimation_);
590 [currentAnimation_ setAnimationBlockingMode:NSAnimationNonblocking]; 452 [currentAnimation_ setAnimationBlockingMode:NSAnimationNonblocking];
591 [currentAnimation_ setDelegate:self]; 453 [currentAnimation_ setDelegate:self];
592 454
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]; 455 [currentAnimation_ startAnimation];
598 } 456 }
599 457
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 { 458 - (void)cancelHideTimer {
711 [hideTimer_ invalidate]; 459 [hideTimer_ invalidate];
712 hideTimer_.reset(); 460 hideTimer_.reset();
713 } 461 }
714 462
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 { 463 - (void)hideTimerFire:(NSTimer*)timer {
728 DCHECK_EQ(hideTimer_, timer); // This better be our hide timer. 464 DCHECK_EQ(hideTimer_, timer); // This better be our hide timer.
729 [hideTimer_ invalidate]; // Make sure it doesn't repeat. 465 [hideTimer_ invalidate]; // Make sure it doesn't repeat.
730 hideTimer_.reset(); // And get rid of it. 466 hideTimer_.reset(); // And get rid of it.
731 [self changeOverlayToFraction:0 withAnimation:YES]; 467 [self changeOverlayToFraction:0 withAnimation:YES];
732 } 468 }
733 469
734 - (void)cleanup { 470 - (void)cleanup {
735 [self cancelMouseExitCheck]; 471 [self cancelAnimationAndTimer];
736 [self cancelAnimationAndTimers];
737 [[NSNotificationCenter defaultCenter] removeObserver:self]; 472 [[NSNotificationCenter defaultCenter] removeObserver:self];
738 473
739 [self removeTrackingAreaIfNecessary];
740 contentView_ = nil;
741
742 // This isn't tracked when not in fullscreen mode. 474 // This isn't tracked when not in fullscreen mode.
743 [browserController_ releaseBarVisibilityForOwner:self 475 [browserController_ releaseBarVisibilityForOwner:self withAnimation:NO];
744 withAnimation:NO
745 delay:NO];
746 476
747 // Call the main status resignation code to perform the associated cleanup, 477 // Call the main status resignation code to perform the associated cleanup,
748 // since we will no longer be receiving actual status resignation 478 // since we will no longer be receiving actual status resignation
749 // notifications. 479 // notifications.
750 [self setSystemFullscreenModeTo:base::mac::kFullScreenModeNormal]; 480 [self setSystemFullscreenModeTo:base::mac::kFullScreenModeNormal];
751 481
752 // No more calls back up to the BWC. 482 // No more calls back up to the BWC.
753 browserController_ = nil; 483 browserController_ = nil;
754 } 484 }
755 485
756 - (void)showActiveWindowUI { 486 - (void)showActiveWindowUI {
757 [self updateMenuBarAndDockVisibility]; 487 [self updateMenuBarAndDockVisibility];
758
759 // TODO(rohitrao): Insert the Exit Fullscreen button. http://crbug.com/35956
760 } 488 }
761 489
762 - (void)hideActiveWindowUI { 490 - (void)hideActiveWindowUI {
763 [self updateMenuBarAndDockVisibility]; 491 [self updateMenuBarAndDockVisibility];
764
765 // TODO(rohitrao): Remove the Exit Fullscreen button. http://crbug.com/35956
766 } 492 }
767 493
768 - (BOOL)shouldShowMenubarInImmersiveFullscreen { 494 - (BOOL)shouldShowMenubarInImmersiveFullscreen {
769 return [self doesScreenHaveMenuBar] && toolbarFraction_ > 0.99; 495 return [self doesScreenHaveMenuBar] && toolbarFraction_ > 0.99;
770 } 496 }
771 497
772 @end 498 @end
OLDNEW
« no previous file with comments | « chrome/browser/ui/cocoa/fullscreen_toolbar_controller.h ('k') | chrome/browser/ui/cocoa/global_error_bubble_controller.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698