OLD | NEW |
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/browser_window_controller_private.h" | 5 #import "chrome/browser/ui/cocoa/browser_window_controller_private.h" |
6 | 6 |
7 #include <cmath> | 7 #include <cmath> |
8 | 8 |
9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
10 #include "base/mac/mac_util.h" | 10 #include "base/mac/mac_util.h" |
11 #import "base/mac/scoped_nsobject.h" | 11 #import "base/mac/scoped_nsobject.h" |
12 #import "base/mac/sdk_forward_declarations.h" | 12 #import "base/mac/sdk_forward_declarations.h" |
13 #include "base/prefs/pref_service.h" | 13 #include "base/prefs/pref_service.h" |
14 #include "base/prefs/scoped_user_pref_update.h" | 14 #include "base/prefs/scoped_user_pref_update.h" |
15 #include "chrome/browser/browser_process.h" | 15 #include "chrome/browser/browser_process.h" |
16 #include "chrome/browser/fullscreen.h" | 16 #include "chrome/browser/fullscreen.h" |
17 #include "chrome/browser/profiles/profile.h" | 17 #include "chrome/browser/profiles/profile.h" |
18 #include "chrome/browser/profiles/profile_avatar_icon_util.h" | 18 #include "chrome/browser/profiles/profile_avatar_icon_util.h" |
19 #include "chrome/browser/ui/bookmarks/bookmark_tab_helper.h" | 19 #include "chrome/browser/ui/bookmarks/bookmark_tab_helper.h" |
20 #include "chrome/browser/ui/browser.h" | 20 #include "chrome/browser/ui/browser.h" |
21 #include "chrome/browser/ui/browser_window_state.h" | 21 #include "chrome/browser/ui/browser_window_state.h" |
| 22 #import "chrome/browser/ui/cocoa/browser_window_layout.h" |
22 #import "chrome/browser/ui/cocoa/dev_tools_controller.h" | 23 #import "chrome/browser/ui/cocoa/dev_tools_controller.h" |
23 #import "chrome/browser/ui/cocoa/fast_resize_view.h" | 24 #import "chrome/browser/ui/cocoa/fast_resize_view.h" |
24 #import "chrome/browser/ui/cocoa/find_bar/find_bar_cocoa_controller.h" | 25 #import "chrome/browser/ui/cocoa/find_bar/find_bar_cocoa_controller.h" |
25 #import "chrome/browser/ui/cocoa/floating_bar_backing_view.h" | 26 #import "chrome/browser/ui/cocoa/floating_bar_backing_view.h" |
26 #import "chrome/browser/ui/cocoa/framed_browser_window.h" | 27 #import "chrome/browser/ui/cocoa/framed_browser_window.h" |
27 #import "chrome/browser/ui/cocoa/fullscreen_window.h" | 28 #import "chrome/browser/ui/cocoa/fullscreen_window.h" |
28 #import "chrome/browser/ui/cocoa/infobars/infobar_container_controller.h" | 29 #import "chrome/browser/ui/cocoa/infobars/infobar_container_controller.h" |
29 #include "chrome/browser/ui/cocoa/last_active_browser_cocoa.h" | 30 #include "chrome/browser/ui/cocoa/last_active_browser_cocoa.h" |
30 #import "chrome/browser/ui/cocoa/nsview_additions.h" | 31 #import "chrome/browser/ui/cocoa/nsview_additions.h" |
31 #import "chrome/browser/ui/cocoa/presentation_mode_controller.h" | 32 #import "chrome/browser/ui/cocoa/presentation_mode_controller.h" |
(...skipping 15 matching lines...) Expand all Loading... |
47 #include "ui/base/ui_base_types.h" | 48 #include "ui/base/ui_base_types.h" |
48 | 49 |
49 using content::RenderWidgetHostView; | 50 using content::RenderWidgetHostView; |
50 using content::WebContents; | 51 using content::WebContents; |
51 | 52 |
52 namespace { | 53 namespace { |
53 | 54 |
54 // Space between the incognito badge and the right edge of the window. | 55 // Space between the incognito badge and the right edge of the window. |
55 const CGFloat kAvatarRightOffset = 4; | 56 const CGFloat kAvatarRightOffset = 4; |
56 | 57 |
57 // Insets for the location bar, used when the full toolbar is hidden. | |
58 // TODO(viettrungluu): We can argue about the "correct" insetting; I like the | |
59 // following best, though arguably 0 inset is better/more correct. | |
60 const CGFloat kLocBarLeftRightInset = 1; | |
61 const CGFloat kLocBarTopInset = 0; | |
62 const CGFloat kLocBarBottomInset = 1; | |
63 | |
64 } // namespace | 58 } // namespace |
65 | 59 |
66 @implementation BrowserWindowController(Private) | 60 @implementation BrowserWindowController(Private) |
67 | 61 |
68 // Create the tab strip controller. | 62 // Create the tab strip controller. |
69 - (void)createTabStripController { | 63 - (void)createTabStripController { |
70 DCHECK([overlayableContentsController_ activeContainer]); | 64 DCHECK([overlayableContentsController_ activeContainer]); |
71 DCHECK([[overlayableContentsController_ activeContainer] window]); | 65 DCHECK([[overlayableContentsController_ activeContainer] window]); |
72 tabStripController_.reset([[TabStripController alloc] | 66 tabStripController_.reset([[TabStripController alloc] |
73 initWithView:[self tabStripView] | 67 initWithView:[self tabStripView] |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
163 defaultSheetRect.origin.y = NSHeight([[window contentView] frame]) - | 157 defaultSheetRect.origin.y = NSHeight([[window contentView] frame]) - |
164 defaultSheetRect.size.height; | 158 defaultSheetRect.size.height; |
165 } | 159 } |
166 break; | 160 break; |
167 } | 161 } |
168 } | 162 } |
169 return defaultSheetRect; | 163 return defaultSheetRect; |
170 } | 164 } |
171 | 165 |
172 - (void)layoutSubviews { | 166 - (void)layoutSubviews { |
173 // With the exception of the top tab strip, the subviews which we lay out are | 167 // Suppress title drawing if necessary. |
174 // subviews of the content view, so we mainly work in the content view's | 168 if ([self.window respondsToSelector:@selector(setShouldHideTitle:)]) |
175 // coordinate system. Note, however, that the content view's coordinate system | 169 [(id)self.window setShouldHideTitle:![self hasTitleBar]]; |
176 // and the window's base coordinate system should coincide. | |
177 NSWindow* window = [self window]; | |
178 NSView* contentView = [window contentView]; | |
179 NSRect contentBounds = [contentView bounds]; | |
180 CGFloat minX = NSMinX(contentBounds); | |
181 CGFloat minY = NSMinY(contentBounds); | |
182 CGFloat width = NSWidth(contentBounds); | |
183 | 170 |
184 // Suppress title drawing if necessary. | 171 [bookmarkBarController_ updateHiddenState]; |
185 if ([window respondsToSelector:@selector(setShouldHideTitle:)]) | 172 [self updateSubviewZOrder]; |
186 [(id)window setShouldHideTitle:![self hasTitleBar]]; | |
187 | 173 |
188 // Update z-order. The code below depends on this. | 174 base::scoped_nsobject<BrowserWindowLayout> layout( |
189 [self updateSubviewZOrder:[self isInFullscreenWithOmniboxSliding]]; | 175 [[BrowserWindowLayout alloc] init]); |
| 176 [self updateLayoutParameters:layout]; |
| 177 [self applyLayout:layout]; |
190 | 178 |
191 CGFloat floatingBarHeight = [self floatingBarHeight]; | |
192 CGFloat yOffset = 0; | |
193 if ([self isInFullscreenWithOmniboxSliding]) { | |
194 yOffset += [presentationModeController_ menubarOffset]; | |
195 switch (presentationModeController_.get().slidingStyle) { | |
196 case fullscreen_mac::OMNIBOX_TABS_PRESENT: | |
197 break; | |
198 case fullscreen_mac::OMNIBOX_TABS_HIDDEN: | |
199 // In presentation mode, |yOffset| accounts for the sliding position of | |
200 // the floating bar and the extra offset needed to dodge the menu bar. | |
201 yOffset += | |
202 std::floor((1 - presentationModeController_.get().toolbarFraction) * | |
203 floatingBarHeight); | |
204 break; | |
205 } | |
206 } | |
207 | |
208 CGFloat maxY = NSMaxY(contentBounds) + yOffset; | |
209 | |
210 if ([self hasTabStrip]) { | |
211 // If we need to lay out the top tab strip, replace |maxY| with a higher | |
212 // value, and then lay out the tab strip. | |
213 NSRect windowFrame = [contentView convertRect:[window frame] fromView:nil]; | |
214 maxY = NSHeight(windowFrame) + yOffset; | |
215 maxY = [self layoutTabStripAtMaxY:maxY | |
216 width:width | |
217 fullscreen:[self isInAnyFullscreenMode]]; | |
218 } | |
219 | |
220 // Sanity-check |maxY|. | |
221 DCHECK_GE(maxY, minY); | |
222 DCHECK_LE(maxY, NSMaxY(contentBounds) + yOffset); | |
223 | |
224 // Place the toolbar at the top of the reserved area. | |
225 maxY = [self layoutToolbarAtMinX:minX maxY:maxY width:width]; | |
226 | |
227 // If we're not displaying the bookmark bar below the info bar, then it goes | |
228 // immediately below the toolbar. | |
229 BOOL placeBookmarkBarBelowInfoBar = [self placeBookmarkBarBelowInfoBar]; | |
230 if (!placeBookmarkBarBelowInfoBar) | |
231 maxY = [self layoutBookmarkBarAtMinX:minX maxY:maxY width:width]; | |
232 | |
233 // The floating bar backing view doesn't actually add any height. | |
234 NSRect floatingBarBackingRect = | |
235 NSMakeRect(minX, maxY, width, floatingBarHeight); | |
236 [self layoutFloatingBarBackingView:floatingBarBackingRect | |
237 presentationMode:[self isInFullscreenWithOmniboxSliding]]; | |
238 | |
239 // Place the find bar immediately below the toolbar/attached bookmark bar. In | |
240 // presentation mode, it hangs off the top of the screen when the bar is | |
241 // hidden. | |
242 [findBarCocoaController_ positionFindBarViewAtMaxY:maxY maxWidth:width]; | |
243 [fullscreenExitBubbleController_ positionInWindowAtTop:maxY width:width]; | |
244 | |
245 if ([self isInFullscreenWithOmniboxSliding]) { | |
246 switch (presentationModeController_.get().slidingStyle) { | |
247 case fullscreen_mac::OMNIBOX_TABS_PRESENT: | |
248 // Do nothing in Canonical Fullscreen. All content slides. | |
249 break; | |
250 case fullscreen_mac::OMNIBOX_TABS_HIDDEN: | |
251 // If in presentation mode, reset |maxY| to top of screen, so that the | |
252 // floating bar slides over the things which appear to be in the content | |
253 // area. | |
254 maxY = NSMaxY(contentBounds); | |
255 break; | |
256 } | |
257 } | |
258 | |
259 // Also place the info bar container immediate below the toolbar, except in | |
260 // presentation mode in which case it's at the top of the visual content area. | |
261 maxY = [self layoutInfoBarAtMinX:minX maxY:maxY width:width]; | |
262 | |
263 // If the bookmark bar is detached, place it next in the visual content area. | |
264 if (placeBookmarkBarBelowInfoBar) | |
265 maxY = [self layoutBookmarkBarAtMinX:minX maxY:maxY width:width]; | |
266 | |
267 // Place the download shelf, if any, at the bottom of the view. | |
268 minY = [self layoutDownloadShelfAtMinX:minX minY:minY width:width]; | |
269 | |
270 // Finally, the content area takes up all of the remaining space. | |
271 NSRect contentAreaRect = NSMakeRect(minX, minY, width, maxY - minY); | |
272 [self layoutTabContentArea:contentAreaRect]; | |
273 | |
274 // Normally, we don't need to tell the toolbar whether or not to show the | |
275 // divider, but things break down during animation. | |
276 [toolbarController_ setDividerOpacity:[self toolbarDividerOpacity]]; | 179 [toolbarController_ setDividerOpacity:[self toolbarDividerOpacity]]; |
277 } | 180 } |
278 | 181 |
279 - (CGFloat)floatingBarHeight { | |
280 if (![self isInFullscreenWithOmniboxSliding]) | |
281 return 0; | |
282 | |
283 CGFloat totalHeight = 0; | |
284 if ([self hasTabStrip]) | |
285 totalHeight += NSHeight([[self tabStripView] frame]); | |
286 | |
287 if ([self hasToolbar]) { | |
288 totalHeight += NSHeight([[toolbarController_ view] frame]); | |
289 } else if ([self hasLocationBar]) { | |
290 totalHeight += NSHeight([[toolbarController_ view] frame]) + | |
291 kLocBarTopInset + kLocBarBottomInset; | |
292 } | |
293 | |
294 if (![self placeBookmarkBarBelowInfoBar]) | |
295 totalHeight += NSHeight([[bookmarkBarController_ view] frame]); | |
296 | |
297 return totalHeight; | |
298 } | |
299 | |
300 - (CGFloat)layoutTabStripAtMaxY:(CGFloat)maxY | 182 - (CGFloat)layoutTabStripAtMaxY:(CGFloat)maxY |
301 width:(CGFloat)width | 183 width:(CGFloat)width |
302 fullscreen:(BOOL)fullscreen { | 184 fullscreen:(BOOL)fullscreen { |
303 // Nothing to do if no tab strip. | 185 // Nothing to do if no tab strip. |
304 if (![self hasTabStrip]) | 186 if (![self hasTabStrip]) |
305 return maxY; | 187 return maxY; |
306 | 188 |
307 NSView* tabStripView = [self tabStripView]; | 189 NSView* tabStripView = [self tabStripView]; |
308 CGFloat tabStripHeight = NSHeight([tabStripView frame]); | 190 CGFloat tabStripHeight = NSHeight([tabStripView frame]); |
309 maxY -= tabStripHeight; | 191 maxY -= tabStripHeight; |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
376 rightIndent += NSWidth([avatarButton frame]) + kAvatarRightOffset; | 258 rightIndent += NSWidth([avatarButton frame]) + kAvatarRightOffset; |
377 } | 259 } |
378 [tabStripController_ setRightIndentForControls:rightIndent]; | 260 [tabStripController_ setRightIndentForControls:rightIndent]; |
379 | 261 |
380 // Go ahead and layout the tabs. | 262 // Go ahead and layout the tabs. |
381 [tabStripController_ layoutTabsWithoutAnimation]; | 263 [tabStripController_ layoutTabsWithoutAnimation]; |
382 | 264 |
383 return maxY; | 265 return maxY; |
384 } | 266 } |
385 | 267 |
386 - (CGFloat)layoutToolbarAtMinX:(CGFloat)minX | |
387 maxY:(CGFloat)maxY | |
388 width:(CGFloat)width { | |
389 NSView* toolbarView = [toolbarController_ view]; | |
390 NSRect toolbarFrame = [toolbarView frame]; | |
391 if ([self hasToolbar]) { | |
392 // The toolbar is present in the window, so we make room for it. | |
393 DCHECK(![toolbarView isHidden]); | |
394 toolbarFrame.origin.x = minX; | |
395 toolbarFrame.origin.y = maxY - NSHeight(toolbarFrame); | |
396 toolbarFrame.size.width = width; | |
397 maxY -= NSHeight(toolbarFrame); | |
398 } else { | |
399 if ([self hasLocationBar]) { | |
400 // Location bar is present with no toolbar. Put a border of | |
401 // |kLocBar...Inset| pixels around the location bar. | |
402 // TODO(viettrungluu): This is moderately ridiculous. The toolbar should | |
403 // really be aware of what its height should be (the way the toolbar | |
404 // compression stuff is currently set up messes things up). | |
405 DCHECK(![toolbarView isHidden]); | |
406 toolbarFrame.origin.x = kLocBarLeftRightInset; | |
407 toolbarFrame.origin.y = maxY - NSHeight(toolbarFrame) - kLocBarTopInset; | |
408 toolbarFrame.size.width = width - 2 * kLocBarLeftRightInset; | |
409 maxY -= kLocBarTopInset + NSHeight(toolbarFrame) + kLocBarBottomInset; | |
410 } else { | |
411 DCHECK([toolbarView isHidden]); | |
412 } | |
413 } | |
414 [toolbarView setFrame:toolbarFrame]; | |
415 return maxY; | |
416 } | |
417 | |
418 - (BOOL)placeBookmarkBarBelowInfoBar { | 268 - (BOOL)placeBookmarkBarBelowInfoBar { |
419 // If we are currently displaying the NTP detached bookmark bar or animating | 269 // If we are currently displaying the NTP detached bookmark bar or animating |
420 // to/from it (from/to anything else), we display the bookmark bar below the | 270 // to/from it (from/to anything else), we display the bookmark bar below the |
421 // info bar. | 271 // info bar. |
422 return [bookmarkBarController_ isInState:BookmarkBar::DETACHED] || | 272 return [bookmarkBarController_ isInState:BookmarkBar::DETACHED] || |
423 [bookmarkBarController_ isAnimatingToState:BookmarkBar::DETACHED] || | 273 [bookmarkBarController_ isAnimatingToState:BookmarkBar::DETACHED] || |
424 [bookmarkBarController_ isAnimatingFromState:BookmarkBar::DETACHED]; | 274 [bookmarkBarController_ isAnimatingFromState:BookmarkBar::DETACHED]; |
425 } | 275 } |
426 | 276 |
427 - (CGFloat)layoutBookmarkBarAtMinX:(CGFloat)minX | |
428 maxY:(CGFloat)maxY | |
429 width:(CGFloat)width { | |
430 [bookmarkBarController_ updateHiddenState]; | |
431 | |
432 NSView* bookmarkBarView = [bookmarkBarController_ view]; | |
433 NSRect frame = [bookmarkBarView frame]; | |
434 frame.origin.x = minX; | |
435 frame.origin.y = maxY - NSHeight(frame); | |
436 frame.size.width = width; | |
437 [bookmarkBarView setFrame:frame]; | |
438 maxY -= NSHeight(frame); | |
439 | |
440 // Pin the bookmark bar to the top of the window and make the width flexible. | |
441 [bookmarkBarView setAutoresizingMask:NSViewWidthSizable | NSViewMinYMargin]; | |
442 | |
443 // TODO(viettrungluu): Does this really belong here? Calling it shouldn't be | |
444 // necessary in the non-NTP case. | |
445 [bookmarkBarController_ layoutSubviews]; | |
446 | |
447 return maxY; | |
448 } | |
449 | |
450 - (void)layoutFloatingBarBackingView:(NSRect)frame | |
451 presentationMode:(BOOL)presentationMode { | |
452 // Only display when in presentation mode. | |
453 if (presentationMode) { | |
454 // For certain window types such as app windows (e.g., the dev tools | |
455 // window), there's no actual overlay. (Displaying one would result in an | |
456 // overly sliding in only under the menu, which gives an ugly effect.) | |
457 if (floatingBarBackingView_.get()) { | |
458 // Set its frame. | |
459 [floatingBarBackingView_ setFrame:frame]; | |
460 } | |
461 | |
462 // But we want the logic to work as usual (for show/hide/etc. purposes). | |
463 [presentationModeController_ overlayFrameChanged:frame]; | |
464 } else { | |
465 // Okay to call even if |floatingBarBackingView_| is nil. | |
466 if ([floatingBarBackingView_ superview]) | |
467 [floatingBarBackingView_ removeFromSuperview]; | |
468 } | |
469 } | |
470 | |
471 - (CGFloat)layoutInfoBarAtMinX:(CGFloat)minX | |
472 maxY:(CGFloat)maxY | |
473 width:(CGFloat)width { | |
474 NSView* containerView = [infoBarContainerController_ view]; | |
475 NSRect containerFrame = [containerView frame]; | |
476 maxY -= NSHeight(containerFrame); | |
477 maxY += [infoBarContainerController_ overlappingTipHeight]; | |
478 containerFrame.origin.x = minX; | |
479 containerFrame.origin.y = maxY; | |
480 containerFrame.size.width = width; | |
481 [containerView setFrame:containerFrame]; | |
482 [infoBarContainerController_ setMaxTopArrowHeight:[self | |
483 infoBarMaxTopArrowHeight]]; | |
484 return maxY; | |
485 } | |
486 | |
487 - (CGFloat)layoutDownloadShelfAtMinX:(CGFloat)minX | |
488 minY:(CGFloat)minY | |
489 width:(CGFloat)width { | |
490 if (downloadShelfController_.get()) { | |
491 NSView* downloadView = [downloadShelfController_ view]; | |
492 NSRect downloadFrame = [downloadView frame]; | |
493 downloadFrame.origin.x = minX; | |
494 downloadFrame.origin.y = minY; | |
495 downloadFrame.size.width = width; | |
496 [downloadView setFrame:downloadFrame]; | |
497 minY += NSHeight(downloadFrame); | |
498 } | |
499 return minY; | |
500 } | |
501 | |
502 - (void)layoutTabContentArea:(NSRect)newFrame { | 277 - (void)layoutTabContentArea:(NSRect)newFrame { |
503 NSView* tabContentView = [self tabContentArea]; | 278 NSView* tabContentView = [self tabContentArea]; |
504 NSRect tabContentFrame = [tabContentView frame]; | 279 NSRect tabContentFrame = [tabContentView frame]; |
505 | 280 |
506 bool contentShifted = | 281 bool contentShifted = |
507 NSMaxY(tabContentFrame) != NSMaxY(newFrame) || | 282 NSMaxY(tabContentFrame) != NSMaxY(newFrame) || |
508 NSMinX(tabContentFrame) != NSMinX(newFrame); | 283 NSMinX(tabContentFrame) != NSMinX(newFrame); |
509 | 284 |
510 tabContentFrame = newFrame; | 285 tabContentFrame = newFrame; |
511 [tabContentView setFrame:tabContentFrame]; | 286 [tabContentView setFrame:tabContentFrame]; |
(...skipping 490 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1002 [superview addSubview:view | 777 [superview addSubview:view |
1003 positioned:NSWindowAbove | 778 positioned:NSWindowAbove |
1004 relativeTo:siblingBelow]; | 779 relativeTo:siblingBelow]; |
1005 } else { | 780 } else { |
1006 [superview addSubview:view | 781 [superview addSubview:view |
1007 positioned:NSWindowBelow | 782 positioned:NSWindowBelow |
1008 relativeTo:nil]; | 783 relativeTo:nil]; |
1009 } | 784 } |
1010 } | 785 } |
1011 | 786 |
1012 // TODO(erikchen): The implementation of this method is quite fragile. The | 787 - (void)updateInfoBarTipVisibility { |
1013 // method cr_ensureSubview:... does not check that the subview is /directly/ | 788 // If there's no toolbar then hide the infobar tip. |
1014 // above/below the given view. e.g. There are 3 subviews: A, B, C, in that | 789 [infoBarContainerController_ |
1015 // order. The method cr_ensureSubview:A isPositioned:NSWindowBelow | 790 setShouldSuppressTopInfoBarTip:![self hasToolbar]]; |
1016 // relativeTo:C will have no effect, even though the desired result may have | 791 } |
1017 // been: B, A, C. Consider changing it? | 792 |
1018 - (void)updateSubviewZOrder:(BOOL)inAnyFullscreen { | 793 - (NSInteger)pageInfoBubblePointY { |
1019 NSView* contentView = [[self window] contentView]; | 794 LocationBarViewMac* locationBarView = [self locationBarBridge]; |
1020 NSView* toolbarView = [toolbarController_ view]; | 795 |
1021 | 796 // The point, in window coordinates. |
1022 if (inAnyFullscreen) { | 797 NSPoint iconBottom = locationBarView->GetPageInfoBubblePoint(); |
1023 // Toolbar is above tab contents so that it can slide down from top of | 798 |
1024 // screen. | 799 // The toolbar, in window coordinates. |
1025 [contentView cr_ensureSubview:toolbarView | 800 NSView* toolbar = [toolbarController_ view]; |
1026 isPositioned:NSWindowAbove | 801 CGFloat toolbarY = NSMinY([toolbar convertRect:[toolbar bounds] toView:nil]); |
1027 relativeTo:[self tabContentArea]]; | 802 |
| 803 return iconBottom.y - toolbarY; |
| 804 } |
| 805 |
| 806 - (void)enterAppKitFullscreen { |
| 807 DCHECK(base::mac::IsOSLionOrLater()); |
| 808 if (FramedBrowserWindow* framedBrowserWindow = |
| 809 base::mac::ObjCCast<FramedBrowserWindow>([self window])) { |
| 810 [framedBrowserWindow toggleSystemFullScreen]; |
| 811 } |
| 812 } |
| 813 |
| 814 - (void)exitAppKitFullscreen { |
| 815 DCHECK(base::mac::IsOSLionOrLater()); |
| 816 if (FramedBrowserWindow* framedBrowserWindow = |
| 817 base::mac::ObjCCast<FramedBrowserWindow>([self window])) { |
| 818 [framedBrowserWindow toggleSystemFullScreen]; |
| 819 } |
| 820 } |
| 821 |
| 822 - (void)updateLayoutParameters:(BrowserWindowLayout*)layout { |
| 823 [layout setContentViewSize:[[[self window] contentView] bounds].size]; |
| 824 [layout setWindowSize:[[self window] frame].size]; |
| 825 |
| 826 [layout setInAnyFullscreen:[self isInFullscreenWithOmniboxSliding]]; |
| 827 [layout setFullscreenSlidingStyle: |
| 828 presentationModeController_.get().slidingStyle]; |
| 829 [layout setFullscreenMenubarOffset: |
| 830 [presentationModeController_ menubarOffset]]; |
| 831 [layout setFullscreenToolbarFraction: |
| 832 [presentationModeController_ toolbarFraction]]; |
| 833 |
| 834 [layout setHasTabStrip:[self hasTabStrip]]; |
| 835 |
| 836 [layout setHasToolbar:[self hasToolbar]]; |
| 837 [layout setToolbarHeight:NSHeight([[toolbarController_ view] bounds])]; |
| 838 |
| 839 [layout setHasLocationBar:[self hasLocationBar]]; |
| 840 |
| 841 [layout setPlaceBookmarkBarBelowInfoBar:[self placeBookmarkBarBelowInfoBar]]; |
| 842 [layout setBookmarkBarHidden:[bookmarkBarController_ view].isHidden]; |
| 843 [layout setBookmarkBarHeight: |
| 844 NSHeight([[bookmarkBarController_ view] bounds])]; |
| 845 |
| 846 [layout setInfoBarHeight:[infoBarContainerController_ heightOfInfoBars]]; |
| 847 [layout setPageInfoBubblePointY:[self pageInfoBubblePointY]]; |
| 848 |
| 849 [layout setHasDownloadShelf:(downloadShelfController_.get() != nil)]; |
| 850 [layout setDownloadShelfHeight: |
| 851 NSHeight([[downloadShelfController_ view] bounds])]; |
| 852 } |
| 853 |
| 854 - (void)applyLayout:(BrowserWindowLayout*)layout { |
| 855 chrome::LayoutOutput output = [layout computeLayout]; |
| 856 |
| 857 if (!NSIsEmptyRect(output.tabStripFrame)) { |
| 858 // Note: The fullscreen parameter passed to the method is different from |
| 859 // the field in |parameters| with the similar name. |
| 860 [self layoutTabStripAtMaxY:NSMaxY(output.tabStripFrame) |
| 861 width:NSWidth(output.tabStripFrame) |
| 862 fullscreen:[self isInAnyFullscreenMode]]; |
| 863 } |
| 864 |
| 865 if (!NSIsEmptyRect(output.toolbarFrame)) { |
| 866 [[toolbarController_ view] setFrame:output.toolbarFrame]; |
| 867 } |
| 868 |
| 869 if (!NSIsEmptyRect(output.bookmarkFrame)) { |
| 870 NSView* bookmarkBarView = [bookmarkBarController_ view]; |
| 871 [bookmarkBarView setFrame:output.bookmarkFrame]; |
| 872 |
| 873 // Pin the bookmark bar to the top of the window and make the width |
| 874 // flexible. |
| 875 [bookmarkBarView setAutoresizingMask:NSViewWidthSizable | NSViewMinYMargin]; |
| 876 |
| 877 [bookmarkBarController_ layoutSubviews]; |
| 878 } |
| 879 |
| 880 // The info bar is never hidden. Sometimes it has zero effective height. |
| 881 [[infoBarContainerController_ view] setFrame:output.infoBarFrame]; |
| 882 [infoBarContainerController_ |
| 883 setMaxTopArrowHeight:output.infoBarMaxTopArrowHeight]; |
| 884 |
| 885 if (!NSIsEmptyRect(output.downloadShelfFrame)) |
| 886 [[downloadShelfController_ view] setFrame:output.downloadShelfFrame]; |
| 887 |
| 888 [self layoutTabContentArea:output.contentAreaFrame]; |
| 889 |
| 890 if (!NSIsEmptyRect(output.fullscreenBackingBarFrame)) { |
| 891 [floatingBarBackingView_ setFrame:output.fullscreenBackingBarFrame]; |
| 892 [presentationModeController_ |
| 893 overlayFrameChanged:output.fullscreenBackingBarFrame]; |
| 894 } |
| 895 |
| 896 [findBarCocoaController_ |
| 897 positionFindBarViewAtMaxY:output.findBarMaxY |
| 898 maxWidth:NSWidth(output.contentAreaFrame)]; |
| 899 |
| 900 [fullscreenExitBubbleController_ |
| 901 positionInWindowAtTop:output.fullscreenExitButtonMaxY |
| 902 width:NSWidth(output.contentAreaFrame)]; |
| 903 } |
| 904 |
| 905 - (void)updateSubviewZOrder { |
| 906 if ([self isInFullscreenWithOmniboxSliding]) |
| 907 [self updateSubviewZOrderFullscreen]; |
| 908 else |
| 909 [self updateSubviewZOrderNormal]; |
| 910 |
| 911 [self updateSubviewZOrderHack]; |
| 912 } |
| 913 |
| 914 - (void)updateSubviewZOrderNormal { |
| 915 base::scoped_nsobject<NSMutableArray> subviews([[NSMutableArray alloc] init]); |
| 916 if ([downloadShelfController_ view]) |
| 917 [subviews addObject:[downloadShelfController_ view]]; |
| 918 if ([bookmarkBarController_ view]) |
| 919 [subviews addObject:[bookmarkBarController_ view]]; |
| 920 if ([toolbarController_ view]) |
| 921 [subviews addObject:[toolbarController_ view]]; |
| 922 if ([infoBarContainerController_ view]) |
| 923 [subviews addObject:[infoBarContainerController_ view]]; |
| 924 if ([self tabContentArea]) |
| 925 [subviews addObject:[self tabContentArea]]; |
| 926 if ([findBarCocoaController_ view]) |
| 927 [subviews addObject:[findBarCocoaController_ view]]; |
| 928 |
| 929 [self setContentViewSubviews:subviews]; |
| 930 } |
| 931 |
| 932 - (void)updateSubviewZOrderFullscreen { |
| 933 base::scoped_nsobject<NSMutableArray> subviews([[NSMutableArray alloc] init]); |
| 934 if ([downloadShelfController_ view]) |
| 935 [subviews addObject:[downloadShelfController_ view]]; |
| 936 if ([infoBarContainerController_ view]) |
| 937 [subviews addObject:[infoBarContainerController_ view]]; |
| 938 if ([self tabContentArea]) |
| 939 [subviews addObject:[self tabContentArea]]; |
| 940 if ([self placeBookmarkBarBelowInfoBar]) { |
| 941 if ([bookmarkBarController_ view]) |
| 942 [subviews addObject:[bookmarkBarController_ view]]; |
| 943 if (floatingBarBackingView_) |
| 944 [subviews addObject:floatingBarBackingView_]; |
1028 } else { | 945 } else { |
1029 // Toolbar is below tab contents so that the info bar arrow can appear above | 946 if (floatingBarBackingView_) |
1030 // it. | 947 [subviews addObject:floatingBarBackingView_]; |
1031 [contentView cr_ensureSubview:toolbarView | 948 if ([bookmarkBarController_ view]) |
1032 isPositioned:NSWindowBelow | 949 [subviews addObject:[bookmarkBarController_ view]]; |
1033 relativeTo:[self tabContentArea]]; | 950 } |
1034 } | 951 |
1035 | 952 if ([toolbarController_ view]) |
1036 // The bookmark bar is always below the toolbar. | 953 [subviews addObject:[toolbarController_ view]]; |
1037 [contentView cr_ensureSubview:[bookmarkBarController_ view] | 954 if ([findBarCocoaController_ view]) |
1038 isPositioned:NSWindowBelow | 955 [subviews addObject:[findBarCocoaController_ view]]; |
1039 relativeTo:toolbarView]; | 956 |
1040 | 957 [self setContentViewSubviews:subviews]; |
1041 if (inAnyFullscreen) { | 958 } |
1042 // In presentation mode the info bar is below all other views. | 959 |
1043 [contentView cr_ensureSubview:[infoBarContainerController_ view] | 960 - (void)setContentViewSubviews:(NSArray*)subviews { |
1044 isPositioned:NSWindowBelow | 961 // Subviews already match. |
1045 relativeTo:[self tabContentArea]]; | 962 if ([[self.window.contentView subviews] isEqual:subviews]) |
1046 } else { | 963 return; |
1047 // Above the toolbar but still below tab contents. Similar to the bookmark | 964 |
1048 // bar, this allows Instant results to be above the info bar. | 965 // The tabContentArea isn't a subview, so just set all the subviews. |
1049 [contentView cr_ensureSubview:[infoBarContainerController_ view] | 966 NSView* tabContentArea = [self tabContentArea]; |
1050 isPositioned:NSWindowAbove | 967 if (![[self.window.contentView subviews] containsObject:tabContentArea]) { |
1051 relativeTo:toolbarView]; | 968 [self.window.contentView setSubviews:subviews]; |
1052 } | 969 return; |
1053 | 970 } |
1054 // The find bar is above everything. | 971 |
1055 if (findBarCocoaController_) { | 972 // Remove all subviews that aren't the tabContentArea. |
1056 NSView* relativeView = nil; | 973 for (NSView* view in [[self.window.contentView subviews] copy]) { |
1057 if (inAnyFullscreen) | 974 if (view != tabContentArea) |
1058 relativeView = toolbarView; | 975 [view removeFromSuperview]; |
1059 else | 976 } |
1060 relativeView = [self tabContentArea]; | 977 |
1061 [contentView cr_ensureSubview:[findBarCocoaController_ view] | 978 // Add in the subviews below the tabContentArea. |
1062 isPositioned:NSWindowAbove | 979 NSInteger index = [subviews indexOfObject:tabContentArea]; |
1063 relativeTo:relativeView]; | 980 for (int i = index - 1; i >= 0; --i) { |
1064 } | 981 NSView* view = [subviews objectAtIndex:i]; |
1065 | 982 [self.window.contentView addSubview:view |
1066 if (floatingBarBackingView_) { | 983 positioned:NSWindowBelow |
1067 if ([floatingBarBackingView_ cr_isBelowView:[self tabContentArea]]) | 984 relativeTo:nil]; |
1068 [floatingBarBackingView_ removeFromSuperview]; | 985 } |
1069 if ([self placeBookmarkBarBelowInfoBar]) { | 986 |
1070 [contentView cr_ensureSubview:floatingBarBackingView_ | 987 // Add in the subviews above the tabContentArea. |
1071 isPositioned:NSWindowAbove | 988 for (NSUInteger i = index + 1; i < [subviews count]; ++i) { |
1072 relativeTo:[bookmarkBarController_ view]]; | 989 NSView* view = [subviews objectAtIndex:i]; |
1073 } else { | 990 [self.window.contentView addSubview:view |
1074 [contentView cr_ensureSubview:floatingBarBackingView_ | 991 positioned:NSWindowAbove |
1075 isPositioned:NSWindowBelow | 992 relativeTo:nil]; |
1076 relativeTo:[bookmarkBarController_ view]]; | 993 } |
1077 } | 994 } |
1078 | 995 |
1079 // TODO(erikchen): This constraint is necessary. See comment at the | 996 - (void)updateSubviewZOrderHack { |
1080 // beginning of the method. | |
1081 [contentView cr_ensureSubview:floatingBarBackingView_ | |
1082 isPositioned:NSWindowAbove | |
1083 relativeTo:[self tabContentArea]]; | |
1084 } | |
1085 | |
1086 // TODO(erikchen): Remove and then add the tabStripView to the root NSView. | 997 // TODO(erikchen): Remove and then add the tabStripView to the root NSView. |
1087 // This fixes a layer ordering problem that occurs between the contentView | 998 // This fixes a layer ordering problem that occurs between the contentView |
1088 // and the tabStripView. This is a hack required because NSThemeFrame is not | 999 // and the tabStripView. This is a hack required because NSThemeFrame is not |
1089 // layer backed, and because Chrome adds subviews directly to the | 1000 // layer backed, and because Chrome adds subviews directly to the |
1090 // NSThemeFrame. | 1001 // NSThemeFrame. |
1091 // http://crbug.com/407921 | 1002 // http://crbug.com/407921 |
1092 if (enteringAppKitFullscreen_) { | 1003 if (enteringAppKitFullscreen_) { |
1093 // The tabstrip frequently lies outside the bounds of its superview. | 1004 // The tabstrip frequently lies outside the bounds of its superview. |
1094 // Repeatedly adding/removing the tabstrip from its superview during the | 1005 // Repeatedly adding/removing the tabstrip from its superview during the |
1095 // AppKit Fullscreen transition causes graphical glitches on 10.10. The | 1006 // AppKit Fullscreen transition causes graphical glitches on 10.10. The |
1096 // correct solution is to use the AppKit fullscreen transition APIs added | 1007 // correct solution is to use the AppKit fullscreen transition APIs added |
1097 // in 10.7+. | 1008 // in 10.7+. |
1098 // http://crbug.com/408791 | 1009 // http://crbug.com/408791 |
1099 if (!hasAdjustedTabStripWhileEnteringAppKitFullscreen_) { | 1010 if (!hasAdjustedTabStripWhileEnteringAppKitFullscreen_) { |
1100 // Disable implicit animations. | 1011 // Disable implicit animations. |
1101 [CATransaction begin]; | 1012 [CATransaction begin]; |
1102 [CATransaction setDisableActions:YES]; | 1013 [CATransaction setDisableActions:YES]; |
1103 | 1014 |
1104 [self updateLayerOrdering:[self tabStripView]]; | 1015 [self updateLayerOrdering:[self tabStripView]]; |
1105 [self updateLayerOrdering:[avatarButtonController_ view]]; | 1016 [self updateLayerOrdering:[avatarButtonController_ view]]; |
1106 | 1017 |
1107 [CATransaction commit]; | 1018 [CATransaction commit]; |
1108 hasAdjustedTabStripWhileEnteringAppKitFullscreen_ = YES; | 1019 hasAdjustedTabStripWhileEnteringAppKitFullscreen_ = YES; |
1109 } | 1020 } |
1110 } else { | 1021 } else { |
1111 hasAdjustedTabStripWhileEnteringAppKitFullscreen_ = NO; | 1022 hasAdjustedTabStripWhileEnteringAppKitFullscreen_ = NO; |
1112 } | 1023 } |
1113 } | 1024 } |
1114 | 1025 |
1115 - (void)updateInfoBarTipVisibility { | |
1116 // If there's no toolbar then hide the infobar tip. | |
1117 [infoBarContainerController_ | |
1118 setShouldSuppressTopInfoBarTip:![self hasToolbar]]; | |
1119 } | |
1120 | |
1121 - (NSInteger)infoBarMaxTopArrowHeight { | |
1122 NSInteger topArrowHeight = 0; | |
1123 LocationBarViewMac* locationBarView = [self locationBarBridge]; | |
1124 NSPoint iconBottom = locationBarView->GetPageInfoBubblePoint(); | |
1125 | |
1126 CGFloat overlappingTipHeight = | |
1127 [infoBarContainerController_ overlappingTipHeight]; | |
1128 NSPoint infoBarTop = | |
1129 NSMakePoint(0, NSHeight([infoBarContainerController_ view].frame) - | |
1130 overlappingTipHeight); | |
1131 infoBarTop = [[infoBarContainerController_ view] convertPoint:infoBarTop | |
1132 toView:nil]; | |
1133 | |
1134 topArrowHeight = iconBottom.y - infoBarTop.y; | |
1135 return topArrowHeight; | |
1136 } | |
1137 | |
1138 - (void)enterAppKitFullscreen { | |
1139 DCHECK(base::mac::IsOSLionOrLater()); | |
1140 if (FramedBrowserWindow* framedBrowserWindow = | |
1141 base::mac::ObjCCast<FramedBrowserWindow>([self window])) { | |
1142 [framedBrowserWindow toggleSystemFullScreen]; | |
1143 } | |
1144 } | |
1145 | |
1146 - (void)exitAppKitFullscreen { | |
1147 DCHECK(base::mac::IsOSLionOrLater()); | |
1148 if (FramedBrowserWindow* framedBrowserWindow = | |
1149 base::mac::ObjCCast<FramedBrowserWindow>([self window])) { | |
1150 [framedBrowserWindow toggleSystemFullScreen]; | |
1151 } | |
1152 } | |
1153 | |
1154 @end // @implementation BrowserWindowController(Private) | 1026 @end // @implementation BrowserWindowController(Private) |
OLD | NEW |