Commit e776f9c0 authored by spqchan's avatar spqchan Committed by Commit bot

[Mac] Fix for fullscreen toolbar

Added back mouse tracking to fix an edge case where the menu
bar disappears when but the mouse is still hovering the toolbar.

The tracking area is only used to keep the toolbar active when this
happens. The toolbar will hide when the mouse leaves the tracking
area.

BUG=639562

Review-Url: https://codereview.chromium.org/2272783002
Cr-Commit-Position: refs/heads/master@{#414888}
parent f8c26a79
......@@ -565,12 +565,14 @@ class Command;
// Query/lock/release the requirement that the tab strip/toolbar/attached
// bookmark bar bar cluster is visible (e.g., when one of its elements has
// focus). This is required for the floating bar in presentation mode, but
// should also be called when not in presentation mode; see the comments for
// focus). This is required for the floating bar if it's hidden in fullscreen,
// but should also be called when not in fullscreen mode; see the comments for
// |barVisibilityLocks_| for more details. Double locks/releases by the same
// owner are ignored. If |animate:| is YES, then an animation may be
// performed. In the case of multiple calls, later calls have precedence with
// the rule that |animate:NO| has precedence over |animate:YES|.
// the rule that |animate:NO| has precedence over |animate:YES|. If |owner| is
// nil in isBarVisibilityLockedForOwner, the method returns YES if there are
// any locks.
- (BOOL)isBarVisibilityLockedForOwner:(id)owner;
- (void)lockBarVisibilityForOwner:(id)owner withAnimation:(BOOL)animate;
- (void)releaseBarVisibilityForOwner:(id)owner withAnimation:(BOOL)animate;
......
......@@ -1979,9 +1979,9 @@ willAnimateFromState:(BookmarkBar::State)oldState
}
- (BOOL)isBarVisibilityLockedForOwner:(id)owner {
DCHECK(owner);
DCHECK(barVisibilityLocks_);
return [barVisibilityLocks_ containsObject:owner];
return owner ? [barVisibilityLocks_ containsObject:owner]
: [barVisibilityLocks_ count];
}
- (void)lockBarVisibilityForOwner:(id)owner withAnimation:(BOOL)animate {
......
......@@ -761,7 +761,6 @@ IN_PROC_BROWSER_TEST_F(BrowserWindowControllerTest,
// Toggle the visibility of the fullscreen toolbar. Verify that the toolbar
// is hidden and the preference is correctly updated.
[[controller() fullscreenToolbarController] setToolbarFraction:0.0];
[[controller() fullscreenToolbarController] setMenuBarRevealProgress:0.0];
chrome::ExecuteCommand(browser(), IDC_TOGGLE_FULLSCREEN_TOOLBAR);
EXPECT_FALSE(prefs->GetBoolean(prefs::kShowFullscreenToolbar));
......
......@@ -454,14 +454,9 @@ willPositionSheet:(NSWindow*)sheet
}
- (void)configureFullscreenToolbarController {
BOOL fullscreenForTab = [self isFullscreenForTabContentOrExtension];
BOOL kioskMode =
base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kKioskMode);
BOOL showDropdown =
!fullscreenForTab && !kioskMode && ([self floatingBarHasFocus]);
NSView* contentView = [[self window] contentView];
[fullscreenToolbarController_
setupFullscreenToolbarWithDropdown:showDropdown];
setupFullscreenToolbarForContentView:contentView];
}
- (void)adjustUIForExitingFullscreenAndStopOmniboxSliding {
......@@ -474,6 +469,10 @@ willPositionSheet:(NSWindow*)sheet
}
- (void)adjustUIForSlidingFullscreenStyle:(fullscreen_mac::SlidingStyle)style {
// The UI should only be adjusted in fullscreen mode.
if (![self isInAnyFullscreenMode])
return;
if (!fullscreenToolbarController_) {
fullscreenToolbarController_.reset(
[self newFullscreenToolbarControllerWithStyle:style]);
......@@ -1009,8 +1008,11 @@ willPositionSheet:(NSWindow*)sheet
[self layoutTabContentArea:output.contentAreaFrame];
if (!NSIsEmptyRect(output.fullscreenBackingBarFrame))
if (!NSIsEmptyRect(output.fullscreenBackingBarFrame)) {
[floatingBarBackingView_ setFrame:output.fullscreenBackingBarFrame];
[fullscreenToolbarController_
setTrackingAreaFromOverlayFrame:output.fullscreenBackingBarFrame];
}
[findBarCocoaController_
positionFindBarViewAtMaxY:output.findBarMaxY
......
......@@ -168,17 +168,8 @@ const CGFloat kLocationBarRightOffset = 35;
CGFloat yOffset = 0;
if (parameters_.inAnyFullscreen) {
yOffset += parameters_.menubarOffset;
switch (parameters_.slidingStyle) {
case fullscreen_mac::OMNIBOX_TABS_PRESENT:
break;
case fullscreen_mac::OMNIBOX_TABS_NONE:
case fullscreen_mac::OMNIBOX_TABS_HIDDEN:
// In presentation mode, |yOffset| accounts for the sliding position of
// the floating bar and the extra offset needed to dodge the menu bar.
yOffset += std::floor((1 - parameters_.toolbarFraction) *
[self fullscreenBackingBarHeight]);
break;
}
yOffset += std::floor((1 - parameters_.toolbarFraction) *
[self fullscreenBackingBarHeight]);
}
fullscreenYOffset_ = yOffset;
}
......
......@@ -47,7 +47,7 @@ class BrowserWindowLayoutTest : public testing::Test {
[layout setInAnyFullscreen:YES];
[layout setFullscreenSlidingStyle:fullscreen_mac::OMNIBOX_TABS_PRESENT];
[layout setFullscreenMenubarOffset:0];
[layout setFullscreenToolbarFraction:0];
[layout setFullscreenToolbarFraction:1];
[layout setFullscreenButtonFrame:NSZeroRect];
}
......
......@@ -12,6 +12,7 @@
#include "chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h"
@class BrowserWindowController;
@class CrTrackingArea;
@class DropdownAnimation;
namespace fullscreen_mac {
......@@ -25,16 +26,12 @@ enum SlidingStyle {
// Provides a controller to fullscreen toolbar for a single browser
// window. This class handles running animations, showing and hiding the
// floating dropdown bar, and managing the tracking area associated with the
// dropdown. This class does not directly manage any views -- the
// fullscreen toolbar, and managing the tracking area associated with the
// toolbar. This class does not directly manage any views -- the
// BrowserWindowController is responsible for positioning and z-ordering views.
//
// Tracking areas are disabled while animations are running. If
// |overlayFrameChanged:| is called while an animation is running, the
// controller saves the new frame and installs the appropriate tracking area
// when the animation finishes. This is largely done for ease of
// implementation; it is easier to check the mouse location at each animation
// step than it is to manage a constantly-changing tracking area.
// TODO (spqchan): Write tests for this class. See crbug.com/640064.
@interface FullscreenToolbarController : NSObject<NSAnimationDelegate> {
@private
// Our parent controller.
......@@ -43,6 +40,18 @@ enum SlidingStyle {
// Whether or not we are in fullscreen mode.
BOOL inFullscreenMode_;
// The content view for the window. This is nil when not in fullscreen mode.
NSView* contentView_; // weak
// The frame for the tracking area. The value is the toolbar overlay's frame
// with additional height added at the bottom.
NSRect trackingAreaFrame_;
// The tracking area associated with the toolbar overlay bar. This tracking
// area is used to keep the toolbar active if the menubar had animated out
// but the mouse is still on the toolbar.
base::scoped_nsobject<CrTrackingArea> trackingArea_;
// Pointer to the currently running animation. Is nil if no animation is
// running.
base::scoped_nsobject<DropdownAnimation> currentAnimation_;
......@@ -69,32 +78,36 @@ enum SlidingStyle {
// Only used in AppKit Fullscreen.
CGFloat menubarFraction_;
// The fraction of the omnibox/tabstrip that is showing. Ranges from 0 to 1.
// Used in both AppKit and Immersive Fullscreen.
CGFloat toolbarFraction_;
// The toolbar fraction set by the menu progress.
CGFloat toolbarFractionFromMenuProgress_;
// A Carbon event handler that tracks the revealed fraction of the menu bar.
EventHandlerRef menuBarTrackingHandler_;
// True when the toolbar is dropped to show tabstrip changes.
BOOL revealToolbarForTabStripChanges_;
BOOL isRevealingToolbarForTabStripChanges_;
// True when the toolbar should be animated back out via a DropdownAnimation.
// This is set and unset in hideTimer:. It's set to YES before it calls
// animateToolbarVisibility: and then set to NO after the animation has
// started.
BOOL shouldAnimateToolbarOut_;
}
@property(nonatomic, assign) fullscreen_mac::SlidingStyle slidingStyle;
@property(nonatomic, assign) CGFloat toolbarFraction;
// Designated initializer.
- (id)initWithBrowserController:(BrowserWindowController*)controller
style:(fullscreen_mac::SlidingStyle)style;
// Informs the controller that the browser has entered or exited presentation
// Informs the controller that the browser has entered or exited fullscreen
// mode. |-setupFullscreenToolbarForContentView:showDropdown:| should be called
// after the window is setup, just before it is shown. |-exitFullscreenMode|
// should be called before any views are moved back to the non-fullscreen
// window. If |-setupFullscreenToolbarForContentView:showDropdown:| is called,
// it must be balanced with a call to |-exitFullscreenMode| before the
// controller is released.
- (void)setupFullscreenToolbarWithDropdown:(BOOL)showDropdown;
- (void)setupFullscreenToolbarForContentView:(NSView*)contentView;
- (void)exitFullscreenMode;
// Returns the amount by which the floating bar should be offset downwards (to
......@@ -119,15 +132,30 @@ enum SlidingStyle {
// Ranges from 0 to -22.
- (CGFloat)menubarOffset;
// Returns the fraction of the toolbar exposed at the top.
// It returns 1.0 if the toolbar is fully shown and 0.0 if the toolbar is
// hidden. Otherwise, if the toolbar is in progress of animating, it will
// return a float that ranges from (0, 1).
- (CGFloat)toolbarFraction;
// Returns YES if the mouse is on the window's screen. This is used to check
// if the menubar events belong to window's screen since the menubar would
// only be revealed if the mouse is there.
- (BOOL)isMouseOnScreen;
// Returns true if the browser is in the process of entering/exiting
// Sets |trackingAreaFrame_| from the given overlay frame.
- (void)setTrackingAreaFromOverlayFrame:(NSRect)frame;
// Returns YES if the browser is in the process of entering/exiting
// fullscreen.
- (BOOL)isFullscreenTransitionInProgress;
// Returns YES if the browser in in fullscreen.
- (BOOL)isInFullscreen;
// Updates the toolbar by updating the layout, menubar and dock.
- (void)updateToolbar;
@end
// Private methods exposed for testing.
......@@ -138,11 +166,6 @@ enum SlidingStyle {
// Callback for menu bar animations.
- (void)setMenuBarRevealProgress:(CGFloat)progress;
// Updates the local state that reflects the fraction of the toolbar area that
// is showing. This function has the side effect of changing the AppKit
// Fullscreen option for whether the menu bar is shown.
- (void)changeToolbarFraction:(CGFloat)fraction;
@end
#endif // CHROME_BROWSER_UI_COCOA_FULLSCREEN_TOOLBAR_CONTROLLER_H_
......@@ -13,15 +13,24 @@
#include "chrome/common/chrome_switches.h"
#import "third_party/google_toolbox_for_mac/src/AppKit/GTMNSAnimation+Duration.h"
#import "ui/base/cocoa/nsview_additions.h"
#import "ui/base/cocoa/tracking_area.h"
namespace {
// The activation zone for the main menu is 4 pixels high; if we make it any
// smaller, then the menu can be made to appear without the bar sliding down.
const NSTimeInterval kDropdownAnimationDuration = 0.12;
// The duration of the toolbar show/hide animation.
const NSTimeInterval kDropdownAnimationDuration = 0.20;
// The duration the toolbar is revealed for tab strip changes.
const NSTimeInterval kDropdownForTabStripChangesDuration = 0.75;
// If the fullscreen toolbar is hidden, it is difficult for the user to see
// changes in the tabstrip. As a result, if a tab is inserted or the current
// tab switched to a new one, the toolbar must animate in and out to display
// the tabstrip changes to the user. The animation drops down the toolbar and
// then wait for 0.75 seconds before it hides the toolbar.
const NSTimeInterval kTabStripChangesDelay = 0.75;
// Additional height threshold added at the toolbar's bottom. This is to mimic
// threshold the mouse position needs to be at before the menubar automatically
// hides.
const CGFloat kTrackingAreaAdditionalThreshold = 20;
// The event kind value for a undocumented menubar show/hide Carbon event.
const CGFloat kMenuBarRevealEventKind = 2004;
......@@ -31,6 +40,15 @@ const CGFloat kMenuBarRevealEventKind = 2004;
// returns 0 when the menu bar is hidden.)
const CGFloat kFloatingBarVerticalOffset = 22;
// Visibility fractions for the menubar and toolbar.
const CGFloat kHideFraction = 0.0;
const CGFloat kShowFraction = 1.0;
// Helper function for comparing CGFloat values.
BOOL IsCGFloatEqual(CGFloat a, CGFloat b) {
return fabs(a - b) <= std::numeric_limits<CGFloat>::epsilon();
}
OSStatus MenuBarRevealHandler(EventHandlerCallRef handler,
EventRef event,
void* context) {
......@@ -44,17 +62,17 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler,
// As such, we should ignore the kMenuBarRevealEventKind event if it gives
// us a fraction of 0.0 or 1.0, and rely on kEventMenuBarShown and
// kEventMenuBarHidden to set these values.
if (![self isFullscreenTransitionInProgress]) {
if (![self isFullscreenTransitionInProgress] && [self isInFullscreen]) {
if (GetEventKind(event) == kMenuBarRevealEventKind) {
CGFloat revealFraction = 0;
GetEventParameter(event, FOUR_CHAR_CODE('rvlf'), typeCGFloat, NULL,
sizeof(CGFloat), NULL, &revealFraction);
if (revealFraction > 0.0 && revealFraction < 1.0)
if (revealFraction > kHideFraction && revealFraction < kShowFraction)
[self setMenuBarRevealProgress:revealFraction];
} else if (GetEventKind(event) == kEventMenuBarShown) {
[self setMenuBarRevealProgress:1.0];
[self setMenuBarRevealProgress:kShowFraction];
} else {
[self setMenuBarRevealProgress:0.0];
[self setMenuBarRevealProgress:kHideFraction];
}
}
......@@ -71,10 +89,11 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler,
FullscreenToolbarController* controller_;
CGFloat startFraction_;
CGFloat endFraction_;
CGFloat toolbarFraction_;
}
@property(readonly, nonatomic) CGFloat startFraction;
@property(readonly, nonatomic) CGFloat endFraction;
@property(readonly, nonatomic) CGFloat toolbarFraction;
// Designated initializer. Asks |controller| for the current shown fraction, so
// if the bar is already partially shown or partially hidden, the animation
......@@ -88,8 +107,8 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler,
@implementation DropdownAnimation
@synthesize startFraction = startFraction_;
@synthesize endFraction = endFraction_;
@synthesize toolbarFraction = toolbarFraction_;
- (id)initWithFraction:(CGFloat)toFraction
fullDuration:(CGFloat)fullDuration
......@@ -97,7 +116,7 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler,
controller:(FullscreenToolbarController*)controller {
// Calculate the effective duration, based on the current shown fraction.
DCHECK(controller);
CGFloat fromFraction = controller.toolbarFraction;
CGFloat fromFraction = [controller toolbarFraction];
CGFloat effectiveDuration = fabs(fullDuration * (fromFraction - toFraction));
if ((self = [super gtm_initWithDuration:effectiveDuration
......@@ -113,9 +132,9 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler,
// Called once per animation step. Overridden to change the floating bar's
// position based on the animation's progress.
- (void)setCurrentProgress:(NSAnimationProgress)progress {
CGFloat fraction =
toolbarFraction_ =
startFraction_ + (progress * (endFraction_ - startFraction_));
[controller_ changeToolbarFraction:fraction];
[controller_ updateToolbar];
}
@end
......@@ -125,6 +144,13 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler,
// Updates the visibility of the menu bar and the dock.
- (void)updateMenuBarAndDockVisibility;
// Methods to set up or remove the tracking area.
- (void)setupTrackingArea;
- (void)removeTrackingAreaIfNecessary;
// Returns YES if the mouse is inside the tracking area.
- (BOOL)mouseInsideTrackingArea;
// Whether the current screen is expected to have a menu bar, regardless of
// current visibility of the menu bar.
- (BOOL)doesScreenHaveMenuBar;
......@@ -136,10 +162,9 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler,
// |kFullScreenModeHideDock| when the overlay is shown.
- (base::mac::FullScreenMode)desiredSystemFullscreenMode;
// Change the overlay to the given fraction, with or without animation. Only
// guaranteed to work properly with |fraction == 0| or |fraction == 1|. This
// performs the show/hide (animation) immediately. It does not touch the timers.
- (void)changeOverlayToFraction:(CGFloat)fraction withAnimation:(BOOL)animate;
// Animate the overlay to the given visibility with animation. If |visible|
// is true, animate the toolbar to a fraction of 1.0. Otherwise it's 0.0.
- (void)animateToolbarVisibility:(BOOL)visible;
// Cancels the timer for hiding the floating bar.
- (void)cancelHideTimer;
......@@ -150,12 +175,6 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler,
// Stops any running animations, etc.
- (void)cleanup;
// Shows and hides the UI associated with this window being active (having main
// status). This includes hiding the menu bar. These functions are called when
// the window gains or loses main status as well as in |-cleanup|.
- (void)showActiveWindowUI;
- (void)hideActiveWindowUI;
// Whether the menu bar should be shown in immersive fullscreen for the screen
// that contains the window.
- (BOOL)shouldShowMenubarInImmersiveFullscreen;
......@@ -165,7 +184,6 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler,
@implementation FullscreenToolbarController
@synthesize slidingStyle = slidingStyle_;
@synthesize toolbarFraction = toolbarFraction_;
- (id)initWithBrowserController:(BrowserWindowController*)controller
style:(fullscreen_mac::SlidingStyle)style {
......@@ -200,10 +218,11 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler,
[super dealloc];
}
- (void)setupFullscreenToolbarWithDropdown:(BOOL)showDropdown {
- (void)setupFullscreenToolbarForContentView:(NSView*)contentView {
DCHECK(!inFullscreenMode_);
contentView_ = contentView;
inFullscreenMode_ = YES;
[self changeToolbarFraction:(showDropdown ? 1 : 0)];
[self updateMenuBarAndDockVisibility];
// Register for notifications. Self is removed as an observer in |-cleanup|.
......@@ -237,11 +256,11 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler,
}
- (void)windowDidBecomeMain:(NSNotification*)notification {
[self showActiveWindowUI];
[self updateMenuBarAndDockVisibility];
}
- (void)windowDidResignMain:(NSNotification*)notification {
[self hideActiveWindowUI];
[self updateMenuBarAndDockVisibility];
}
- (CGFloat)floatingBarVerticalOffset {
......@@ -255,22 +274,22 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler,
if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kKioskMode))
return;
if (self.slidingStyle == fullscreen_mac::OMNIBOX_TABS_PRESENT)
if (self.slidingStyle != fullscreen_mac::OMNIBOX_TABS_HIDDEN)
return;
[self cancelHideTimer];
[self changeOverlayToFraction:1 withAnimation:animate];
[self animateToolbarVisibility:YES];
}
- (void)ensureOverlayHiddenWithAnimation:(BOOL)animate {
if (!inFullscreenMode_)
return;
if (self.slidingStyle == fullscreen_mac::OMNIBOX_TABS_PRESENT)
if (self.slidingStyle != fullscreen_mac::OMNIBOX_TABS_HIDDEN)
return;
[self cancelHideTimer];
[self changeOverlayToFraction:0 withAnimation:animate];
[self animateToolbarVisibility:NO];
}
- (void)cancelAnimationAndTimer {
......@@ -285,8 +304,11 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler,
return;
}
revealToolbarForTabStripChanges_ = YES;
[self ensureOverlayShownWithAnimation:YES];
// Reveal the toolbar for tabstrip changes if the toolbar is hidden.
if (IsCGFloatEqual([self toolbarFraction], kHideFraction)) {
isRevealingToolbarForTabStripChanges_ = YES;
[self ensureOverlayShownWithAnimation:YES];
}
}
- (void)setSystemFullscreenModeTo:(base::mac::FullScreenMode)mode {
......@@ -301,8 +323,22 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler,
systemFullscreenMode_ = mode;
}
- (void)changeToolbarFraction:(CGFloat)fraction {
toolbarFraction_ = fraction;
- (void)mouseEntered:(NSEvent*)event {
// Empty implementation. Required for CrTrackingArea.
}
- (void)mouseExited:(NSEvent*)event {
DCHECK(inFullscreenMode_);
DCHECK_EQ([event trackingArea], trackingArea_.get());
// If the menubar is gone, animate the toolbar out.
if (IsCGFloatEqual(menubarFraction_, kHideFraction))
[self ensureOverlayHiddenWithAnimation:YES];
[self removeTrackingAreaIfNecessary];
}
- (void)updateToolbar {
[browserController_ layoutSubviews];
// In AppKit fullscreen, moving the mouse to the top of the screen toggles
......@@ -331,37 +367,73 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler,
: 0;
}
- (CGFloat)toolbarFraction {
if ([browserController_ isBarVisibilityLockedForOwner:nil])
return kShowFraction;
if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kKioskMode))
return kHideFraction;
switch (slidingStyle_) {
case fullscreen_mac::OMNIBOX_TABS_PRESENT:
return kShowFraction;
case fullscreen_mac::OMNIBOX_TABS_NONE:
return kHideFraction;
case fullscreen_mac::OMNIBOX_TABS_HIDDEN:
if (currentAnimation_.get())
return [currentAnimation_ toolbarFraction];
if (hideTimer_.get() || shouldAnimateToolbarOut_)
return kShowFraction;
return toolbarFractionFromMenuProgress_;
}
}
- (BOOL)isFullscreenTransitionInProgress {
return [browserController_ isFullscreenTransitionInProgress];
}
- (BOOL)isInFullscreen {
return inFullscreenMode_;
}
- (BOOL)isMouseOnScreen {
return NSMouseInRect([NSEvent mouseLocation],
[[browserController_ window] screen].frame, false);
}
- (void)animationDidStop:(NSAnimation*)animation {
// Reset the |currentAnimation_| pointer now that the animation is over.
currentAnimation_.reset();
- (void)setTrackingAreaFromOverlayFrame:(NSRect)frame {
NSRect contentBounds = [contentView_ bounds];
trackingAreaFrame_ = frame;
trackingAreaFrame_.origin.y -= kTrackingAreaAdditionalThreshold;
trackingAreaFrame_.size.height =
NSMaxY(contentBounds) - trackingAreaFrame_.origin.y;
}
if (revealToolbarForTabStripChanges_) {
if (toolbarFraction_ > 0.0) {
- (void)animationDidStop:(NSAnimation*)animation {
if (isRevealingToolbarForTabStripChanges_) {
if ([self toolbarFraction] > 0.0) {
// Set the timer to hide the toolbar.
[hideTimer_ invalidate];
hideTimer_.reset([[NSTimer
scheduledTimerWithTimeInterval:kDropdownForTabStripChangesDuration
target:self
selector:@selector(hideTimerFire:)
userInfo:nil
repeats:NO] retain]);
hideTimer_.reset(
[[NSTimer scheduledTimerWithTimeInterval:kTabStripChangesDelay
target:self
selector:@selector(hideTimerFire:)
userInfo:nil
repeats:NO] retain]);
} else {
revealToolbarForTabStripChanges_ = NO;
isRevealingToolbarForTabStripChanges_ = NO;
}
}
// Reset the |currentAnimation_| pointer now that the animation is over.
currentAnimation_.reset();
}
- (void)animationDidEnd:(NSAnimation*)animation {
[self animationDidStop:animation];
[self setupTrackingArea];
}
- (void)setMenuBarRevealProgress:(CGFloat)progress {
......@@ -372,16 +444,27 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler,
menubarFraction_ = progress;
if (self.slidingStyle == fullscreen_mac::OMNIBOX_TABS_HIDDEN) {
if (IsCGFloatEqual(menubarFraction_, kShowFraction))
[self setupTrackingArea];
// If the menubar is disappearing from the screen, check if the mouse
// is still interacting with the toolbar. If it is, don't set
// |toolbarFractionFromMenuProgress_| so that the the toolbar will remain
// on the screen.
BOOL isMenuBarDisappearing =
menubarFraction_ < toolbarFractionFromMenuProgress_;
if (!(isMenuBarDisappearing && [self mouseInsideTrackingArea]))
toolbarFractionFromMenuProgress_ = progress;
}
// If an animation is not running, then -layoutSubviews will not be called
// for each tick of the menu bar reveal. Do that manually.
// TODO(erikchen): The animation is janky. layoutSubviews need a refactor so
// that it calls setFrameOffset: instead of setFrame: if the frame's size has
// not changed.
if (!currentAnimation_.get()) {
if (self.slidingStyle != fullscreen_mac::OMNIBOX_TABS_NONE)
toolbarFraction_ = progress;
if (!currentAnimation_.get())
[browserController_ layoutSubviews];
}
}
@end
......@@ -404,6 +487,42 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler,
[self setSystemFullscreenModeTo:[self desiredSystemFullscreenMode]];
}
- (void)setupTrackingArea {
if (trackingArea_) {
// If the tracking rectangle is already |trackingAreaBounds_|, quit early.
NSRect oldRect = [trackingArea_ rect];
if (NSEqualRects(trackingAreaFrame_, oldRect))
return;
// Otherwise, remove it.
[self removeTrackingAreaIfNecessary];
}
// Create and add a new tracking area for |frame|.
trackingArea_.reset([[CrTrackingArea alloc]
initWithRect:trackingAreaFrame_
options:NSTrackingMouseEnteredAndExited | NSTrackingActiveInKeyWindow
owner:self
userInfo:nil]);
DCHECK(contentView_);
[contentView_ addTrackingArea:trackingArea_];
}
- (void)removeTrackingAreaIfNecessary {
if (trackingArea_) {
DCHECK(contentView_); // |contentView_| better be valid.
[contentView_ removeTrackingArea:trackingArea_];
trackingArea_.reset();
}
}
- (BOOL)mouseInsideTrackingArea {
NSWindow* window = [browserController_ window];
NSPoint mouseLoc = [window mouseLocationOutsideOfEventStream];
NSPoint mousePos = [contentView_ convertPoint:mouseLoc fromView:nil];
return NSMouseInRect(mousePos, trackingAreaFrame_, [contentView_ isFlipped]);
}
- (BOOL)doesScreenHaveMenuBar {
if (![[NSScreen class]
respondsToSelector:@selector(screensHaveSeparateSpaces)])
......@@ -425,16 +544,11 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler,
return base::mac::kFullScreenModeHideAll;
}
- (void)changeOverlayToFraction:(CGFloat)fraction withAnimation:(BOOL)animate {
// The non-animated case is really simple, so do it and return.
if (!animate) {
[currentAnimation_ stopAnimation];
[self changeToolbarFraction:fraction];
return;
}
- (void)animateToolbarVisibility:(BOOL)visible {
CGFloat fraction = visible ? kShowFraction : kHideFraction;
// If we're already animating to the given fraction, then there's nothing more
// to do.
// If we're already animating to the given fraction, then there's nothing
// more to do.
if (currentAnimation_ && [currentAnimation_ endFraction] == fraction)
return;
......@@ -452,6 +566,10 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler,
[currentAnimation_ setAnimationBlockingMode:NSAnimationNonblocking];
[currentAnimation_ setDelegate:self];
// If there is an existing tracking area, remove it. We do not track mouse
// movements during animations (see class comment in the header file).
[self removeTrackingAreaIfNecessary];
[currentAnimation_ startAnimation];
}
......@@ -464,15 +582,16 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler,
DCHECK_EQ(hideTimer_, timer); // This better be our hide timer.
[hideTimer_ invalidate]; // Make sure it doesn't repeat.
hideTimer_.reset(); // And get rid of it.
[self changeOverlayToFraction:0 withAnimation:YES];
shouldAnimateToolbarOut_ = YES;
[self animateToolbarVisibility:NO];
shouldAnimateToolbarOut_ = NO;
}
- (void)cleanup {
[self cancelAnimationAndTimer];
[[NSNotificationCenter defaultCenter] removeObserver:self];
// This isn't tracked when not in fullscreen mode.
[browserController_ releaseBarVisibilityForOwner:self withAnimation:NO];
[self removeTrackingAreaIfNecessary];
// Call the main status resignation code to perform the associated cleanup,
// since we will no longer be receiving actual status resignation
......@@ -483,16 +602,8 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler,
browserController_ = nil;
}
- (void)showActiveWindowUI {
[self updateMenuBarAndDockVisibility];
}
- (void)hideActiveWindowUI {
[self updateMenuBarAndDockVisibility];
}
- (BOOL)shouldShowMenubarInImmersiveFullscreen {
return [self doesScreenHaveMenuBar] && toolbarFraction_ > 0.99;
return [self doesScreenHaveMenuBar] && [self toolbarFraction] > 0.99;
}
@end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment