| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #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) | |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 } | |
| OLD | NEW |