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

Side by Side Diff: chrome/browser/ui/views/frame/opaque_browser_frame_view.cc

Issue 23531006: Factor out the layout code from OpaqueBrowserFrameView for testing. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: More clean, hopefully fix that final chromeos test Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/ui/views/frame/opaque_browser_frame_view.h" 5 #include "chrome/browser/ui/views/frame/opaque_browser_frame_view.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <string> 8 #include <string>
9 9
10 #include "base/command_line.h" 10 #include "base/command_line.h"
11 #include "base/compiler_specific.h" 11 #include "base/compiler_specific.h"
12 #include "base/prefs/pref_service.h" 12 #include "base/prefs/pref_service.h"
13 #include "base/strings/utf_string_conversions.h" 13 #include "base/strings/utf_string_conversions.h"
14 #include "chrome/browser/chrome_notification_types.h" 14 #include "chrome/browser/chrome_notification_types.h"
15 #include "chrome/browser/themes/theme_properties.h" 15 #include "chrome/browser/themes/theme_properties.h"
16 #include "chrome/browser/ui/views/avatar_label.h" 16 #include "chrome/browser/ui/views/avatar_label.h"
17 #include "chrome/browser/ui/views/avatar_menu_button.h" 17 #include "chrome/browser/ui/views/avatar_menu_button.h"
18 #include "chrome/browser/ui/views/frame/browser_frame.h" 18 #include "chrome/browser/ui/views/frame/browser_frame.h"
19 #include "chrome/browser/ui/views/frame/browser_view.h" 19 #include "chrome/browser/ui/views/frame/browser_view.h"
20 #include "chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.h"
20 #include "chrome/browser/ui/views/tab_icon_view.h" 21 #include "chrome/browser/ui/views/tab_icon_view.h"
21 #include "chrome/browser/ui/views/tabs/tab_strip.h" 22 #include "chrome/browser/ui/views/tabs/tab_strip.h"
22 #include "chrome/browser/ui/views/toolbar_view.h" 23 #include "chrome/browser/ui/views/toolbar_view.h"
23 #include "chrome/common/chrome_switches.h" 24 #include "chrome/common/chrome_switches.h"
24 #include "chrome/common/pref_names.h" 25 #include "chrome/common/pref_names.h"
25 #include "content/public/browser/notification_service.h" 26 #include "content/public/browser/notification_service.h"
26 #include "content/public/browser/web_contents.h" 27 #include "content/public/browser/web_contents.h"
27 #include "grit/chromium_strings.h" 28 #include "grit/chromium_strings.h"
28 #include "grit/generated_resources.h" 29 #include "grit/generated_resources.h"
29 #include "grit/theme_resources.h" 30 #include "grit/theme_resources.h"
30 #include "grit/ui_resources.h" 31 #include "grit/ui_resources.h"
31 #include "ui/base/accessibility/accessible_view_state.h" 32 #include "ui/base/accessibility/accessible_view_state.h"
32 #include "ui/base/hit_test.h" 33 #include "ui/base/hit_test.h"
33 #include "ui/base/l10n/l10n_util.h" 34 #include "ui/base/l10n/l10n_util.h"
34 #include "ui/base/resource/resource_bundle.h" 35 #include "ui/base/resource/resource_bundle.h"
35 #include "ui/base/theme_provider.h" 36 #include "ui/base/theme_provider.h"
36 #include "ui/gfx/canvas.h" 37 #include "ui/gfx/canvas.h"
37 #include "ui/gfx/font.h" 38 #include "ui/gfx/font.h"
38 #include "ui/gfx/image/image.h" 39 #include "ui/gfx/image/image.h"
39 #include "ui/gfx/image/image_skia.h" 40 #include "ui/gfx/image/image_skia.h"
40 #include "ui/gfx/path.h" 41 #include "ui/gfx/path.h"
41 #include "ui/views/controls/button/image_button.h" 42 #include "ui/views/controls/button/image_button.h"
42 #include "ui/views/controls/image_view.h" 43 #include "ui/views/controls/image_view.h"
43 #include "ui/views/controls/label.h" 44 #include "ui/views/controls/label.h"
44 #include "ui/views/layout/layout_constants.h" 45 #include "ui/views/layout/layout_constants.h"
45 #include "ui/views/widget/root_view.h" 46 #include "ui/views/widget/root_view.h"
46 #include "ui/views/window/frame_background.h" 47 #include "ui/views/window/frame_background.h"
47 #include "ui/views/window/window_shape.h" 48 #include "ui/views/window/window_shape.h"
48 49
49 #if defined(OS_WIN)
50 #include "win8/util/win8_util.h"
51 #endif // OS_WIN
52
53 using content::WebContents; 50 using content::WebContents;
54 51
55 namespace { 52 namespace {
56 53
57 // The frame border is only visible in restored mode and is hardcoded to 4 px on
58 // each side regardless of the system window border size.
59 const int kFrameBorderThickness = 4;
60 // Besides the frame border, there's another 9 px of empty space atop the
61 // window in restored mode, to use to drag the window around.
62 const int kNonClientRestoredExtraThickness = 9;
63 // While resize areas on Windows are normally the same size as the window 54 // While resize areas on Windows are normally the same size as the window
64 // borders, our top area is shrunk by 1 px to make it easier to move the window 55 // borders, our top area is shrunk by 1 px to make it easier to move the window
65 // around with our thinner top grabbable strip. (Incidentally, our side and 56 // around with our thinner top grabbable strip. (Incidentally, our side and
66 // bottom resize areas don't match the frame border thickness either -- they 57 // bottom resize areas don't match the frame border thickness either -- they
67 // span the whole nonclient area, so there's no "dead zone" for the mouse.) 58 // span the whole nonclient area, so there's no "dead zone" for the mouse.)
68 const int kTopResizeAdjust = 1; 59 const int kTopResizeAdjust = 1;
60
69 // In the window corners, the resize areas don't actually expand bigger, but the 61 // In the window corners, the resize areas don't actually expand bigger, but the
70 // 16 px at the end of each edge triggers diagonal resizing. 62 // 16 px at the end of each edge triggers diagonal resizing.
71 const int kResizeAreaCornerSize = 16; 63 const int kResizeAreaCornerSize = 16;
72 // The titlebar never shrinks too short to show the caption button plus some 64
73 // padding below it.
74 const int kCaptionButtonHeightWithPadding = 19;
75 // The content left/right images have a shadow built into them. 65 // The content left/right images have a shadow built into them.
76 const int kContentEdgeShadowThickness = 2; 66 const int kContentEdgeShadowThickness = 2;
77 // The titlebar has a 2 px 3D edge along the top and bottom. 67
78 const int kTitlebarTopAndBottomEdgeThickness = 2;
79 // The icon is inset 2 px from the left frame border.
80 const int kIconLeftSpacing = 2;
81 // The icon never shrinks below 16 px on a side. 68 // The icon never shrinks below 16 px on a side.
82 const int kIconMinimumSize = 16; 69 const int kIconMinimumSize = 16;
83 // There is a 4 px gap between the icon and the title text. 70
84 const int kIconTitleSpacing = 4;
85 // There is a 5 px gap between the title text and the caption buttons.
86 const int kTitleLogoSpacing = 5;
87 // The avatar ends 2 px above the bottom of the tabstrip (which, given the
88 // way the tabstrip draws its bottom edge, will appear like a 1 px gap to the
89 // user).
90 const int kAvatarBottomSpacing = 2;
91 // Space between the frame border and the left edge of the avatar.
92 const int kAvatarLeftSpacing = 2;
93 // Space between the right edge of the avatar and the tabstrip.
94 const int kAvatarRightSpacing = -2;
95 // The top 3 px of the tabstrip is shadow; in maximized mode we push this off 71 // The top 3 px of the tabstrip is shadow; in maximized mode we push this off
96 // the top of the screen so the tabs appear flush against the screen edge. 72 // the top of the screen so the tabs appear flush against the screen edge.
97 const int kTabstripTopShadowThickness = 3; 73 const int kTabstripTopShadowThickness = 3;
98 // In restored mode, the New Tab button isn't at the same height as the caption
99 // buttons, but the space will look cluttered if it actually slides under them,
100 // so we stop it when the gap between the two is down to 5 px.
101 const int kNewTabCaptionRestoredSpacing = 5;
102 // In maximized mode, where the New Tab button and the caption buttons are at
103 // similar vertical coordinates, we need to reserve a larger, 16 px gap to avoid
104 // looking too cluttered.
105 const int kNewTabCaptionMaximizedSpacing = 16;
106 // How far to indent the tabstrip from the left side of the screen when there
107 // is no avatar icon.
108 const int kTabStripIndent = -6;
109 74
110 // Converts |bounds| from |src|'s coordinate system to |dst|, and checks if 75 // Converts |bounds| from |src|'s coordinate system to |dst|, and checks if
111 // |pt| is contained within. 76 // |pt| is contained within.
112 bool ConvertedContainsCheck(gfx::Rect bounds, const views::View* src, 77 bool ConvertedContainsCheck(gfx::Rect bounds, const views::View* src,
113 const views::View* dst, const gfx::Point& pt) { 78 const views::View* dst, const gfx::Point& pt) {
114 DCHECK(src); 79 DCHECK(src);
115 DCHECK(dst); 80 DCHECK(dst);
116 gfx::Point origin(bounds.origin()); 81 gfx::Point origin(bounds.origin());
117 views::View::ConvertPointToTarget(src, dst, &origin); 82 views::View::ConvertPointToTarget(src, dst, &origin);
118 bounds.set_origin(origin); 83 bounds.set_origin(origin);
119 return bounds.Contains(pt); 84 return bounds.Contains(pt);
120 } 85 }
121 86
122 bool ShouldAddDefaultCaptionButtons() {
123 #if defined(OS_WIN)
124 return !win8::IsSingleWindowMetroMode();
125 #endif // OS_WIN
126 return true;
127 }
128
129 } // namespace 87 } // namespace
130 88
131 /////////////////////////////////////////////////////////////////////////////// 89 ///////////////////////////////////////////////////////////////////////////////
132 // OpaqueBrowserFrameView, public: 90 // OpaqueBrowserFrameView, public:
133 91
134 OpaqueBrowserFrameView::OpaqueBrowserFrameView(BrowserFrame* frame, 92 OpaqueBrowserFrameView::OpaqueBrowserFrameView(BrowserFrame* frame,
135 BrowserView* browser_view) 93 BrowserView* browser_view)
136 : BrowserNonClientFrameView(frame, browser_view), 94 : BrowserNonClientFrameView(frame, browser_view),
95 layout_(new OpaqueBrowserFrameViewLayout(this)),
137 minimize_button_(NULL), 96 minimize_button_(NULL),
138 maximize_button_(NULL), 97 maximize_button_(NULL),
139 restore_button_(NULL), 98 restore_button_(NULL),
140 close_button_(NULL), 99 close_button_(NULL),
141 window_icon_(NULL), 100 window_icon_(NULL),
142 window_title_(NULL), 101 window_title_(NULL),
143 frame_background_(new views::FrameBackground()) { 102 frame_background_(new views::FrameBackground()) {
144 if (ShouldAddDefaultCaptionButtons()) { 103 SetLayoutManager(layout_);
104
105 if (OpaqueBrowserFrameViewLayout::ShouldAddDefaultCaptionButtons()) {
145 minimize_button_ = InitWindowCaptionButton(IDR_MINIMIZE, 106 minimize_button_ = InitWindowCaptionButton(IDR_MINIMIZE,
146 IDR_MINIMIZE_H, 107 IDR_MINIMIZE_H,
147 IDR_MINIMIZE_P, 108 IDR_MINIMIZE_P,
148 IDR_MINIMIZE_BUTTON_MASK, 109 IDR_MINIMIZE_BUTTON_MASK,
149 IDS_ACCNAME_MINIMIZE); 110 IDS_ACCNAME_MINIMIZE,
111 VIEW_ID_MINIMIZE_BUTTON);
150 maximize_button_ = InitWindowCaptionButton(IDR_MAXIMIZE, 112 maximize_button_ = InitWindowCaptionButton(IDR_MAXIMIZE,
151 IDR_MAXIMIZE_H, 113 IDR_MAXIMIZE_H,
152 IDR_MAXIMIZE_P, 114 IDR_MAXIMIZE_P,
153 IDR_MAXIMIZE_BUTTON_MASK, 115 IDR_MAXIMIZE_BUTTON_MASK,
154 IDS_ACCNAME_MAXIMIZE); 116 IDS_ACCNAME_MAXIMIZE,
117 VIEW_ID_MAXIMIZE_BUTTON);
155 restore_button_ = InitWindowCaptionButton(IDR_RESTORE, 118 restore_button_ = InitWindowCaptionButton(IDR_RESTORE,
156 IDR_RESTORE_H, 119 IDR_RESTORE_H,
157 IDR_RESTORE_P, 120 IDR_RESTORE_P,
158 IDR_RESTORE_BUTTON_MASK, 121 IDR_RESTORE_BUTTON_MASK,
159 IDS_ACCNAME_RESTORE); 122 IDS_ACCNAME_RESTORE,
123 VIEW_ID_RESTORE_BUTTON);
160 close_button_ = InitWindowCaptionButton(IDR_CLOSE, 124 close_button_ = InitWindowCaptionButton(IDR_CLOSE,
161 IDR_CLOSE_H, 125 IDR_CLOSE_H,
162 IDR_CLOSE_P, 126 IDR_CLOSE_P,
163 IDR_CLOSE_BUTTON_MASK, 127 IDR_CLOSE_BUTTON_MASK,
164 IDS_ACCNAME_CLOSE); 128 IDS_ACCNAME_CLOSE,
129 VIEW_ID_CLOSE_BUTTON);
165 } 130 }
166 131
167 // Initializing the TabIconView is expensive, so only do it if we need to. 132 // Initializing the TabIconView is expensive, so only do it if we need to.
168 if (browser_view->ShouldShowWindowIcon()) { 133 if (browser_view->ShouldShowWindowIcon()) {
169 window_icon_ = new TabIconView(this); 134 window_icon_ = new TabIconView(this);
170 window_icon_->set_is_light(true); 135 window_icon_->set_is_light(true);
136 window_icon_->set_id(VIEW_ID_WINDOW_ICON);
171 AddChildView(window_icon_); 137 AddChildView(window_icon_);
172 window_icon_->Update(); 138 window_icon_->Update();
173 } 139 }
174 140
175 window_title_ = new views::Label(browser_view->GetWindowTitle(), 141 window_title_ = new views::Label(browser_view->GetWindowTitle(),
176 BrowserFrame::GetTitleFont()); 142 BrowserFrame::GetTitleFont());
177 window_title_->SetVisible(browser_view->ShouldShowWindowTitle()); 143 window_title_->SetVisible(browser_view->ShouldShowWindowTitle());
178 window_title_->SetEnabledColor(SK_ColorWHITE); 144 window_title_->SetEnabledColor(SK_ColorWHITE);
179 // TODO(msw): Use a transparent background color as a workaround to use the 145 // TODO(msw): Use a transparent background color as a workaround to use the
180 // gfx::Canvas::NO_SUBPIXEL_RENDERING flag and avoid some visual artifacts. 146 // gfx::Canvas::NO_SUBPIXEL_RENDERING flag and avoid some visual artifacts.
181 window_title_->SetBackgroundColor(0x00000000); 147 window_title_->SetBackgroundColor(0x00000000);
182 window_title_->SetHorizontalAlignment(gfx::ALIGN_LEFT); 148 window_title_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
149 window_title_->set_id(VIEW_ID_WINDOW_TITLE);
183 AddChildView(window_title_); 150 AddChildView(window_title_);
184 151
185 UpdateAvatarInfo(); 152 UpdateAvatarInfo();
186 if (!browser_view->IsOffTheRecord()) { 153 if (!browser_view->IsOffTheRecord()) {
187 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED, 154 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED,
188 content::NotificationService::AllSources()); 155 content::NotificationService::AllSources());
189 } 156 }
190 } 157 }
191 158
192 OpaqueBrowserFrameView::~OpaqueBrowserFrameView() { 159 OpaqueBrowserFrameView::~OpaqueBrowserFrameView() {
193 } 160 }
194 161
195 /////////////////////////////////////////////////////////////////////////////// 162 ///////////////////////////////////////////////////////////////////////////////
196 // OpaqueBrowserFrameView, protected:
197
198 int OpaqueBrowserFrameView::GetReservedHeight() const {
199 return 0;
200 }
201
202 gfx::Rect OpaqueBrowserFrameView::GetBoundsForReservedArea() const {
203 gfx::Rect client_view_bounds = CalculateClientAreaBounds(width(), height());
204 return gfx::Rect(
205 client_view_bounds.x(),
206 client_view_bounds.y() + client_view_bounds.height(),
207 client_view_bounds.width(),
208 GetReservedHeight());
209 }
210
211 int OpaqueBrowserFrameView::NonClientTopBorderHeight(
212 bool restored) const {
213 views::WidgetDelegate* delegate = frame()->widget_delegate();
214 // |delegate| may be NULL if called from callback of InputMethodChanged while
215 // a window is being destroyed.
216 // See more discussion at http://crosbug.com/8958
217 if (delegate && delegate->ShouldShowWindowTitle()) {
218 return std::max(FrameBorderThickness(restored) + IconSize(),
219 CaptionButtonY(restored) + kCaptionButtonHeightWithPadding) +
220 TitlebarBottomThickness(restored);
221 }
222
223 return FrameBorderThickness(restored) -
224 ((browser_view()->IsTabStripVisible() &&
225 !restored && !frame()->ShouldLeaveOffsetNearTopBorder())
226 ? kTabstripTopShadowThickness : 0);
227 }
228
229 ///////////////////////////////////////////////////////////////////////////////
230 // OpaqueBrowserFrameView, BrowserNonClientFrameView implementation: 163 // OpaqueBrowserFrameView, BrowserNonClientFrameView implementation:
231 164
232 gfx::Rect OpaqueBrowserFrameView::GetBoundsForTabStrip( 165 gfx::Rect OpaqueBrowserFrameView::GetBoundsForTabStrip(
233 views::View* tabstrip) const { 166 views::View* tabstrip) const {
234 if (!tabstrip) 167 if (!tabstrip)
235 return gfx::Rect(); 168 return gfx::Rect();
236 169
237 gfx::Rect bounds = GetBoundsForTabStripAndAvatarArea(tabstrip); 170 return layout_->GetBoundsForTabStrip(tabstrip->GetPreferredSize(), width());
238 int space_left_of_tabstrip = kTabStripIndent;
239 if (browser_view()->ShouldShowAvatar()) {
240 if (avatar_label() && avatar_label()->bounds().width()) {
241 // Space between the right edge of the avatar label and the tabstrip.
242 const int kAvatarLabelRightSpacing = -10;
243 space_left_of_tabstrip =
244 avatar_label()->bounds().right() + kAvatarLabelRightSpacing;
245 } else {
246 space_left_of_tabstrip =
247 kAvatarLeftSpacing + avatar_bounds_.width() + kAvatarRightSpacing;
248 }
249 }
250 bounds.Inset(space_left_of_tabstrip, 0, 0, 0);
251 return bounds;
252 } 171 }
253 172
254 BrowserNonClientFrameView::TabStripInsets 173 BrowserNonClientFrameView::TabStripInsets
255 OpaqueBrowserFrameView::GetTabStripInsets(bool restored) const { 174 OpaqueBrowserFrameView::GetTabStripInsets(bool restored) const {
256 int top = NonClientTopBorderHeight(restored) + ((!restored &&
257 (!frame()->ShouldLeaveOffsetNearTopBorder() ||
258 frame()->IsFullscreen())) ?
259 0 : kNonClientRestoredExtraThickness);
260 // TODO: include OTR and caption. 175 // TODO: include OTR and caption.
261 return TabStripInsets(top, 0, 0); 176 return TabStripInsets(layout_->GetTabStripInsetsTop(restored), 0, 0);
262 } 177 }
263 178
264 int OpaqueBrowserFrameView::GetThemeBackgroundXInset() const { 179 int OpaqueBrowserFrameView::GetThemeBackgroundXInset() const {
265 return 0; 180 return 0;
266 } 181 }
267 182
268 void OpaqueBrowserFrameView::UpdateThrobber(bool running) { 183 void OpaqueBrowserFrameView::UpdateThrobber(bool running) {
269 if (window_icon_) 184 if (window_icon_)
270 window_icon_->Update(); 185 window_icon_->Update();
271 } 186 }
272 187
273 gfx::Size OpaqueBrowserFrameView::GetMinimumSize() { 188 gfx::Size OpaqueBrowserFrameView::GetMinimumSize() {
274 gfx::Size min_size(browser_view()->GetMinimumSize()); 189 return layout_->GetMinimumSize(width());
275 int border_thickness = NonClientBorderThickness();
276 min_size.Enlarge(2 * border_thickness,
277 NonClientTopBorderHeight(false) + border_thickness);
278
279 views::WidgetDelegate* delegate = frame()->widget_delegate();
280 int min_titlebar_width = (2 * FrameBorderThickness(false)) +
281 kIconLeftSpacing +
282 (delegate && delegate->ShouldShowWindowIcon() ?
283 (IconSize() + kTitleLogoSpacing) : 0);
284 #if !defined(OS_CHROMEOS)
sky 2013/08/30 16:35:18 It looks like you nuked this in the new code. Inte
Elliot Glaysher 2013/08/30 17:55:01 Intentional, and I had to do some history diving t
285 if (ShouldAddDefaultCaptionButtons()) {
286 min_titlebar_width +=
287 minimize_button_->GetMinimumSize().width() +
288 restore_button_->GetMinimumSize().width() +
289 close_button_->GetMinimumSize().width();
290 }
291 #endif
292 min_size.set_width(std::max(min_size.width(), min_titlebar_width));
293
294 // Ensure that the minimum width is enough to hold a minimum width tab strip
295 // and avatar icon at their usual insets.
296 if (browser_view()->IsTabStripVisible()) {
297 TabStrip* tabstrip = browser_view()->tabstrip();
298 const int min_tabstrip_width = tabstrip->GetMinimumSize().width();
299 const int min_tabstrip_area_width =
300 width() - GetBoundsForTabStripAndAvatarArea(tabstrip).width() +
301 min_tabstrip_width + browser_view()->GetOTRAvatarIcon().width() +
302 kAvatarLeftSpacing + kAvatarRightSpacing;
303 min_size.set_width(std::max(min_size.width(), min_tabstrip_area_width));
304 }
305
306 return min_size;
307 } 190 }
308 191
309 /////////////////////////////////////////////////////////////////////////////// 192 ///////////////////////////////////////////////////////////////////////////////
310 // OpaqueBrowserFrameView, views::NonClientFrameView implementation: 193 // OpaqueBrowserFrameView, views::NonClientFrameView implementation:
311 194
312 gfx::Rect OpaqueBrowserFrameView::GetBoundsForClientView() const { 195 gfx::Rect OpaqueBrowserFrameView::GetBoundsForClientView() const {
313 return client_view_bounds_; 196 return layout_->client_view_bounds();
314 } 197 }
315 198
316 gfx::Rect OpaqueBrowserFrameView::GetWindowBoundsForClientBounds( 199 gfx::Rect OpaqueBrowserFrameView::GetWindowBoundsForClientBounds(
317 const gfx::Rect& client_bounds) const { 200 const gfx::Rect& client_bounds) const {
318 int top_height = NonClientTopBorderHeight(false); 201 return layout_->GetWindowBoundsForClientBounds(client_bounds);
319 int border_thickness = NonClientBorderThickness();
320 return gfx::Rect(std::max(0, client_bounds.x() - border_thickness),
321 std::max(0, client_bounds.y() - top_height),
322 client_bounds.width() + (2 * border_thickness),
323 client_bounds.height() + top_height + border_thickness);
324 } 202 }
325 203
326 int OpaqueBrowserFrameView::NonClientHitTest(const gfx::Point& point) { 204 int OpaqueBrowserFrameView::NonClientHitTest(const gfx::Point& point) {
327 if (!bounds().Contains(point)) 205 if (!bounds().Contains(point))
328 return HTNOWHERE; 206 return HTNOWHERE;
329 207
330 // See if the point is within the avatar menu button or within the avatar 208 // See if the point is within the avatar menu button or within the avatar
331 // label. 209 // label.
332 if ((avatar_button() && 210 if ((avatar_button() &&
333 avatar_button()->GetMirroredBounds().Contains(point)) || 211 avatar_button()->GetMirroredBounds().Contains(point)) ||
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
380 gfx::Path* window_mask) { 258 gfx::Path* window_mask) {
381 DCHECK(window_mask); 259 DCHECK(window_mask);
382 260
383 if (frame()->IsMaximized() || frame()->IsFullscreen()) 261 if (frame()->IsMaximized() || frame()->IsFullscreen())
384 return; 262 return;
385 263
386 views::GetDefaultWindowMask(size, window_mask); 264 views::GetDefaultWindowMask(size, window_mask);
387 } 265 }
388 266
389 void OpaqueBrowserFrameView::ResetWindowControls() { 267 void OpaqueBrowserFrameView::ResetWindowControls() {
390 if (!ShouldAddDefaultCaptionButtons()) 268 if (!OpaqueBrowserFrameViewLayout::ShouldAddDefaultCaptionButtons())
391 return; 269 return;
392 restore_button_->SetState(views::CustomButton::STATE_NORMAL); 270 restore_button_->SetState(views::CustomButton::STATE_NORMAL);
393 minimize_button_->SetState(views::CustomButton::STATE_NORMAL); 271 minimize_button_->SetState(views::CustomButton::STATE_NORMAL);
394 maximize_button_->SetState(views::CustomButton::STATE_NORMAL); 272 maximize_button_->SetState(views::CustomButton::STATE_NORMAL);
395 // The close button isn't affected by this constraint. 273 // The close button isn't affected by this constraint.
396 } 274 }
397 275
398 void OpaqueBrowserFrameView::UpdateWindowIcon() { 276 void OpaqueBrowserFrameView::UpdateWindowIcon() {
399 window_icon_->SchedulePaint(); 277 window_icon_->SchedulePaint();
400 } 278 }
(...skipping 22 matching lines...) Expand all
423 * alpha-blend either (since the Windows text APIs don't really do this). 301 * alpha-blend either (since the Windows text APIs don't really do this).
424 * So we'd need to sample the background color at the right location and 302 * So we'd need to sample the background color at the right location and
425 * synthesize a good shadow color. */ 303 * synthesize a good shadow color. */
426 304
427 if (browser_view()->IsToolbarVisible()) 305 if (browser_view()->IsToolbarVisible())
428 PaintToolbarBackground(canvas); 306 PaintToolbarBackground(canvas);
429 if (!frame()->IsMaximized()) 307 if (!frame()->IsMaximized())
430 PaintRestoredClientEdge(canvas); 308 PaintRestoredClientEdge(canvas);
431 } 309 }
432 310
433 void OpaqueBrowserFrameView::Layout() {
434 LayoutWindowControls();
435 LayoutTitleBar();
436 LayoutAvatar();
437 client_view_bounds_ = CalculateClientAreaBounds(width(), height());
438 }
439
440 bool OpaqueBrowserFrameView::HitTestRect(const gfx::Rect& rect) const { 311 bool OpaqueBrowserFrameView::HitTestRect(const gfx::Rect& rect) const {
441 if (!views::View::HitTestRect(rect)) { 312 if (!views::View::HitTestRect(rect)) {
442 // |rect| is outside OpaqueBrowserFrameView's bounds. 313 // |rect| is outside OpaqueBrowserFrameView's bounds.
443 return false; 314 return false;
444 } 315 }
445 316
446 // If the rect is outside the bounds of the client area, claim it. 317 // If the rect is outside the bounds of the client area, claim it.
447 // TODO(tdanderson): Implement View::ConvertRectToTarget(). 318 // TODO(tdanderson): Implement View::ConvertRectToTarget().
448 gfx::Point rect_in_client_view_coords_origin(rect.origin()); 319 gfx::Point rect_in_client_view_coords_origin(rect.origin());
449 View::ConvertPointToTarget(this, frame()->client_view(), 320 View::ConvertPointToTarget(this, frame()->client_view(),
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
552 case chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED: 423 case chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED:
553 UpdateAvatarInfo(); 424 UpdateAvatarInfo();
554 break; 425 break;
555 default: 426 default:
556 NOTREACHED() << "Got a notification we didn't register for!"; 427 NOTREACHED() << "Got a notification we didn't register for!";
557 break; 428 break;
558 } 429 }
559 } 430 }
560 431
561 /////////////////////////////////////////////////////////////////////////////// 432 ///////////////////////////////////////////////////////////////////////////////
433 // OpaqueBrowserFrameView, OpaqueBrowserFrameViewLayoutDelegate implementation:
434
435 bool OpaqueBrowserFrameView::ShouldShowWindowIcon() const {
436 views::WidgetDelegate* delegate = frame()->widget_delegate();
437 return delegate && delegate->ShouldShowWindowIcon();
438 }
439
440 bool OpaqueBrowserFrameView::ShouldShowWindowTitle() const {
441 // |delegate| may be NULL if called from callback of InputMethodChanged while
442 // a window is being destroyed.
443 // See more discussion at http://crosbug.com/8958
444 views::WidgetDelegate* delegate = frame()->widget_delegate();
445 return delegate && delegate->ShouldShowWindowTitle();
446 }
447
448 string16 OpaqueBrowserFrameView::GetWindowTitle() const {
449 return frame()->widget_delegate()->GetWindowTitle();
450 }
451
452 int OpaqueBrowserFrameView::GetIconSize() const {
453 #if defined(OS_WIN)
454 // This metric scales up if either the titlebar height or the titlebar font
455 // size are increased.
456 return GetSystemMetrics(SM_CYSMICON);
457 #else
458 return std::max(BrowserFrame::GetTitleFont().GetHeight(), kIconMinimumSize);
459 #endif
460 }
461
462 bool OpaqueBrowserFrameView::ShouldLeaveOffsetNearTopBorder() const {
463 return frame()->ShouldLeaveOffsetNearTopBorder();
464 }
465
466 gfx::Size OpaqueBrowserFrameView::GetBrowserViewMinimumSize() const {
467 return browser_view()->GetMinimumSize();
468 }
469
470 bool OpaqueBrowserFrameView::ShouldShowAvatar() const {
471 return browser_view()->ShouldShowAvatar();
472 }
473
474 gfx::ImageSkia OpaqueBrowserFrameView::GetOTRAvatarIcon() const {
475 return browser_view()->GetOTRAvatarIcon();
476 }
477
478 bool OpaqueBrowserFrameView::IsMaximized() const {
479 return frame()->IsMaximized();
480 }
481
482 bool OpaqueBrowserFrameView::IsMinimized() const {
483 return frame()->IsMinimized();
484 }
485
486 bool OpaqueBrowserFrameView::IsFullscreen() const {
487 return frame()->IsFullscreen();
488 }
489
490 bool OpaqueBrowserFrameView::IsTabStripVisible() const {
491 return browser_view()->IsTabStripVisible();
492 }
493
494 int OpaqueBrowserFrameView::GetTabStripHeight() const {
495 return browser_view()->GetTabStripHeight();
496 }
497
498 int OpaqueBrowserFrameView::GetAdditionalReservedSpaceInTabStrip() const {
499 // We don't have the sysmenu buttons in Windows 8 metro mode. However there
500 // are buttons like the window switcher which are drawn in the non client
501 // are in the BrowserView. We need to ensure that the tab strip does not
502 // draw on the window switcher button.
503 views::View* button = browser_view()->window_switcher_button();
504 return button ? button->width() : 0;
505 }
506
507 gfx::Size OpaqueBrowserFrameView::GetTabstripPreferredSize() const {
508 gfx::Size s = browser_view()->tabstrip()->GetPreferredSize();
509 return s;
510 }
511
512 ///////////////////////////////////////////////////////////////////////////////
562 // OpaqueBrowserFrameView, private: 513 // OpaqueBrowserFrameView, private:
563 514
564 views::ImageButton* OpaqueBrowserFrameView::InitWindowCaptionButton( 515 views::ImageButton* OpaqueBrowserFrameView::InitWindowCaptionButton(
565 int normal_image_id, 516 int normal_image_id,
566 int hot_image_id, 517 int hot_image_id,
567 int pushed_image_id, 518 int pushed_image_id,
568 int mask_image_id, 519 int mask_image_id,
569 int accessibility_string_id) { 520 int accessibility_string_id,
521 ViewID view_id) {
570 views::ImageButton* button = new views::ImageButton(this); 522 views::ImageButton* button = new views::ImageButton(this);
571 ui::ThemeProvider* tp = frame()->GetThemeProvider(); 523 ui::ThemeProvider* tp = frame()->GetThemeProvider();
572 button->SetImage(views::CustomButton::STATE_NORMAL, 524 button->SetImage(views::CustomButton::STATE_NORMAL,
573 tp->GetImageSkiaNamed(normal_image_id)); 525 tp->GetImageSkiaNamed(normal_image_id));
574 button->SetImage(views::CustomButton::STATE_HOVERED, 526 button->SetImage(views::CustomButton::STATE_HOVERED,
575 tp->GetImageSkiaNamed(hot_image_id)); 527 tp->GetImageSkiaNamed(hot_image_id));
576 button->SetImage(views::CustomButton::STATE_PRESSED, 528 button->SetImage(views::CustomButton::STATE_PRESSED,
577 tp->GetImageSkiaNamed(pushed_image_id)); 529 tp->GetImageSkiaNamed(pushed_image_id));
578 if (browser_view()->IsBrowserTypeNormal()) { 530 if (browser_view()->IsBrowserTypeNormal()) {
579 button->SetBackground( 531 button->SetBackground(
580 tp->GetColor(ThemeProperties::COLOR_BUTTON_BACKGROUND), 532 tp->GetColor(ThemeProperties::COLOR_BUTTON_BACKGROUND),
581 tp->GetImageSkiaNamed(IDR_THEME_WINDOW_CONTROL_BACKGROUND), 533 tp->GetImageSkiaNamed(IDR_THEME_WINDOW_CONTROL_BACKGROUND),
582 tp->GetImageSkiaNamed(mask_image_id)); 534 tp->GetImageSkiaNamed(mask_image_id));
583 } 535 }
584 button->SetAccessibleName( 536 button->SetAccessibleName(
585 l10n_util::GetStringUTF16(accessibility_string_id)); 537 l10n_util::GetStringUTF16(accessibility_string_id));
538 button->set_id(view_id);
586 AddChildView(button); 539 AddChildView(button);
587 return button; 540 return button;
588 } 541 }
589 542
590 int OpaqueBrowserFrameView::FrameBorderThickness(bool restored) const { 543 int OpaqueBrowserFrameView::FrameBorderThickness(bool restored) const {
591 return (!restored && (frame()->IsMaximized() || frame()->IsFullscreen())) ? 544 return layout_->FrameBorderThickness(restored);
592 0 : kFrameBorderThickness;
593 } 545 }
594 546
595 int OpaqueBrowserFrameView::TopResizeHeight() const { 547 int OpaqueBrowserFrameView::TopResizeHeight() const {
596 return FrameBorderThickness(false) - kTopResizeAdjust; 548 return FrameBorderThickness(false) - kTopResizeAdjust;
597 } 549 }
598 550
599 int OpaqueBrowserFrameView::NonClientBorderThickness() const { 551 int OpaqueBrowserFrameView::NonClientBorderThickness() const {
600 // When we fill the screen, we don't show a client edge. 552 return layout_->NonClientBorderThickness();
601 return FrameBorderThickness(false) +
602 ((frame()->IsMaximized() || frame()->IsFullscreen()) ?
603 0 : kClientEdgeThickness);
604 }
605
606 int OpaqueBrowserFrameView::CaptionButtonY(bool restored) const {
607 // Maximized buttons start at window top so that even if their images aren't
608 // drawn flush with the screen edge, they still obey Fitts' Law.
609 return (!restored && frame()->IsMaximized()) ?
610 FrameBorderThickness(false) : kFrameShadowThickness;
611 }
612
613 int OpaqueBrowserFrameView::TitlebarBottomThickness(bool restored) const {
614 return kTitlebarTopAndBottomEdgeThickness +
615 ((!restored && frame()->IsMaximized()) ? 0 : kClientEdgeThickness);
616 }
617
618 int OpaqueBrowserFrameView::IconSize() const {
619 #if defined(OS_WIN)
620 // This metric scales up if either the titlebar height or the titlebar font
621 // size are increased.
622 return GetSystemMetrics(SM_CYSMICON);
623 #else
624 return std::max(BrowserFrame::GetTitleFont().GetHeight(), kIconMinimumSize);
625 #endif
626 } 553 }
627 554
628 gfx::Rect OpaqueBrowserFrameView::IconBounds() const { 555 gfx::Rect OpaqueBrowserFrameView::IconBounds() const {
629 int size = IconSize(); 556 return layout_->IconBounds();
630 int frame_thickness = FrameBorderThickness(false);
631 int y;
632 views::WidgetDelegate* delegate = frame()->widget_delegate();
633 if (delegate && (delegate->ShouldShowWindowIcon() ||
634 delegate->ShouldShowWindowTitle())) {
635 // Our frame border has a different "3D look" than Windows'. Theirs has a
636 // more complex gradient on the top that they push their icon/title below;
637 // then the maximized window cuts this off and the icon/title are centered
638 // in the remaining space. Because the apparent shape of our border is
639 // simpler, using the same positioning makes things look slightly uncentered
640 // with restored windows, so when the window is restored, instead of
641 // calculating the remaining space from below the frame border, we calculate
642 // from below the 3D edge.
643 int unavailable_px_at_top = frame()->IsMaximized() ?
644 frame_thickness : kTitlebarTopAndBottomEdgeThickness;
645 // When the icon is shorter than the minimum space we reserve for the
646 // caption button, we vertically center it. We want to bias rounding to put
647 // extra space above the icon, since the 3D edge (+ client edge, for
648 // restored windows) below looks (to the eye) more like additional space
649 // than does the 3D edge (or nothing at all, for maximized windows) above;
650 // hence the +1.
651 y = unavailable_px_at_top + (NonClientTopBorderHeight(false) -
652 unavailable_px_at_top - size - TitlebarBottomThickness(false) + 1) / 2;
653 } else {
654 // For "browser mode" windows, we use the native positioning, which is just
655 // below the top frame border.
656 y = frame_thickness;
657 }
658 return gfx::Rect(frame_thickness + kIconLeftSpacing, y, size, size);
659 }
660
661 gfx::Rect OpaqueBrowserFrameView::GetBoundsForTabStripAndAvatarArea(
662 views::View* tabstrip) const {
663 int available_width = width();
664 if (minimize_button_) {
665 available_width = minimize_button_->x();
666 } else if (browser_view()->window_switcher_button()) {
667 // We don't have the sysmenu buttons in Windows 8 metro mode. However there
668 // are buttons like the window switcher which are drawn in the non client
669 // are in the BrowserView. We need to ensure that the tab strip does not
670 // draw on the window switcher button.
671 available_width -= browser_view()->window_switcher_button()->width();
672 }
673 const int caption_spacing = frame()->IsMaximized() ?
674 kNewTabCaptionMaximizedSpacing : kNewTabCaptionRestoredSpacing;
675 const int tabstrip_x = NonClientBorderThickness();
676 const int tabstrip_width = available_width - tabstrip_x - caption_spacing;
677 return gfx::Rect(tabstrip_x, GetTabStripInsets(false).top,
678 std::max(0, tabstrip_width),
679 tabstrip->GetPreferredSize().height());
680 } 557 }
681 558
682 void OpaqueBrowserFrameView::PaintRestoredFrameBorder(gfx::Canvas* canvas) { 559 void OpaqueBrowserFrameView::PaintRestoredFrameBorder(gfx::Canvas* canvas) {
683 frame_background_->set_frame_color(GetFrameColor()); 560 frame_background_->set_frame_color(GetFrameColor());
684 frame_background_->set_theme_image(GetFrameImage()); 561 frame_background_->set_theme_image(GetFrameImage());
685 frame_background_->set_theme_overlay_image(GetFrameOverlayImage()); 562 frame_background_->set_theme_overlay_image(GetFrameOverlayImage());
686 frame_background_->set_top_area_height(GetTopAreaHeight()); 563 frame_background_->set_top_area_height(GetTopAreaHeight());
687 564
688 ui::ThemeProvider* tp = GetThemeProvider(); 565 ui::ThemeProvider* tp = GetThemeProvider();
689 frame_background_->SetSideImages( 566 frame_background_->SetSideImages(
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
838 kClientEdgeThickness), 715 kClientEdgeThickness),
839 ThemeProperties::GetDefaultColor( 716 ThemeProperties::GetDefaultColor(
840 ThemeProperties::COLOR_TOOLBAR_SEPARATOR)); 717 ThemeProperties::COLOR_TOOLBAR_SEPARATOR));
841 } 718 }
842 719
843 void OpaqueBrowserFrameView::PaintRestoredClientEdge(gfx::Canvas* canvas) { 720 void OpaqueBrowserFrameView::PaintRestoredClientEdge(gfx::Canvas* canvas) {
844 ui::ThemeProvider* tp = GetThemeProvider(); 721 ui::ThemeProvider* tp = GetThemeProvider();
845 int client_area_top = frame()->client_view()->y(); 722 int client_area_top = frame()->client_view()->y();
846 int image_top = client_area_top; 723 int image_top = client_area_top;
847 724
848 gfx::Rect client_area_bounds = CalculateClientAreaBounds(width(), height()); 725 gfx::Rect client_area_bounds =
726 layout_->CalculateClientAreaBounds(width(), height());
849 SkColor toolbar_color = tp->GetColor(ThemeProperties::COLOR_TOOLBAR); 727 SkColor toolbar_color = tp->GetColor(ThemeProperties::COLOR_TOOLBAR);
850 728
851 if (browser_view()->IsToolbarVisible()) { 729 if (browser_view()->IsToolbarVisible()) {
852 // The client edge images always start below the toolbar corner images. The 730 // The client edge images always start below the toolbar corner images. The
853 // client edge filled rects start there or at the bottom of the toolbar, 731 // client edge filled rects start there or at the bottom of the toolbar,
854 // whichever is shorter. 732 // whichever is shorter.
855 gfx::Rect toolbar_bounds(browser_view()->GetToolbarBounds()); 733 gfx::Rect toolbar_bounds(browser_view()->GetToolbarBounds());
856 image_top += toolbar_bounds.y() + 734 image_top += toolbar_bounds.y() +
857 tp->GetImageSkiaNamed(IDR_CONTENT_TOP_LEFT_CORNER)->height(); 735 tp->GetImageSkiaNamed(IDR_CONTENT_TOP_LEFT_CORNER)->height();
858 client_area_top = std::min(image_top, 736 client_area_top = std::min(image_top,
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
982 860
983 int OpaqueBrowserFrameView::GetTopAreaHeight() const { 861 int OpaqueBrowserFrameView::GetTopAreaHeight() const {
984 gfx::ImageSkia* frame_image = GetFrameImage(); 862 gfx::ImageSkia* frame_image = GetFrameImage();
985 int top_area_height = frame_image->height(); 863 int top_area_height = frame_image->height();
986 if (browser_view()->IsTabStripVisible()) { 864 if (browser_view()->IsTabStripVisible()) {
987 top_area_height = std::max(top_area_height, 865 top_area_height = std::max(top_area_height,
988 GetBoundsForTabStrip(browser_view()->tabstrip()).bottom()); 866 GetBoundsForTabStrip(browser_view()->tabstrip()).bottom());
989 } 867 }
990 return top_area_height; 868 return top_area_height;
991 } 869 }
992
993 void OpaqueBrowserFrameView::LayoutWindowControls() {
994 if (!ShouldAddDefaultCaptionButtons())
995 return;
996 bool is_maximized = frame()->IsMaximized();
997 close_button_->SetImageAlignment(views::ImageButton::ALIGN_LEFT,
998 views::ImageButton::ALIGN_BOTTOM);
999 int caption_y = CaptionButtonY(false);
1000 // There should always be the same number of non-shadow pixels visible to the
1001 // side of the caption buttons. In maximized mode we extend the rightmost
1002 // button to the screen corner to obey Fitts' Law.
1003 int right_extra_width = is_maximized ?
1004 (kFrameBorderThickness - kFrameShadowThickness) : 0;
1005 gfx::Size close_button_size = close_button_->GetPreferredSize();
1006 close_button_->SetBounds(width() - FrameBorderThickness(false) -
1007 right_extra_width - close_button_size.width(), caption_y,
1008 close_button_size.width() + right_extra_width,
1009 close_button_size.height());
1010
1011 // When the window is restored, we show a maximized button; otherwise, we show
1012 // a restore button.
1013 bool is_restored = !is_maximized && !frame()->IsMinimized();
1014 views::ImageButton* invisible_button = is_restored ?
1015 restore_button_ : maximize_button_;
1016 invisible_button->SetVisible(false);
1017
1018 views::ImageButton* visible_button = is_restored ?
1019 maximize_button_ : restore_button_;
1020 visible_button->SetVisible(true);
1021 visible_button->SetImageAlignment(views::ImageButton::ALIGN_LEFT,
1022 views::ImageButton::ALIGN_BOTTOM);
1023 gfx::Size visible_button_size = visible_button->GetPreferredSize();
1024 visible_button->SetBounds(close_button_->x() - visible_button_size.width(),
1025 caption_y, visible_button_size.width(),
1026 visible_button_size.height());
1027
1028 minimize_button_->SetVisible(true);
1029 minimize_button_->SetImageAlignment(views::ImageButton::ALIGN_LEFT,
1030 views::ImageButton::ALIGN_BOTTOM);
1031 gfx::Size minimize_button_size = minimize_button_->GetPreferredSize();
1032 minimize_button_->SetBounds(
1033 visible_button->x() - minimize_button_size.width(), caption_y,
1034 minimize_button_size.width(),
1035 minimize_button_size.height());
1036 }
1037
1038 void OpaqueBrowserFrameView::LayoutTitleBar() {
1039 const views::WidgetDelegate* delegate = frame()->widget_delegate();
1040 if (delegate) {
1041 gfx::Rect icon_bounds(IconBounds());
1042 if (delegate->ShouldShowWindowIcon())
1043 window_icon_->SetBoundsRect(icon_bounds);
1044
1045 window_title_->SetVisible(delegate->ShouldShowWindowTitle());
1046 if (delegate->ShouldShowWindowTitle()) {
1047 window_title_->SetText(delegate->GetWindowTitle());
1048 const int title_x = delegate->ShouldShowWindowIcon() ?
1049 icon_bounds.right() + kIconTitleSpacing : icon_bounds.x();
1050 window_title_->SetBounds(title_x, icon_bounds.y(),
1051 std::max(0, minimize_button_->x() - kTitleLogoSpacing - title_x),
1052 icon_bounds.height());
1053 }
1054 }
1055 }
1056
1057 void OpaqueBrowserFrameView::LayoutAvatar() {
1058 // Even though the avatar is used for both incognito and profiles we always
1059 // use the incognito icon to layout the avatar button. The profile icon
1060 // can be customized so we can't depend on its size to perform layout.
1061 gfx::ImageSkia incognito_icon = browser_view()->GetOTRAvatarIcon();
1062
1063 int avatar_bottom = GetTabStripInsets(false).top +
1064 browser_view()->GetTabStripHeight() - kAvatarBottomSpacing;
1065 int avatar_restored_y = avatar_bottom - incognito_icon.height();
1066 int avatar_y = frame()->IsMaximized() ?
1067 (NonClientTopBorderHeight(false) + kTabstripTopShadowThickness) :
1068 avatar_restored_y;
1069 avatar_bounds_.SetRect(NonClientBorderThickness() + kAvatarLeftSpacing,
1070 avatar_y, incognito_icon.width(),
1071 browser_view()->ShouldShowAvatar() ? (avatar_bottom - avatar_y) : 0);
1072 if (avatar_button())
1073 avatar_button()->SetBoundsRect(avatar_bounds_);
1074
1075 if (avatar_label()) {
1076 // Space between the bottom of the avatar and the bottom of the avatar
1077 // label.
1078 const int kAvatarLabelBottomSpacing = 3;
1079 // Space between the frame border and the left edge of the avatar label.
1080 const int kAvatarLabelLeftSpacing = -1;
1081 gfx::Size label_size = avatar_label()->GetPreferredSize();
1082 gfx::Rect label_bounds(
1083 FrameBorderThickness(false) + kAvatarLabelLeftSpacing,
1084 avatar_bottom - kAvatarLabelBottomSpacing - label_size.height(),
1085 label_size.width(),
1086 browser_view()->ShouldShowAvatar() ? label_size.height() : 0);
1087 avatar_label()->SetBoundsRect(label_bounds);
1088 }
1089 }
1090
1091 gfx::Rect OpaqueBrowserFrameView::CalculateClientAreaBounds(int width,
1092 int height) const {
1093 int top_height = NonClientTopBorderHeight(false);
1094 int border_thickness = NonClientBorderThickness();
1095 return gfx::Rect(border_thickness, top_height,
1096 std::max(0, width - (2 * border_thickness)),
1097 std::max(0, height - GetReservedHeight() -
1098 top_height - border_thickness));
1099 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698