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

Side by Side 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: comments 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
« no previous file with comments | « chrome/browser/ui/cocoa/fullscreen_toolbar_controller.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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"
16 17
17 namespace { 18 namespace {
18 19
19 // The activation zone for the main menu is 4 pixels high; if we make it any 20 // The duration of the toolbar show/hide animation.
20 // smaller, then the menu can be made to appear without the bar sliding down. 21 const NSTimeInterval kDropdownAnimationDuration = 0.20;
21 const NSTimeInterval kDropdownAnimationDuration = 0.12;
22 22
23 // The duration the toolbar is revealed for tab strip changes. 23 // If the fullscreen toolbar is hidden, it is difficult for the user to see
24 const NSTimeInterval kDropdownForTabStripChangesDuration = 0.75; 24 // changes in the tabstrip. As a result, if a tab is inserted or the current
25 // tab switched to a new one, the toolbar must animate in and out to display
26 // the tabstrip changes to the user. The animation drops down the toolbar and
27 // then wait for 0.75 seconds before it hides the toolbar.
28 const NSTimeInterval kTabStripChangesDelay = 0.75;
29
30 // Additional height threshold added at the toolbar's bottom. This is to mimic
31 // threshold the mouse position needs to be at before the menubar automatically
32 // hides.
33 const CGFloat kTrackingAreaAdditionalThreshold = 20;
25 34
26 // The event kind value for a undocumented menubar show/hide Carbon event. 35 // The event kind value for a undocumented menubar show/hide Carbon event.
27 const CGFloat kMenuBarRevealEventKind = 2004; 36 const CGFloat kMenuBarRevealEventKind = 2004;
28 37
29 // The amount by which the floating bar is offset downwards (to avoid the menu) 38 // The amount by which the floating bar is offset downwards (to avoid the menu)
30 // when the toolbar is hidden. (We can't use |-[NSMenu menuBarHeight]| since it 39 // when the toolbar is hidden. (We can't use |-[NSMenu menuBarHeight]| since it
31 // returns 0 when the menu bar is hidden.) 40 // returns 0 when the menu bar is hidden.)
32 const CGFloat kFloatingBarVerticalOffset = 22; 41 const CGFloat kFloatingBarVerticalOffset = 22;
33 42
34 OSStatus MenuBarRevealHandler(EventHandlerCallRef handler, 43 OSStatus MenuBarRevealHandler(EventHandlerCallRef handler,
35 EventRef event, 44 EventRef event,
36 void* context) { 45 void* context) {
37 FullscreenToolbarController* self = 46 FullscreenToolbarController* self =
38 static_cast<FullscreenToolbarController*>(context); 47 static_cast<FullscreenToolbarController*>(context);
39 48
40 // If Chrome has multiple fullscreen windows in their own space, the Handler 49 // If Chrome has multiple fullscreen windows in their own space, the Handler
41 // becomes flaky and might start receiving kMenuBarRevealEventKind events 50 // becomes flaky and might start receiving kMenuBarRevealEventKind events
42 // from another space. Since the menubar in the another space is in either a 51 // from another space. Since the menubar in the another space is in either a
43 // shown or hidden state, it will give us a reveal fraction of 0.0 or 1.0. 52 // shown or hidden state, it will give us a reveal fraction of 0.0 or 1.0.
44 // As such, we should ignore the kMenuBarRevealEventKind event if it gives 53 // As such, we should ignore the kMenuBarRevealEventKind event if it gives
45 // us a fraction of 0.0 or 1.0, and rely on kEventMenuBarShown and 54 // us a fraction of 0.0 or 1.0, and rely on kEventMenuBarShown and
46 // kEventMenuBarHidden to set these values. 55 // kEventMenuBarHidden to set these values.
47 if (![self isFullscreenTransitionInProgress]) { 56 if (![self isFullscreenTransitionInProgress] && [self isInFullscreen]) {
48 if (GetEventKind(event) == kMenuBarRevealEventKind) { 57 if (GetEventKind(event) == kMenuBarRevealEventKind) {
49 CGFloat revealFraction = 0; 58 CGFloat revealFraction = 0;
50 GetEventParameter(event, FOUR_CHAR_CODE('rvlf'), typeCGFloat, NULL, 59 GetEventParameter(event, FOUR_CHAR_CODE('rvlf'), typeCGFloat, NULL,
51 sizeof(CGFloat), NULL, &revealFraction); 60 sizeof(CGFloat), NULL, &revealFraction);
52 if (revealFraction > 0.0 && revealFraction < 1.0) 61 if (revealFraction > 0.0 && revealFraction < 1.0)
53 [self setMenuBarRevealProgress:revealFraction]; 62 [self setMenuBarRevealProgress:revealFraction];
54 } else if (GetEventKind(event) == kEventMenuBarShown) { 63 } else if (GetEventKind(event) == kEventMenuBarShown) {
55 [self setMenuBarRevealProgress:1.0]; 64 [self setMenuBarRevealProgress:1.0];
56 } else { 65 } else {
57 [self setMenuBarRevealProgress:0.0]; 66 [self setMenuBarRevealProgress:0.0];
58 } 67 }
59 } 68 }
60 69
61 return CallNextEventHandler(handler, event); 70 return CallNextEventHandler(handler, event);
62 } 71 }
63 72
64 } // end namespace 73 } // end namespace
65 74
66 // Helper class to manage animations for the dropdown bar. Calls 75 // Helper class to manage animations for the dropdown bar. Calls
67 // [FullscreenToolbarController changeToolbarFraction] once per 76 // [FullscreenToolbarController changeToolbarFraction] once per
68 // animation step. 77 // animation step.
69 @interface DropdownAnimation : NSAnimation { 78 @interface DropdownAnimation : NSAnimation {
70 @private 79 @private
71 FullscreenToolbarController* controller_; 80 FullscreenToolbarController* controller_;
72 CGFloat startFraction_; 81 CGFloat startFraction_;
73 CGFloat endFraction_; 82 CGFloat endFraction_;
83 CGFloat toolbarFraction_;
74 } 84 }
75 85
76 @property(readonly, nonatomic) CGFloat startFraction;
77 @property(readonly, nonatomic) CGFloat endFraction; 86 @property(readonly, nonatomic) CGFloat endFraction;
87 @property(readonly, nonatomic) CGFloat toolbarFraction;
78 88
79 // Designated initializer. Asks |controller| for the current shown fraction, so 89 // Designated initializer. Asks |controller| for the current shown fraction, so
80 // if the bar is already partially shown or partially hidden, the animation 90 // if the bar is already partially shown or partially hidden, the animation
81 // duration may be less than |fullDuration|. 91 // duration may be less than |fullDuration|.
82 - (id)initWithFraction:(CGFloat)fromFraction 92 - (id)initWithFraction:(CGFloat)fromFraction
83 fullDuration:(CGFloat)fullDuration 93 fullDuration:(CGFloat)fullDuration
84 animationCurve:(NSAnimationCurve)animationCurve 94 animationCurve:(NSAnimationCurve)animationCurve
85 controller:(FullscreenToolbarController*)controller; 95 controller:(FullscreenToolbarController*)controller;
86 96
87 @end 97 @end
88 98
89 @implementation DropdownAnimation 99 @implementation DropdownAnimation
90 100
91 @synthesize startFraction = startFraction_;
92 @synthesize endFraction = endFraction_; 101 @synthesize endFraction = endFraction_;
102 @synthesize toolbarFraction = toolbarFraction_;
93 103
94 - (id)initWithFraction:(CGFloat)toFraction 104 - (id)initWithFraction:(CGFloat)toFraction
95 fullDuration:(CGFloat)fullDuration 105 fullDuration:(CGFloat)fullDuration
96 animationCurve:(NSAnimationCurve)animationCurve 106 animationCurve:(NSAnimationCurve)animationCurve
97 controller:(FullscreenToolbarController*)controller { 107 controller:(FullscreenToolbarController*)controller {
98 // Calculate the effective duration, based on the current shown fraction. 108 // Calculate the effective duration, based on the current shown fraction.
99 DCHECK(controller); 109 DCHECK(controller);
100 CGFloat fromFraction = controller.toolbarFraction; 110 CGFloat fromFraction = [controller toolbarFraction];
101 CGFloat effectiveDuration = fabs(fullDuration * (fromFraction - toFraction)); 111 CGFloat effectiveDuration = fabs(fullDuration * (fromFraction - toFraction));
102 112
103 if ((self = [super gtm_initWithDuration:effectiveDuration 113 if ((self = [super gtm_initWithDuration:effectiveDuration
104 eventMask:NSLeftMouseDownMask 114 eventMask:NSLeftMouseDownMask
105 animationCurve:animationCurve])) { 115 animationCurve:animationCurve])) {
106 startFraction_ = fromFraction; 116 startFraction_ = fromFraction;
107 endFraction_ = toFraction; 117 endFraction_ = toFraction;
108 controller_ = controller; 118 controller_ = controller;
109 } 119 }
110 return self; 120 return self;
111 } 121 }
112 122
113 // Called once per animation step. Overridden to change the floating bar's 123 // Called once per animation step. Overridden to change the floating bar's
114 // position based on the animation's progress. 124 // position based on the animation's progress.
115 - (void)setCurrentProgress:(NSAnimationProgress)progress { 125 - (void)setCurrentProgress:(NSAnimationProgress)progress {
116 CGFloat fraction = 126 toolbarFraction_ =
117 startFraction_ + (progress * (endFraction_ - startFraction_)); 127 startFraction_ + (progress * (endFraction_ - startFraction_));
118 [controller_ changeToolbarFraction:fraction]; 128 [controller_ updateToolbar];
119 } 129 }
120 130
121 @end 131 @end
122 132
123 @interface FullscreenToolbarController (PrivateMethods) 133 @interface FullscreenToolbarController (PrivateMethods)
124 134
125 // Updates the visibility of the menu bar and the dock. 135 // Updates the visibility of the menu bar and the dock.
126 - (void)updateMenuBarAndDockVisibility; 136 - (void)updateMenuBarAndDockVisibility;
127 137
138 // Methods to set up or remove the tracking area.
139 - (void)setupTrackingArea;
140 - (void)removeTrackingAreaIfNecessary;
141
142 // Returns YES if the mouse is inside the tracking area.
143 - (BOOL)mouseInsideTrackingArea;
144
128 // Whether the current screen is expected to have a menu bar, regardless of 145 // Whether the current screen is expected to have a menu bar, regardless of
129 // current visibility of the menu bar. 146 // current visibility of the menu bar.
130 - (BOOL)doesScreenHaveMenuBar; 147 - (BOOL)doesScreenHaveMenuBar;
131 148
132 // Returns YES if the window is on the primary screen. 149 // Returns YES if the window is on the primary screen.
133 - (BOOL)isWindowOnPrimaryScreen; 150 - (BOOL)isWindowOnPrimaryScreen;
134 151
135 // Returns |kFullScreenModeHideAll| when the overlay is hidden and 152 // Returns |kFullScreenModeHideAll| when the overlay is hidden and
136 // |kFullScreenModeHideDock| when the overlay is shown. 153 // |kFullScreenModeHideDock| when the overlay is shown.
137 - (base::mac::FullScreenMode)desiredSystemFullscreenMode; 154 - (base::mac::FullScreenMode)desiredSystemFullscreenMode;
138 155
139 // Change the overlay to the given fraction, with or without animation. Only 156 // Animate the overlay to the given visibility with animation. If |visible|
140 // guaranteed to work properly with |fraction == 0| or |fraction == 1|. This 157 // is true, animate the toolbar to a fraction of 1.0. Otherwise it's 0.0.
141 // performs the show/hide (animation) immediately. It does not touch the timers. 158 - (void)animateToolbarVisibility:(BOOL)visible;
142 - (void)changeOverlayToFraction:(CGFloat)fraction withAnimation:(BOOL)animate;
143 159
144 // Cancels the timer for hiding the floating bar. 160 // Cancels the timer for hiding the floating bar.
145 - (void)cancelHideTimer; 161 - (void)cancelHideTimer;
146 162
147 // Methods called when the hide timers fire. Do not call directly. 163 // Methods called when the hide timers fire. Do not call directly.
148 - (void)hideTimerFire:(NSTimer*)timer; 164 - (void)hideTimerFire:(NSTimer*)timer;
149 165
150 // Stops any running animations, etc. 166 // Stops any running animations, etc.
151 - (void)cleanup; 167 - (void)cleanup;
152 168
153 // Shows and hides the UI associated with this window being active (having main
154 // status). This includes hiding the menu bar. These functions are called when
155 // the window gains or loses main status as well as in |-cleanup|.
156 - (void)showActiveWindowUI;
157 - (void)hideActiveWindowUI;
158
159 // Whether the menu bar should be shown in immersive fullscreen for the screen 169 // Whether the menu bar should be shown in immersive fullscreen for the screen
160 // that contains the window. 170 // that contains the window.
161 - (BOOL)shouldShowMenubarInImmersiveFullscreen; 171 - (BOOL)shouldShowMenubarInImmersiveFullscreen;
162 172
163 @end 173 @end
164 174
165 @implementation FullscreenToolbarController 175 @implementation FullscreenToolbarController
166 176
167 @synthesize slidingStyle = slidingStyle_; 177 @synthesize slidingStyle = slidingStyle_;
168 @synthesize toolbarFraction = toolbarFraction_;
169 178
170 - (id)initWithBrowserController:(BrowserWindowController*)controller 179 - (id)initWithBrowserController:(BrowserWindowController*)controller
171 style:(fullscreen_mac::SlidingStyle)style { 180 style:(fullscreen_mac::SlidingStyle)style {
172 if ((self = [super init])) { 181 if ((self = [super init])) {
173 browserController_ = controller; 182 browserController_ = controller;
174 systemFullscreenMode_ = base::mac::kFullScreenModeNormal; 183 systemFullscreenMode_ = base::mac::kFullScreenModeNormal;
175 slidingStyle_ = style; 184 slidingStyle_ = style;
176 } 185 }
177 186
178 // Install the Carbon event handler for the menubar show, hide and 187 // Install the Carbon event handler for the menubar show, hide and
(...skipping 14 matching lines...) Expand all
193 202
194 return self; 203 return self;
195 } 204 }
196 205
197 - (void)dealloc { 206 - (void)dealloc {
198 RemoveEventHandler(menuBarTrackingHandler_); 207 RemoveEventHandler(menuBarTrackingHandler_);
199 DCHECK(!inFullscreenMode_); 208 DCHECK(!inFullscreenMode_);
200 [super dealloc]; 209 [super dealloc];
201 } 210 }
202 211
203 - (void)setupFullscreenToolbarWithDropdown:(BOOL)showDropdown { 212 - (void)setupFullscreenToolbarForContentView:(NSView*)contentView {
204 DCHECK(!inFullscreenMode_); 213 DCHECK(!inFullscreenMode_);
214 contentView_ = contentView;
205 inFullscreenMode_ = YES; 215 inFullscreenMode_ = YES;
206 [self changeToolbarFraction:(showDropdown ? 1 : 0)]; 216
207 [self updateMenuBarAndDockVisibility]; 217 [self updateMenuBarAndDockVisibility];
208 218
209 // Register for notifications. Self is removed as an observer in |-cleanup|. 219 // Register for notifications. Self is removed as an observer in |-cleanup|.
210 NSNotificationCenter* nc = [NSNotificationCenter defaultCenter]; 220 NSNotificationCenter* nc = [NSNotificationCenter defaultCenter];
211 NSWindow* window = [browserController_ window]; 221 NSWindow* window = [browserController_ window];
212 222
213 [nc addObserver:self 223 [nc addObserver:self
214 selector:@selector(windowDidBecomeMain:) 224 selector:@selector(windowDidBecomeMain:)
215 name:NSWindowDidBecomeMainNotification 225 name:NSWindowDidBecomeMainNotification
216 object:window]; 226 object:window];
(...skipping 13 matching lines...) Expand all
230 240
231 - (void)windowDidChangeScreen:(NSNotification*)notification { 241 - (void)windowDidChangeScreen:(NSNotification*)notification {
232 [browserController_ resizeFullscreenWindow]; 242 [browserController_ resizeFullscreenWindow];
233 } 243 }
234 244
235 - (void)windowDidMove:(NSNotification*)notification { 245 - (void)windowDidMove:(NSNotification*)notification {
236 [browserController_ resizeFullscreenWindow]; 246 [browserController_ resizeFullscreenWindow];
237 } 247 }
238 248
239 - (void)windowDidBecomeMain:(NSNotification*)notification { 249 - (void)windowDidBecomeMain:(NSNotification*)notification {
240 [self showActiveWindowUI]; 250 [self updateMenuBarAndDockVisibility];
241 } 251 }
242 252
243 - (void)windowDidResignMain:(NSNotification*)notification { 253 - (void)windowDidResignMain:(NSNotification*)notification {
244 [self hideActiveWindowUI]; 254 [self updateMenuBarAndDockVisibility];
245 } 255 }
246 256
247 - (CGFloat)floatingBarVerticalOffset { 257 - (CGFloat)floatingBarVerticalOffset {
248 return kFloatingBarVerticalOffset; 258 return kFloatingBarVerticalOffset;
249 } 259 }
250 260
251 - (void)ensureOverlayShownWithAnimation:(BOOL)animate { 261 - (void)ensureOverlayShownWithAnimation:(BOOL)animate {
252 if (!inFullscreenMode_) 262 if (!inFullscreenMode_)
253 return; 263 return;
254 264
255 if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kKioskMode)) 265 if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kKioskMode))
256 return; 266 return;
257 267
258 if (self.slidingStyle == fullscreen_mac::OMNIBOX_TABS_PRESENT) 268 if (self.slidingStyle != fullscreen_mac::OMNIBOX_TABS_HIDDEN)
259 return; 269 return;
260 270
261 [self cancelHideTimer]; 271 [self cancelHideTimer];
262 [self changeOverlayToFraction:1 withAnimation:animate]; 272 [self animateToolbarVisibility:YES];
263 } 273 }
264 274
265 - (void)ensureOverlayHiddenWithAnimation:(BOOL)animate { 275 - (void)ensureOverlayHiddenWithAnimation:(BOOL)animate {
266 if (!inFullscreenMode_) 276 if (!inFullscreenMode_)
267 return; 277 return;
268 278
269 if (self.slidingStyle == fullscreen_mac::OMNIBOX_TABS_PRESENT) 279 if (self.slidingStyle != fullscreen_mac::OMNIBOX_TABS_HIDDEN)
270 return; 280 return;
271 281
272 [self cancelHideTimer]; 282 [self cancelHideTimer];
273 [self changeOverlayToFraction:0 withAnimation:animate]; 283 [self animateToolbarVisibility:NO];
274 } 284 }
275 285
276 - (void)cancelAnimationAndTimer { 286 - (void)cancelAnimationAndTimer {
277 [self cancelHideTimer]; 287 [self cancelHideTimer];
278 [currentAnimation_ stopAnimation]; 288 [currentAnimation_ stopAnimation];
279 currentAnimation_.reset(); 289 currentAnimation_.reset();
280 } 290 }
281 291
282 - (void)revealToolbarForTabStripChanges { 292 - (void)revealToolbarForTabStripChanges {
erikchen 2016/08/24 23:52:58 nit: Having a method named "foo" which changes the
spqchan 2016/08/26 00:46:30 Done.
283 if (!base::CommandLine::ForCurrentProcess()->HasSwitch( 293 if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
284 switches::kEnableFullscreenToolbarReveal)) { 294 switches::kEnableFullscreenToolbarReveal)) {
285 return; 295 return;
286 } 296 }
287 297
288 revealToolbarForTabStripChanges_ = YES; 298 // Reveal the toolbar for tabstrip changes if the toolbar
289 [self ensureOverlayShownWithAnimation:YES]; 299 // isn't shown.
300 if ([self toolbarFraction] == 0.0) {
erikchen 2016/08/24 23:52:58 nit: You have a lot of double comparisons in your
spqchan 2016/08/26 00:46:30 Added IsCGFloatEqual(). Is this what you mean?
erikchen 2016/08/26 00:56:58 Ideally, we would be able to avoid any type of flo
301 revealToolbarForTabStripChanges_ = YES;
302 [self ensureOverlayShownWithAnimation:YES];
303 }
290 } 304 }
291 305
292 - (void)setSystemFullscreenModeTo:(base::mac::FullScreenMode)mode { 306 - (void)setSystemFullscreenModeTo:(base::mac::FullScreenMode)mode {
293 if (mode == systemFullscreenMode_) 307 if (mode == systemFullscreenMode_)
294 return; 308 return;
295 if (systemFullscreenMode_ == base::mac::kFullScreenModeNormal) 309 if (systemFullscreenMode_ == base::mac::kFullScreenModeNormal)
296 base::mac::RequestFullScreen(mode); 310 base::mac::RequestFullScreen(mode);
297 else if (mode == base::mac::kFullScreenModeNormal) 311 else if (mode == base::mac::kFullScreenModeNormal)
298 base::mac::ReleaseFullScreen(systemFullscreenMode_); 312 base::mac::ReleaseFullScreen(systemFullscreenMode_);
299 else 313 else
300 base::mac::SwitchFullScreenModes(systemFullscreenMode_, mode); 314 base::mac::SwitchFullScreenModes(systemFullscreenMode_, mode);
301 systemFullscreenMode_ = mode; 315 systemFullscreenMode_ = mode;
302 } 316 }
303 317
304 - (void)changeToolbarFraction:(CGFloat)fraction { 318 - (void)mouseEntered:(NSEvent*)event {
305 toolbarFraction_ = fraction; 319 // Empty implementation. Required for CrTrackingArea.
320 }
321
322 - (void)mouseExited:(NSEvent*)event {
323 DCHECK(inFullscreenMode_);
324
325 // If the menubar is gone, animate the toolbar out.
326 if ([event trackingArea] == trackingArea_.get()) {
erikchen 2016/08/24 23:52:58 nit: Should this be DCHECK_EQ([event trackingArea]
spqchan 2016/08/26 00:46:30 Done.
327 if (menubarFraction_ == 0.0)
328 [self ensureOverlayHiddenWithAnimation:YES];
329
330 [self removeTrackingAreaIfNecessary];
331 }
332 }
333
334 - (void)updateToolbar {
306 [browserController_ layoutSubviews]; 335 [browserController_ layoutSubviews];
307 336
308 // In AppKit fullscreen, moving the mouse to the top of the screen toggles 337 // In AppKit fullscreen, moving the mouse to the top of the screen toggles
309 // menu visibility. Replicate the same effect for immersive fullscreen. 338 // menu visibility. Replicate the same effect for immersive fullscreen.
310 if ([browserController_ isInImmersiveFullscreen]) 339 if ([browserController_ isInImmersiveFullscreen])
311 [self updateMenuBarAndDockVisibility]; 340 [self updateMenuBarAndDockVisibility];
312 } 341 }
313 342
314 // This method works, but is fragile. 343 // This method works, but is fragile.
315 // 344 //
316 // It gets used during view layout, which sometimes needs to be done at the 345 // It gets used during view layout, which sometimes needs to be done at the
317 // beginning of an animation. As such, this method needs to reflect the 346 // beginning of an animation. As such, this method needs to reflect the
318 // menubarOffset expected at the end of the animation. This information is not 347 // menubarOffset expected at the end of the animation. This information is not
319 // readily available. (The layout logic needs a refactor). 348 // readily available. (The layout logic needs a refactor).
320 // 349 //
321 // For AppKit Fullscreen, the menubar always starts hidden, and 350 // For AppKit Fullscreen, the menubar always starts hidden, and
322 // menubarFraction_ always starts at 0, so the logic happens to work. For 351 // menubarFraction_ always starts at 0, so the logic happens to work. For
323 // Immersive Fullscreen, this class controls the visibility of the menu bar, so 352 // Immersive Fullscreen, this class controls the visibility of the menu bar, so
324 // the logic is correct and not fragile. 353 // the logic is correct and not fragile.
325 - (CGFloat)menubarOffset { 354 - (CGFloat)menubarOffset {
326 if ([browserController_ isInAppKitFullscreen]) 355 if ([browserController_ isInAppKitFullscreen])
327 return -std::floor(menubarFraction_ * [self floatingBarVerticalOffset]); 356 return -std::floor(menubarFraction_ * [self floatingBarVerticalOffset]);
328 357
329 return [self shouldShowMenubarInImmersiveFullscreen] 358 return [self shouldShowMenubarInImmersiveFullscreen]
330 ? -[self floatingBarVerticalOffset] 359 ? -[self floatingBarVerticalOffset]
331 : 0; 360 : 0;
332 } 361 }
333 362
363 - (CGFloat)toolbarFraction {
erikchen 2016/08/24 23:52:58 Wow. This is amazing. Thank you.
spqchan 2016/08/26 00:46:30 Ack
364 if ([browserController_ isBarVisibilityLockedForOwner:nil])
365 return 1.0;
366
367 if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kKioskMode))
368 return 0.0;
369
370 switch (slidingStyle_) {
371 case fullscreen_mac::OMNIBOX_TABS_PRESENT:
372 return 1.0;
373 case fullscreen_mac::OMNIBOX_TABS_NONE:
374 return 0.0;
375 case fullscreen_mac::OMNIBOX_TABS_HIDDEN:
376 if (currentAnimation_.get())
377 return [currentAnimation_ toolbarFraction];
378 return toolbarFractionFromMenuProgress_;
379 }
380 }
381
334 - (BOOL)isFullscreenTransitionInProgress { 382 - (BOOL)isFullscreenTransitionInProgress {
335 return [browserController_ isFullscreenTransitionInProgress]; 383 return [browserController_ isFullscreenTransitionInProgress];
336 } 384 }
337 385
386 - (BOOL)isInFullscreen {
387 return inFullscreenMode_;
388 }
389
338 - (BOOL)isMouseOnScreen { 390 - (BOOL)isMouseOnScreen {
339 return NSMouseInRect([NSEvent mouseLocation], 391 return NSMouseInRect([NSEvent mouseLocation],
340 [[browserController_ window] screen].frame, false); 392 [[browserController_ window] screen].frame, false);
341 } 393 }
342 394
395 - (void)setTrackingAreaFromOverlayFrame:(NSRect)frame {
396 NSRect contentBounds = [contentView_ bounds];
397 trackingAreaFrame_ = frame;
398 trackingAreaFrame_.origin.y -= kTrackingAreaAdditionalThreshold;
399 trackingAreaFrame_.size.height =
400 NSMaxY(contentBounds) - trackingAreaFrame_.origin.y;
401 }
402
343 - (void)animationDidStop:(NSAnimation*)animation { 403 - (void)animationDidStop:(NSAnimation*)animation {
344 // Reset the |currentAnimation_| pointer now that the animation is over. 404 // Reset the |currentAnimation_| pointer now that the animation is over.
345 currentAnimation_.reset(); 405 currentAnimation_.reset();
erikchen 2016/08/24 23:52:58 If -toolbarFraction is called after the animation
spqchan 2016/08/26 00:46:30 Good point.
346 406
347 if (revealToolbarForTabStripChanges_) { 407 if (revealToolbarForTabStripChanges_) {
348 if (toolbarFraction_ > 0.0) { 408 if ([self toolbarFraction] > 0.0) {
349 // Set the timer to hide the toolbar. 409 // Set the timer to hide the toolbar.
350 [hideTimer_ invalidate]; 410 [hideTimer_ invalidate];
351 hideTimer_.reset([[NSTimer 411 hideTimer_.reset(
352 scheduledTimerWithTimeInterval:kDropdownForTabStripChangesDuration 412 [[NSTimer scheduledTimerWithTimeInterval:kTabStripChangesDelay
353 target:self 413 target:self
354 selector:@selector(hideTimerFire:) 414 selector:@selector(hideTimerFire:)
355 userInfo:nil 415 userInfo:nil
356 repeats:NO] retain]); 416 repeats:NO] retain]);
357 } else { 417 } else {
358 revealToolbarForTabStripChanges_ = NO; 418 revealToolbarForTabStripChanges_ = NO;
359 } 419 }
360 } 420 }
361 } 421 }
362 422
363 - (void)animationDidEnd:(NSAnimation*)animation { 423 - (void)animationDidEnd:(NSAnimation*)animation {
364 [self animationDidStop:animation]; 424 [self animationDidStop:animation];
425 [self setupTrackingArea];
365 } 426 }
366 427
367 - (void)setMenuBarRevealProgress:(CGFloat)progress { 428 - (void)setMenuBarRevealProgress:(CGFloat)progress {
368 // If the menubarFraction increases, check if we are in the right screen 429 // If the menubarFraction increases, check if we are in the right screen
369 // so that the toolbar is not revealed on the wrong screen. 430 // so that the toolbar is not revealed on the wrong screen.
370 if (![self isMouseOnScreen] && progress > menubarFraction_) 431 if (![self isMouseOnScreen] && progress > menubarFraction_)
371 return; 432 return;
372 433
373 menubarFraction_ = progress; 434 menubarFraction_ = progress;
374 435
436 if (self.slidingStyle == fullscreen_mac::OMNIBOX_TABS_HIDDEN) {
437 if (menubarFraction_ == 1.0)
erikchen 2016/08/24 23:52:58 This double comparison relies on the assumption th
spqchan 2016/08/26 00:46:30 Ditto from above
438 [self setupTrackingArea];
439
440 // If the menubar is disappearing from the screen, check if the mouse
441 // is still interacting with the. If it is, then don't set
erikchen 2016/08/24 23:52:58 incomplete sentence?
spqchan 2016/08/26 00:46:30 Done.
442 // |toolbarFractionFromMenuProgress_| so that the the toolbar will remain
443 // on the screen.
444 BOOL isMenuBarDisappearing =
445 menubarFraction_ < toolbarFractionFromMenuProgress_;
446 if (!(isMenuBarDisappearing && [self mouseInsideTrackingArea]))
447 toolbarFractionFromMenuProgress_ = progress;
erikchen 2016/08/24 23:52:58 Can we separate the logic for toolbarFractionFromM
spqchan 2016/08/26 00:46:30 I already tried that. I find that having |toolbarF
erikchen 2016/08/26 00:56:58 Acknowledged.
448 }
449
375 // If an animation is not running, then -layoutSubviews will not be called 450 // If an animation is not running, then -layoutSubviews will not be called
376 // for each tick of the menu bar reveal. Do that manually. 451 // for each tick of the menu bar reveal. Do that manually.
377 // TODO(erikchen): The animation is janky. layoutSubviews need a refactor so 452 // TODO(erikchen): The animation is janky. layoutSubviews need a refactor so
378 // that it calls setFrameOffset: instead of setFrame: if the frame's size has 453 // that it calls setFrameOffset: instead of setFrame: if the frame's size has
379 // not changed. 454 // not changed.
380 if (!currentAnimation_.get()) { 455 if (!currentAnimation_.get())
381 if (self.slidingStyle != fullscreen_mac::OMNIBOX_TABS_NONE)
382 toolbarFraction_ = progress;
383 [browserController_ layoutSubviews]; 456 [browserController_ layoutSubviews];
384 }
385 } 457 }
386 458
387 @end 459 @end
388 460
389 @implementation FullscreenToolbarController (PrivateMethods) 461 @implementation FullscreenToolbarController (PrivateMethods)
390 462
391 - (void)updateMenuBarAndDockVisibility { 463 - (void)updateMenuBarAndDockVisibility {
392 if (![self isMouseOnScreen] || 464 if (![self isMouseOnScreen] ||
393 ![browserController_ isInImmersiveFullscreen]) { 465 ![browserController_ isInImmersiveFullscreen]) {
394 [self setSystemFullscreenModeTo:base::mac::kFullScreenModeNormal]; 466 [self setSystemFullscreenModeTo:base::mac::kFullScreenModeNormal];
395 return; 467 return;
396 } 468 }
397 469
398 // The screen does not have a menu bar, so there's no need to hide it. 470 // The screen does not have a menu bar, so there's no need to hide it.
399 if (![self doesScreenHaveMenuBar]) { 471 if (![self doesScreenHaveMenuBar]) {
400 [self setSystemFullscreenModeTo:base::mac::kFullScreenModeHideDock]; 472 [self setSystemFullscreenModeTo:base::mac::kFullScreenModeHideDock];
401 return; 473 return;
402 } 474 }
403 475
404 [self setSystemFullscreenModeTo:[self desiredSystemFullscreenMode]]; 476 [self setSystemFullscreenModeTo:[self desiredSystemFullscreenMode]];
405 } 477 }
406 478
479 - (void)setupTrackingArea {
480 if (trackingArea_) {
481 // If the tracking rectangle is already |trackingAreaBounds_|, quit early.
482 NSRect oldRect = [trackingArea_ rect];
483 if (NSEqualRects(trackingAreaFrame_, oldRect))
484 return;
485
486 // Otherwise, remove it.
487 [self removeTrackingAreaIfNecessary];
488 }
489
490 // Create and add a new tracking area for |frame|.
491 trackingArea_.reset([[CrTrackingArea alloc]
492 initWithRect:trackingAreaFrame_
493 options:NSTrackingMouseEnteredAndExited | NSTrackingActiveInKeyWindow
494 owner:self
495 userInfo:nil]);
496 DCHECK(contentView_);
497 [contentView_ addTrackingArea:trackingArea_];
498 }
499
500 - (void)removeTrackingAreaIfNecessary {
501 if (trackingArea_) {
502 DCHECK(contentView_); // |contentView_| better be valid.
503 [contentView_ removeTrackingArea:trackingArea_];
504 trackingArea_.reset();
505 }
506 }
507
508 - (BOOL)mouseInsideTrackingArea {
509 NSWindow* window = [browserController_ window];
510 NSPoint mouseLoc = [window mouseLocationOutsideOfEventStream];
511 NSPoint mousePos = [contentView_ convertPoint:mouseLoc fromView:nil];
512 return NSMouseInRect(mousePos, trackingAreaFrame_, [contentView_ isFlipped]);
513 }
514
407 - (BOOL)doesScreenHaveMenuBar { 515 - (BOOL)doesScreenHaveMenuBar {
408 if (![[NSScreen class] 516 if (![[NSScreen class]
409 respondsToSelector:@selector(screensHaveSeparateSpaces)]) 517 respondsToSelector:@selector(screensHaveSeparateSpaces)])
410 return [self isWindowOnPrimaryScreen]; 518 return [self isWindowOnPrimaryScreen];
411 519
412 BOOL eachScreenShouldHaveMenuBar = [NSScreen screensHaveSeparateSpaces]; 520 BOOL eachScreenShouldHaveMenuBar = [NSScreen screensHaveSeparateSpaces];
413 return eachScreenShouldHaveMenuBar ?: [self isWindowOnPrimaryScreen]; 521 return eachScreenShouldHaveMenuBar ?: [self isWindowOnPrimaryScreen];
414 } 522 }
415 523
416 - (BOOL)isWindowOnPrimaryScreen { 524 - (BOOL)isWindowOnPrimaryScreen {
417 NSScreen* screen = [[browserController_ window] screen]; 525 NSScreen* screen = [[browserController_ window] screen];
418 NSScreen* primaryScreen = [[NSScreen screens] firstObject]; 526 NSScreen* primaryScreen = [[NSScreen screens] firstObject];
419 return (screen == primaryScreen); 527 return (screen == primaryScreen);
420 } 528 }
421 529
422 - (base::mac::FullScreenMode)desiredSystemFullscreenMode { 530 - (base::mac::FullScreenMode)desiredSystemFullscreenMode {
423 if ([self shouldShowMenubarInImmersiveFullscreen]) 531 if ([self shouldShowMenubarInImmersiveFullscreen])
424 return base::mac::kFullScreenModeHideDock; 532 return base::mac::kFullScreenModeHideDock;
425 return base::mac::kFullScreenModeHideAll; 533 return base::mac::kFullScreenModeHideAll;
426 } 534 }
427 535
428 - (void)changeOverlayToFraction:(CGFloat)fraction withAnimation:(BOOL)animate { 536 - (void)animateToolbarVisibility:(BOOL)visible {
429 // The non-animated case is really simple, so do it and return. 537 CGFloat fraction = visible ? 1.0 : 0.0;
430 if (!animate) {
431 [currentAnimation_ stopAnimation];
432 [self changeToolbarFraction:fraction];
433 return;
434 }
435 538
436 // If we're already animating to the given fraction, then there's nothing more 539 // If we're already animating to the given fraction, then there's nothing
437 // to do. 540 // more to do.
438 if (currentAnimation_ && [currentAnimation_ endFraction] == fraction) 541 if (currentAnimation_ && [currentAnimation_ endFraction] == fraction)
439 return; 542 return;
440 543
441 // In all other cases, we want to cancel any running animation (which may be 544 // In all other cases, we want to cancel any running animation (which may be
442 // to show or to hide). 545 // to show or to hide).
443 [currentAnimation_ stopAnimation]; 546 [currentAnimation_ stopAnimation];
444 547
445 // Create the animation and set it up. 548 // Create the animation and set it up.
446 currentAnimation_.reset([[DropdownAnimation alloc] 549 currentAnimation_.reset([[DropdownAnimation alloc]
447 initWithFraction:fraction 550 initWithFraction:fraction
448 fullDuration:kDropdownAnimationDuration 551 fullDuration:kDropdownAnimationDuration
449 animationCurve:NSAnimationEaseOut 552 animationCurve:NSAnimationEaseOut
450 controller:self]); 553 controller:self]);
451 DCHECK(currentAnimation_); 554 DCHECK(currentAnimation_);
452 [currentAnimation_ setAnimationBlockingMode:NSAnimationNonblocking]; 555 [currentAnimation_ setAnimationBlockingMode:NSAnimationNonblocking];
453 [currentAnimation_ setDelegate:self]; 556 [currentAnimation_ setDelegate:self];
454 557
558 // If there is an existing tracking area, remove it. We do not track mouse
559 // movements during animations (see class comment in the header file).
560 [self removeTrackingAreaIfNecessary];
561
455 [currentAnimation_ startAnimation]; 562 [currentAnimation_ startAnimation];
456 } 563 }
457 564
458 - (void)cancelHideTimer { 565 - (void)cancelHideTimer {
459 [hideTimer_ invalidate]; 566 [hideTimer_ invalidate];
460 hideTimer_.reset(); 567 hideTimer_.reset();
461 } 568 }
462 569
463 - (void)hideTimerFire:(NSTimer*)timer { 570 - (void)hideTimerFire:(NSTimer*)timer {
464 DCHECK_EQ(hideTimer_, timer); // This better be our hide timer. 571 DCHECK_EQ(hideTimer_, timer); // This better be our hide timer.
465 [hideTimer_ invalidate]; // Make sure it doesn't repeat. 572 [hideTimer_ invalidate]; // Make sure it doesn't repeat.
466 hideTimer_.reset(); // And get rid of it. 573 hideTimer_.reset(); // And get rid of it.
467 [self changeOverlayToFraction:0 withAnimation:YES]; 574 [self animateToolbarVisibility:NO];
468 } 575 }
469 576
470 - (void)cleanup { 577 - (void)cleanup {
471 [self cancelAnimationAndTimer]; 578 [self cancelAnimationAndTimer];
472 [[NSNotificationCenter defaultCenter] removeObserver:self]; 579 [[NSNotificationCenter defaultCenter] removeObserver:self];
473 580
474 // This isn't tracked when not in fullscreen mode. 581 [self removeTrackingAreaIfNecessary];
475 [browserController_ releaseBarVisibilityForOwner:self withAnimation:NO];
476 582
477 // Call the main status resignation code to perform the associated cleanup, 583 // Call the main status resignation code to perform the associated cleanup,
478 // since we will no longer be receiving actual status resignation 584 // since we will no longer be receiving actual status resignation
479 // notifications. 585 // notifications.
480 [self setSystemFullscreenModeTo:base::mac::kFullScreenModeNormal]; 586 [self setSystemFullscreenModeTo:base::mac::kFullScreenModeNormal];
481 587
482 // No more calls back up to the BWC. 588 // No more calls back up to the BWC.
483 browserController_ = nil; 589 browserController_ = nil;
484 } 590 }
485 591
486 - (void)showActiveWindowUI {
487 [self updateMenuBarAndDockVisibility];
488 }
489
490 - (void)hideActiveWindowUI {
491 [self updateMenuBarAndDockVisibility];
492 }
493
494 - (BOOL)shouldShowMenubarInImmersiveFullscreen { 592 - (BOOL)shouldShowMenubarInImmersiveFullscreen {
495 return [self doesScreenHaveMenuBar] && toolbarFraction_ > 0.99; 593 return [self doesScreenHaveMenuBar] && [self toolbarFraction] > 0.99;
496 } 594 }
497 595
498 @end 596 @end
OLDNEW
« 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