172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/views/frame/browser_view_layout.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
73345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/browser/sidebar/sidebar_manager.h"
821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/ui/find_bar/find_bar.h"
921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/ui/find_bar/find_bar_controller.h"
1021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/ui/view_ids.h"
11dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "chrome/browser/ui/views/bookmarks/bookmark_bar_view.h"
12ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/views/download/download_shelf_view.h"
1321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/ui/views/frame/browser_frame.h"
1421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/ui/views/frame/browser_view.h"
1521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/ui/views/frame/contents_container.h"
16ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/views/infobars/infobar_container_view.h"
1772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/views/tab_contents/tab_contents_container.h"
18ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/views/tabs/abstract_tab_strip_view.h"
1921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/ui/views/toolbar_view.h"
2072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/point.h"
2172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/scrollbar_size.h"
2272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/size.h"
2372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "views/controls/single_split_view.h"
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "views/window/window.h"
25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_LINUX)
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "views/window/hit_test.h"
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace {
31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The visible height of the shadow above the tabs. Clicks in this area are
33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// treated as clicks to the frame, rather than clicks to the tab.
34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kTabShadowSize = 2;
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The vertical overlap between the TabStrip and the Toolbar.
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kToolbarTabStripVerticalOverlap = 3;
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace
39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch////////////////////////////////////////////////////////////////////////////////
41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// BrowserViewLayout, public:
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochBrowserViewLayout::BrowserViewLayout()
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    : tabstrip_(NULL),
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      toolbar_(NULL),
46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      contents_split_(NULL),
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      contents_container_(NULL),
48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      infobar_container_(NULL),
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      download_shelf_(NULL),
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      active_bookmark_bar_(NULL),
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      browser_view_(NULL),
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      find_bar_y_(0) {
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenBrowserViewLayout::~BrowserViewLayout() {
5672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
5772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgfx::Size BrowserViewLayout::GetMinimumSize() {
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // TODO(noname): In theory the tabstrip width should probably be
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // (OTR + tabstrip + caption buttons) width.
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gfx::Size tabstrip_size(
62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      browser()->SupportsWindowFeature(Browser::FEATURE_TABSTRIP) ?
63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      tabstrip_->GetMinimumSize() : gfx::Size());
64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gfx::Size toolbar_size(
65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      (browser()->SupportsWindowFeature(Browser::FEATURE_TOOLBAR) ||
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch       browser()->SupportsWindowFeature(Browser::FEATURE_LOCATIONBAR)) ?
67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      toolbar_->GetMinimumSize() : gfx::Size());
68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (tabstrip_size.height() && toolbar_size.height())
69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    toolbar_size.Enlarge(0, -kToolbarTabStripVerticalOverlap);
70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gfx::Size bookmark_bar_size;
71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (active_bookmark_bar_ &&
72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      browser()->SupportsWindowFeature(Browser::FEATURE_BOOKMARKBAR)) {
73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    bookmark_bar_size = active_bookmark_bar_->GetMinimumSize();
74ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    bookmark_bar_size.Enlarge(0,
75ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        -(views::NonClientFrameView::kClientEdgeThickness +
76ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            active_bookmark_bar_->GetToolbarOverlap(true)));
77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gfx::Size contents_size(contents_split_->GetMinimumSize());
79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int min_height = tabstrip_size.height() + toolbar_size.height() +
81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      bookmark_bar_size.height() + contents_size.height();
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int widths[] = { tabstrip_size.width(), toolbar_size.width(),
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   bookmark_bar_size.width(), contents_size.width() };
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int min_width = *std::max_element(&widths[0], &widths[arraysize(widths)]);
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return gfx::Size(min_width, min_height);
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgfx::Rect BrowserViewLayout::GetFindBarBoundingBox() const {
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // This function returns the area the Find Bar can be laid out
90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // within. This basically implies the "user-perceived content
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // area" of the browser window excluding the vertical
92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // scrollbar. This is not quite so straightforward as positioning
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // based on the TabContentsContainer since the BookmarkBarView may
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // be visible but not persistent (in the New Tab case) and we
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // position the Find Bar over the top of it in that case since the
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // BookmarkBarView is not _visually_ connected to the Toolbar.
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // First determine the bounding box of the content area in Widget
99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // coordinates.
100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gfx::Rect bounding_box(contents_container_->bounds());
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gfx::Point topleft;
103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  views::View::ConvertPointToWidget(contents_container_, &topleft);
104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bounding_box.set_origin(topleft);
105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Adjust the position and size of the bounding box by the find bar offset
107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // calculated during the last Layout.
108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int height_delta = find_bar_y_ - bounding_box.y();
109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bounding_box.set_y(find_bar_y_);
110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bounding_box.set_height(std::max(0, bounding_box.height() + height_delta));
111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Finally decrease the width of the bounding box by the width of
113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // the vertical scroll bar.
114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int scrollbar_width = gfx::scrollbar_size();
115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bounding_box.set_width(std::max(0, bounding_box.width() - scrollbar_width));
116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (base::i18n::IsRTL())
117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    bounding_box.set_x(bounding_box.x() + scrollbar_width);
118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return bounding_box;
120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool BrowserViewLayout::IsPositionInWindowCaption(
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const gfx::Point& point) {
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gfx::Point tabstrip_point(point);
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  views::View::ConvertPointToView(browser_view_, tabstrip_, &tabstrip_point);
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return tabstrip_->IsPositionInWindowCaption(tabstrip_point);
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint BrowserViewLayout::NonClientHitTest(
130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const gfx::Point& point) {
131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Since the TabStrip only renders in some parts of the top of the window,
132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // the un-obscured area is considered to be part of the non-client caption
133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // area of the window. So we need to treat hit-tests in these regions as
134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // hit-tests of the titlebar.
135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
13672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  views::View* parent = browser_view_->parent();
137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gfx::Point point_in_browser_view_coords(point);
139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  views::View::ConvertPointToView(
140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      parent, browser_view_, &point_in_browser_view_coords);
141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Determine if the TabStrip exists and is capable of being clicked on. We
143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // might be a popup window without a TabStrip.
144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (browser_view_->IsTabStripVisible()) {
145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // See if the mouse pointer is within the bounds of the TabStrip.
146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gfx::Point point_in_tabstrip_coords(point);
147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    views::View::ConvertPointToView(parent, tabstrip_,
148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                    &point_in_tabstrip_coords);
149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (tabstrip_->HitTest(point_in_tabstrip_coords)) {
150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (tabstrip_->IsPositionInWindowCaption(point_in_tabstrip_coords))
151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        return HTCAPTION;
152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return HTCLIENT;
153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // The top few pixels of the TabStrip are a drop-shadow - as we're pretty
156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // starved of dragable area, let's give it to window dragging (this also
157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // makes sense visually).
158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!browser_view_->IsMaximized() &&
159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        (point_in_browser_view_coords.y() <
160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch         (tabstrip_->y() + kTabShadowSize))) {
161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // We return HTNOWHERE as this is a signal to our containing
162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // NonClientView that it should figure out what the correct hit-test
163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // code is given the mouse position...
164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return HTNOWHERE;
165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // If the point's y coordinate is below the top of the toolbar and otherwise
169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // within the bounds of this view, the point is considered to be within the
170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // client area.
171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gfx::Rect bv_bounds = browser_view_->bounds();
172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bv_bounds.Offset(0, toolbar_->y());
173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bv_bounds.set_height(bv_bounds.height() - toolbar_->y());
174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (bv_bounds.Contains(point))
175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return HTCLIENT;
176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // If the point's y coordinate is above the top of the toolbar, but not in
178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // the tabstrip (per previous checking in this function), then we consider it
179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // in the window caption (e.g. the area to the right of the tabstrip
180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // underneath the window controls). However, note that we DO NOT return
181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // HTCAPTION here, because when the window is maximized the window controls
182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // will fall into this space (since the BrowserView is sized to entire size
183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // of the window at that point), and the HTCAPTION value will cause the
184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // window controls not to work. So we return HTNOWHERE so that the caller
185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // will hit-test the window controls before finally falling back to
186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // HTCAPTION.
187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bv_bounds = browser_view_->bounds();
188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bv_bounds.set_height(toolbar_->y());
189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (bv_bounds.Contains(point))
190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return HTNOWHERE;
191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // If the point is somewhere else, delegate to the default implementation.
193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return browser_view_->views::ClientView::NonClientHitTest(point);
194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//////////////////////////////////////////////////////////////////////////////
197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// BrowserViewLayout, views::LayoutManager implementation:
198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserViewLayout::Installed(views::View* host) {
200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  toolbar_ = NULL;
201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  contents_split_ = NULL;
202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  contents_container_ = NULL;
203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  infobar_container_ = NULL;
204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  download_shelf_ = NULL;
205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  active_bookmark_bar_ = NULL;
206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  tabstrip_ = NULL;
207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  browser_view_ = static_cast<BrowserView*>(host);
208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserViewLayout::Uninstalled(views::View* host) {}
211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserViewLayout::ViewAdded(views::View* host, views::View* view) {
213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  switch (view->GetID()) {
2143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    case VIEW_ID_CONTENTS_SPLIT: {
21572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      contents_split_ = static_cast<views::SingleSplitView*>(view);
2163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      // We're installed as the LayoutManager before BrowserView creates the
21772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      // contents, so we have to set contents_container_ here rather than in
2183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      // Installed.
2193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      contents_container_ = browser_view_->contents_;
220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
2213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case VIEW_ID_INFO_BAR_CONTAINER:
223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      infobar_container_ = view;
224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case VIEW_ID_DOWNLOAD_SHELF:
226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      download_shelf_ = static_cast<DownloadShelfView*>(view);
227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case VIEW_ID_BOOKMARK_BAR:
229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      active_bookmark_bar_ = static_cast<BookmarkBarView*>(view);
230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case VIEW_ID_TOOLBAR:
232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      toolbar_ = static_cast<ToolbarView*>(view);
233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case VIEW_ID_TAB_STRIP:
235ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      tabstrip_ = static_cast<AbstractTabStripView*>(view);
236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserViewLayout::ViewRemoved(views::View* host, views::View* view) {
241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  switch (view->GetID()) {
242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case VIEW_ID_BOOKMARK_BAR:
243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      active_bookmark_bar_ = NULL;
244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserViewLayout::Layout(views::View* host) {
24972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  vertical_layout_rect_ = browser_view_->GetLocalBounds();
250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int top = LayoutTabStrip();
2513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (browser_view_->IsTabStripVisible() && !browser_view_->UseVerticalTabs()) {
2523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    tabstrip_->SetBackgroundOffset(gfx::Point(
25372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        tabstrip_->GetMirroredX() + browser_view_->GetMirroredX(),
2543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        browser_view_->frame()->GetHorizontalTabStripVerticalOffset(false)));
2553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  top = LayoutToolbar(top);
257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  top = LayoutBookmarkAndInfoBars(top);
2583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int bottom = LayoutDownloadShelf(browser_view_->height());
2593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int active_top_margin = GetTopMarginForActiveContent();
2603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  top -= active_top_margin;
2613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  contents_container_->SetActiveTopMargin(active_top_margin);
262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  LayoutTabContents(top, bottom);
263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // This must be done _after_ we lay out the TabContents since this
264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // code calls back into us to find the bounding box the find bar
265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // must be laid out within, and that code depends on the
266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // TabContentsContainer's bounds being up to date.
267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (browser()->HasFindBarController()) {
268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    browser()->GetFindBarController()->find_bar()->MoveWindowIfNecessary(
269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        gfx::Rect(), true);
270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Return the preferred size which is the size required to give each
274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// children their respective preferred size.
275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgfx::Size BrowserViewLayout::GetPreferredSize(views::View* host) {
276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return gfx::Size();
277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//////////////////////////////////////////////////////////////////////////////
280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// BrowserViewLayout, private:
281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2823345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickBrowser* BrowserViewLayout::browser() {
2833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return browser_view_->browser();
2843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
2853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickconst Browser* BrowserViewLayout::browser() const {
2873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return browser_view_->browser();
2883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
2893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint BrowserViewLayout::LayoutTabStrip() {
291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!browser_view_->IsTabStripVisible()) {
292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    tabstrip_->SetVisible(false);
293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    tabstrip_->SetBounds(0, 0, 0, 0);
294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return 0;
295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  gfx::Rect tabstrip_bounds(
2983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      browser_view_->frame()->GetBoundsForTabStrip(tabstrip_));
2993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  gfx::Point tabstrip_origin(tabstrip_bounds.origin());
30072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  views::View::ConvertPointToView(browser_view_->parent(), browser_view_,
301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                  &tabstrip_origin);
3023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  tabstrip_bounds.set_origin(tabstrip_origin);
3033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
3043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (browser_view_->UseVerticalTabs())
3053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    vertical_layout_rect_.Inset(tabstrip_bounds.width(), 0, 0, 0);
3063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  tabstrip_->SetVisible(true);
30872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  tabstrip_->SetBoundsRect(tabstrip_bounds);
309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return browser_view_->UseVerticalTabs() ?
3103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      tabstrip_bounds.y() : tabstrip_bounds.bottom();
311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint BrowserViewLayout::LayoutToolbar(int top) {
314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int browser_view_width = vertical_layout_rect_.width();
315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool visible = browser_view_->IsToolbarVisible();
316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  toolbar_->location_bar()->SetFocusable(visible);
317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int y = top;
318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!browser_view_->UseVerticalTabs()) {
319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    y -= ((visible && browser_view_->IsTabStripVisible()) ?
320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          kToolbarTabStripVerticalOverlap : 0);
321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int height = visible ? toolbar_->GetPreferredSize().height() : 0;
323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  toolbar_->SetVisible(visible);
324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  toolbar_->SetBounds(vertical_layout_rect_.x(), y, browser_view_width, height);
325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return y + height;
326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint BrowserViewLayout::LayoutBookmarkAndInfoBars(int top) {
329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  find_bar_y_ = top + browser_view_->y() - 1;
330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (active_bookmark_bar_) {
331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // If we're showing the Bookmark bar in detached style, then we
332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // need to show any Info bar _above_ the Bookmark bar, since the
333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Bookmark bar is styled to look like it's part of the page.
334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (active_bookmark_bar_->IsDetached())
335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return LayoutBookmarkBar(LayoutInfoBar(top));
336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Otherwise, Bookmark bar first, Info bar second.
3373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    top = std::max(toolbar_->bounds().bottom(), LayoutBookmarkBar(top));
338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  find_bar_y_ = top + browser_view_->y() - 1;
340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return LayoutInfoBar(top);
341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint BrowserViewLayout::LayoutBookmarkBar(int top) {
344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(active_bookmark_bar_);
345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int y = top;
346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!browser_view_->IsBookmarkBarVisible()) {
347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    active_bookmark_bar_->SetVisible(false);
348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    active_bookmark_bar_->SetBounds(0, y, browser_view_->width(), 0);
349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return y;
350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  active_bookmark_bar_->set_infobar_visible(InfobarVisible());
353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int bookmark_bar_height = active_bookmark_bar_->GetPreferredSize().height();
354ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  y -= views::NonClientFrameView::kClientEdgeThickness +
355ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      active_bookmark_bar_->GetToolbarOverlap(false);
356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  active_bookmark_bar_->SetVisible(true);
357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  active_bookmark_bar_->SetBounds(vertical_layout_rect_.x(), y,
358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                  vertical_layout_rect_.width(),
359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                  bookmark_bar_height);
360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return y + bookmark_bar_height;
361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint BrowserViewLayout::LayoutInfoBar(int top) {
364ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Raise the |infobar_container_| by its vertical overlap.
365ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  infobar_container_->SetVisible(InfobarVisible());
366ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  int height;
367ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  int overlapped_top = top -
368ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      static_cast<InfoBarContainerView*>(infobar_container_)->
369ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          GetVerticalOverlap(&height);
370ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  infobar_container_->SetBounds(vertical_layout_rect_.x(),
371ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                overlapped_top,
372ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                vertical_layout_rect_.width(),
373ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                height);
374ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return overlapped_top + height;
375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
37772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// |browser_reserved_rect| is in browser_view_ coordinates.
37872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// |future_source_bounds| is in |source|'s parent coordinates.
37972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// |future_parent_offset| is required, since parent view is not moved yet.
38072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Note that |future_parent_offset| is relative to browser_view_, not to
38172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// the parent view.
38272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid BrowserViewLayout::UpdateReservedContentsRect(
38372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    const gfx::Rect& browser_reserved_rect,
38472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    TabContentsContainer* source,
38572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    const gfx::Rect& future_source_bounds,
38672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    const gfx::Point& future_parent_offset) {
38772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  gfx::Point resize_corner_origin(browser_reserved_rect.origin());
38872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Convert |resize_corner_origin| from browser_view_ to source's parent
38972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // coordinates.
39072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  views::View::ConvertPointToView(browser_view_, source->parent(),
39172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                  &resize_corner_origin);
39272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Create |reserved_rect| in source's parent coordinates.
39372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  gfx::Rect reserved_rect(resize_corner_origin, browser_reserved_rect.size());
39472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Apply source's parent future offset to it.
39572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  reserved_rect.Offset(-future_parent_offset.x(), -future_parent_offset.y());
39672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (future_source_bounds.Intersects(reserved_rect)) {
39772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // |source| is not properly positioned yet to use ConvertPointToView,
39872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // so convert it into |source|'s coordinates manually.
39972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    reserved_rect.Offset(-future_source_bounds.x(), -future_source_bounds.y());
40072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  } else {
40172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    reserved_rect = gfx::Rect();
40272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
40372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
40472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  source->SetReservedContentsRect(reserved_rect);
40572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
40672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserViewLayout::LayoutTabContents(int top, int bottom) {
40872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // The ultimate idea is to calcualte bounds and reserved areas for all
40972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // contents views first and then resize them all, so every view
41072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // (and its contents) is resized and laid out only once.
41172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
41272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // The views hierarcy (see browser_view.h for more details):
41372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // 1) Sidebar is not allowed:
41472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  //     contents_split_ -> [contents_container_ | devtools]
41572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // 2) Sidebar is allowed:
41672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  //     contents_split_ ->
41772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  //         [sidebar_split -> [contents_container_ | sidebar]] | devtools
41872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
41972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  gfx::Rect sidebar_split_bounds;
42072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  gfx::Rect contents_bounds;
42172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  gfx::Rect sidebar_bounds;
42272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  gfx::Rect devtools_bounds;
42372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
42472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  gfx::Rect contents_split_bounds(vertical_layout_rect_.x(), top,
42572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                  vertical_layout_rect_.width(),
42672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                  std::max(0, bottom - top));
42772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  contents_split_->CalculateChildrenBounds(
42872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      contents_split_bounds, &sidebar_split_bounds, &devtools_bounds);
42972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  gfx::Point contents_split_offset(
43072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      contents_split_bounds.x() - contents_split_->bounds().x(),
43172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      contents_split_bounds.y() - contents_split_->bounds().y());
43272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  gfx::Point sidebar_split_offset(contents_split_offset);
43372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  sidebar_split_offset.Offset(sidebar_split_bounds.x(),
43472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                              sidebar_split_bounds.y());
43572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
43672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  views::SingleSplitView* sidebar_split = browser_view_->sidebar_split_;
43772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (sidebar_split) {
43872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    DCHECK(sidebar_split == contents_split_->GetChildViewAt(0));
43972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    sidebar_split->CalculateChildrenBounds(
44072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        sidebar_split_bounds, &contents_bounds, &sidebar_bounds);
44172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  } else {
44272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    contents_bounds = sidebar_split_bounds;
44372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
44472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
44572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Layout resize corner, sidebar mini tabs and calculate reserved contents
44672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // rects here as all contents view bounds are already determined, but not yet
44772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // set at this point, so contents will be laid out once at most.
44872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // TODO(alekseys): layout sidebar minitabs and adjust reserved rect
44972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // accordingly.
45072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  gfx::Rect browser_reserved_rect;
45172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (!browser_view_->frame_->GetWindow()->IsMaximized() &&
45272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      !browser_view_->frame_->GetWindow()->IsFullscreen()) {
45372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    gfx::Size resize_corner_size = browser_view_->GetResizeCornerSize();
45472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (!resize_corner_size.IsEmpty()) {
45572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      gfx::Rect bounds = browser_view_->GetContentsBounds();
45672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      gfx::Point resize_corner_origin(
45772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen          bounds.right() - resize_corner_size.width(),
45872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen          bounds.bottom() - resize_corner_size.height());
45972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      browser_reserved_rect =
46072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen          gfx::Rect(resize_corner_origin, resize_corner_size);
46172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    }
46272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
46372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
46472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  UpdateReservedContentsRect(browser_reserved_rect,
46572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                             browser_view_->contents_container_,
46672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                             contents_bounds,
46772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                             sidebar_split_offset);
46872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (sidebar_split) {
46972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    UpdateReservedContentsRect(browser_reserved_rect,
47072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                               browser_view_->sidebar_container_,
47172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                               sidebar_bounds,
47272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                               sidebar_split_offset);
47372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
47472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  UpdateReservedContentsRect(browser_reserved_rect,
47572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                             browser_view_->devtools_container_,
47672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                             devtools_bounds,
47772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                             contents_split_offset);
47872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
47972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Now it's safe to actually resize all contents views in the hierarchy.
48072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  contents_split_->SetBoundsRect(contents_split_bounds);
48172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (sidebar_split)
48272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    sidebar_split->SetBoundsRect(sidebar_split_bounds);
483c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
484c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickint BrowserViewLayout::GetTopMarginForActiveContent() {
4863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!active_bookmark_bar_ || !browser_view_->IsBookmarkBarVisible() ||
4873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      !active_bookmark_bar_->IsDetached()) {
4883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return 0;
4893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
4903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
4913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (contents_split_->GetChildViewAt(1) &&
4923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      contents_split_->GetChildViewAt(1)->IsVisible())
4933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return 0;
4943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
4953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (SidebarManager::IsSidebarAllowed()) {
4963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    views::View* sidebar_split = contents_split_->GetChildViewAt(0);
4973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (sidebar_split->GetChildViewAt(1) &&
4983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        sidebar_split->GetChildViewAt(1)->IsVisible())
4993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return 0;
500c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
5013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
5023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Adjust for separator.
503ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return active_bookmark_bar_->height() -
504ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      views::NonClientFrameView::kClientEdgeThickness;
505c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
506c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
507c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint BrowserViewLayout::LayoutDownloadShelf(int bottom) {
508c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Re-layout the shelf either if it is visible or if it's close animation
509c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // is currently running.
510c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (browser_view_->IsDownloadShelfVisible() ||
511c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      (download_shelf_ && download_shelf_->IsClosing())) {
512c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    bool visible = browser()->SupportsWindowFeature(
513c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        Browser::FEATURE_DOWNLOADSHELF);
514c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DCHECK(download_shelf_);
515c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int height = visible ? download_shelf_->GetPreferredSize().height() : 0;
516c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    download_shelf_->SetVisible(visible);
517c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    download_shelf_->SetBounds(vertical_layout_rect_.x(), bottom - height,
518c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                               vertical_layout_rect_.width(), height);
519c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    download_shelf_->Layout();
520c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    bottom -= height;
521c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
522c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return bottom;
523c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
524c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool BrowserViewLayout::InfobarVisible() const {
5263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // NOTE: Can't check if the size IsEmpty() since it's always 0-width.
5273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return browser()->SupportsWindowFeature(Browser::FEATURE_INFOBAR) &&
5283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      (infobar_container_->GetPreferredSize().height() != 0);
529c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
530