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
3 // found in the LICENSE file.
4 
5 #ifndef CHROME_BROWSER_UI_VIEWS_FRAME_BROWSER_VIEW_LAYOUT_H_
6 #define CHROME_BROWSER_UI_VIEWS_FRAME_BROWSER_VIEW_LAYOUT_H_
7 
8 #include <memory>
9 
10 #include "base/compiler_specific.h"
11 #include "base/gtest_prod_util.h"
12 #include "base/macros.h"
13 #include "ui/gfx/geometry/rect.h"
14 #include "ui/gfx/geometry/size.h"
15 #include "ui/gfx/native_widget_types.h"
16 #include "ui/views/layout/layout_manager.h"
17 
18 class BookmarkBarView;
19 class BrowserView;
20 class BrowserViewLayoutDelegate;
21 class ImmersiveModeController;
22 class InfoBarContainerView;
23 class TabStrip;
24 class TabStripRegionView;
25 
26 namespace gfx {
27 class Point;
28 }  // namespace gfx
29 
30 namespace views {
31 class View;
32 class Widget;
33 }  // namespace views
34 
35 namespace web_modal {
36 class WebContentsModalDialogHost;
37 }
38 
39 // The layout manager used in chrome browser.
40 class BrowserViewLayout : public views::LayoutManager {
41  public:
42   // The minimum width for the normal (tabbed) browser window's contents area.
43   // This should be wide enough that WebUI pages (e.g. chrome://settings) and
44   // the various associated WebUI dialogs (e.g. Import Bookmarks) can still be
45   // functional. This value provides a trade-off between browser usability and
46   // privacy - specifically, the ability to browse in a very small window, even
47   // on large monitors (which is why a minimum height is not specified). This
48   // value is used for the main browser window only, not for popups.
49   static constexpr int kMainBrowserContentsMinimumWidth = 500;
50 
51   // |browser_view| may be null in tests.
52   BrowserViewLayout(std::unique_ptr<BrowserViewLayoutDelegate> delegate,
53                     gfx::NativeView host_view,
54                     BrowserView* browser_view,
55                     views::View* top_container,
56                     TabStripRegionView* tab_strip_region_view,
57                     TabStrip* tab_strip,
58                     views::View* toolbar,
59                     InfoBarContainerView* infobar_container,
60                     views::View* contents_container,
61                     views::View* side_panel,
62                     ImmersiveModeController* immersive_mode_controller,
63                     views::View* web_footer_experiment,
64                     views::View* contents_separator);
65   ~BrowserViewLayout() override;
66 
67   // Sets or updates views that are not available when |this| is initialized.
set_tab_strip(TabStrip * tab_strip)68   void set_tab_strip(TabStrip* tab_strip) { tab_strip_ = tab_strip; }
set_webui_tab_strip(views::View * webui_tab_strip)69   void set_webui_tab_strip(views::View* webui_tab_strip) {
70     webui_tab_strip_ = webui_tab_strip;
71   }
set_loading_bar(views::View * loading_bar)72   void set_loading_bar(views::View* loading_bar) { loading_bar_ = loading_bar; }
set_bookmark_bar(BookmarkBarView * bookmark_bar)73   void set_bookmark_bar(BookmarkBarView* bookmark_bar) {
74     bookmark_bar_ = bookmark_bar;
75   }
set_download_shelf(views::View * download_shelf)76   void set_download_shelf(views::View* download_shelf) {
77     download_shelf_ = download_shelf;
78   }
set_contents_border_widget(views::Widget * contents_border_widget)79   void set_contents_border_widget(views::Widget* contents_border_widget) {
80     contents_border_widget_ = contents_border_widget;
81   }
contents_border_widget()82   views::Widget* contents_border_widget() { return contents_border_widget_; }
83 
84   web_modal::WebContentsModalDialogHost* GetWebContentsModalDialogHost();
85 
86   // Returns the view against which the dialog is positioned and parented.
87   gfx::NativeView GetHostView();
88 
89   // Tests to see if the specified |point| (in nonclient view's coordinates)
90   // is within the views managed by the laymanager. Returns one of
91   // HitTestCompat enum defined in ui/base/hit_test.h.
92   // See also ClientView::NonClientHitTest.
93   int NonClientHitTest(const gfx::Point& point);
94 
95   // views::LayoutManager overrides:
96   void Layout(views::View* host) override;
97   gfx::Size GetMinimumSize(const views::View* host) const override;
98   gfx::Size GetPreferredSize(const views::View* host) const override;
99 
100   // Returns true if an infobar is showing.
101   bool IsInfobarVisible() const;
102 
103  private:
104   FRIEND_TEST_ALL_PREFIXES(BrowserViewLayoutTest, BrowserViewLayout);
105   FRIEND_TEST_ALL_PREFIXES(BrowserViewLayoutTest, Layout);
106   FRIEND_TEST_ALL_PREFIXES(BrowserViewLayoutTest, LayoutDownloadShelf);
107   class WebContentsModalDialogHostViews;
108 
109   // Layout the following controls, starting at |top|, returns the coordinate
110   // of the bottom of the control, for laying out the next control.
111   int LayoutTabStripRegion(int top);
112   int LayoutWebUITabStrip(int top);
113   int LayoutToolbar(int top);
114   int LayoutBookmarkAndInfoBars(int top, int browser_view_y);
115   int LayoutBookmarkBar(int top);
116   int LayoutInfoBar(int top);
117 
118   // Layout the |contents_container_| view between the coordinates |top| and
119   // |bottom|. See browser_view.h for details of the relationship between
120   // |contents_container_| and other views.
121   void LayoutContentsContainerView(int top, int bottom);
122 
123   // Updates |top_container_|'s bounds. The new bounds depend on the size of
124   // the bookmark bar and the toolbar.
125   void UpdateTopContainerBounds();
126 
127   // Layout the Download Shelf, returns the coordinate of the top of the
128   // control, for laying out the previous control.
129   int LayoutDownloadShelf(int bottom);
130 
131   // Returns the y coordinate of the client area.
132   int GetClientAreaTop();
133 
134   // Layout the web-footer experiment if enabled, returns the top of the
135   // control. See https://crbug.com/993502.
136   int LayoutWebFooterExperiment(int bottom);
137 
138   // The delegate interface. May be a mock in tests.
139   const std::unique_ptr<BrowserViewLayoutDelegate> delegate_;
140 
141   // The view against which the web dialog is positioned and parented.
142   gfx::NativeView const host_view_;
143 
144   // The owning browser view.
145   BrowserView* const browser_view_;
146 
147   // Child views that the layout manager manages.
148   // NOTE: If you add a view, try to add it as a views::View, which makes
149   // testing much easier.
150   views::View* const top_container_;
151   TabStripRegionView* const tab_strip_region_view_;
152   views::View* const toolbar_;
153   InfoBarContainerView* const infobar_container_;
154   views::View* const contents_container_;
155   views::View* const side_panel_;
156   ImmersiveModeController* const immersive_mode_controller_;
157   views::View* const web_footer_experiment_;
158   views::View* const contents_separator_;
159 
160   views::View* webui_tab_strip_ = nullptr;
161   views::View* loading_bar_ = nullptr;
162   TabStrip* tab_strip_ = nullptr;
163   BookmarkBarView* bookmark_bar_ = nullptr;
164   views::View* download_shelf_ = nullptr;
165 
166   // The widget displaying a border on top of contents container for
167   // highlighting the content. Not created by default.
168   views::Widget* contents_border_widget_ = nullptr;
169 
170   // The bounds within which the vertically-stacked contents of the BrowserView
171   // should be laid out within. This is just the local bounds of the
172   // BrowserView.
173   // TODO(jamescook): Remove this and just use browser_view_->GetLocalBounds().
174   gfx::Rect vertical_layout_rect_;
175 
176   // The host for use in positioning the web contents modal dialog.
177   std::unique_ptr<WebContentsModalDialogHostViews> dialog_host_;
178 
179   // The latest dialog bounds applied during a layout pass.
180   gfx::Rect latest_dialog_bounds_;
181 
182   // The distance the web contents modal dialog is from the top of the window,
183   // in pixels.
184   int web_contents_modal_dialog_top_y_ = -1;
185 
186   DISALLOW_COPY_AND_ASSIGN(BrowserViewLayout);
187 };
188 
189 #endif  // CHROME_BROWSER_UI_VIEWS_FRAME_BROWSER_VIEW_LAYOUT_H_
190