| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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/views/frame/aero_glass_non_client_view.h" | 5 #include "chrome/browser/views/frame/aero_glass_non_client_view.h" |
| 6 | 6 |
| 7 #include "chrome/app/theme/theme_resources.h" | 7 #include "chrome/app/theme/theme_resources.h" |
| 8 #include "chrome/browser/views/frame/browser_view.h" | 8 #include "chrome/browser/views/frame/browser_view.h" |
| 9 #include "chrome/browser/views/tabs/tab_strip.h" | 9 #include "chrome/browser/views/tabs/tab_strip.h" |
| 10 #include "chrome/common/gfx/chrome_canvas.h" | |
| 11 #include "chrome/common/gfx/chrome_font.h" | |
| 12 #include "chrome/common/gfx/path.h" | |
| 13 #include "chrome/common/resource_bundle.h" | 10 #include "chrome/common/resource_bundle.h" |
| 14 #include "chrome/views/client_view.h" | 11 #include "chrome/views/client_view.h" |
| 15 #include "chrome/views/window_delegate.h" | |
| 16 #include "chrome/views/window_resources.h" | 12 #include "chrome/views/window_resources.h" |
| 17 | 13 |
| 18 // An enumeration of bitmap resources used by this window. | 14 // An enumeration of bitmap resources used by this window. |
| 19 enum { | 15 enum { |
| 20 FRAME_PART_BITMAP_FIRST = 0, // must be first. | 16 FRAME_PART_BITMAP_FIRST = 0, // must be first. |
| 21 | 17 |
| 22 // Client Edge Border. | 18 // Client Edge Border. |
| 23 FRAME_CLIENT_EDGE_TOP_LEFT, | 19 FRAME_CLIENT_EDGE_TOP_LEFT, |
| 24 FRAME_CLIENT_EDGE_TOP, | 20 FRAME_CLIENT_EDGE_TOP, |
| 25 FRAME_CLIENT_EDGE_TOP_RIGHT, | 21 FRAME_CLIENT_EDGE_TOP_RIGHT, |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 82 | 78 |
| 83 // static | 79 // static |
| 84 SkBitmap* AeroGlassWindowResources::standard_frame_bitmaps_[]; | 80 SkBitmap* AeroGlassWindowResources::standard_frame_bitmaps_[]; |
| 85 SkBitmap AeroGlassWindowResources::app_top_left_; | 81 SkBitmap AeroGlassWindowResources::app_top_left_; |
| 86 SkBitmap AeroGlassWindowResources::app_top_center_; | 82 SkBitmap AeroGlassWindowResources::app_top_center_; |
| 87 SkBitmap AeroGlassWindowResources::app_top_right_; | 83 SkBitmap AeroGlassWindowResources::app_top_right_; |
| 88 | 84 |
| 89 AeroGlassWindowResources* AeroGlassNonClientView::resources_ = NULL; | 85 AeroGlassWindowResources* AeroGlassNonClientView::resources_ = NULL; |
| 90 SkBitmap AeroGlassNonClientView::distributor_logo_; | 86 SkBitmap AeroGlassNonClientView::distributor_logo_; |
| 91 | 87 |
| 92 // The width of the client edge to the left and right of the window. | 88 namespace { |
| 93 static const int kClientEdgeWidth = 3; | 89 // There are 3 px of client edge drawn inside the outer frame borders. |
| 94 // The height of the client edge to the bottom of the window. | 90 const int kNonClientBorderThickness = 3; |
| 95 static const int kClientEdgeHeight = 2; | 91 // Besides the frame border, there's another 11 px of empty space atop the |
| 92 // window in restored mode, to use to drag the window around. |
| 93 const int kNonClientRestoredExtraThickness = 11; |
| 96 // In the window corners, the resize areas don't actually expand bigger, but the | 94 // In the window corners, the resize areas don't actually expand bigger, but the |
| 97 // 16 px at the end of the top and bottom edges triggers diagonal resizing. | 95 // 16 px at the end of the top and bottom edges triggers diagonal resizing. |
| 98 const int kResizeEdgeWidth = 16; | 96 const int kResizeAreaCornerSize = 16; |
| 99 // The horizontal distance between the left of the minimize button and the | 97 // The distributor logo is drawn 3 px from the top of the window. |
| 100 // right edge of the distributor logo. | 98 static const int kLogoTopSpacing = 3; |
| 101 static const int kDistributorLogoHorizontalOffset = 7; | |
| 102 // The distance from the top of the non-client view and the top edge of the | |
| 103 // distributor logo. | |
| 104 static const int kDistributorLogoVerticalOffset = 3; | |
| 105 // The distance of the TabStrip from the top of the window's client area. | |
| 106 static const int kTabStripY = 19; | |
| 107 // How much space on the right is not used for the tab strip (to provide | |
| 108 // separation between the tabs and the window controls). | |
| 109 static const int kTabStripRightHorizOffset = 30; | |
| 110 // A single pixel. | |
| 111 static const int kPixel = 1; | |
| 112 // The size (width/height) of the window icon. | |
| 113 static const int kWindowIconSize = 16; | |
| 114 // In maximized mode, the OTR avatar starts 2 px below the top of the screen, so | 99 // In maximized mode, the OTR avatar starts 2 px below the top of the screen, so |
| 115 // that it doesn't extend into the "3D edge" portion of the titlebar. | 100 // that it doesn't extend into the "3D edge" portion of the titlebar. |
| 116 const int kOTRMaximizedTopSpacing = 2; | 101 const int kOTRMaximizedTopSpacing = 2; |
| 117 // The OTR avatar ends 2 px above the bottom of the tabstrip (which, given the | 102 // The OTR avatar ends 2 px above the bottom of the tabstrip (which, given the |
| 118 // way the tabstrip draws its bottom edge, will appear like a 1 px gap to the | 103 // way the tabstrip draws its bottom edge, will appear like a 1 px gap to the |
| 119 // user). | 104 // user). |
| 120 const int kOTRBottomSpacing = 2; | 105 const int kOTRBottomSpacing = 2; |
| 121 // There are 2 px on each side of the OTR avatar (between the frame border and | 106 // There are 2 px on each side of the OTR avatar (between the frame border and |
| 122 // it on the left, and between it and the tabstrip on the right). | 107 // it on the left, and between it and the tabstrip on the right). |
| 123 const int kOTRSideSpacing = 2; | 108 const int kOTRSideSpacing = 2; |
| 109 // In restored mode, the New Tab button isn't at the same height as the caption |
| 110 // buttons, but the space will look cluttered if it actually slides under them, |
| 111 // so we stop it when the gap between the two is down to 5 px. |
| 112 const int kNewTabCaptionRestoredSpacing = 5; |
| 113 // In maximized mode, where the New Tab button and the caption buttons are at |
| 114 // similar vertical coordinates, we need to reserve a larger, 16 px gap to avoid |
| 115 // looking too cluttered. |
| 116 const int kNewTabCaptionMaximizedSpacing = 16; |
| 117 // When there's a distributor logo, we leave a 7 px gap between it and the |
| 118 // caption buttons. |
| 119 const int kLogoCaptionSpacing = 7; |
| 120 } |
| 124 | 121 |
| 125 /////////////////////////////////////////////////////////////////////////////// | 122 /////////////////////////////////////////////////////////////////////////////// |
| 126 // AeroGlassNonClientView, public: | 123 // AeroGlassNonClientView, public: |
| 127 | 124 |
| 128 AeroGlassNonClientView::AeroGlassNonClientView(AeroGlassFrame* frame, | 125 AeroGlassNonClientView::AeroGlassNonClientView(AeroGlassFrame* frame, |
| 129 BrowserView* browser_view) | 126 BrowserView* browser_view) |
| 130 : frame_(frame), | 127 : frame_(frame), |
| 131 browser_view_(browser_view) { | 128 browser_view_(browser_view) { |
| 132 InitClass(); | 129 InitClass(); |
| 133 } | 130 } |
| 134 | 131 |
| 135 AeroGlassNonClientView::~AeroGlassNonClientView() { | 132 AeroGlassNonClientView::~AeroGlassNonClientView() { |
| 136 } | 133 } |
| 137 | 134 |
| 138 gfx::Rect AeroGlassNonClientView::GetBoundsForTabStrip(TabStrip* tabstrip) { | 135 gfx::Rect AeroGlassNonClientView::GetBoundsForTabStrip(TabStrip* tabstrip) { |
| 139 int tabstrip_x = browser_view_->ShouldShowOffTheRecordAvatar() ? | 136 int tabstrip_x = browser_view_->ShouldShowOffTheRecordAvatar() ? |
| 140 (otr_avatar_bounds_.right() + kOTRSideSpacing) : kClientEdgeWidth; | 137 (otr_avatar_bounds_.right() + kOTRSideSpacing) : |
| 141 int tabstrip_width = width() - tabstrip_x - kTabStripRightHorizOffset - | 138 NonClientBorderThickness(); |
| 142 (frame_->IsMaximized() ? frame_->GetMinimizeButtonOffset() : 0); | 139 int tabstrip_width = frame_->GetMinimizeButtonOffset() - tabstrip_x - |
| 143 int tabstrip_y = | 140 (frame_->IsMaximized() ? |
| 144 frame_->IsMaximized() ? (CalculateNonClientTopHeight() - 2) : kTabStripY; | 141 kNewTabCaptionMaximizedSpacing : kNewTabCaptionRestoredSpacing); |
| 145 return gfx::Rect(tabstrip_x, tabstrip_y, std::max(0, tabstrip_width), | 142 return gfx::Rect(tabstrip_x, NonClientTopBorderHeight(), |
| 146 tabstrip->GetPreferredHeight()); | 143 std::max(0, tabstrip_width), tabstrip->GetPreferredHeight()); |
| 147 } | 144 } |
| 148 | 145 |
| 149 /////////////////////////////////////////////////////////////////////////////// | 146 /////////////////////////////////////////////////////////////////////////////// |
| 150 // AeroGlassNonClientView, views::NonClientView implementation: | 147 // AeroGlassNonClientView, views::NonClientView implementation: |
| 151 | 148 |
| 152 gfx::Rect AeroGlassNonClientView::CalculateClientAreaBounds(int win_width, | 149 gfx::Rect AeroGlassNonClientView::CalculateClientAreaBounds(int width, |
| 153 int win_height) cons
t { | 150 int height) const { |
| 154 if (!browser_view_->IsTabStripVisible()) | 151 if (!browser_view_->IsTabStripVisible()) |
| 155 return gfx::Rect(0, 0, width(), height()); | 152 return gfx::Rect(0, 0, this->width(), this->height()); |
| 156 | 153 |
| 157 int top_margin = CalculateNonClientTopHeight(); | 154 int top_height = NonClientTopBorderHeight(); |
| 158 return gfx::Rect(kClientEdgeWidth, top_margin, | 155 int border_thickness = NonClientBorderThickness(); |
| 159 std::max(0, win_width - (2 * kClientEdgeWidth)), | 156 return gfx::Rect(border_thickness, top_height, |
| 160 std::max(0, win_height - top_margin - kClientEdgeHeight)); | 157 std::max(0, width - (2 * border_thickness)), |
| 161 } | 158 std::max(0, height - top_height - border_thickness)); |
| 162 | |
| 163 gfx::Size AeroGlassNonClientView::CalculateWindowSizeForClientSize( | |
| 164 int width, | |
| 165 int height) const { | |
| 166 int top_margin = CalculateNonClientTopHeight(); | |
| 167 return gfx::Size(width + (2 * kClientEdgeWidth), | |
| 168 height + top_margin + kClientEdgeHeight); | |
| 169 } | 159 } |
| 170 | 160 |
| 171 CPoint AeroGlassNonClientView::GetSystemMenuPoint() const { | 161 CPoint AeroGlassNonClientView::GetSystemMenuPoint() const { |
| 172 CPoint offset(0, 0); | 162 CPoint offset; |
| 173 MapWindowPoints(GetWidget()->GetHWND(), HWND_DESKTOP, &offset, 1); | 163 MapWindowPoints(GetWidget()->GetHWND(), HWND_DESKTOP, &offset, 1); |
| 174 return offset; | 164 return offset; |
| 175 } | 165 } |
| 176 | 166 |
| 177 int AeroGlassNonClientView::NonClientHitTest(const gfx::Point& point) { | 167 int AeroGlassNonClientView::NonClientHitTest(const gfx::Point& point) { |
| 178 // If we don't have a tabstrip, we haven't customized the frame, so Windows | 168 // If we don't have a tabstrip, we haven't customized the frame, so Windows |
| 179 // can figure this out. If the point isn't within our bounds, then it's in | 169 // can figure this out. If the point isn't within our bounds, then it's in |
| 180 // the native portion of the frame, so again Windows can figure it out. | 170 // the native portion of the frame, so again Windows can figure it out. |
| 181 if (!browser_view_->IsTabStripVisible() || !bounds().Contains(point)) | 171 if (!browser_view_->IsTabStripVisible() || !bounds().Contains(point)) |
| 182 return HTNOWHERE; | 172 return HTNOWHERE; |
| 183 | 173 |
| 184 // See if the client view intersects the non-client area (e.g. blank areas | |
| 185 // of the TabStrip). | |
| 186 int frame_component = frame_->client_view()->NonClientHitTest(point); | 174 int frame_component = frame_->client_view()->NonClientHitTest(point); |
| 187 if (frame_component != HTNOWHERE) | 175 if (frame_component != HTNOWHERE) |
| 188 return frame_component; | 176 return frame_component; |
| 189 | 177 |
| 190 int border_thickness = GetSystemMetrics(SM_CXSIZEFRAME); | 178 int border_thickness = FrameBorderThickness(); |
| 191 int resize_width = kResizeEdgeWidth - border_thickness; | 179 int window_component = GetHTComponentForFrame(point, border_thickness, |
| 192 if (point.x() < kClientEdgeWidth) { | 180 NonClientBorderThickness(), border_thickness, |
| 193 if (point.y() < border_thickness) | 181 kResizeAreaCornerSize - border_thickness, |
| 194 return HTTOPLEFT; | 182 frame_->window_delegate()->CanResize()); |
| 195 if (point.y() >= (height() - kClientEdgeHeight)) | 183 // Fall back to the caption if no other component matches. |
| 196 return HTBOTTOMLEFT; | 184 return (window_component == HTNOWHERE) ? HTCAPTION : window_component; |
| 197 return HTLEFT; | |
| 198 } | |
| 199 if (point.x() >= (width() - kClientEdgeWidth)) { | |
| 200 if (point.y() < border_thickness) | |
| 201 return HTTOPRIGHT; | |
| 202 if (point.y() >= (height() - kClientEdgeHeight)) | |
| 203 return HTBOTTOMRIGHT; | |
| 204 return HTRIGHT; | |
| 205 } | |
| 206 if (point.y() < border_thickness) { | |
| 207 if (point.x() < resize_width) | |
| 208 return HTTOPLEFT; | |
| 209 if (point.x() >= (width() - resize_width)) | |
| 210 return HTTOPRIGHT; | |
| 211 return HTTOP; | |
| 212 } | |
| 213 if (point.y() >= (height() - kClientEdgeHeight)) { | |
| 214 if (point.x() < resize_width) | |
| 215 return HTBOTTOMLEFT; | |
| 216 if (point.x() >= (width() - resize_width)) | |
| 217 return HTBOTTOMRIGHT; | |
| 218 return HTBOTTOM; | |
| 219 } | |
| 220 return HTCAPTION; | |
| 221 } | |
| 222 | |
| 223 void AeroGlassNonClientView::GetWindowMask(const gfx::Size& size, | |
| 224 gfx::Path* window_mask) { | |
| 225 // We use the native window region. | |
| 226 } | |
| 227 | |
| 228 void AeroGlassNonClientView::EnableClose(bool enable) { | |
| 229 // This is handled exclusively by Window. | |
| 230 } | |
| 231 | |
| 232 void AeroGlassNonClientView::ResetWindowControls() { | |
| 233 // Our window controls are rendered by the system and do not require reset. | |
| 234 } | 185 } |
| 235 | 186 |
| 236 /////////////////////////////////////////////////////////////////////////////// | 187 /////////////////////////////////////////////////////////////////////////////// |
| 237 // AeroGlassNonClientView, views::View overrides: | 188 // AeroGlassNonClientView, views::View overrides: |
| 238 | 189 |
| 239 void AeroGlassNonClientView::Paint(ChromeCanvas* canvas) { | 190 void AeroGlassNonClientView::Paint(ChromeCanvas* canvas) { |
| 240 PaintDistributorLogo(canvas); | 191 PaintDistributorLogo(canvas); |
| 241 if (browser_view_->IsTabStripVisible()) | 192 if (browser_view_->IsTabStripVisible()) |
| 242 PaintToolbarBackground(canvas); | 193 PaintToolbarBackground(canvas); |
| 243 PaintOTRAvatar(canvas); | 194 PaintOTRAvatar(canvas); |
| 244 if (browser_view_->IsTabStripVisible()) | 195 if (browser_view_->IsTabStripVisible()) |
| 245 PaintClientEdge(canvas); | 196 PaintClientEdge(canvas); |
| 246 } | 197 } |
| 247 | 198 |
| 248 void AeroGlassNonClientView::Layout() { | 199 void AeroGlassNonClientView::Layout() { |
| 200 LayoutDistributorLogo(); |
| 249 LayoutOTRAvatar(); | 201 LayoutOTRAvatar(); |
| 250 LayoutDistributorLogo(); | |
| 251 LayoutClientView(); | 202 LayoutClientView(); |
| 252 } | 203 } |
| 253 | 204 |
| 254 gfx::Size AeroGlassNonClientView::GetPreferredSize() { | |
| 255 gfx::Size prefsize = frame_->client_view()->GetPreferredSize(); | |
| 256 prefsize.Enlarge(2 * kClientEdgeWidth, | |
| 257 CalculateNonClientTopHeight() + kClientEdgeHeight); | |
| 258 return prefsize; | |
| 259 } | |
| 260 | |
| 261 void AeroGlassNonClientView::ViewHierarchyChanged(bool is_add, | 205 void AeroGlassNonClientView::ViewHierarchyChanged(bool is_add, |
| 262 views::View* parent, | 206 views::View* parent, |
| 263 views::View* child) { | 207 views::View* child) { |
| 264 if (is_add && child == this) { | 208 if (is_add && child == this) { |
| 265 DCHECK(GetWidget()); | 209 DCHECK(GetWidget()); |
| 266 DCHECK(frame_->client_view()->GetParent() != this); | 210 DCHECK(frame_->client_view()->GetParent() != this); |
| 267 AddChildView(frame_->client_view()); | 211 AddChildView(frame_->client_view()); |
| 268 } | 212 } |
| 269 } | 213 } |
| 270 | 214 |
| 271 /////////////////////////////////////////////////////////////////////////////// | 215 /////////////////////////////////////////////////////////////////////////////// |
| 272 // AeroGlassNonClientView, private: | 216 // AeroGlassNonClientView, private: |
| 273 | 217 |
| 274 int AeroGlassNonClientView::CalculateNonClientTopHeight() const { | 218 int AeroGlassNonClientView::FrameBorderThickness() const { |
| 275 return browser_view_->IsTabStripVisible() ? | 219 return GetSystemMetrics(SM_CXSIZEFRAME); |
| 276 GetSystemMetrics(SM_CYSIZEFRAME) : 0; | 220 } |
| 221 |
| 222 int AeroGlassNonClientView::NonClientBorderThickness() const { |
| 223 return kNonClientBorderThickness; |
| 224 } |
| 225 |
| 226 int AeroGlassNonClientView::NonClientTopBorderHeight() const { |
| 227 return FrameBorderThickness() + |
| 228 (frame_->IsMaximized() ? 0 : kNonClientRestoredExtraThickness); |
| 229 } |
| 230 |
| 231 void AeroGlassNonClientView::PaintDistributorLogo(ChromeCanvas* canvas) { |
| 232 // The distributor logo is only painted when the frame is not maximized and |
| 233 // when we actually have a logo. |
| 234 if (!frame_->IsMaximized() && !distributor_logo_.empty()) { |
| 235 // TODO: Do we need to mirror this? |
| 236 canvas->DrawBitmapInt(distributor_logo_, logo_bounds_.x(), |
| 237 logo_bounds_.y()); |
| 238 } |
| 239 } |
| 240 |
| 241 void AeroGlassNonClientView::PaintToolbarBackground(ChromeCanvas* canvas) { |
| 242 gfx::Rect toolbar_bounds(browser_view_->GetToolbarBounds()); |
| 243 gfx::Point toolbar_origin(toolbar_bounds.origin()); |
| 244 View::ConvertPointToView(frame_->client_view(), this, &toolbar_origin); |
| 245 toolbar_bounds.set_origin(toolbar_origin); |
| 246 |
| 247 SkBitmap* toolbar_left = |
| 248 resources_->GetPartBitmap(FRAME_CLIENT_EDGE_TOP_LEFT); |
| 249 canvas->DrawBitmapInt(*toolbar_left, |
| 250 toolbar_bounds.x() - toolbar_left->width(), |
| 251 toolbar_bounds.y()); |
| 252 |
| 253 SkBitmap* toolbar_center = |
| 254 resources_->GetPartBitmap(FRAME_CLIENT_EDGE_TOP); |
| 255 canvas->TileImageInt(*toolbar_center, toolbar_bounds.x(), toolbar_bounds.y(), |
| 256 toolbar_bounds.width(), toolbar_center->height()); |
| 257 |
| 258 canvas->DrawBitmapInt(*resources_->GetPartBitmap(FRAME_CLIENT_EDGE_TOP_RIGHT), |
| 259 toolbar_bounds.right(), toolbar_bounds.y()); |
| 277 } | 260 } |
| 278 | 261 |
| 279 void AeroGlassNonClientView::PaintOTRAvatar(ChromeCanvas* canvas) { | 262 void AeroGlassNonClientView::PaintOTRAvatar(ChromeCanvas* canvas) { |
| 280 if (!browser_view_->ShouldShowOffTheRecordAvatar()) | 263 if (!browser_view_->ShouldShowOffTheRecordAvatar()) |
| 281 return; | 264 return; |
| 282 | 265 |
| 283 SkBitmap otr_avatar_icon = browser_view_->GetOTRAvatarIcon(); | 266 SkBitmap otr_avatar_icon = browser_view_->GetOTRAvatarIcon(); |
| 284 canvas->DrawBitmapInt(otr_avatar_icon, 0, | 267 canvas->DrawBitmapInt(otr_avatar_icon, 0, |
| 285 (otr_avatar_icon.height() - otr_avatar_bounds_.height()) / 2, | 268 (otr_avatar_icon.height() - otr_avatar_bounds_.height()) / 2, |
| 286 otr_avatar_bounds_.width(), otr_avatar_bounds_.height(), | 269 otr_avatar_bounds_.width(), otr_avatar_bounds_.height(), |
| 287 MirroredLeftPointForRect(otr_avatar_bounds_), otr_avatar_bounds_.y(), | 270 MirroredLeftPointForRect(otr_avatar_bounds_), otr_avatar_bounds_.y(), |
| 288 otr_avatar_bounds_.width(), otr_avatar_bounds_.height(), false); | 271 otr_avatar_bounds_.width(), otr_avatar_bounds_.height(), false); |
| 289 } | 272 } |
| 290 | 273 |
| 291 void AeroGlassNonClientView::PaintDistributorLogo(ChromeCanvas* canvas) { | 274 void AeroGlassNonClientView::PaintClientEdge(ChromeCanvas* canvas) { |
| 292 // The distributor logo is only painted when the frame is not maximized and | 275 int client_area_top = |
| 293 // when we actually have a logo. | 276 frame_->client_view()->y() + browser_view_->GetToolbarBounds().bottom(); |
| 294 if (!frame_->IsMaximized() && !frame_->IsMinimized() && | 277 gfx::Rect client_area_bounds = CalculateClientAreaBounds(width(), height()); |
| 295 !distributor_logo_.empty()) { | 278 // The toolbar draws a client edge along its own bottom edge when it's visible |
| 296 canvas->DrawBitmapInt(distributor_logo_, logo_bounds_.x(), | 279 // and in normal mode. However, it only draws this for the width of the |
| 297 logo_bounds_.y()); | 280 // actual client area, leaving a gap at the left and right edges: |
| 298 } | 281 // |
| 282 // | Toolbar | <-- part of toolbar |
| 283 // ----- (toolbar client edge) ----- <-- gap |
| 284 // | Client area | <-- right client edge |
| 285 // |
| 286 // To address this, we extend the left and right client edges up to fill the |
| 287 // gap, by pretending the toolbar is shorter than it really is. |
| 288 client_area_top -= kClientEdgeThickness; |
| 289 |
| 290 int client_area_bottom = |
| 291 std::max(client_area_top, height() - NonClientBorderThickness()); |
| 292 int client_area_height = client_area_bottom - client_area_top; |
| 293 SkBitmap* right = resources_->GetPartBitmap(FRAME_CLIENT_EDGE_RIGHT); |
| 294 canvas->TileImageInt(*right, client_area_bounds.right(), client_area_top, |
| 295 right->width(), client_area_height); |
| 296 |
| 297 canvas->DrawBitmapInt( |
| 298 *resources_->GetPartBitmap(FRAME_CLIENT_EDGE_BOTTOM_RIGHT), |
| 299 client_area_bounds.right(), client_area_bottom); |
| 300 |
| 301 SkBitmap* bottom = resources_->GetPartBitmap(FRAME_CLIENT_EDGE_BOTTOM); |
| 302 canvas->TileImageInt(*bottom, client_area_bounds.x(), |
| 303 client_area_bottom, client_area_bounds.width(), |
| 304 bottom->height()); |
| 305 |
| 306 SkBitmap* bottom_left = |
| 307 resources_->GetPartBitmap(FRAME_CLIENT_EDGE_BOTTOM_LEFT); |
| 308 canvas->DrawBitmapInt(*bottom_left, |
| 309 client_area_bounds.x() - bottom_left->width(), client_area_bottom); |
| 310 |
| 311 SkBitmap* left = resources_->GetPartBitmap(FRAME_CLIENT_EDGE_LEFT); |
| 312 canvas->TileImageInt(*left, client_area_bounds.x() - left->width(), |
| 313 client_area_top, left->width(), client_area_height); |
| 299 } | 314 } |
| 300 | 315 |
| 301 void AeroGlassNonClientView::PaintToolbarBackground(ChromeCanvas* canvas) { | 316 void AeroGlassNonClientView::LayoutDistributorLogo() { |
| 302 SkBitmap* toolbar_left = | 317 int logo_x = frame_->GetMinimizeButtonOffset() - (distributor_logo_.empty() ? |
| 303 resources_->GetPartBitmap(FRAME_CLIENT_EDGE_TOP_LEFT); | 318 0 : (distributor_logo_.width() + kLogoCaptionSpacing)); |
| 304 SkBitmap* toolbar_center = | 319 logo_bounds_.SetRect(logo_x, kLogoTopSpacing, distributor_logo_.width(), |
| 305 resources_->GetPartBitmap(FRAME_CLIENT_EDGE_TOP); | 320 distributor_logo_.height()); |
| 306 SkBitmap* toolbar_right = | |
| 307 resources_->GetPartBitmap(FRAME_CLIENT_EDGE_TOP_RIGHT); | |
| 308 | |
| 309 gfx::Rect toolbar_bounds = browser_view_->GetToolbarBounds(); | |
| 310 gfx::Point topleft(toolbar_bounds.x(), toolbar_bounds.y()); | |
| 311 View::ConvertPointToView(frame_->client_view(), this, &topleft); | |
| 312 toolbar_bounds.set_x(topleft.x()); | |
| 313 toolbar_bounds.set_y(topleft.y()); | |
| 314 | |
| 315 // We use TileImageInt for the left and right caps to clip the rendering | |
| 316 // to the appropriate height of the toolbar. | |
| 317 canvas->TileImageInt(*toolbar_left, | |
| 318 toolbar_bounds.x() - toolbar_left->width(), | |
| 319 toolbar_bounds.y(), toolbar_left->width(), | |
| 320 toolbar_bounds.height()); | |
| 321 canvas->TileImageInt(*toolbar_center, | |
| 322 toolbar_bounds.x(), toolbar_bounds.y(), | |
| 323 toolbar_bounds.width(), toolbar_center->height()); | |
| 324 canvas->TileImageInt(*toolbar_right, toolbar_bounds.right(), | |
| 325 toolbar_bounds.y(), toolbar_right->width(), | |
| 326 toolbar_bounds.height()); | |
| 327 } | |
| 328 | |
| 329 void AeroGlassNonClientView::PaintClientEdge(ChromeCanvas* canvas) { | |
| 330 SkBitmap* right = resources_->GetPartBitmap(FRAME_CLIENT_EDGE_RIGHT); | |
| 331 SkBitmap* bottom_right = | |
| 332 resources_->GetPartBitmap(FRAME_CLIENT_EDGE_BOTTOM_RIGHT); | |
| 333 SkBitmap* bottom = resources_->GetPartBitmap(FRAME_CLIENT_EDGE_BOTTOM); | |
| 334 SkBitmap* bottom_left = | |
| 335 resources_->GetPartBitmap(FRAME_CLIENT_EDGE_BOTTOM_LEFT); | |
| 336 SkBitmap* left = resources_->GetPartBitmap(FRAME_CLIENT_EDGE_LEFT); | |
| 337 | |
| 338 // The toolbar renders its own client edge in PaintToolbarBackground, however | |
| 339 // there are other bands that need to have a client edge rendered along their | |
| 340 // sides, such as the Bookmark bar, infobars, etc. | |
| 341 gfx::Rect toolbar_bounds = browser_view_->GetToolbarBounds(); | |
| 342 gfx::Rect client_area_bounds = browser_view_->GetClientAreaBounds(); | |
| 343 // For some reason things don't line up quite right, so we add and subtract | |
| 344 // pixels here and there for aesthetic bliss. | |
| 345 // Enlarge the client area to include the toolbar, since the top edge of | |
| 346 // the client area is the toolbar background and the client edge renders | |
| 347 // the left and right sides of the toolbar background. | |
| 348 client_area_bounds.SetRect( | |
| 349 client_area_bounds.x(), | |
| 350 frame_->client_view()->y() + toolbar_bounds.bottom() - kPixel, | |
| 351 client_area_bounds.width(), | |
| 352 std::max(0, height() - frame_->client_view()->y() - | |
| 353 toolbar_bounds.bottom() + kPixel)); | |
| 354 | |
| 355 int fudge = frame_->window_delegate()->ShouldShowWindowTitle() ? kPixel : 0; | |
| 356 canvas->TileImageInt(*right, client_area_bounds.right(), | |
| 357 client_area_bounds.y() + fudge, right->width(), | |
| 358 client_area_bounds.height() - bottom_right->height() + | |
| 359 kPixel - fudge); | |
| 360 canvas->DrawBitmapInt(*bottom_right, client_area_bounds.right(), | |
| 361 client_area_bounds.bottom() - bottom_right->height() + | |
| 362 kPixel); | |
| 363 canvas->TileImageInt(*bottom, client_area_bounds.x(), | |
| 364 client_area_bounds.bottom() - bottom_right->height() + | |
| 365 kPixel, client_area_bounds.width(), | |
| 366 bottom_right->height()); | |
| 367 canvas->DrawBitmapInt(*bottom_left, | |
| 368 client_area_bounds.x() - bottom_left->width(), | |
| 369 client_area_bounds.bottom() - bottom_left->height() + | |
| 370 kPixel); | |
| 371 canvas->TileImageInt(*left, client_area_bounds.x() - left->width(), | |
| 372 client_area_bounds.y() + fudge, left->width(), | |
| 373 client_area_bounds.height() - bottom_left->height() + | |
| 374 kPixel - fudge); | |
| 375 } | 321 } |
| 376 | 322 |
| 377 void AeroGlassNonClientView::LayoutOTRAvatar() { | 323 void AeroGlassNonClientView::LayoutOTRAvatar() { |
| 378 SkBitmap otr_avatar_icon = browser_view_->GetOTRAvatarIcon(); | 324 SkBitmap otr_avatar_icon = browser_view_->GetOTRAvatarIcon(); |
| 379 int top_height = (frame_->IsMaximized() ? | 325 int top_height = NonClientTopBorderHeight(); |
| 380 (CalculateNonClientTopHeight() - 2) : kTabStripY); | |
| 381 int tabstrip_height = browser_view_->GetTabStripHeight() - kOTRBottomSpacing; | 326 int tabstrip_height = browser_view_->GetTabStripHeight() - kOTRBottomSpacing; |
| 382 int otr_height = frame_->IsMaximized() ? | 327 int otr_height = frame_->IsMaximized() ? |
| 383 (tabstrip_height - kOTRMaximizedTopSpacing) : | 328 (tabstrip_height - kOTRMaximizedTopSpacing) : |
| 384 otr_avatar_icon.height(); | 329 otr_avatar_icon.height(); |
| 385 otr_avatar_bounds_.SetRect(kClientEdgeWidth + kOTRSideSpacing, | 330 otr_avatar_bounds_.SetRect(NonClientBorderThickness() + kOTRSideSpacing, |
| 386 top_height + tabstrip_height - otr_height, otr_avatar_icon.width(), | 331 top_height + tabstrip_height - otr_height, |
| 387 otr_height); | 332 otr_avatar_icon.width(), otr_height); |
| 388 } | |
| 389 | |
| 390 void AeroGlassNonClientView::LayoutDistributorLogo() { | |
| 391 if (distributor_logo_.empty()) | |
| 392 return; | |
| 393 | |
| 394 int logo_w = distributor_logo_.width(); | |
| 395 int logo_h = distributor_logo_.height(); | |
| 396 | |
| 397 int w = width(); | |
| 398 int mbx = frame_->GetMinimizeButtonOffset(); | |
| 399 | |
| 400 logo_bounds_.SetRect( | |
| 401 width() - frame_->GetMinimizeButtonOffset() - logo_w, | |
| 402 kDistributorLogoVerticalOffset, logo_w, logo_h); | |
| 403 } | 333 } |
| 404 | 334 |
| 405 void AeroGlassNonClientView::LayoutClientView() { | 335 void AeroGlassNonClientView::LayoutClientView() { |
| 406 gfx::Rect client_bounds = CalculateClientAreaBounds(width(), height()); | 336 frame_->client_view()->SetBounds(CalculateClientAreaBounds(width(), |
| 407 frame_->client_view()->SetBounds(client_bounds); | 337 height())); |
| 408 } | 338 } |
| 409 | 339 |
| 410 // static | 340 // static |
| 411 void AeroGlassNonClientView::InitClass() { | 341 void AeroGlassNonClientView::InitClass() { |
| 412 static bool initialized = false; | 342 static bool initialized = false; |
| 413 if (!initialized) { | 343 if (!initialized) { |
| 414 resources_ = new AeroGlassWindowResources; | 344 resources_ = new AeroGlassWindowResources; |
| 345 |
| 415 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); | 346 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); |
| 416 #if defined(GOOGLE_CHROME_BUILD) | 347 #if defined(GOOGLE_CHROME_BUILD) |
| 417 distributor_logo_ = *rb.GetBitmapNamed(IDR_DISTRIBUTOR_LOGO); | 348 distributor_logo_ = *rb.GetBitmapNamed(IDR_DISTRIBUTOR_LOGO); |
| 418 #endif | 349 #endif |
| 419 | 350 |
| 420 initialized = true; | 351 initialized = true; |
| 421 } | 352 } |
| 422 } | 353 } |
| 423 | 354 |
| OLD | NEW |