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

Unified Diff: chrome/browser/ui/cocoa/fullscreen_toolbar_controller.mm

Issue 2272783002: [Mac] Fix for fullscreen toolbar (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: The fullscreen changes 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/browser/ui/cocoa/fullscreen_toolbar_controller.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/ui/cocoa/fullscreen_toolbar_controller.mm
diff --git a/chrome/browser/ui/cocoa/fullscreen_toolbar_controller.mm b/chrome/browser/ui/cocoa/fullscreen_toolbar_controller.mm
index d9d4617700b9a2463271e13337d977853b011cd6..aeb7b7ef378847734ca3e1158e61fc8ca433dac9 100644
--- a/chrome/browser/ui/cocoa/fullscreen_toolbar_controller.mm
+++ b/chrome/browser/ui/cocoa/fullscreen_toolbar_controller.mm
@@ -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 = 24;
// The event kind value for a undocumented menubar show/hide Carbon event.
const CGFloat kMenuBarRevealEventKind = 2004;
@@ -44,7 +53,7 @@ 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,
@@ -125,6 +134,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;
@@ -141,6 +157,9 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler,
// performs the show/hide (animation) immediately. It does not touch the timers.
- (void)changeOverlayToFraction:(CGFloat)fraction withAnimation:(BOOL)animate;
+// Releases the bar visibility and hides the toolbar.
+- (void)releaseAndHideBarVisibility;
+
// Cancels the timer for hiding the floating bar.
- (void)cancelHideTimer;
@@ -200,9 +219,13 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler,
[super dealloc];
}
-- (void)setupFullscreenToolbarWithDropdown:(BOOL)showDropdown {
+- (void)setupFullscreenToolbarForContentView:(NSView*)contentView
+ showDropdown:(BOOL)showDropdown {
DCHECK(!inFullscreenMode_);
+ contentView_ = contentView;
+
inFullscreenMode_ = YES;
+
[self changeToolbarFraction:(showDropdown ? 1 : 0)];
[self updateMenuBarAndDockVisibility];
@@ -301,8 +324,22 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler,
systemFullscreenMode_ = mode;
}
+- (void)mouseEntered:(NSEvent*)event {
+ // Empty implementation. Required for CrTrackingArea.
+}
+
+- (void)mouseExited:(NSEvent*)event {
+ DCHECK(inFullscreenMode_);
+
+ // Release the toolbar if the mouse exits the tracking area,
+ if ([event trackingArea] == trackingArea_.get())
+ [self releaseAndHideBarVisibility];
+}
+
- (void)changeToolbarFraction:(CGFloat)fraction {
- toolbarFraction_ = fraction;
+ toolbarFraction_ =
+ [browserController_ isBarVisibilityLockedForOwner:nil] ? 1.0 : fraction;
erikchen 2016/08/23 21:19:58 This line concerns me a lot. The previous method s
+
[browserController_ layoutSubviews];
// In AppKit fullscreen, moving the mouse to the top of the screen toggles
@@ -335,11 +372,21 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler,
return [browserController_ isFullscreenTransitionInProgress];
}
+- (BOOL)isInFullscreen {
+ return inFullscreenMode_;
+}
+
- (BOOL)isMouseOnScreen {
return NSMouseInRect([NSEvent mouseLocation],
[[browserController_ window] screen].frame, false);
}
+- (void)setTrackingAreaFromOverlayFrame:(NSRect)frame {
+ trackingAreaFrame_ = frame;
+ trackingAreaFrame_.origin.y -= kTrackingAreaAdditionalThreshold;
+ trackingAreaFrame_.size.height += kTrackingAreaAdditionalThreshold;
+}
+
- (void)animationDidStop:(NSAnimation*)animation {
// Reset the |currentAnimation_| pointer now that the animation is over.
currentAnimation_.reset();
@@ -348,12 +395,12 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler,
if (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;
}
@@ -362,6 +409,7 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler,
- (void)animationDidEnd:(NSAnimation*)animation {
[self animationDidStop:animation];
+ [self setupTrackingArea];
}
- (void)setMenuBarRevealProgress:(CGFloat)progress {
@@ -379,8 +427,22 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler,
// not changed.
if (!currentAnimation_.get()) {
if (self.slidingStyle != fullscreen_mac::OMNIBOX_TABS_NONE)
- toolbarFraction_ = progress;
- [browserController_ layoutSubviews];
+ [self changeToolbarFraction:progress];
+ else
+ [browserController_ layoutSubviews];
+ }
+
+ if (toolbarFraction_ == 1.0) {
+ // Lock the toolbar's visibility and set up the tracking area.
+ [browserController_ lockBarVisibilityForOwner:self withAnimation:NO];
+ [self setupTrackingArea];
+
+ // If the menubar is gone, check if the mouse is inside the new tracking
+ // area. There's a chance that the tracking area had slipped away from the
+ // cursor when toolbar shifted up from the menubar changes. As a result,
+ // this would've prevent us from getting a |mouseExited:| call.
+ if (menubarFraction_ == 0 && ![self mouseInsideTrackingArea])
+ [self releaseAndHideBarVisibility];
}
}
@@ -404,6 +466,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)])
@@ -452,9 +550,30 @@ 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];
}
+- (void)releaseAndHideBarVisibility {
+ // There are two ways for the toolbar to hide:
+ // 1. Via the menubar, if the menubar is fully visible.
+ // With its visibility released, the Carbon menubar events will hide the
+ // toobar in sync with the menubar. For this case, we need to call
+ // ensureOverlayShownWithAnimation: so that the toolbar won't hide before
+ // the menubar does.
+ // 2. Via DropdownAnimation, if the menubar is already gone. The animation is
+ // created when we call releaseBarVisibilityForOwner:, and it will hide
+ // the toolbar.
+ [browserController_ releaseBarVisibilityForOwner:self withAnimation:YES];
+ if (menubarFraction_ == 1.0)
+ [self ensureOverlayShownWithAnimation:NO];
+
+ [self removeTrackingAreaIfNecessary];
+}
+
- (void)cancelHideTimer {
[hideTimer_ invalidate];
hideTimer_.reset();
@@ -471,6 +590,8 @@ OSStatus MenuBarRevealHandler(EventHandlerCallRef handler,
[self cancelAnimationAndTimer];
[[NSNotificationCenter defaultCenter] removeObserver:self];
+ [self removeTrackingAreaIfNecessary];
+
// This isn't tracked when not in fullscreen mode.
[browserController_ releaseBarVisibilityForOwner:self withAnimation:NO];
« no previous file with comments | « chrome/browser/ui/cocoa/fullscreen_toolbar_controller.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698