BookmarkManager: Fix 'new folder text field size changes on clicking it' issue.
[chromium-blink-merge.git] / chrome / browser / ui / cocoa / browser_window_layout.mm
bloba0278250fcc469912e596d36096f5af5a6a50d76
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #import "chrome/browser/ui/cocoa/browser_window_layout.h"
7 #include <math.h>
8 #include <string.h>
10 #include "base/logging.h"
11 #include "base/mac/mac_util.h"
12 #import "chrome/browser/ui/cocoa/tabs/tab_strip_controller.h"
14 namespace chrome {
16 // The height of the tab strip.
17 const CGFloat kTabStripHeight = 37;
19 }  // namespace chrome
21 namespace {
23 // Insets for the location bar, used when the full toolbar is hidden.
24 // TODO(viettrungluu): We can argue about the "correct" insetting; I like the
25 // following best, though arguably 0 inset is better/more correct.
26 const CGFloat kLocBarLeftRightInset = 1;
27 const CGFloat kLocBarTopInset = 0;
28 const CGFloat kLocBarBottomInset = 1;
30 // Space between the incognito badge and the right edge of the window.
31 const CGFloat kAvatarRightOffset = 4;
33 // Space between the location bar and the right edge of the window, when there
34 // are no extension buttons present.
35 // When there is a fullscreen button to the right of the new style profile
36 // button, we align the profile button with the location bar (although it won't
37 // be aligned when there are extension buttons).
38 const CGFloat kLocationBarRightOffset = 35;
40 }  // namespace
42 @interface BrowserWindowLayout ()
44 // Computes the y offset to use when laying out the tab strip in fullscreen
45 // mode.
46 - (void)computeFullscreenYOffset;
48 // Computes the layout of the tab strip.
49 - (void)computeTabStripLayout;
51 // Computes the layout of the subviews of the content view.
52 - (void)computeContentViewLayout;
54 // Computes the height of the backing bar for the views in the omnibox area in
55 // fullscreen mode.
56 - (CGFloat)fullscreenBackingBarHeight;
58 @end
60 @implementation BrowserWindowLayout
62 - (instancetype)init {
63   if ((self = [super init])) {
64     parameters_.isOSYosemiteOrLater = base::mac::IsOSYosemiteOrLater();
65   }
66   return self;
69 - (chrome::LayoutOutput)computeLayout {
70   memset(&output_, 0, sizeof(chrome::LayoutOutput));
72   [self computeFullscreenYOffset];
73   [self computeTabStripLayout];
74   [self computeContentViewLayout];
76   return output_;
79 - (void)setContentViewSize:(NSSize)size {
80   parameters_.contentViewSize = size;
83 - (void)setWindowSize:(NSSize)size {
84   parameters_.windowSize = size;
87 - (void)setInAnyFullscreen:(BOOL)inAnyFullscreen {
88   parameters_.inAnyFullscreen = inAnyFullscreen;
91 - (void)setFullscreenSlidingStyle:(fullscreen_mac::SlidingStyle)slidingStyle {
92   parameters_.slidingStyle = slidingStyle;
95 - (void)setFullscreenMenubarOffset:(CGFloat)menubarOffset {
96   parameters_.menubarOffset = menubarOffset;
99 - (void)setFullscreenToolbarFraction:(CGFloat)toolbarFraction {
100   parameters_.toolbarFraction = toolbarFraction;
103 - (void)setHasTabStrip:(BOOL)hasTabStrip {
104   parameters_.hasTabStrip = hasTabStrip;
107 - (void)setFullscreenButtonFrame:(NSRect)frame {
108   parameters_.fullscreenButtonFrame = frame;
111 - (void)setShouldShowAvatar:(BOOL)shouldShowAvatar {
112   parameters_.shouldShowAvatar = shouldShowAvatar;
115 - (void)setShouldUseNewAvatar:(BOOL)shouldUseNewAvatar {
116   parameters_.shouldUseNewAvatar = shouldUseNewAvatar;
119 - (void)setAvatarSize:(NSSize)avatarSize {
120   parameters_.avatarSize = avatarSize;
123 - (void)setAvatarLineWidth:(CGFloat)avatarLineWidth {
124   parameters_.avatarLineWidth = avatarLineWidth;
127 - (void)setHasToolbar:(BOOL)hasToolbar {
128   parameters_.hasToolbar = hasToolbar;
131 - (void)setHasLocationBar:(BOOL)hasLocationBar {
132   parameters_.hasLocationBar = hasLocationBar;
135 - (void)setToolbarHeight:(CGFloat)toolbarHeight {
136   parameters_.toolbarHeight = toolbarHeight;
139 - (void)setBookmarkBarHidden:(BOOL)bookmarkBarHidden {
140   parameters_.bookmarkBarHidden = bookmarkBarHidden;
143 - (void)setPlaceBookmarkBarBelowInfoBar:(BOOL)placeBookmarkBarBelowInfoBar {
144   parameters_.placeBookmarkBarBelowInfoBar = placeBookmarkBarBelowInfoBar;
147 - (void)setBookmarkBarHeight:(CGFloat)bookmarkBarHeight {
148   parameters_.bookmarkBarHeight = bookmarkBarHeight;
151 - (void)setInfoBarHeight:(CGFloat)infoBarHeight {
152   parameters_.infoBarHeight = infoBarHeight;
155 - (void)setPageInfoBubblePointY:(CGFloat)pageInfoBubblePointY {
156   parameters_.pageInfoBubblePointY = pageInfoBubblePointY;
159 - (void)setHasDownloadShelf:(BOOL)hasDownloadShelf {
160   parameters_.hasDownloadShelf = hasDownloadShelf;
163 - (void)setDownloadShelfHeight:(CGFloat)downloadShelfHeight {
164   parameters_.downloadShelfHeight = downloadShelfHeight;
167 - (void)computeFullscreenYOffset {
168   CGFloat yOffset = 0;
169   if (parameters_.inAnyFullscreen) {
170     yOffset += parameters_.menubarOffset;
171     switch (parameters_.slidingStyle) {
172       case fullscreen_mac::OMNIBOX_TABS_PRESENT:
173         break;
174       case fullscreen_mac::OMNIBOX_TABS_NONE:
175       case fullscreen_mac::OMNIBOX_TABS_HIDDEN:
176         // In presentation mode, |yOffset| accounts for the sliding position of
177         // the floating bar and the extra offset needed to dodge the menu bar.
178         yOffset += std::floor((1 - parameters_.toolbarFraction) *
179                               [self fullscreenBackingBarHeight]);
180         break;
181     }
182   }
183   fullscreenYOffset_ = yOffset;
186 - (void)computeTabStripLayout {
187   if (!parameters_.hasTabStrip) {
188     maxY_ = parameters_.contentViewSize.height + fullscreenYOffset_;
189     return;
190   }
192   // Temporary variable to hold the output.
193   chrome::TabStripLayout layout = {};
195   // Lay out the tab strip.
196   maxY_ = parameters_.windowSize.height + fullscreenYOffset_;
197   CGFloat width = parameters_.contentViewSize.width;
198   layout.frame = NSMakeRect(
199       0, maxY_ - chrome::kTabStripHeight, width, chrome::kTabStripHeight);
200   maxY_ = NSMinY(layout.frame);
202   // In Yosemite, there is no longer an exit fullscreen button in the top-right
203   // corner of the OSX Menu Bar. Instead, a Cocoa application's toolbar is
204   // expected to have traffic lights. Chrome doesn't use an NSToolbar, so it
205   // needs to manually add the traffic lights to the tab strip.
206   layout.addCustomWindowControls =
207       parameters_.inAnyFullscreen && parameters_.isOSYosemiteOrLater;
209   // Set left indentation based on fullscreen mode status.
210   if (!parameters_.inAnyFullscreen || layout.addCustomWindowControls)
211     layout.leftIndent = [TabStripController defaultLeftIndentForControls];
213   // Lay out the icognito/avatar badge because calculating the indentation on
214   // the right depends on it.
215   if (parameters_.shouldShowAvatar) {
216     CGFloat badgeXOffset = -kAvatarRightOffset;
217     CGFloat badgeYOffset = 0;
218     CGFloat buttonHeight = parameters_.avatarSize.height;
220     if (parameters_.shouldUseNewAvatar) {
221       // The fullscreen icon (if present) is displayed to the right of the
222       // new style profile button.
223       if (!NSIsEmptyRect(parameters_.fullscreenButtonFrame))
224         badgeXOffset = -kLocationBarRightOffset;
226       // Center the button, but make sure that it's pixel aligned on non-retina
227       // displays. Use trunc() instead of round() to mimic the behavior of
228       // autoresizesSubviews.
229       badgeYOffset = trunc((chrome::kTabStripHeight - buttonHeight) / 2);
230     } else {
231       // Actually place the badge *above* |maxY|, by +2 to miss the divider.
232       badgeYOffset = 2 * parameters_.avatarLineWidth;
233     }
235     NSSize size = NSMakeSize(parameters_.avatarSize.width,
236                              std::min(buttonHeight, chrome::kTabStripHeight));
237     NSPoint origin =
238         NSMakePoint(width - parameters_.avatarSize.width + badgeXOffset,
239                     maxY_ + badgeYOffset);
240     layout.avatarFrame =
241         NSMakeRect(origin.x, origin.y, size.width, size.height);
242   }
244   // Calculate the right indentation.
245   // On 10.7 Lion to 10.9 Mavericks, there will be a fullscreen button when not
246   // in fullscreen mode.
247   // There may also be a profile button, which can be on the right of the
248   // fullscreen button (old style), or to its left (new style).
249   // The right indentation is calculated to prevent the tab strip from
250   // overlapping these buttons.
251   CGFloat maxX = width;
252   if (!NSIsEmptyRect(parameters_.fullscreenButtonFrame)) {
253     maxX = NSMinX(parameters_.fullscreenButtonFrame);
254   }
255   if (parameters_.shouldShowAvatar) {
256     maxX = std::min(maxX, NSMinX(layout.avatarFrame));
257   }
258   layout.rightIndent = width - maxX;
260   output_.tabStripLayout = layout;
263 - (void)computeContentViewLayout {
264   chrome::LayoutParameters parameters = parameters_;
265   CGFloat maxY = maxY_;
267   // Sanity-check |maxY|.
268   DCHECK_GE(maxY, 0);
269   DCHECK_LE(maxY, parameters_.contentViewSize.height + fullscreenYOffset_);
271   CGFloat width = parameters_.contentViewSize.width;
273   // Lay out the toolbar.
274   if (parameters.hasToolbar) {
275     output_.toolbarFrame = NSMakeRect(
276         0, maxY - parameters_.toolbarHeight, width, parameters_.toolbarHeight);
277     maxY = NSMinY(output_.toolbarFrame);
278   } else if (parameters_.hasLocationBar) {
279     CGFloat toolbarX = kLocBarLeftRightInset;
280     CGFloat toolbarY = maxY - parameters_.toolbarHeight - kLocBarTopInset;
281     CGFloat toolbarWidth = width - 2 * kLocBarLeftRightInset;
282     output_.toolbarFrame =
283         NSMakeRect(toolbarX, toolbarY, toolbarWidth, parameters_.toolbarHeight);
284     maxY = NSMinY(output_.toolbarFrame) - kLocBarBottomInset;
285   }
287   // Lay out the bookmark bar, if it's above the info bar.
288   if (!parameters.bookmarkBarHidden &&
289       !parameters.placeBookmarkBarBelowInfoBar) {
290     output_.bookmarkFrame = NSMakeRect(0,
291                                        maxY - parameters.bookmarkBarHeight,
292                                        width,
293                                        parameters.bookmarkBarHeight);
294     maxY = NSMinY(output_.bookmarkFrame);
295   }
297   // Lay out the backing bar in fullscreen mode.
298   if (parameters_.inAnyFullscreen) {
299     output_.fullscreenBackingBarFrame =
300         NSMakeRect(0, maxY, width, [self fullscreenBackingBarHeight]);
301   }
303   // Place the find bar immediately below the toolbar/attached bookmark bar.
304   output_.findBarMaxY = maxY;
305   output_.fullscreenExitButtonMaxY = maxY;
307   if (parameters_.inAnyFullscreen &&
308       parameters_.slidingStyle == fullscreen_mac::OMNIBOX_TABS_HIDDEN) {
309     // If in presentation mode, reset |maxY| to top of screen, so that the
310     // floating bar slides over the things which appear to be in the content
311     // area.
312     maxY = parameters_.windowSize.height;
313   }
315   // Lay out the info bar. It is never hidden.
316   if (parameters_.infoBarHeight != 0) {
317     CGFloat infoBarMaxY = maxY;
318     CGFloat infoBarMinY = maxY - parameters_.infoBarHeight;
320     // If there's a toolbar, then the frame needs to be high enough to
321     // accomodate the top arrow, which might stretch all the way to the page
322     // info bubble icon.
323     if (parameters_.hasToolbar) {
324       infoBarMaxY =
325           NSMinY(output_.toolbarFrame) + parameters.pageInfoBubblePointY;
326     }
328     output_.infoBarFrame =
329         NSMakeRect(0, infoBarMinY, width, infoBarMaxY - infoBarMinY);
330     output_.infoBarMaxTopArrowHeight =
331         NSHeight(output_.infoBarFrame) - parameters_.infoBarHeight;
332     maxY = NSMinY(output_.infoBarFrame);
333   } else {
334     // The info bar has 0 height, but tests still expect it in the right
335     // location.
336     output_.infoBarFrame = NSMakeRect(0, maxY, width, 0);
337   }
339   // Lay out the bookmark bar when it is below the info bar.
340   if (!parameters.bookmarkBarHidden &&
341       parameters.placeBookmarkBarBelowInfoBar) {
342     output_.bookmarkFrame = NSMakeRect(0,
343                                        maxY - parameters.bookmarkBarHeight,
344                                        width,
345                                        parameters.bookmarkBarHeight);
346     maxY = NSMinY(output_.bookmarkFrame);
347   }
349   // Layout the download shelf at the bottom of the content view.
350   CGFloat minY = 0;
351   if (parameters.hasDownloadShelf) {
352     output_.downloadShelfFrame =
353         NSMakeRect(0, 0, width, parameters.downloadShelfHeight);
354     minY = NSMaxY(output_.downloadShelfFrame);
355   }
357   if (parameters_.inAnyFullscreen &&
358       parameters_.slidingStyle == fullscreen_mac::OMNIBOX_TABS_PRESENT) {
359     // If in Canonical Fullscreen, content should be shifted down by an amount
360     // equal to all the widgets and views at the top of the window. It should
361     // not be further shifted by the appearance/disappearance of the AppKit
362     // menu bar.
363     maxY = parameters_.windowSize.height;
364     maxY -= NSHeight(output_.toolbarFrame) +
365             NSHeight(output_.tabStripLayout.frame) +
366             NSHeight(output_.bookmarkFrame) + parameters.infoBarHeight;
367   }
369   // All the remaining space becomes the frame of the content area.
370   output_.contentAreaFrame = NSMakeRect(0, minY, width, maxY - minY);
373 - (CGFloat)fullscreenBackingBarHeight {
374   if (!parameters_.inAnyFullscreen)
375     return 0;
377   CGFloat totalHeight = 0;
378   if (parameters_.hasTabStrip)
379     totalHeight += chrome::kTabStripHeight;
381   if (parameters_.hasToolbar) {
382     totalHeight += parameters_.toolbarHeight;
383   } else if (parameters_.hasLocationBar) {
384     totalHeight +=
385         parameters_.toolbarHeight + kLocBarTopInset + kLocBarBottomInset;
386   }
388   if (!parameters_.bookmarkBarHidden &&
389       !parameters_.placeBookmarkBarBelowInfoBar)
390     totalHeight += parameters_.bookmarkBarHeight;
392   return totalHeight;
395 @end
397 @implementation BrowserWindowLayout (ExposedForTesting)
399 - (void)setOSYosemiteOrLater:(BOOL)osYosemiteOrLater {
400   parameters_.isOSYosemiteOrLater = osYosemiteOrLater;
403 @end