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

Side by Side Diff: chrome/browser/ui/cocoa/fullscreen_toolbar_controller.mm

Issue 2484973004: [Mac] Refactor Immersive Fullscreen Logic (Closed)
Patch Set: fix for rsesek Created 4 years, 1 month 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') | ui/base/cocoa/tracking_area.h » ('j') | 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 #include "chrome/browser/profiles/profile.h" 12 #include "chrome/browser/profiles/profile.h"
13 #import "chrome/browser/ui/cocoa/browser_window_controller.h" 13 #import "chrome/browser/ui/cocoa/browser_window_controller.h"
14 #import "chrome/browser/ui/cocoa/fullscreen/fullscreen_menubar_tracker.h" 14 #import "chrome/browser/ui/cocoa/fullscreen/fullscreen_menubar_tracker.h"
15 #import "chrome/browser/ui/cocoa/fullscreen/fullscreen_toolbar_animation_control ler.h" 15 #import "chrome/browser/ui/cocoa/fullscreen/fullscreen_toolbar_animation_control ler.h"
16 #import "chrome/browser/ui/cocoa/fullscreen/fullscreen_toolbar_mouse_tracker.h" 16 #import "chrome/browser/ui/cocoa/fullscreen/fullscreen_toolbar_mouse_tracker.h"
17 #import "chrome/browser/ui/cocoa/fullscreen/fullscreen_toolbar_visibility_lock_c ontroller.h" 17 #import "chrome/browser/ui/cocoa/fullscreen/fullscreen_toolbar_visibility_lock_c ontroller.h"
18 #import "chrome/browser/ui/cocoa/fullscreen/immersive_fullscreen_controller.h"
18 #include "chrome/common/chrome_switches.h" 19 #include "chrome/common/chrome_switches.h"
19 #include "chrome/common/pref_names.h" 20 #include "chrome/common/pref_names.h"
20 #include "ui/base/cocoa/appkit_utils.h" 21 #include "ui/base/cocoa/appkit_utils.h"
21 #import "ui/base/cocoa/nsview_additions.h" 22 #import "ui/base/cocoa/nsview_additions.h"
22 23
23 namespace { 24 namespace {
24 25
25 // Visibility fractions for the menubar and toolbar. 26 // Visibility fractions for the menubar and toolbar.
26 const CGFloat kHideFraction = 0.0; 27 const CGFloat kHideFraction = 0.0;
27 const CGFloat kShowFraction = 1.0; 28 const CGFloat kShowFraction = 1.0;
28 29
29 // The amount by which the toolbar is offset downwards (to avoid the menu) 30 // The amount by which the toolbar is offset downwards (to avoid the menu)
30 // when the toolbar style is TOOLBAR_HIDDEN. (We can't use 31 // when the toolbar style is TOOLBAR_HIDDEN. (We can't use
31 // |-[NSMenu menuBarHeight]| since it returns 0 when the menu bar is hidden.) 32 // |-[NSMenu menuBarHeight]| since it returns 0 when the menu bar is hidden.)
32 const CGFloat kToolbarVerticalOffset = 22; 33 const CGFloat kToolbarVerticalOffset = 22;
33 34
34 } // end namespace 35 } // end namespace
35 36
36 @interface FullscreenToolbarController (PrivateMethods)
37
38 // Updates the visibility of the menu bar and the dock.
39 - (void)updateMenuBarAndDockVisibility;
40
41 // Whether the current screen is expected to have a menu bar, regardless of
42 // current visibility of the menu bar.
43 - (BOOL)doesScreenHaveMenuBar;
44
45 // Returns YES if the window is on the primary screen.
46 - (BOOL)isWindowOnPrimaryScreen;
47
48 // Returns |kFullScreenModeHideAll| when the overlay is hidden and
49 // |kFullScreenModeHideDock| when the overlay is shown.
50 - (base::mac::FullScreenMode)desiredSystemFullscreenMode;
51
52 // Stops any running animations, etc.
53 - (void)cleanup;
54
55 // Whether the menu bar should be shown in immersive fullscreen for the screen
56 // that contains the window.
57 - (BOOL)shouldShowMenubarInImmersiveFullscreen;
58
59 @end
60
61 @implementation FullscreenToolbarController 37 @implementation FullscreenToolbarController
62 38
63 @synthesize toolbarStyle = toolbarStyle_; 39 @synthesize toolbarStyle = toolbarStyle_;
64 40
65 - (id)initWithBrowserController:(BrowserWindowController*)controller { 41 - (id)initWithBrowserController:(BrowserWindowController*)controller {
66 if ((self = [super init])) { 42 if ((self = [super init])) {
67 browserController_ = controller; 43 browserController_ = controller;
68 systemFullscreenMode_ = base::mac::kFullScreenModeNormal;
69 animationController_.reset(new FullscreenToolbarAnimationController(self)); 44 animationController_.reset(new FullscreenToolbarAnimationController(self));
70 visibilityLockController_.reset( 45 visibilityLockController_.reset(
71 [[FullscreenToolbarVisibilityLockController alloc] 46 [[FullscreenToolbarVisibilityLockController alloc]
72 initWithFullscreenToolbarController:self 47 initWithFullscreenToolbarController:self
73 animationController:animationController_.get()]); 48 animationController:animationController_.get()]);
74 } 49 }
75 50
76 return self; 51 return self;
77 } 52 }
78 53
79 - (void)dealloc { 54 - (void)dealloc {
80 DCHECK(!inFullscreenMode_); 55 DCHECK(!inFullscreenMode_);
81 [super dealloc]; 56 [super dealloc];
82 } 57 }
83 58
84 - (void)enterFullscreenMode { 59 - (void)enterFullscreenMode {
85 DCHECK(!inFullscreenMode_); 60 DCHECK(!inFullscreenMode_);
86 inFullscreenMode_ = YES; 61 inFullscreenMode_ = YES;
87 62
88 [self updateToolbarStyle]; 63 [self updateToolbarStyle];
89 64
90 menubarTracker_.reset([[FullscreenMenubarTracker alloc] 65 if ([browserController_ isInImmersiveFullscreen]) {
91 initWithFullscreenToolbarController:self]); 66 immersiveFullscreenController_.reset([[ImmersiveFullscreenController alloc]
92 mouseTracker_.reset([[FullscreenToolbarMouseTracker alloc] 67 initWithBrowserController:browserController_]);
93 initWithFullscreenToolbarController:self 68 [immersiveFullscreenController_ updateMenuBarAndDockVisibility];
94 animationController:animationController_.get()]); 69 } else {
95 70 menubarTracker_.reset([[FullscreenMenubarTracker alloc]
96 [self updateMenuBarAndDockVisibility]; 71 initWithFullscreenToolbarController:self]);
97 72 mouseTracker_.reset([[FullscreenToolbarMouseTracker alloc]
98 // Register for notifications. Self is removed as an observer in |-cleanup|. 73 initWithFullscreenToolbarController:self
99 NSNotificationCenter* nc = [NSNotificationCenter defaultCenter]; 74 animationController:animationController_.get()]);
100 NSWindow* window = [browserController_ window]; 75 }
101
102 [nc addObserver:self
103 selector:@selector(windowDidBecomeMain:)
104 name:NSWindowDidBecomeMainNotification
105 object:window];
106
107 [nc addObserver:self
108 selector:@selector(windowDidResignMain:)
109 name:NSWindowDidResignMainNotification
110 object:window];
111 } 76 }
112 77
113 - (void)exitFullscreenMode { 78 - (void)exitFullscreenMode {
114 DCHECK(inFullscreenMode_); 79 DCHECK(inFullscreenMode_);
115 inFullscreenMode_ = NO; 80 inFullscreenMode_ = NO;
116 [self cleanup];
117 }
118 81
119 - (void)windowDidChangeScreen:(NSNotification*)notification { 82 animationController_->StopAnimationAndTimer();
120 [browserController_ resizeFullscreenWindow]; 83 [[NSNotificationCenter defaultCenter] removeObserver:self];
121 }
122 84
123 - (void)windowDidMove:(NSNotification*)notification { 85 menubarTracker_.reset();
124 [browserController_ resizeFullscreenWindow]; 86 mouseTracker_.reset();
125 } 87 immersiveFullscreenController_.reset();
126 88
127 - (void)windowDidBecomeMain:(NSNotification*)notification { 89 // No more calls back up to the BWC.
128 [self updateMenuBarAndDockVisibility]; 90 browserController_ = nil;
129 }
130
131 - (void)windowDidResignMain:(NSNotification*)notification {
132 [self updateMenuBarAndDockVisibility];
133 } 91 }
134 92
135 // Cancels any running animation and timers. 93 // Cancels any running animation and timers.
136 - (void)cancelAnimationAndTimer { 94 - (void)cancelAnimationAndTimer {
137 animationController_->StopAnimationAndTimer(); 95 animationController_->StopAnimationAndTimer();
138 } 96 }
139 97
140 - (void)revealToolbarForTabStripChanges { 98 - (void)revealToolbarForTabStripChanges {
141 if (!base::CommandLine::ForCurrentProcess()->HasSwitch( 99 if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
142 switches::kEnableFullscreenToolbarReveal)) { 100 switches::kEnableFullscreenToolbarReveal)) {
143 return; 101 return;
144 } 102 }
145 103
146 animationController_->AnimateToolbarForTabstripChanges(); 104 animationController_->AnimateToolbarForTabstripChanges();
147 } 105 }
148 106
149 - (void)setSystemFullscreenModeTo:(base::mac::FullScreenMode)mode {
150 if (mode == systemFullscreenMode_)
151 return;
152 if (systemFullscreenMode_ == base::mac::kFullScreenModeNormal)
153 base::mac::RequestFullScreen(mode);
154 else if (mode == base::mac::kFullScreenModeNormal)
155 base::mac::ReleaseFullScreen(systemFullscreenMode_);
156 else
157 base::mac::SwitchFullScreenModes(systemFullscreenMode_, mode);
158 systemFullscreenMode_ = mode;
159 }
160
161 - (void)updateToolbarStyle { 107 - (void)updateToolbarStyle {
162 FullscreenToolbarStyle oldStyle = toolbarStyle_; 108 FullscreenToolbarStyle oldStyle = toolbarStyle_;
163 109
164 if ([browserController_ isFullscreenForTabContentOrExtension]) { 110 if ([browserController_ isFullscreenForTabContentOrExtension]) {
165 toolbarStyle_ = FullscreenToolbarStyle::TOOLBAR_NONE; 111 toolbarStyle_ = FullscreenToolbarStyle::TOOLBAR_NONE;
166 } else { 112 } else {
167 PrefService* prefs = [browserController_ profile]->GetPrefs(); 113 PrefService* prefs = [browserController_ profile]->GetPrefs();
168 toolbarStyle_ = prefs->GetBoolean(prefs::kShowFullscreenToolbar) 114 toolbarStyle_ = prefs->GetBoolean(prefs::kShowFullscreenToolbar)
169 ? FullscreenToolbarStyle::TOOLBAR_PRESENT 115 ? FullscreenToolbarStyle::TOOLBAR_PRESENT
170 : FullscreenToolbarStyle::TOOLBAR_HIDDEN; 116 : FullscreenToolbarStyle::TOOLBAR_HIDDEN;
171 } 117 }
172 118
173 if (oldStyle != toolbarStyle_) 119 if (oldStyle != toolbarStyle_)
174 [self updateToolbar]; 120 [self updateToolbar];
175 } 121 }
176 122
177 - (void)updateToolbar { 123 - (void)updateToolbar {
178 [browserController_ layoutSubviews]; 124 [browserController_ layoutSubviews];
179 animationController_->ToolbarDidUpdate(); 125 animationController_->ToolbarDidUpdate();
180 [mouseTracker_ updateTrackingArea]; 126 [mouseTracker_ updateTrackingArea];
181
182 // In AppKit fullscreen, moving the mouse to the top of the screen toggles
183 // menu visibility. Replicate the same effect for immersive fullscreen.
184 if ([browserController_ isInImmersiveFullscreen])
185 [self updateMenuBarAndDockVisibility];
186 } 127 }
187 128
188 - (BrowserWindowController*)browserWindowController { 129 - (BrowserWindowController*)browserWindowController {
189 return browserController_; 130 return browserController_;
190 } 131 }
191 132
192 - (FullscreenToolbarVisibilityLockController*)visibilityLockController { 133 - (FullscreenToolbarVisibilityLockController*)visibilityLockController {
193 return visibilityLockController_.get(); 134 return visibilityLockController_.get();
194 } 135 }
195 136
196 // This method works, but is fragile. 137 // This method works, but is fragile.
197 // 138 //
198 // It gets used during view layout, which sometimes needs to be done at the 139 // It gets used during view layout, which sometimes needs to be done at the
199 // beginning of an animation. As such, this method needs to reflect the 140 // beginning of an animation. As such, this method needs to reflect the
200 // menubarOffset expected at the end of the animation. This information is not 141 // menubarOffset expected at the end of the animation. This information is not
201 // readily available. (The layout logic needs a refactor). 142 // readily available. (The layout logic needs a refactor).
202 // 143 //
203 // For AppKit Fullscreen, the menubar always starts hidden, and 144 // For AppKit Fullscreen, the menubar always starts hidden, and
204 // menubarFraction_ always starts at 0, so the logic happens to work. For 145 // menubarFraction_ always starts at 0, so the logic happens to work. For
205 // Immersive Fullscreen, this class controls the visibility of the menu bar, so 146 // Immersive Fullscreen, this class controls the visibility of the menu bar, so
206 // the logic is correct and not fragile. 147 // the logic is correct and not fragile.
207 - (CGFloat)menubarOffset { 148 - (CGFloat)menubarOffset {
208 if ([browserController_ isInAppKitFullscreen]) { 149 if ([browserController_ isInAppKitFullscreen]) {
209 return -std::floor([menubarTracker_ menubarFraction] * 150 return -std::floor([menubarTracker_ menubarFraction] *
210 kToolbarVerticalOffset); 151 kToolbarVerticalOffset);
211 } 152 }
212 153
213 return [self shouldShowMenubarInImmersiveFullscreen] ? -kToolbarVerticalOffset 154 return [immersiveFullscreenController_ shouldShowMenubar]
214 : 0; 155 ? -kToolbarVerticalOffset
156 : 0;
215 } 157 }
216 158
217 - (CGFloat)toolbarFraction { 159 - (CGFloat)toolbarFraction {
218 if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kKioskMode)) 160 if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kKioskMode))
219 return kHideFraction; 161 return kHideFraction;
220 162
221 switch (toolbarStyle_) { 163 switch (toolbarStyle_) {
222 case FullscreenToolbarStyle::TOOLBAR_PRESENT: 164 case FullscreenToolbarStyle::TOOLBAR_PRESENT:
223 return kShowFraction; 165 return kShowFraction;
224 case FullscreenToolbarStyle::TOOLBAR_NONE: 166 case FullscreenToolbarStyle::TOOLBAR_NONE:
(...skipping 18 matching lines...) Expand all
243 185
244 if (toolbarStyle_ == FullscreenToolbarStyle::TOOLBAR_NONE) 186 if (toolbarStyle_ == FullscreenToolbarStyle::TOOLBAR_NONE)
245 return NO; 187 return NO;
246 188
247 FullscreenMenubarState menubarState = [menubarTracker_ state]; 189 FullscreenMenubarState menubarState = [menubarTracker_ state];
248 return menubarState == FullscreenMenubarState::SHOWN || 190 return menubarState == FullscreenMenubarState::SHOWN ||
249 [mouseTracker_ mouseInsideTrackingArea] || 191 [mouseTracker_ mouseInsideTrackingArea] ||
250 [visibilityLockController_ isToolbarVisibilityLocked]; 192 [visibilityLockController_ isToolbarVisibilityLocked];
251 } 193 }
252 194
253 - (BOOL)isFullscreenTransitionInProgress {
254 return [browserController_ isFullscreenTransitionInProgress];
255 }
256
257 - (BOOL)isInFullscreen { 195 - (BOOL)isInFullscreen {
258 return inFullscreenMode_; 196 return inFullscreenMode_;
259 } 197 }
260 198
261 - (BOOL)isMouseOnScreen {
262 return NSMouseInRect([NSEvent mouseLocation],
263 [[browserController_ window] screen].frame, false);
264 }
265
266 - (void)updateToolbarFrame:(NSRect)frame { 199 - (void)updateToolbarFrame:(NSRect)frame {
267 if (mouseTracker_.get()) 200 if (mouseTracker_.get())
268 [mouseTracker_ updateToolbarFrame:frame]; 201 [mouseTracker_ updateToolbarFrame:frame];
269 } 202 }
270 203
271 @end 204 @end
272 205
273 @implementation FullscreenToolbarController (PrivateMethods)
274
275 - (void)updateMenuBarAndDockVisibility {
276 if (![self isMouseOnScreen] ||
277 ![browserController_ isInImmersiveFullscreen]) {
278 [self setSystemFullscreenModeTo:base::mac::kFullScreenModeNormal];
279 return;
280 }
281
282 // The screen does not have a menu bar, so there's no need to hide it.
283 if (![self doesScreenHaveMenuBar]) {
284 [self setSystemFullscreenModeTo:base::mac::kFullScreenModeHideDock];
285 return;
286 }
287
288 [self setSystemFullscreenModeTo:[self desiredSystemFullscreenMode]];
289 }
290
291 - (BOOL)doesScreenHaveMenuBar {
292 if (![[NSScreen class]
293 respondsToSelector:@selector(screensHaveSeparateSpaces)])
294 return [self isWindowOnPrimaryScreen];
295
296 BOOL eachScreenShouldHaveMenuBar = [NSScreen screensHaveSeparateSpaces];
297 return eachScreenShouldHaveMenuBar ?: [self isWindowOnPrimaryScreen];
298 }
299
300 - (BOOL)isWindowOnPrimaryScreen {
301 NSScreen* screen = [[browserController_ window] screen];
302 NSScreen* primaryScreen = [[NSScreen screens] firstObject];
303 return (screen == primaryScreen);
304 }
305
306 - (base::mac::FullScreenMode)desiredSystemFullscreenMode {
307 if ([self shouldShowMenubarInImmersiveFullscreen])
308 return base::mac::kFullScreenModeHideDock;
309 return base::mac::kFullScreenModeHideAll;
310 }
311
312 - (void)cleanup {
313 animationController_->StopAnimationAndTimer();
314 [[NSNotificationCenter defaultCenter] removeObserver:self];
315
316 // Call the main status resignation code to perform the associated cleanup,
317 // since we will no longer be receiving actual status resignation
318 // notifications.
319 [self setSystemFullscreenModeTo:base::mac::kFullScreenModeNormal];
320
321 // No more calls back up to the BWC.
322 browserController_ = nil;
323
324 menubarTracker_.reset();
325 mouseTracker_.reset();
326 }
327
328 - (BOOL)shouldShowMenubarInImmersiveFullscreen {
329 return [self doesScreenHaveMenuBar] && [self toolbarFraction] > 0.99;
330 }
331
332 @end
OLDNEW
« no previous file with comments | « chrome/browser/ui/cocoa/fullscreen_toolbar_controller.h ('k') | ui/base/cocoa/tracking_area.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698