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; ...@@ -565,12 +565,14 @@ class Command;
// Query/lock/release the requirement that the tab strip/toolbar/attached // 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 // 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 // focus). This is required for the floating bar if it's hidden in fullscreen,
// should also be called when not in presentation mode; see the comments for // but should also be called when not in fullscreen mode; see the comments for
// |barVisibilityLocks_| for more details. Double locks/releases by the same // |barVisibilityLocks_| for more details. Double locks/releases by the same
// owner are ignored. If |animate:| is YES, then an animation may be // owner are ignored. If |animate:| is YES, then an animation may be
// performed. In the case of multiple calls, later calls have precedence with // 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; - (BOOL)isBarVisibilityLockedForOwner:(id)owner;
- (void)lockBarVisibilityForOwner:(id)owner withAnimation:(BOOL)animate; - (void)lockBarVisibilityForOwner:(id)owner withAnimation:(BOOL)animate;
- (void)releaseBarVisibilityForOwner:(id)owner withAnimation:(BOOL)animate; - (void)releaseBarVisibilityForOwner:(id)owner withAnimation:(BOOL)animate;
......
...@@ -1979,9 +1979,9 @@ willAnimateFromState:(BookmarkBar::State)oldState ...@@ -1979,9 +1979,9 @@ willAnimateFromState:(BookmarkBar::State)oldState
} }
- (BOOL)isBarVisibilityLockedForOwner:(id)owner { - (BOOL)isBarVisibilityLockedForOwner:(id)owner {
DCHECK(owner);
DCHECK(barVisibilityLocks_); DCHECK(barVisibilityLocks_);
return [barVisibilityLocks_ containsObject:owner]; return owner ? [barVisibilityLocks_ containsObject:owner]
: [barVisibilityLocks_ count];
} }
- (void)lockBarVisibilityForOwner:(id)owner withAnimation:(BOOL)animate { - (void)lockBarVisibilityForOwner:(id)owner withAnimation:(BOOL)animate {
......
...@@ -761,7 +761,6 @@ IN_PROC_BROWSER_TEST_F(BrowserWindowControllerTest, ...@@ -761,7 +761,6 @@ IN_PROC_BROWSER_TEST_F(BrowserWindowControllerTest,
// Toggle the visibility of the fullscreen toolbar. Verify that the toolbar // Toggle the visibility of the fullscreen toolbar. Verify that the toolbar
// is hidden and the preference is correctly updated. // is hidden and the preference is correctly updated.
[[controller() fullscreenToolbarController] setToolbarFraction:0.0];
[[controller() fullscreenToolbarController] setMenuBarRevealProgress:0.0]; [[controller() fullscreenToolbarController] setMenuBarRevealProgress:0.0];
chrome::ExecuteCommand(browser(), IDC_TOGGLE_FULLSCREEN_TOOLBAR); chrome::ExecuteCommand(browser(), IDC_TOGGLE_FULLSCREEN_TOOLBAR);
EXPECT_FALSE(prefs->GetBoolean(prefs::kShowFullscreenToolbar)); EXPECT_FALSE(prefs->GetBoolean(prefs::kShowFullscreenToolbar));
......
...@@ -454,14 +454,9 @@ willPositionSheet:(NSWindow*)sheet ...@@ -454,14 +454,9 @@ willPositionSheet:(NSWindow*)sheet
} }
- (void)configureFullscreenToolbarController { - (void)configureFullscreenToolbarController {
BOOL fullscreenForTab = [self isFullscreenForTabContentOrExtension]; NSView* contentView = [[self window] contentView];
BOOL kioskMode =
base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kKioskMode);
BOOL showDropdown =
!fullscreenForTab && !kioskMode && ([self floatingBarHasFocus]);
[fullscreenToolbarController_ [fullscreenToolbarController_
setupFullscreenToolbarWithDropdown:showDropdown]; setupFullscreenToolbarForContentView:contentView];
} }
- (void)adjustUIForExitingFullscreenAndStopOmniboxSliding { - (void)adjustUIForExitingFullscreenAndStopOmniboxSliding {
...@@ -474,6 +469,10 @@ willPositionSheet:(NSWindow*)sheet ...@@ -474,6 +469,10 @@ willPositionSheet:(NSWindow*)sheet
} }
- (void)adjustUIForSlidingFullscreenStyle:(fullscreen_mac::SlidingStyle)style { - (void)adjustUIForSlidingFullscreenStyle:(fullscreen_mac::SlidingStyle)style {
// The UI should only be adjusted in fullscreen mode.
if (![self isInAnyFullscreenMode])
return;
if (!fullscreenToolbarController_) { if (!fullscreenToolbarController_) {
fullscreenToolbarController_.reset( fullscreenToolbarController_.reset(
[self newFullscreenToolbarControllerWithStyle:style]); [self newFullscreenToolbarControllerWithStyle:style]);
...@@ -1009,8 +1008,11 @@ willPositionSheet:(NSWindow*)sheet ...@@ -1009,8 +1008,11 @@ willPositionSheet:(NSWindow*)sheet
[self layoutTabContentArea:output.contentAreaFrame]; [self layoutTabContentArea:output.contentAreaFrame];
if (!NSIsEmptyRect(output.fullscreenBackingBarFrame)) if (!NSIsEmptyRect(output.fullscreenBackingBarFrame)) {
[floatingBarBackingView_ setFrame:output.fullscreenBackingBarFrame]; [floatingBarBackingView_ setFrame:output.fullscreenBackingBarFrame];
[fullscreenToolbarController_
setTrackingAreaFromOverlayFrame:output.fullscreenBackingBarFrame];
}
[findBarCocoaController_ [findBarCocoaController_
positionFindBarViewAtMaxY:output.findBarMaxY positionFindBarViewAtMaxY:output.findBarMaxY
......
...@@ -168,17 +168,8 @@ const CGFloat kLocationBarRightOffset = 35; ...@@ -168,17 +168,8 @@ const CGFloat kLocationBarRightOffset = 35;
CGFloat yOffset = 0; CGFloat yOffset = 0;
if (parameters_.inAnyFullscreen) { if (parameters_.inAnyFullscreen) {
yOffset += parameters_.menubarOffset; yOffset += parameters_.menubarOffset;
switch (parameters_.slidingStyle) { yOffset += std::floor((1 - parameters_.toolbarFraction) *
case fullscreen_mac::OMNIBOX_TABS_PRESENT: [self fullscreenBackingBarHeight]);
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;
}
} }
fullscreenYOffset_ = yOffset; fullscreenYOffset_ = yOffset;
} }
......
...@@ -47,7 +47,7 @@ class BrowserWindowLayoutTest : public testing::Test { ...@@ -47,7 +47,7 @@ class BrowserWindowLayoutTest : public testing::Test {
[layout setInAnyFullscreen:YES]; [layout setInAnyFullscreen:YES];
[layout setFullscreenSlidingStyle:fullscreen_mac::OMNIBOX_TABS_PRESENT]; [layout setFullscreenSlidingStyle:fullscreen_mac::OMNIBOX_TABS_PRESENT];
[layout setFullscreenMenubarOffset:0]; [layout setFullscreenMenubarOffset:0];
[layout setFullscreenToolbarFraction:0]; [layout setFullscreenToolbarFraction:1];
[layout setFullscreenButtonFrame:NSZeroRect]; [layout setFullscreenButtonFrame:NSZeroRect];
} }
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h" #include "chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h"
@class BrowserWindowController; @class BrowserWindowController;
@class CrTrackingArea;
@class DropdownAnimation; @class DropdownAnimation;
namespace fullscreen_mac { namespace fullscreen_mac {
...@@ -25,16 +26,12 @@ enum SlidingStyle { ...@@ -25,16 +26,12 @@ enum SlidingStyle {
// Provides a controller to fullscreen toolbar for a single browser // Provides a controller to fullscreen toolbar for a single browser
// window. This class handles running animations, showing and hiding the // window. This class handles running animations, showing and hiding the
// floating dropdown bar, and managing the tracking area associated with the // fullscreen toolbar, and managing the tracking area associated with the
// dropdown. This class does not directly manage any views -- the // toolbar. This class does not directly manage any views -- the
// BrowserWindowController is responsible for positioning and z-ordering views. // 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 // TODO (spqchan): Write tests for this class. See crbug.com/640064.
// 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.
@interface FullscreenToolbarController : NSObject<NSAnimationDelegate> { @interface FullscreenToolbarController : NSObject<NSAnimationDelegate> {
@private @private
// Our parent controller. // Our parent controller.
...@@ -43,6 +40,18 @@ enum SlidingStyle { ...@@ -43,6 +40,18 @@ enum SlidingStyle {
// Whether or not we are in fullscreen mode. // Whether or not we are in fullscreen mode.
BOOL inFullscreenMode_; 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 // Pointer to the currently running animation. Is nil if no animation is
// running. // running.
base::scoped_nsobject<DropdownAnimation> currentAnimation_; base::scoped_nsobject<DropdownAnimation> currentAnimation_;
...@@ -69,32 +78,36 @@ enum SlidingStyle { ...@@ -69,32 +78,36 @@ enum SlidingStyle {
// Only used in AppKit Fullscreen. // Only used in AppKit Fullscreen.
CGFloat menubarFraction_; CGFloat menubarFraction_;
// The fraction of the omnibox/tabstrip that is showing. Ranges from 0 to 1. // The toolbar fraction set by the menu progress.
// Used in both AppKit and Immersive Fullscreen. CGFloat toolbarFractionFromMenuProgress_;
CGFloat toolbarFraction_;
// A Carbon event handler that tracks the revealed fraction of the menu bar. // A Carbon event handler that tracks the revealed fraction of the menu bar.
EventHandlerRef menuBarTrackingHandler_; EventHandlerRef menuBarTrackingHandler_;
// True when the toolbar is dropped to show tabstrip changes. // 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) fullscreen_mac::SlidingStyle slidingStyle;
@property(nonatomic, assign) CGFloat toolbarFraction;
// Designated initializer. // Designated initializer.
- (id)initWithBrowserController:(BrowserWindowController*)controller - (id)initWithBrowserController:(BrowserWindowController*)controller
style:(fullscreen_mac::SlidingStyle)style; 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 // mode. |-setupFullscreenToolbarForContentView:showDropdown:| should be called
// after the window is setup, just before it is shown. |-exitFullscreenMode| // after the window is setup, just before it is shown. |-exitFullscreenMode|
// should be called before any views are moved back to the non-fullscreen // should be called before any views are moved back to the non-fullscreen
// window. If |-setupFullscreenToolbarForContentView:showDropdown:| is called, // window. If |-setupFullscreenToolbarForContentView:showDropdown:| is called,
// it must be balanced with a call to |-exitFullscreenMode| before the // it must be balanced with a call to |-exitFullscreenMode| before the
// controller is released. // controller is released.
- (void)setupFullscreenToolbarWithDropdown:(BOOL)showDropdown; - (void)setupFullscreenToolbarForContentView:(NSView*)contentView;
- (void)exitFullscreenMode; - (void)exitFullscreenMode;
// Returns the amount by which the floating bar should be offset downwards (to // Returns the amount by which the floating bar should be offset downwards (to
...@@ -119,15 +132,30 @@ enum SlidingStyle { ...@@ -119,15 +132,30 @@ enum SlidingStyle {
// Ranges from 0 to -22. // Ranges from 0 to -22.
- (CGFloat)menubarOffset; - (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 // 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 // if the menubar events belong to window's screen since the menubar would
// only be revealed if the mouse is there. // only be revealed if the mouse is there.
- (BOOL)isMouseOnScreen; - (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. // fullscreen.
- (BOOL)isFullscreenTransitionInProgress; - (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 @end
// Private methods exposed for testing. // Private methods exposed for testing.
...@@ -138,11 +166,6 @@ enum SlidingStyle { ...@@ -138,11 +166,6 @@ enum SlidingStyle {
// Callback for menu bar animations. // Callback for menu bar animations.
- (void)setMenuBarRevealProgress:(CGFloat)progress; - (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 @end
#endif // CHROME_BROWSER_UI_COCOA_FULLSCREEN_TOOLBAR_CONTROLLER_H_ #endif // CHROME_BROWSER_UI_COCOA_FULLSCREEN_TOOLBAR_CONTROLLER_H_
...@@ -13,15 +13,24 @@ ...@@ -13,15 +13,24 @@
#include "chrome/common/chrome_switches.h" #include "chrome/common/chrome_switches.h"
#import "third_party/google_toolbox_for_mac/src/AppKit/GTMNSAnimation+Duration.h" #import "third_party/google_toolbox_for_mac/src/AppKit/GTMNSAnimation+Duration.h"
#import "ui/base/cocoa/nsview_additions.h" #import "ui/base/cocoa/nsview_additions.h"
#import "ui/base/cocoa/tracking_area.h"
namespace { namespace {
// The activation zone for the main menu is 4 pixels high; if we make it any // The duration of the toolbar show/hide animation.
// smaller, then the menu can be made to appear without the bar sliding down. const NSTimeInterval kDropdownAnimationDuration = 0.20;
const NSTimeInterval kDropdownAnimationDuration = 0.12;
// The duration the toolbar is revealed for tab strip changes. // If the fullscreen toolbar is hidden, it is difficult for the user to see
const NSTimeInterval kDropdownForTabStripChangesDuration = 0.75; // 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. // The event kind value for a undocumented menubar show/hide Carbon event.
const CGFloat kMenuBarRevealEventKind = 2004; const CGFloat kMenuBarRevealEventKind = 2004;
...@@ -31,6 +40,15 @@ const CGFloat kMenuBarRevealEventKind = 2004; ...@@ -31,6 +40,15 @@ const CGFloat kMenuBarRevealEventKind = 2004;
// returns 0 when the menu bar is hidden.) // returns 0 when the menu bar is hidden.)
const CGFloat kFloatingBarVerticalOffset = 22; 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, OSStatus MenuBarRevealHandler(EventHandlerCallRef handler,
EventRef event, EventRef event,
void* context) { void* context) {
...@@ -44,17 +62,17 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler, ...@@ -44,17 +62,17 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler,
// As such, we should ignore the kMenuBarRevealEventKind event if it gives // 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 // us a fraction of 0.0 or 1.0, and rely on kEventMenuBarShown and
// kEventMenuBarHidden to set these values. // kEventMenuBarHidden to set these values.
if (![self isFullscreenTransitionInProgress]) { if (![self isFullscreenTransitionInProgress] && [self isInFullscreen]) {
if (GetEventKind(event) == kMenuBarRevealEventKind) { if (GetEventKind(event) == kMenuBarRevealEventKind) {
CGFloat revealFraction = 0; CGFloat revealFraction = 0;
GetEventParameter(event, FOUR_CHAR_CODE('rvlf'), typeCGFloat, NULL, GetEventParameter(event, FOUR_CHAR_CODE('rvlf'), typeCGFloat, NULL,
sizeof(CGFloat), NULL, &revealFraction); sizeof(CGFloat), NULL, &revealFraction);
if (revealFraction > 0.0 && revealFraction < 1.0) if (revealFraction > kHideFraction && revealFraction < kShowFraction)
[self setMenuBarRevealProgress:revealFraction]; [self setMenuBarRevealProgress:revealFraction];
} else if (GetEventKind(event) == kEventMenuBarShown) { } else if (GetEventKind(event) == kEventMenuBarShown) {
[self setMenuBarRevealProgress:1.0]; [self setMenuBarRevealProgress:kShowFraction];
} else { } else {
[self setMenuBarRevealProgress:0.0]; [self setMenuBarRevealProgress:kHideFraction];
} }
} }
...@@ -71,10 +89,11 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler, ...@@ -71,10 +89,11 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler,
FullscreenToolbarController* controller_; FullscreenToolbarController* controller_;
CGFloat startFraction_; CGFloat startFraction_;
CGFloat endFraction_; CGFloat endFraction_;
CGFloat toolbarFraction_;
} }
@property(readonly, nonatomic) CGFloat startFraction;
@property(readonly, nonatomic) CGFloat endFraction; @property(readonly, nonatomic) CGFloat endFraction;
@property(readonly, nonatomic) CGFloat toolbarFraction;
// Designated initializer. Asks |controller| for the current shown fraction, so // Designated initializer. Asks |controller| for the current shown fraction, so
// if the bar is already partially shown or partially hidden, the animation // if the bar is already partially shown or partially hidden, the animation
...@@ -88,8 +107,8 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler, ...@@ -88,8 +107,8 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler,
@implementation DropdownAnimation @implementation DropdownAnimation
@synthesize startFraction = startFraction_;
@synthesize endFraction = endFraction_; @synthesize endFraction = endFraction_;
@synthesize toolbarFraction = toolbarFraction_;
- (id)initWithFraction:(CGFloat)toFraction - (id)initWithFraction:(CGFloat)toFraction
fullDuration:(CGFloat)fullDuration fullDuration:(CGFloat)fullDuration
...@@ -97,7 +116,7 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler, ...@@ -97,7 +116,7 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler,
controller:(FullscreenToolbarController*)controller { controller:(FullscreenToolbarController*)controller {
// Calculate the effective duration, based on the current shown fraction. // Calculate the effective duration, based on the current shown fraction.
DCHECK(controller); DCHECK(controller);
CGFloat fromFraction = controller.toolbarFraction; CGFloat fromFraction = [controller toolbarFraction];
CGFloat effectiveDuration = fabs(fullDuration * (fromFraction - toFraction)); CGFloat effectiveDuration = fabs(fullDuration * (fromFraction - toFraction));
if ((self = [super gtm_initWithDuration:effectiveDuration if ((self = [super gtm_initWithDuration:effectiveDuration
...@@ -113,9 +132,9 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler, ...@@ -113,9 +132,9 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler,
// Called once per animation step. Overridden to change the floating bar's // Called once per animation step. Overridden to change the floating bar's
// position based on the animation's progress. // position based on the animation's progress.
- (void)setCurrentProgress:(NSAnimationProgress)progress { - (void)setCurrentProgress:(NSAnimationProgress)progress {
CGFloat fraction = toolbarFraction_ =
startFraction_ + (progress * (endFraction_ - startFraction_)); startFraction_ + (progress * (endFraction_ - startFraction_));
[controller_ changeToolbarFraction:fraction]; [controller_ updateToolbar];
} }
@end @end
...@@ -125,6 +144,13 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler, ...@@ -125,6 +144,13 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler,
// Updates the visibility of the menu bar and the dock. // Updates the visibility of the menu bar and the dock.
- (void)updateMenuBarAndDockVisibility; - (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 // Whether the current screen is expected to have a menu bar, regardless of
// current visibility of the menu bar. // current visibility of the menu bar.
- (BOOL)doesScreenHaveMenuBar; - (BOOL)doesScreenHaveMenuBar;
...@@ -136,10 +162,9 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler, ...@@ -136,10 +162,9 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler,
// |kFullScreenModeHideDock| when the overlay is shown. // |kFullScreenModeHideDock| when the overlay is shown.
- (base::mac::FullScreenMode)desiredSystemFullscreenMode; - (base::mac::FullScreenMode)desiredSystemFullscreenMode;
// Change the overlay to the given fraction, with or without animation. Only // Animate the overlay to the given visibility with animation. If |visible|
// guaranteed to work properly with |fraction == 0| or |fraction == 1|. This // is true, animate the toolbar to a fraction of 1.0. Otherwise it's 0.0.
// performs the show/hide (animation) immediately. It does not touch the timers. - (void)animateToolbarVisibility:(BOOL)visible;
- (void)changeOverlayToFraction:(CGFloat)fraction withAnimation:(BOOL)animate;
// Cancels the timer for hiding the floating bar. // Cancels the timer for hiding the floating bar.
- (void)cancelHideTimer; - (void)cancelHideTimer;
...@@ -150,12 +175,6 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler, ...@@ -150,12 +175,6 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler,
// Stops any running animations, etc. // Stops any running animations, etc.
- (void)cleanup; - (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 // Whether the menu bar should be shown in immersive fullscreen for the screen
// that contains the window. // that contains the window.
- (BOOL)shouldShowMenubarInImmersiveFullscreen; - (BOOL)shouldShowMenubarInImmersiveFullscreen;
...@@ -165,7 +184,6 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler, ...@@ -165,7 +184,6 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler,
@implementation FullscreenToolbarController @implementation FullscreenToolbarController
@synthesize slidingStyle = slidingStyle_; @synthesize slidingStyle = slidingStyle_;
@synthesize toolbarFraction = toolbarFraction_;
- (id)initWithBrowserController:(BrowserWindowController*)controller - (id)initWithBrowserController:(BrowserWindowController*)controller
style:(fullscreen_mac::SlidingStyle)style { style:(fullscreen_mac::SlidingStyle)style {
...@@ -200,10 +218,11 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler, ...@@ -200,10 +218,11 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler,
[super dealloc]; [super dealloc];
} }
- (void)setupFullscreenToolbarWithDropdown:(BOOL)showDropdown { - (void)setupFullscreenToolbarForContentView:(NSView*)contentView {
DCHECK(!inFullscreenMode_); DCHECK(!inFullscreenMode_);
contentView_ = contentView;
inFullscreenMode_ = YES; inFullscreenMode_ = YES;
[self changeToolbarFraction:(showDropdown ? 1 : 0)];
[self updateMenuBarAndDockVisibility]; [self updateMenuBarAndDockVisibility];
// Register for notifications. Self is removed as an observer in |-cleanup|. // Register for notifications. Self is removed as an observer in |-cleanup|.
...@@ -237,11 +256,11 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler, ...@@ -237,11 +256,11 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler,
} }
- (void)windowDidBecomeMain:(NSNotification*)notification { - (void)windowDidBecomeMain:(NSNotification*)notification {
[self showActiveWindowUI]; [self updateMenuBarAndDockVisibility];
} }
- (void)windowDidResignMain:(NSNotification*)notification { - (void)windowDidResignMain:(NSNotification*)notification {
[self hideActiveWindowUI]; [self updateMenuBarAndDockVisibility];
} }
- (CGFloat)floatingBarVerticalOffset { - (CGFloat)floatingBarVerticalOffset {
...@@ -255,22 +274,22 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler, ...@@ -255,22 +274,22 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler,
if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kKioskMode)) if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kKioskMode))
return; return;
if (self.slidingStyle == fullscreen_mac::OMNIBOX_TABS_PRESENT) if (self.slidingStyle != fullscreen_mac::OMNIBOX_TABS_HIDDEN)
return; return;
[self cancelHideTimer]; [self cancelHideTimer];
[self changeOverlayToFraction:1 withAnimation:animate]; [self animateToolbarVisibility:YES];
} }
- (void)ensureOverlayHiddenWithAnimation:(BOOL)animate { - (void)ensureOverlayHiddenWithAnimation:(BOOL)animate {
if (!inFullscreenMode_) if (!inFullscreenMode_)
return; return;
if (self.slidingStyle == fullscreen_mac::OMNIBOX_TABS_PRESENT) if (self.slidingStyle != fullscreen_mac::OMNIBOX_TABS_HIDDEN)
return; return;
[self cancelHideTimer]; [self cancelHideTimer];
[self changeOverlayToFraction:0 withAnimation:animate]; [self animateToolbarVisibility:NO];
} }
- (void)cancelAnimationAndTimer { - (void)cancelAnimationAndTimer {
...@@ -285,8 +304,11 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler, ...@@ -285,8 +304,11 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler,
return; return;
} }
revealToolbarForTabStripChanges_ = YES; // Reveal the toolbar for tabstrip changes if the toolbar is hidden.
[self ensureOverlayShownWithAnimation:YES]; if (IsCGFloatEqual([self toolbarFraction], kHideFraction)) {
isRevealingToolbarForTabStripChanges_ = YES;
[self ensureOverlayShownWithAnimation:YES];
}
} }
- (void)setSystemFullscreenModeTo:(base::mac::FullScreenMode)mode { - (void)setSystemFullscreenModeTo:(base::mac::FullScreenMode)mode {
...@@ -301,8 +323,22 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler, ...@@ -301,8 +323,22 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler,
systemFullscreenMode_ = mode; systemFullscreenMode_ = mode;
} }
- (void)changeToolbarFraction:(CGFloat)fraction { - (void)mouseEntered:(NSEvent*)event {
toolbarFraction_ = fraction; // 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]; [browserController_ layoutSubviews];
// In AppKit fullscreen, moving the mouse to the top of the screen toggles // In AppKit fullscreen, moving the mouse to the top of the screen toggles
...@@ -331,37 +367,73 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler, ...@@ -331,37 +367,73 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler,
: 0; : 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 { - (BOOL)isFullscreenTransitionInProgress {
return [browserController_ isFullscreenTransitionInProgress]; return [browserController_ isFullscreenTransitionInProgress];
} }
- (BOOL)isInFullscreen {
return inFullscreenMode_;
}
- (BOOL)isMouseOnScreen { - (BOOL)isMouseOnScreen {
return NSMouseInRect([NSEvent mouseLocation], return NSMouseInRect([NSEvent mouseLocation],
[[browserController_ window] screen].frame, false); [[browserController_ window] screen].frame, false);
} }
- (void)animationDidStop:(NSAnimation*)animation { - (void)setTrackingAreaFromOverlayFrame:(NSRect)frame {
// Reset the |currentAnimation_| pointer now that the animation is over. NSRect contentBounds = [contentView_ bounds];
currentAnimation_.reset(); trackingAreaFrame_ = frame;
trackingAreaFrame_.origin.y -= kTrackingAreaAdditionalThreshold;
trackingAreaFrame_.size.height =
NSMaxY(contentBounds) - trackingAreaFrame_.origin.y;
}
if (revealToolbarForTabStripChanges_) { - (void)animationDidStop:(NSAnimation*)animation {
if (toolbarFraction_ > 0.0) { if (isRevealingToolbarForTabStripChanges_) {
if ([self toolbarFraction] > 0.0) {
// Set the timer to hide the toolbar. // Set the timer to hide the toolbar.
[hideTimer_ invalidate]; [hideTimer_ invalidate];
hideTimer_.reset([[NSTimer hideTimer_.reset(
scheduledTimerWithTimeInterval:kDropdownForTabStripChangesDuration [[NSTimer scheduledTimerWithTimeInterval:kTabStripChangesDelay
target:self target:self
selector:@selector(hideTimerFire:) selector:@selector(hideTimerFire:)
userInfo:nil userInfo:nil
repeats:NO] retain]); repeats:NO] retain]);
} else { } else {
revealToolbarForTabStripChanges_ = NO; isRevealingToolbarForTabStripChanges_ = NO;
} }
} }
// Reset the |currentAnimation_| pointer now that the animation is over.
currentAnimation_.reset();
} }
- (void)animationDidEnd:(NSAnimation*)animation { - (void)animationDidEnd:(NSAnimation*)animation {
[self animationDidStop:animation]; [self animationDidStop:animation];
[self setupTrackingArea];
} }
- (void)setMenuBarRevealProgress:(CGFloat)progress { - (void)setMenuBarRevealProgress:(CGFloat)progress {
...@@ -372,16 +444,27 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler, ...@@ -372,16 +444,27 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler,
menubarFraction_ = progress; 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 // If an animation is not running, then -layoutSubviews will not be called
// for each tick of the menu bar reveal. Do that manually. // for each tick of the menu bar reveal. Do that manually.
// TODO(erikchen): The animation is janky. layoutSubviews need a refactor so // TODO(erikchen): The animation is janky. layoutSubviews need a refactor so
// that it calls setFrameOffset: instead of setFrame: if the frame's size has // that it calls setFrameOffset: instead of setFrame: if the frame's size has
// not changed. // not changed.
if (!currentAnimation_.get()) { if (!currentAnimation_.get())
if (self.slidingStyle != fullscreen_mac::OMNIBOX_TABS_NONE)
toolbarFraction_ = progress;
[browserController_ layoutSubviews]; [browserController_ layoutSubviews];
}
} }
@end @end
...@@ -404,6 +487,42 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler, ...@@ -404,6 +487,42 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler,
[self setSystemFullscreenModeTo:[self desiredSystemFullscreenMode]]; [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 { - (BOOL)doesScreenHaveMenuBar {
if (![[NSScreen class] if (![[NSScreen class]
respondsToSelector:@selector(screensHaveSeparateSpaces)]) respondsToSelector:@selector(screensHaveSeparateSpaces)])
...@@ -425,16 +544,11 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler, ...@@ -425,16 +544,11 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler,
return base::mac::kFullScreenModeHideAll; return base::mac::kFullScreenModeHideAll;
} }
- (void)changeOverlayToFraction:(CGFloat)fraction withAnimation:(BOOL)animate { - (void)animateToolbarVisibility:(BOOL)visible {
// The non-animated case is really simple, so do it and return. CGFloat fraction = visible ? kShowFraction : kHideFraction;
if (!animate) {
[currentAnimation_ stopAnimation];
[self changeToolbarFraction:fraction];
return;
}
// If we're already animating to the given fraction, then there's nothing more // If we're already animating to the given fraction, then there's nothing
// to do. // more to do.
if (currentAnimation_ && [currentAnimation_ endFraction] == fraction) if (currentAnimation_ && [currentAnimation_ endFraction] == fraction)
return; return;
...@@ -452,6 +566,10 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler, ...@@ -452,6 +566,10 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler,
[currentAnimation_ setAnimationBlockingMode:NSAnimationNonblocking]; [currentAnimation_ setAnimationBlockingMode:NSAnimationNonblocking];
[currentAnimation_ setDelegate:self]; [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]; [currentAnimation_ startAnimation];
} }
...@@ -464,15 +582,16 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler, ...@@ -464,15 +582,16 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler,
DCHECK_EQ(hideTimer_, timer); // This better be our hide timer. DCHECK_EQ(hideTimer_, timer); // This better be our hide timer.
[hideTimer_ invalidate]; // Make sure it doesn't repeat. [hideTimer_ invalidate]; // Make sure it doesn't repeat.
hideTimer_.reset(); // And get rid of it. hideTimer_.reset(); // And get rid of it.
[self changeOverlayToFraction:0 withAnimation:YES]; shouldAnimateToolbarOut_ = YES;
[self animateToolbarVisibility:NO];
shouldAnimateToolbarOut_ = NO;
} }
- (void)cleanup { - (void)cleanup {
[self cancelAnimationAndTimer]; [self cancelAnimationAndTimer];
[[NSNotificationCenter defaultCenter] removeObserver:self]; [[NSNotificationCenter defaultCenter] removeObserver:self];
// This isn't tracked when not in fullscreen mode. [self removeTrackingAreaIfNecessary];
[browserController_ releaseBarVisibilityForOwner:self withAnimation:NO];
// Call the main status resignation code to perform the associated cleanup, // Call the main status resignation code to perform the associated cleanup,
// since we will no longer be receiving actual status resignation // since we will no longer be receiving actual status resignation
...@@ -483,16 +602,8 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler, ...@@ -483,16 +602,8 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler,
browserController_ = nil; browserController_ = nil;
} }
- (void)showActiveWindowUI {
[self updateMenuBarAndDockVisibility];
}
- (void)hideActiveWindowUI {
[self updateMenuBarAndDockVisibility];
}
- (BOOL)shouldShowMenubarInImmersiveFullscreen { - (BOOL)shouldShowMenubarInImmersiveFullscreen {
return [self doesScreenHaveMenuBar] && toolbarFraction_ > 0.99; return [self doesScreenHaveMenuBar] && [self toolbarFraction] > 0.99;
} }
@end @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