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

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