| 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/glass_browser_frame_view.h" | 5 #include "chrome/browser/ui/views/frame/glass_browser_frame_view.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/strings/utf_string_conversions.h" | 9 #include "base/strings/utf_string_conversions.h" |
| 10 #include "base/win/windows_version.h" | 10 #include "base/win/windows_version.h" |
| (...skipping 24 matching lines...) Expand all Loading... |
| 35 #include "ui/views/controls/label.h" | 35 #include "ui/views/controls/label.h" |
| 36 #include "ui/views/layout/layout_constants.h" | 36 #include "ui/views/layout/layout_constants.h" |
| 37 #include "ui/views/resources/grit/views_resources.h" | 37 #include "ui/views/resources/grit/views_resources.h" |
| 38 #include "ui/views/win/hwnd_util.h" | 38 #include "ui/views/win/hwnd_util.h" |
| 39 #include "ui/views/window/client_view.h" | 39 #include "ui/views/window/client_view.h" |
| 40 | 40 |
| 41 HICON GlassBrowserFrameView::throbber_icons_[ | 41 HICON GlassBrowserFrameView::throbber_icons_[ |
| 42 GlassBrowserFrameView::kThrobberIconCount]; | 42 GlassBrowserFrameView::kThrobberIconCount]; |
| 43 | 43 |
| 44 namespace { | 44 namespace { |
| 45 // Size of client edge drawn inside the outer frame borders. | 45 // Thickness of the border in the client area that separates it from the |
| 46 const int kNonClientBorderThicknessPreWin10 = 3; | 46 // non-client area. Includes but is distinct from kClientEdgeThickness, which is |
| 47 const int kNonClientBorderThicknessWin10 = 1; | 47 // the thickness of the border between the web content and our frame border. |
| 48 const int kClientBorderThicknessPreWin10 = 3; |
| 49 const int kClientBorderThicknessWin10 = 1; |
| 48 // Besides the frame border, there's empty space atop the window in restored | 50 // Besides the frame border, there's empty space atop the window in restored |
| 49 // mode, to use to drag the window around. | 51 // mode, to use to drag the window around. |
| 50 const int kNonClientRestoredExtraThickness = 11; | 52 const int kNonClientRestoredExtraThickness = 11; |
| 51 // In the window corners, the resize areas don't actually expand bigger, but the | 53 // At the window corners the resize area is not actually bigger, but the 16 |
| 52 // 16 px at the end of the top and bottom edges triggers diagonal resizing. | 54 // pixels at the end of the top and bottom edges trigger diagonal resizing. |
| 53 const int kResizeCornerWidth = 16; | 55 const int kResizeCornerWidth = 16; |
| 54 // How far the new avatar button is from the left of the minimize button. | 56 // How far the profile switcher button is from the left of the minimize button. |
| 55 const int kNewAvatarButtonOffset = 5; | 57 const int kProfileSwitcherButtonOffset = 5; |
| 56 // The content edge images have a shadow built into them. | 58 // The content edge images have a shadow built into them. |
| 57 const int kContentEdgeShadowThickness = 2; | 59 const int kContentEdgeShadowThickness = 2; |
| 58 // In restored mode, the New Tab button isn't at the same height as the caption | 60 // In restored mode, the New Tab button isn't at the same height as the caption |
| 59 // buttons, but the space will look cluttered if it actually slides under them, | 61 // buttons, but the space will look cluttered if it actually slides under them, |
| 60 // so we stop it when the gap between the two is down to 5 px. | 62 // so we stop it when the gap between the two is down to 5 px. |
| 61 const int kNewTabCaptionRestoredSpacing = 5; | 63 const int kNewTabCaptionRestoredSpacing = 5; |
| 62 // In maximized mode, where the New Tab button and the caption buttons are at | 64 // In maximized mode, where the New Tab button and the caption buttons are at |
| 63 // similar vertical coordinates, we need to reserve a larger, 16 px gap to avoid | 65 // similar vertical coordinates, we need to reserve a larger, 16 px gap to avoid |
| 64 // looking too cluttered. | 66 // looking too cluttered. |
| 65 const int kNewTabCaptionMaximizedSpacing = 16; | 67 const int kNewTabCaptionMaximizedSpacing = 16; |
| 68 // Height of the profile switcher button. Same as the height of the Windows 7/8 |
| 69 // caption buttons. |
| 70 // TODO(bsep): Windows 10 caption buttons look very different and we would like |
| 71 // the profile switcher button to match on that platform. |
| 72 const int kProfileSwitcherButtonHeight = 20; |
| 66 | 73 |
| 67 // Converts the |image| to a Windows icon and returns the corresponding HICON | 74 // Converts the |image| to a Windows icon and returns the corresponding HICON |
| 68 // handle. |image| is resized to desired |width| and |height| if needed. | 75 // handle. |image| is resized to desired |width| and |height| if needed. |
| 69 base::win::ScopedHICON CreateHICONFromSkBitmapSizedTo( | 76 base::win::ScopedHICON CreateHICONFromSkBitmapSizedTo( |
| 70 const gfx::ImageSkia& image, | 77 const gfx::ImageSkia& image, |
| 71 int width, | 78 int width, |
| 72 int height) { | 79 int height) { |
| 73 return IconUtil::CreateHICONFromSkBitmap( | 80 return IconUtil::CreateHICONFromSkBitmap( |
| 74 width == image.width() && height == image.height() | 81 width == image.width() && height == image.height() |
| 75 ? *image.bitmap() | 82 ? *image.bitmap() |
| (...skipping 19 matching lines...) Expand all Loading... |
| 95 | 102 |
| 96 GlassBrowserFrameView::~GlassBrowserFrameView() { | 103 GlassBrowserFrameView::~GlassBrowserFrameView() { |
| 97 } | 104 } |
| 98 | 105 |
| 99 /////////////////////////////////////////////////////////////////////////////// | 106 /////////////////////////////////////////////////////////////////////////////// |
| 100 // GlassBrowserFrameView, BrowserNonClientFrameView implementation: | 107 // GlassBrowserFrameView, BrowserNonClientFrameView implementation: |
| 101 | 108 |
| 102 gfx::Rect GlassBrowserFrameView::GetBoundsForTabStrip( | 109 gfx::Rect GlassBrowserFrameView::GetBoundsForTabStrip( |
| 103 views::View* tabstrip) const { | 110 views::View* tabstrip) const { |
| 104 // In maximized RTL windows, don't let the tabstrip overlap the caption area, | 111 // In maximized RTL windows, don't let the tabstrip overlap the caption area, |
| 105 // or the alpha-blending it does will make things like the new avatar button | 112 // or the alpha-blending it does will make things like the profile switcher |
| 106 // look glitchy. | 113 // button look glitchy. |
| 107 const int offset = | 114 const int offset = (ui::MaterialDesignController::IsModeMaterial() || |
| 108 (ui::MaterialDesignController::IsModeMaterial() || !base::i18n::IsRTL() || | 115 !CaptionButtonsOnLeadingEdge() || !frame()->IsMaximized()) |
| 109 !frame()->IsMaximized()) ? | 116 ? GetLayoutInsets(AVATAR_ICON).right() |
| 110 GetLayoutInsets(AVATAR_ICON).right() : 0; | 117 : 0; |
| 111 const int x = incognito_bounds_.right() + offset; | 118 const int x = incognito_bounds_.right() + offset; |
| 112 int end_x = width() - NonClientBorderThickness(false); | 119 int end_x = width() - ClientBorderThickness(false); |
| 113 if (!base::i18n::IsRTL()) { | 120 if (!CaptionButtonsOnLeadingEdge()) { |
| 114 end_x = std::min(frame()->GetMinimizeButtonOffset(), end_x) - | 121 end_x = std::min(frame()->GetMinimizeButtonOffset(), end_x) - |
| 115 (frame()->IsMaximized() ? | 122 (frame()->IsMaximized() ? |
| 116 kNewTabCaptionMaximizedSpacing : kNewTabCaptionRestoredSpacing); | 123 kNewTabCaptionMaximizedSpacing : kNewTabCaptionRestoredSpacing); |
| 117 | 124 |
| 118 // The new avatar button is optionally displayed to the left of the | 125 // The profile switcher button is optionally displayed to the left of the |
| 119 // minimize button. | 126 // minimize button. |
| 120 if (profile_switcher_.view()) { | 127 if (profile_switcher_.view()) { |
| 121 const int old_end_x = end_x; | 128 const int old_end_x = end_x; |
| 122 end_x -= profile_switcher_.view()->width() + kNewAvatarButtonOffset; | 129 end_x -= profile_switcher_.view()->width() + kProfileSwitcherButtonOffset; |
| 123 | 130 |
| 124 // In non-maximized mode, allow the new tab button to slide completely | 131 // In non-maximized mode, allow the new tab button to slide completely |
| 125 // under the avatar button. | 132 // under the profile switcher button. |
| 126 if (!frame()->IsMaximized()) { | 133 if (!frame()->IsMaximized()) { |
| 127 end_x = std::min(end_x + GetLayoutSize(NEW_TAB_BUTTON).width() + | 134 end_x = std::min(end_x + GetLayoutSize(NEW_TAB_BUTTON).width() + |
| 128 kNewTabCaptionRestoredSpacing, | 135 kNewTabCaptionRestoredSpacing, |
| 129 old_end_x); | 136 old_end_x); |
| 130 } | 137 } |
| 131 } | 138 } |
| 132 } | 139 } |
| 133 return gfx::Rect(x, NonClientTopBorderHeight(false), std::max(0, end_x - x), | 140 return gfx::Rect(x, TopAreaHeight(false), std::max(0, end_x - x), |
| 134 tabstrip->GetPreferredSize().height()); | 141 tabstrip->GetPreferredSize().height()); |
| 135 } | 142 } |
| 136 | 143 |
| 137 int GlassBrowserFrameView::GetTopInset(bool restored) const { | 144 int GlassBrowserFrameView::GetTopInset(bool restored) const { |
| 138 return GetClientAreaInsets(restored).top(); | 145 return GetClientAreaInsets(restored).top(); |
| 139 } | 146 } |
| 140 | 147 |
| 141 int GlassBrowserFrameView::GetThemeBackgroundXInset() const { | 148 int GlassBrowserFrameView::GetThemeBackgroundXInset() const { |
| 142 return 0; | 149 return 0; |
| 143 } | 150 } |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 209 } | 216 } |
| 210 | 217 |
| 211 int GlassBrowserFrameView::NonClientHitTest(const gfx::Point& point) { | 218 int GlassBrowserFrameView::NonClientHitTest(const gfx::Point& point) { |
| 212 // If the browser isn't in normal mode, we haven't customized the frame, so | 219 // If the browser isn't in normal mode, we haven't customized the frame, so |
| 213 // Windows can figure this out. If the point isn't within our bounds, then | 220 // Windows can figure this out. If the point isn't within our bounds, then |
| 214 // it's in the native portion of the frame, so again Windows can figure it | 221 // it's in the native portion of the frame, so again Windows can figure it |
| 215 // out. | 222 // out. |
| 216 if (!browser_view()->IsBrowserTypeNormal() || !bounds().Contains(point)) | 223 if (!browser_view()->IsBrowserTypeNormal() || !bounds().Contains(point)) |
| 217 return HTNOWHERE; | 224 return HTNOWHERE; |
| 218 | 225 |
| 219 // See if the point is within the incognito icon or the new avatar menu. | 226 // See if the point is within the incognito icon or the profile switcher menu. |
| 220 if ((avatar_button() && | 227 if ((avatar_button() && |
| 221 avatar_button()->GetMirroredBounds().Contains(point)) || | 228 avatar_button()->GetMirroredBounds().Contains(point)) || |
| 222 (profile_switcher_.view() && | 229 (profile_switcher_.view() && |
| 223 profile_switcher_.view()->GetMirroredBounds().Contains(point))) | 230 profile_switcher_.view()->GetMirroredBounds().Contains(point))) |
| 224 return HTCLIENT; | 231 return HTCLIENT; |
| 225 | 232 |
| 226 int frame_component = frame()->client_view()->NonClientHitTest(point); | 233 int frame_component = frame()->client_view()->NonClientHitTest(point); |
| 227 | 234 |
| 228 // See if we're in the sysmenu region. We still have to check the tabstrip | 235 // See if we're in the sysmenu region. We still have to check the tabstrip |
| 229 // first so that clicks in a tab don't get treated as sysmenu clicks. | 236 // first so that clicks in a tab don't get treated as sysmenu clicks. |
| 230 int nonclient_border_thickness = NonClientBorderThickness(false); | 237 int client_border_thickness = ClientBorderThickness(false); |
| 231 gfx::Rect sys_menu_region(nonclient_border_thickness, | 238 gfx::Rect sys_menu_region(client_border_thickness, |
| 232 display::win::GetSystemMetricsInDIP(SM_CYSIZEFRAME), | 239 display::win::GetSystemMetricsInDIP(SM_CYSIZEFRAME), |
| 233 display::win::GetSystemMetricsInDIP(SM_CXSMICON), | 240 display::win::GetSystemMetricsInDIP(SM_CXSMICON), |
| 234 display::win::GetSystemMetricsInDIP(SM_CYSMICON)); | 241 display::win::GetSystemMetricsInDIP(SM_CYSMICON)); |
| 235 if (sys_menu_region.Contains(point)) | 242 if (sys_menu_region.Contains(point)) |
| 236 return (frame_component == HTCLIENT) ? HTCLIENT : HTSYSMENU; | 243 return (frame_component == HTCLIENT) ? HTCLIENT : HTSYSMENU; |
| 237 | 244 |
| 238 if (frame_component != HTNOWHERE) | 245 if (frame_component != HTNOWHERE) |
| 239 return frame_component; | 246 return frame_component; |
| 240 | 247 |
| 241 int frame_top_border_height = FrameTopBorderHeight(false); | 248 int top_border_thickness = FrameTopBorderThickness(false); |
| 242 // We want the resize corner behavior to apply to the kResizeCornerWidth | 249 // We want the resize corner behavior to apply to the kResizeCornerWidth |
| 243 // pixels at each end of the top and bottom edges. Because |point|'s x | 250 // pixels at each end of the top and bottom edges. Because |point|'s x |
| 244 // coordinate is based on the DWM-inset portion of the window (so, it's 0 at | 251 // coordinate is based on the DWM-inset portion of the window (so, it's 0 at |
| 245 // the first pixel inside the left DWM margin), we need to subtract the DWM | 252 // the first pixel inside the left DWM margin), we need to subtract the DWM |
| 246 // margin thickness, which we calculate as the total frame border thickness | 253 // margin thickness, which we calculate as the total frame border thickness |
| 247 // minus the nonclient border thickness. | 254 // minus the nonclient border thickness. |
| 248 const int dwm_margin = FrameBorderThickness() - nonclient_border_thickness; | 255 const int dwm_margin = FrameBorderThickness() - client_border_thickness; |
| 249 int window_component = GetHTComponentForFrame(point, frame_top_border_height, | 256 int window_component = GetHTComponentForFrame( |
| 250 nonclient_border_thickness, frame_top_border_height, | 257 point, top_border_thickness, client_border_thickness, |
| 251 kResizeCornerWidth - dwm_margin, frame()->widget_delegate()->CanResize()); | 258 top_border_thickness, kResizeCornerWidth - dwm_margin, |
| 259 frame()->widget_delegate()->CanResize()); |
| 252 // Fall back to the caption if no other component matches. | 260 // Fall back to the caption if no other component matches. |
| 253 return (window_component == HTNOWHERE) ? HTCAPTION : window_component; | 261 return (window_component == HTNOWHERE) ? HTCAPTION : window_component; |
| 254 } | 262 } |
| 255 | 263 |
| 256 /////////////////////////////////////////////////////////////////////////////// | 264 /////////////////////////////////////////////////////////////////////////////// |
| 257 // GlassBrowserFrameView, views::View overrides: | 265 // GlassBrowserFrameView, views::View overrides: |
| 258 | 266 |
| 259 void GlassBrowserFrameView::OnPaint(gfx::Canvas* canvas) { | 267 void GlassBrowserFrameView::OnPaint(gfx::Canvas* canvas) { |
| 260 if (!browser_view()->IsTabStripVisible()) | 268 if (!browser_view()->IsTabStripVisible()) |
| 261 return; | 269 return; |
| 262 if (IsToolbarVisible()) | 270 if (IsToolbarVisible()) |
| 263 PaintToolbarBackground(canvas); | 271 PaintToolbarBackground(canvas); |
| 264 if (!frame()->IsMaximized()) | 272 if (!frame()->IsMaximized()) |
| 265 PaintClientEdge(canvas); | 273 PaintClientEdge(canvas); |
| 266 } | 274 } |
| 267 | 275 |
| 268 void GlassBrowserFrameView::Layout() { | 276 void GlassBrowserFrameView::Layout() { |
| 269 if (browser_view()->IsRegularOrGuestSession()) | 277 if (browser_view()->IsRegularOrGuestSession()) |
| 270 LayoutNewStyleAvatar(); | 278 LayoutProfileSwitcher(); |
| 271 LayoutIncognitoIcon(); | 279 LayoutIncognitoIcon(); |
| 272 LayoutClientView(); | 280 LayoutClientView(); |
| 273 } | 281 } |
| 274 | 282 |
| 275 /////////////////////////////////////////////////////////////////////////////// | 283 /////////////////////////////////////////////////////////////////////////////// |
| 276 // GlassBrowserFrameView, protected: | 284 // GlassBrowserFrameView, protected: |
| 277 | 285 |
| 278 // BrowserNonClientFrameView: | 286 // BrowserNonClientFrameView: |
| 279 void GlassBrowserFrameView::UpdateAvatar() { | 287 void GlassBrowserFrameView::UpdateAvatar() { |
| 280 if (browser_view()->IsRegularOrGuestSession()) | 288 if (browser_view()->IsRegularOrGuestSession()) |
| 281 profile_switcher_.Update(AvatarButtonStyle::NATIVE); | 289 profile_switcher_.Update(AvatarButtonStyle::NATIVE); |
| 282 else | 290 else |
| 283 UpdateOldAvatarButton(); | 291 UpdateOldAvatarButton(); |
| 284 } | 292 } |
| 285 | 293 |
| 286 /////////////////////////////////////////////////////////////////////////////// | 294 /////////////////////////////////////////////////////////////////////////////// |
| 287 // GlassBrowserFrameView, private: | 295 // GlassBrowserFrameView, private: |
| 288 | 296 |
| 289 // views::NonClientFrameView: | 297 // views::NonClientFrameView: |
| 290 bool GlassBrowserFrameView::DoesIntersectRect(const views::View* target, | 298 bool GlassBrowserFrameView::DoesIntersectRect(const views::View* target, |
| 291 const gfx::Rect& rect) const { | 299 const gfx::Rect& rect) const { |
| 292 CHECK_EQ(target, this); | 300 CHECK_EQ(target, this); |
| 293 bool hit_incognito_icon = avatar_button() && | 301 bool hit_incognito_icon = avatar_button() && |
| 294 avatar_button()->GetMirroredBounds().Intersects(rect); | 302 avatar_button()->GetMirroredBounds().Intersects(rect); |
| 295 bool hit_new_avatar_button = | 303 bool hit_profile_switcher_button = |
| 296 profile_switcher_.view() && | 304 profile_switcher_.view() && |
| 297 profile_switcher_.view()->GetMirroredBounds().Intersects(rect); | 305 profile_switcher_.view()->GetMirroredBounds().Intersects(rect); |
| 298 return hit_incognito_icon || hit_new_avatar_button || | 306 return hit_incognito_icon || hit_profile_switcher_button || |
| 299 !frame()->client_view()->bounds().Intersects(rect); | 307 !frame()->client_view()->bounds().Intersects(rect); |
| 300 } | 308 } |
| 301 | 309 |
| 310 int GlassBrowserFrameView::ClientBorderThickness(bool restored) const { |
| 311 if ((frame()->IsMaximized() || frame()->IsFullscreen()) && !restored) |
| 312 return 0; |
| 313 |
| 314 return (base::win::GetVersion() < base::win::VERSION_WIN10) |
| 315 ? kClientBorderThicknessPreWin10 |
| 316 : kClientBorderThicknessWin10; |
| 317 } |
| 318 |
| 302 int GlassBrowserFrameView::FrameBorderThickness() const { | 319 int GlassBrowserFrameView::FrameBorderThickness() const { |
| 303 return (frame()->IsMaximized() || frame()->IsFullscreen()) ? | 320 return (frame()->IsMaximized() || frame()->IsFullscreen()) ? |
| 304 0 : display::win::GetSystemMetricsInDIP(SM_CXSIZEFRAME); | 321 0 : display::win::GetSystemMetricsInDIP(SM_CXSIZEFRAME); |
| 305 } | 322 } |
| 306 | 323 |
| 307 int GlassBrowserFrameView::FrameTopBorderHeight(bool restored) const { | 324 int GlassBrowserFrameView::FrameTopBorderThickness(bool restored) const { |
| 308 // We'd like to use FrameBorderThickness() here, but the maximized Aero glass | 325 // Distinct from FrameBorderThickness() because Windows gives maximized |
| 309 // frame has a 0 frame border around most edges and a CYSIZEFRAME-thick border | 326 // windows an offscreen CYSIZEFRAME-thick region around the edges. The |
| 310 // at the top (see AeroGlassFrame::OnGetMinMaxInfo()). | 327 // left/right/bottom edges don't worry about this because we cancel them out |
| 328 // in BrowserDesktopWindowTreeHostWin::GetClientAreaInsets() so the offscreen |
| 329 // area is non-client as far as Windows is concerned. However because we want |
| 330 // to push away the top part of the glass's gradient in Win7 we set the top |
| 331 // client inset to 0. Thus we must compensate here to avoid having UI elements |
| 332 // drift off the top of the screen. |
| 311 return (frame()->IsFullscreen() && !restored) ? | 333 return (frame()->IsFullscreen() && !restored) ? |
| 312 0 : display::win::GetSystemMetricsInDIP(SM_CYSIZEFRAME); | 334 0 : display::win::GetSystemMetricsInDIP(SM_CYSIZEFRAME); |
| 313 } | 335 } |
| 314 | 336 |
| 315 int GlassBrowserFrameView::NonClientBorderThickness(bool restored) const { | 337 int GlassBrowserFrameView::TopAreaHeight(bool restored) const { |
| 316 if ((frame()->IsMaximized() || frame()->IsFullscreen()) && !restored) | |
| 317 return 0; | |
| 318 | |
| 319 return (base::win::GetVersion() < base::win::VERSION_WIN10) | |
| 320 ? kNonClientBorderThicknessPreWin10 | |
| 321 : kNonClientBorderThicknessWin10; | |
| 322 } | |
| 323 | |
| 324 int GlassBrowserFrameView::NonClientTopBorderHeight(bool restored) const { | |
| 325 if (frame()->IsFullscreen() && !restored) | 338 if (frame()->IsFullscreen() && !restored) |
| 326 return 0; | 339 return 0; |
| 327 | 340 |
| 328 const int top = FrameTopBorderHeight(restored); | 341 const int top = FrameTopBorderThickness(restored); |
| 329 // The tab top inset is equal to the height of any shadow region above the | 342 // The tab top inset is equal to the height of any shadow region above the |
| 330 // tabs, plus a 1 px top stroke. In maximized mode, we want to push the | 343 // tabs, plus a 1 px top stroke. In maximized mode, we want to push the |
| 331 // shadow region off the top of the screen but leave the top stroke. | 344 // shadow region off the top of the screen but leave the top stroke. |
| 332 // Annoyingly, the pre-MD layout uses different heights for the hit-test | 345 // Annoyingly, the pre-MD layout uses different heights for the hit-test |
| 333 // exclusion region (which we want here, since we're trying to size the border | 346 // exclusion region (which we want here, since we're trying to size the border |
| 334 // so that the region above the tab's hit-test zone matches) versus the shadow | 347 // so that the region above the tab's hit-test zone matches) versus the shadow |
| 335 // thickness. | 348 // thickness. |
| 336 const int exclusion = GetLayoutConstant(TAB_TOP_EXCLUSION_HEIGHT); | 349 const int exclusion = GetLayoutConstant(TAB_TOP_EXCLUSION_HEIGHT); |
| 337 return (frame()->IsMaximized() && !restored) ? | 350 return (frame()->IsMaximized() && !restored) ? |
| 338 (top - GetLayoutInsets(TAB).top() + 1) : | 351 (top - GetLayoutInsets(TAB).top() + 1) : |
| 339 (top + kNonClientRestoredExtraThickness - exclusion); | 352 (top + kNonClientRestoredExtraThickness - exclusion); |
| 340 } | 353 } |
| 341 | 354 |
| 355 int GlassBrowserFrameView::WindowTopY() const { |
| 356 return frame()->IsMaximized() ? FrameTopBorderThickness(false) : 1; |
| 357 } |
| 358 |
| 342 bool GlassBrowserFrameView::IsToolbarVisible() const { | 359 bool GlassBrowserFrameView::IsToolbarVisible() const { |
| 343 return browser_view()->IsToolbarVisible() && | 360 return browser_view()->IsToolbarVisible() && |
| 344 !browser_view()->toolbar()->GetPreferredSize().IsEmpty(); | 361 !browser_view()->toolbar()->GetPreferredSize().IsEmpty(); |
| 345 } | 362 } |
| 346 | 363 |
| 364 bool GlassBrowserFrameView::CaptionButtonsOnLeadingEdge() const { |
| 365 // Because we don't set WS_EX_LAYOUTRTL (which would conflict with Chrome's |
| 366 // own RTL layout logic), Windows always draws the caption buttons on the |
| 367 // right, even when we want to be RTL. See crbug.com/560619. |
| 368 return base::i18n::IsRTL(); |
| 369 } |
| 370 |
| 347 void GlassBrowserFrameView::PaintToolbarBackground(gfx::Canvas* canvas) const { | 371 void GlassBrowserFrameView::PaintToolbarBackground(gfx::Canvas* canvas) const { |
| 348 gfx::Rect toolbar_bounds(browser_view()->GetToolbarBounds()); | 372 gfx::Rect toolbar_bounds(browser_view()->GetToolbarBounds()); |
| 349 if (toolbar_bounds.IsEmpty()) | 373 if (toolbar_bounds.IsEmpty()) |
| 350 return; | 374 return; |
| 351 gfx::Point toolbar_origin(toolbar_bounds.origin()); | 375 gfx::Point toolbar_origin(toolbar_bounds.origin()); |
| 352 ConvertPointToTarget(browser_view(), this, &toolbar_origin); | 376 ConvertPointToTarget(browser_view(), this, &toolbar_origin); |
| 353 toolbar_bounds.set_origin(toolbar_origin); | 377 toolbar_bounds.set_origin(toolbar_origin); |
| 354 | 378 |
| 355 const ui::ThemeProvider* tp = GetThemeProvider(); | 379 const ui::ThemeProvider* tp = GetThemeProvider(); |
| 356 const gfx::ImageSkia* const bg = tp->GetImageSkiaNamed(IDR_THEME_TOOLBAR); | 380 const gfx::ImageSkia* const bg = tp->GetImageSkiaNamed(IDR_THEME_TOOLBAR); |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 443 // Pre-Material Design, the client edge images start below the toolbar. In MD | 467 // Pre-Material Design, the client edge images start below the toolbar. In MD |
| 444 // the client edge images start at the top of the toolbar. | 468 // the client edge images start at the top of the toolbar. |
| 445 gfx::Rect client_bounds = CalculateClientAreaBounds(); | 469 gfx::Rect client_bounds = CalculateClientAreaBounds(); |
| 446 const int x = client_bounds.x(); | 470 const int x = client_bounds.x(); |
| 447 const bool md = ui::MaterialDesignController::IsModeMaterial(); | 471 const bool md = ui::MaterialDesignController::IsModeMaterial(); |
| 448 const gfx::Rect toolbar_bounds(browser_view()->GetToolbarBounds()); | 472 const gfx::Rect toolbar_bounds(browser_view()->GetToolbarBounds()); |
| 449 const int y = | 473 const int y = |
| 450 client_bounds.y() + (md ? toolbar_bounds.y() : toolbar_bounds.bottom()); | 474 client_bounds.y() + (md ? toolbar_bounds.y() : toolbar_bounds.bottom()); |
| 451 const int w = client_bounds.width(); | 475 const int w = client_bounds.width(); |
| 452 const int right = client_bounds.right(); | 476 const int right = client_bounds.right(); |
| 453 const int bottom = std::max(y, height() - NonClientBorderThickness(false)); | 477 const int bottom = std::max(y, height() - ClientBorderThickness(false)); |
| 454 const int height = bottom - y; | 478 const int height = bottom - y; |
| 455 | 479 |
| 456 // Draw the client edge images. For non-MD, we fill the toolbar color | 480 // Draw the client edge images. For non-MD, we fill the toolbar color |
| 457 // underneath these images so they will lighten/darken it appropriately to | 481 // underneath these images so they will lighten/darken it appropriately to |
| 458 // create a "3D shaded" effect. For MD, where we want a flatter appearance, | 482 // create a "3D shaded" effect. For MD, where we want a flatter appearance, |
| 459 // we do the filling afterwards so the user sees the unmodified toolbar color. | 483 // we do the filling afterwards so the user sees the unmodified toolbar color. |
| 460 const ui::ThemeProvider* tp = GetThemeProvider(); | 484 const ui::ThemeProvider* tp = GetThemeProvider(); |
| 461 const SkColor toolbar_color = tp->GetColor(ThemeProperties::COLOR_TOOLBAR); | 485 const SkColor toolbar_color = tp->GetColor(ThemeProperties::COLOR_TOOLBAR); |
| 462 if (!md) | 486 if (!md) |
| 463 FillClientEdgeRects(x, y, right, bottom, toolbar_color, canvas); | 487 FillClientEdgeRects(x, y, right, bottom, toolbar_color, canvas); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 486 gfx::Canvas* canvas) const { | 510 gfx::Canvas* canvas) const { |
| 487 gfx::Rect side(x - kClientEdgeThickness, y, kClientEdgeThickness, | 511 gfx::Rect side(x - kClientEdgeThickness, y, kClientEdgeThickness, |
| 488 bottom + kClientEdgeThickness - y); | 512 bottom + kClientEdgeThickness - y); |
| 489 canvas->FillRect(side, color); | 513 canvas->FillRect(side, color); |
| 490 canvas->FillRect(gfx::Rect(x, bottom, right - x, kClientEdgeThickness), | 514 canvas->FillRect(gfx::Rect(x, bottom, right - x, kClientEdgeThickness), |
| 491 color); | 515 color); |
| 492 side.set_x(right); | 516 side.set_x(right); |
| 493 canvas->FillRect(side, color); | 517 canvas->FillRect(side, color); |
| 494 } | 518 } |
| 495 | 519 |
| 496 void GlassBrowserFrameView::LayoutNewStyleAvatar() { | 520 void GlassBrowserFrameView::LayoutProfileSwitcher() { |
| 497 DCHECK(browser_view()->IsRegularOrGuestSession()); | 521 DCHECK(browser_view()->IsRegularOrGuestSession()); |
| 498 if (!profile_switcher_.view()) | 522 if (!profile_switcher_.view()) |
| 499 return; | 523 return; |
| 500 | 524 |
| 501 gfx::Size label_size = profile_switcher_.view()->GetPreferredSize(); | 525 gfx::Size label_size = profile_switcher_.view()->GetPreferredSize(); |
| 502 | 526 |
| 503 int button_x = frame()->GetMinimizeButtonOffset() - | 527 int button_x = frame()->GetMinimizeButtonOffset() - |
| 504 kNewAvatarButtonOffset - label_size.width(); | 528 kProfileSwitcherButtonOffset - label_size.width(); |
| 505 if (base::i18n::IsRTL()) | 529 if (CaptionButtonsOnLeadingEdge()) |
| 506 button_x = width() - frame()->GetMinimizeButtonOffset() + | 530 button_x = width() - frame()->GetMinimizeButtonOffset() + |
| 507 kNewAvatarButtonOffset; | 531 kProfileSwitcherButtonOffset; |
| 508 | 532 |
| 509 // The caption button position and size is confusing. In maximized mode, the | 533 int button_y = WindowTopY(); |
| 510 // caption buttons are SM_CYMENUSIZE pixels high and are placed | 534 if (frame()->IsMaximized()) { |
| 511 // FrameTopBorderHeight() pixels from the top of the window; all those top | 535 // In maximized mode the caption buttons appear only 19 pixels high, but |
| 512 // border pixels are offscreen, so this result in caption buttons flush with | 536 // their contents are aligned as if they were 20 pixels high and extended |
| 513 // the top of the screen. In restored mode, the caption buttons are first | 537 // 1 pixel off the top of the screen. We position the profile switcher |
| 514 // placed just below a 2 px border at the top of the window (which is the | 538 // button the same way to match. |
| 515 // first two pixels' worth of FrameTopBorderHeight()), then extended upwards | 539 button_y -= 1; |
| 516 // one extra pixel to overlap part of this border. | 540 } |
| 517 // | 541 profile_switcher_.view()->SetBounds(button_x, button_y, label_size.width(), |
| 518 // To match both of these, we size the button as if it's always the extra one | 542 kProfileSwitcherButtonHeight); |
| 519 // pixel in height, then we place it at the correct position in restored mode, | |
| 520 // or one pixel above the top of the screen in maximized mode. | |
| 521 int button_y = frame()->IsMaximized() ? (FrameTopBorderHeight(false) - 1) : 1; | |
| 522 profile_switcher_.view()->SetBounds( | |
| 523 button_x, button_y, label_size.width(), | |
| 524 display::win::GetSystemMetricsInDIP(SM_CYMENUSIZE) + 1); | |
| 525 } | 543 } |
| 526 | 544 |
| 527 void GlassBrowserFrameView::LayoutIncognitoIcon() { | 545 void GlassBrowserFrameView::LayoutIncognitoIcon() { |
| 528 const bool md = ui::MaterialDesignController::IsModeMaterial(); | 546 const bool md = ui::MaterialDesignController::IsModeMaterial(); |
| 529 const gfx::Insets insets(GetLayoutInsets(AVATAR_ICON)); | 547 const gfx::Insets insets(GetLayoutInsets(AVATAR_ICON)); |
| 530 const gfx::Size size(GetOTRAvatarIcon().size()); | 548 const gfx::Size size(GetOTRAvatarIcon().size()); |
| 531 int x = NonClientBorderThickness(false); | 549 int x = ClientBorderThickness(false); |
| 532 // In RTL, the icon needs to start after the caption buttons. | 550 // In RTL, the icon needs to start after the caption buttons. |
| 533 if (base::i18n::IsRTL()) { | 551 if (CaptionButtonsOnLeadingEdge()) { |
| 534 x = width() - frame()->GetMinimizeButtonOffset() + | 552 x = width() - frame()->GetMinimizeButtonOffset() + |
| 535 (profile_switcher_.view() | 553 (profile_switcher_.view() ? (profile_switcher_.view()->width() + |
| 536 ? (profile_switcher_.view()->width() + kNewAvatarButtonOffset) | 554 kProfileSwitcherButtonOffset) |
| 537 : 0); | 555 : 0); |
| 538 } else if (!md && !avatar_button() && IsToolbarVisible() && | 556 } else if (!md && !avatar_button() && IsToolbarVisible() && |
| 539 (base::win::GetVersion() < base::win::VERSION_WIN10)) { | 557 (base::win::GetVersion() < base::win::VERSION_WIN10)) { |
| 540 // In non-MD before Win 10, the toolbar has a rounded corner that we don't | 558 // In non-MD before Win 10, the toolbar has a rounded corner that we don't |
| 541 // want the tabstrip to overlap. | 559 // want the tabstrip to overlap. |
| 542 x += browser_view()->GetToolbarBounds().x() - kContentEdgeShadowThickness + | 560 x += browser_view()->GetToolbarBounds().x() - kContentEdgeShadowThickness + |
| 543 GetThemeProvider()->GetImageSkiaNamed( | 561 GetThemeProvider()->GetImageSkiaNamed( |
| 544 IDR_CONTENT_TOP_LEFT_CORNER)->width(); | 562 IDR_CONTENT_TOP_LEFT_CORNER)->width(); |
| 545 } | 563 } |
| 546 const int bottom = GetTopInset(false) + browser_view()->GetTabStripHeight() - | 564 const int bottom = GetTopInset(false) + browser_view()->GetTabStripHeight() - |
| 547 insets.bottom(); | 565 insets.bottom(); |
| 548 const int y = (md || !frame()->IsMaximized()) ? | 566 const int y = (md || !frame()->IsMaximized()) |
| 549 (bottom - size.height()) : FrameTopBorderHeight(false); | 567 ? (bottom - size.height()) |
| 568 : FrameTopBorderThickness(false); |
| 550 incognito_bounds_.SetRect(x + (avatar_button() ? insets.left() : 0), y, | 569 incognito_bounds_.SetRect(x + (avatar_button() ? insets.left() : 0), y, |
| 551 avatar_button() ? size.width() : 0, bottom - y); | 570 avatar_button() ? size.width() : 0, bottom - y); |
| 552 if (avatar_button()) | 571 if (avatar_button()) |
| 553 avatar_button()->SetBoundsRect(incognito_bounds_); | 572 avatar_button()->SetBoundsRect(incognito_bounds_); |
| 554 } | 573 } |
| 555 | 574 |
| 556 void GlassBrowserFrameView::LayoutClientView() { | 575 void GlassBrowserFrameView::LayoutClientView() { |
| 557 client_view_bounds_ = CalculateClientAreaBounds(); | 576 client_view_bounds_ = CalculateClientAreaBounds(); |
| 558 } | 577 } |
| 559 | 578 |
| 560 gfx::Insets GlassBrowserFrameView::GetClientAreaInsets(bool restored) const { | 579 gfx::Insets GlassBrowserFrameView::GetClientAreaInsets(bool restored) const { |
| 561 if (!browser_view()->IsTabStripVisible()) | 580 if (!browser_view()->IsTabStripVisible()) |
| 562 return gfx::Insets(); | 581 return gfx::Insets(); |
| 563 | 582 |
| 564 const int top_height = NonClientTopBorderHeight(restored); | 583 const int top_height = TopAreaHeight(restored); |
| 565 const int border_thickness = NonClientBorderThickness(restored); | 584 const int border_thickness = ClientBorderThickness(restored); |
| 566 return gfx::Insets(top_height, | 585 return gfx::Insets(top_height, |
| 567 border_thickness, | 586 border_thickness, |
| 568 border_thickness, | 587 border_thickness, |
| 569 border_thickness); | 588 border_thickness); |
| 570 } | 589 } |
| 571 | 590 |
| 572 gfx::Rect GlassBrowserFrameView::CalculateClientAreaBounds() const { | 591 gfx::Rect GlassBrowserFrameView::CalculateClientAreaBounds() const { |
| 573 gfx::Rect bounds(GetLocalBounds()); | 592 gfx::Rect bounds(GetLocalBounds()); |
| 574 bounds.Inset(GetClientAreaInsets(false)); | 593 bounds.Inset(GetClientAreaInsets(false)); |
| 575 return bounds; | 594 return bounds; |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 649 static bool initialized = false; | 668 static bool initialized = false; |
| 650 if (!initialized) { | 669 if (!initialized) { |
| 651 for (int i = 0; i < kThrobberIconCount; ++i) { | 670 for (int i = 0; i < kThrobberIconCount; ++i) { |
| 652 throbber_icons_[i] = | 671 throbber_icons_[i] = |
| 653 ui::LoadThemeIconFromResourcesDataDLL(IDI_THROBBER_01 + i); | 672 ui::LoadThemeIconFromResourcesDataDLL(IDI_THROBBER_01 + i); |
| 654 DCHECK(throbber_icons_[i]); | 673 DCHECK(throbber_icons_[i]); |
| 655 } | 674 } |
| 656 initialized = true; | 675 initialized = true; |
| 657 } | 676 } |
| 658 } | 677 } |
| OLD | NEW |