| Index: chrome/browser/ui/views/frame/glass_browser_frame_view.cc
|
| diff --git a/chrome/browser/ui/views/frame/glass_browser_frame_view.cc b/chrome/browser/ui/views/frame/glass_browser_frame_view.cc
|
| index b9553425685f33aaa1591cd071630e6476ba50ab..c596d600496495a5270763052688065d76efd906 100644
|
| --- a/chrome/browser/ui/views/frame/glass_browser_frame_view.cc
|
| +++ b/chrome/browser/ui/views/frame/glass_browser_frame_view.cc
|
| @@ -42,17 +42,19 @@ HICON GlassBrowserFrameView::throbber_icons_[
|
| GlassBrowserFrameView::kThrobberIconCount];
|
|
|
| namespace {
|
| -// Size of client edge drawn inside the outer frame borders.
|
| -const int kNonClientBorderThicknessPreWin10 = 3;
|
| -const int kNonClientBorderThicknessWin10 = 1;
|
| +// Thickness of the border in the client area that separates it from the
|
| +// non-client area. Includes but is distinct from kClientEdgeThickness, which is
|
| +// the thickness of the border between the web content and our frame border.
|
| +const int kClientBorderThicknessPreWin10 = 3;
|
| +const int kClientBorderThicknessWin10 = 1;
|
| // Besides the frame border, there's empty space atop the window in restored
|
| // mode, to use to drag the window around.
|
| const int kNonClientRestoredExtraThickness = 11;
|
| -// In the window corners, the resize areas don't actually expand bigger, but the
|
| -// 16 px at the end of the top and bottom edges triggers diagonal resizing.
|
| +// At the window corners the resize area is not actually bigger, but the 16
|
| +// pixels at the end of the top and bottom edges trigger diagonal resizing.
|
| const int kResizeCornerWidth = 16;
|
| -// How far the new avatar button is from the left of the minimize button.
|
| -const int kNewAvatarButtonOffset = 5;
|
| +// How far the profile switcher button is from the left of the minimize button.
|
| +const int kProfileSwitcherButtonOffset = 5;
|
| // The content edge images have a shadow built into them.
|
| const int kContentEdgeShadowThickness = 2;
|
| // In restored mode, the New Tab button isn't at the same height as the caption
|
| @@ -63,6 +65,11 @@ const int kNewTabCaptionRestoredSpacing = 5;
|
| // similar vertical coordinates, we need to reserve a larger, 16 px gap to avoid
|
| // looking too cluttered.
|
| const int kNewTabCaptionMaximizedSpacing = 16;
|
| +// Height of the profile switcher button. Same as the height of the Windows 7/8
|
| +// caption buttons.
|
| +// TODO(bsep): Windows 10 caption buttons look very different and we would like
|
| +// the profile switcher button to match on that platform.
|
| +const int kProfileSwitcherButtonHeight = 20;
|
|
|
| // Converts the |image| to a Windows icon and returns the corresponding HICON
|
| // handle. |image| is resized to desired |width| and |height| if needed.
|
| @@ -102,27 +109,27 @@ GlassBrowserFrameView::~GlassBrowserFrameView() {
|
| gfx::Rect GlassBrowserFrameView::GetBoundsForTabStrip(
|
| views::View* tabstrip) const {
|
| // In maximized RTL windows, don't let the tabstrip overlap the caption area,
|
| - // or the alpha-blending it does will make things like the new avatar button
|
| - // look glitchy.
|
| - const int offset =
|
| - (ui::MaterialDesignController::IsModeMaterial() || !base::i18n::IsRTL() ||
|
| - !frame()->IsMaximized()) ?
|
| - GetLayoutInsets(AVATAR_ICON).right() : 0;
|
| + // or the alpha-blending it does will make things like the profile switcher
|
| + // button look glitchy.
|
| + const int offset = (ui::MaterialDesignController::IsModeMaterial() ||
|
| + !CaptionButtonsOnLeadingEdge() || !frame()->IsMaximized())
|
| + ? GetLayoutInsets(AVATAR_ICON).right()
|
| + : 0;
|
| const int x = incognito_bounds_.right() + offset;
|
| - int end_x = width() - NonClientBorderThickness(false);
|
| - if (!base::i18n::IsRTL()) {
|
| + int end_x = width() - ClientBorderThickness(false);
|
| + if (!CaptionButtonsOnLeadingEdge()) {
|
| end_x = std::min(frame()->GetMinimizeButtonOffset(), end_x) -
|
| (frame()->IsMaximized() ?
|
| kNewTabCaptionMaximizedSpacing : kNewTabCaptionRestoredSpacing);
|
|
|
| - // The new avatar button is optionally displayed to the left of the
|
| + // The profile switcher button is optionally displayed to the left of the
|
| // minimize button.
|
| if (profile_switcher_.view()) {
|
| const int old_end_x = end_x;
|
| - end_x -= profile_switcher_.view()->width() + kNewAvatarButtonOffset;
|
| + end_x -= profile_switcher_.view()->width() + kProfileSwitcherButtonOffset;
|
|
|
| // In non-maximized mode, allow the new tab button to slide completely
|
| - // under the avatar button.
|
| + // under the profile switcher button.
|
| if (!frame()->IsMaximized()) {
|
| end_x = std::min(end_x + GetLayoutSize(NEW_TAB_BUTTON).width() +
|
| kNewTabCaptionRestoredSpacing,
|
| @@ -130,7 +137,7 @@ gfx::Rect GlassBrowserFrameView::GetBoundsForTabStrip(
|
| }
|
| }
|
| }
|
| - return gfx::Rect(x, NonClientTopBorderHeight(false), std::max(0, end_x - x),
|
| + return gfx::Rect(x, TopAreaHeight(false), std::max(0, end_x - x),
|
| tabstrip->GetPreferredSize().height());
|
| }
|
|
|
| @@ -216,7 +223,7 @@ int GlassBrowserFrameView::NonClientHitTest(const gfx::Point& point) {
|
| if (!browser_view()->IsBrowserTypeNormal() || !bounds().Contains(point))
|
| return HTNOWHERE;
|
|
|
| - // See if the point is within the incognito icon or the new avatar menu.
|
| + // See if the point is within the incognito icon or the profile switcher menu.
|
| if ((avatar_button() &&
|
| avatar_button()->GetMirroredBounds().Contains(point)) ||
|
| (profile_switcher_.view() &&
|
| @@ -227,8 +234,8 @@ int GlassBrowserFrameView::NonClientHitTest(const gfx::Point& point) {
|
|
|
| // See if we're in the sysmenu region. We still have to check the tabstrip
|
| // first so that clicks in a tab don't get treated as sysmenu clicks.
|
| - int nonclient_border_thickness = NonClientBorderThickness(false);
|
| - gfx::Rect sys_menu_region(nonclient_border_thickness,
|
| + int client_border_thickness = ClientBorderThickness(false);
|
| + gfx::Rect sys_menu_region(client_border_thickness,
|
| display::win::GetSystemMetricsInDIP(SM_CYSIZEFRAME),
|
| display::win::GetSystemMetricsInDIP(SM_CXSMICON),
|
| display::win::GetSystemMetricsInDIP(SM_CYSMICON));
|
| @@ -238,17 +245,18 @@ int GlassBrowserFrameView::NonClientHitTest(const gfx::Point& point) {
|
| if (frame_component != HTNOWHERE)
|
| return frame_component;
|
|
|
| - int frame_top_border_height = FrameTopBorderHeight(false);
|
| + int top_border_thickness = FrameTopBorderThickness(false);
|
| // We want the resize corner behavior to apply to the kResizeCornerWidth
|
| // pixels at each end of the top and bottom edges. Because |point|'s x
|
| // coordinate is based on the DWM-inset portion of the window (so, it's 0 at
|
| // the first pixel inside the left DWM margin), we need to subtract the DWM
|
| // margin thickness, which we calculate as the total frame border thickness
|
| // minus the nonclient border thickness.
|
| - const int dwm_margin = FrameBorderThickness() - nonclient_border_thickness;
|
| - int window_component = GetHTComponentForFrame(point, frame_top_border_height,
|
| - nonclient_border_thickness, frame_top_border_height,
|
| - kResizeCornerWidth - dwm_margin, frame()->widget_delegate()->CanResize());
|
| + const int dwm_margin = FrameBorderThickness() - client_border_thickness;
|
| + int window_component = GetHTComponentForFrame(
|
| + point, top_border_thickness, client_border_thickness,
|
| + top_border_thickness, kResizeCornerWidth - dwm_margin,
|
| + frame()->widget_delegate()->CanResize());
|
| // Fall back to the caption if no other component matches.
|
| return (window_component == HTNOWHERE) ? HTCAPTION : window_component;
|
| }
|
| @@ -267,7 +275,7 @@ void GlassBrowserFrameView::OnPaint(gfx::Canvas* canvas) {
|
|
|
| void GlassBrowserFrameView::Layout() {
|
| if (browser_view()->IsRegularOrGuestSession())
|
| - LayoutNewStyleAvatar();
|
| + LayoutProfileSwitcher();
|
| LayoutIncognitoIcon();
|
| LayoutClientView();
|
| }
|
| @@ -292,40 +300,45 @@ bool GlassBrowserFrameView::DoesIntersectRect(const views::View* target,
|
| CHECK_EQ(target, this);
|
| bool hit_incognito_icon = avatar_button() &&
|
| avatar_button()->GetMirroredBounds().Intersects(rect);
|
| - bool hit_new_avatar_button =
|
| + bool hit_profile_switcher_button =
|
| profile_switcher_.view() &&
|
| profile_switcher_.view()->GetMirroredBounds().Intersects(rect);
|
| - return hit_incognito_icon || hit_new_avatar_button ||
|
| + return hit_incognito_icon || hit_profile_switcher_button ||
|
| !frame()->client_view()->bounds().Intersects(rect);
|
| }
|
|
|
| +int GlassBrowserFrameView::ClientBorderThickness(bool restored) const {
|
| + if ((frame()->IsMaximized() || frame()->IsFullscreen()) && !restored)
|
| + return 0;
|
| +
|
| + return (base::win::GetVersion() < base::win::VERSION_WIN10)
|
| + ? kClientBorderThicknessPreWin10
|
| + : kClientBorderThicknessWin10;
|
| +}
|
| +
|
| int GlassBrowserFrameView::FrameBorderThickness() const {
|
| return (frame()->IsMaximized() || frame()->IsFullscreen()) ?
|
| 0 : display::win::GetSystemMetricsInDIP(SM_CXSIZEFRAME);
|
| }
|
|
|
| -int GlassBrowserFrameView::FrameTopBorderHeight(bool restored) const {
|
| - // We'd like to use FrameBorderThickness() here, but the maximized Aero glass
|
| - // frame has a 0 frame border around most edges and a CYSIZEFRAME-thick border
|
| - // at the top (see AeroGlassFrame::OnGetMinMaxInfo()).
|
| +int GlassBrowserFrameView::FrameTopBorderThickness(bool restored) const {
|
| + // Distinct from FrameBorderThickness() because Windows gives maximized
|
| + // windows an offscreen CYSIZEFRAME-thick region around the edges. The
|
| + // left/right/bottom edges don't worry about this because we cancel them out
|
| + // in BrowserDesktopWindowTreeHostWin::GetClientAreaInsets() so the offscreen
|
| + // area is non-client as far as Windows is concerned. However because we want
|
| + // to push away the top part of the glass's gradient in Win7 we set the top
|
| + // client inset to 0. Thus we must compensate here to avoid having UI elements
|
| + // drift off the top of the screen.
|
| return (frame()->IsFullscreen() && !restored) ?
|
| 0 : display::win::GetSystemMetricsInDIP(SM_CYSIZEFRAME);
|
| }
|
|
|
| -int GlassBrowserFrameView::NonClientBorderThickness(bool restored) const {
|
| - if ((frame()->IsMaximized() || frame()->IsFullscreen()) && !restored)
|
| - return 0;
|
| -
|
| - return (base::win::GetVersion() < base::win::VERSION_WIN10)
|
| - ? kNonClientBorderThicknessPreWin10
|
| - : kNonClientBorderThicknessWin10;
|
| -}
|
| -
|
| -int GlassBrowserFrameView::NonClientTopBorderHeight(bool restored) const {
|
| +int GlassBrowserFrameView::TopAreaHeight(bool restored) const {
|
| if (frame()->IsFullscreen() && !restored)
|
| return 0;
|
|
|
| - const int top = FrameTopBorderHeight(restored);
|
| + const int top = FrameTopBorderThickness(restored);
|
| // The tab top inset is equal to the height of any shadow region above the
|
| // tabs, plus a 1 px top stroke. In maximized mode, we want to push the
|
| // shadow region off the top of the screen but leave the top stroke.
|
| @@ -339,11 +352,22 @@ int GlassBrowserFrameView::NonClientTopBorderHeight(bool restored) const {
|
| (top + kNonClientRestoredExtraThickness - exclusion);
|
| }
|
|
|
| +int GlassBrowserFrameView::WindowTopY() const {
|
| + return frame()->IsMaximized() ? FrameTopBorderThickness(false) : 1;
|
| +}
|
| +
|
| bool GlassBrowserFrameView::IsToolbarVisible() const {
|
| return browser_view()->IsToolbarVisible() &&
|
| !browser_view()->toolbar()->GetPreferredSize().IsEmpty();
|
| }
|
|
|
| +bool GlassBrowserFrameView::CaptionButtonsOnLeadingEdge() const {
|
| + // Because we don't set WS_EX_LAYOUTRTL (which would conflict with Chrome's
|
| + // own RTL layout logic), Windows always draws the caption buttons on the
|
| + // right, even when we want to be RTL. See crbug.com/560619.
|
| + return base::i18n::IsRTL();
|
| +}
|
| +
|
| void GlassBrowserFrameView::PaintToolbarBackground(gfx::Canvas* canvas) const {
|
| gfx::Rect toolbar_bounds(browser_view()->GetToolbarBounds());
|
| if (toolbar_bounds.IsEmpty())
|
| @@ -450,7 +474,7 @@ void GlassBrowserFrameView::PaintClientEdge(gfx::Canvas* canvas) const {
|
| client_bounds.y() + (md ? toolbar_bounds.y() : toolbar_bounds.bottom());
|
| const int w = client_bounds.width();
|
| const int right = client_bounds.right();
|
| - const int bottom = std::max(y, height() - NonClientBorderThickness(false));
|
| + const int bottom = std::max(y, height() - ClientBorderThickness(false));
|
| const int height = bottom - y;
|
|
|
| // Draw the client edge images. For non-MD, we fill the toolbar color
|
| @@ -493,7 +517,7 @@ void GlassBrowserFrameView::FillClientEdgeRects(int x,
|
| canvas->FillRect(side, color);
|
| }
|
|
|
| -void GlassBrowserFrameView::LayoutNewStyleAvatar() {
|
| +void GlassBrowserFrameView::LayoutProfileSwitcher() {
|
| DCHECK(browser_view()->IsRegularOrGuestSession());
|
| if (!profile_switcher_.view())
|
| return;
|
| @@ -501,40 +525,34 @@ void GlassBrowserFrameView::LayoutNewStyleAvatar() {
|
| gfx::Size label_size = profile_switcher_.view()->GetPreferredSize();
|
|
|
| int button_x = frame()->GetMinimizeButtonOffset() -
|
| - kNewAvatarButtonOffset - label_size.width();
|
| - if (base::i18n::IsRTL())
|
| + kProfileSwitcherButtonOffset - label_size.width();
|
| + if (CaptionButtonsOnLeadingEdge())
|
| button_x = width() - frame()->GetMinimizeButtonOffset() +
|
| - kNewAvatarButtonOffset;
|
| -
|
| - // The caption button position and size is confusing. In maximized mode, the
|
| - // caption buttons are SM_CYMENUSIZE pixels high and are placed
|
| - // FrameTopBorderHeight() pixels from the top of the window; all those top
|
| - // border pixels are offscreen, so this result in caption buttons flush with
|
| - // the top of the screen. In restored mode, the caption buttons are first
|
| - // placed just below a 2 px border at the top of the window (which is the
|
| - // first two pixels' worth of FrameTopBorderHeight()), then extended upwards
|
| - // one extra pixel to overlap part of this border.
|
| - //
|
| - // To match both of these, we size the button as if it's always the extra one
|
| - // pixel in height, then we place it at the correct position in restored mode,
|
| - // or one pixel above the top of the screen in maximized mode.
|
| - int button_y = frame()->IsMaximized() ? (FrameTopBorderHeight(false) - 1) : 1;
|
| - profile_switcher_.view()->SetBounds(
|
| - button_x, button_y, label_size.width(),
|
| - display::win::GetSystemMetricsInDIP(SM_CYMENUSIZE) + 1);
|
| + kProfileSwitcherButtonOffset;
|
| +
|
| + int button_y = WindowTopY();
|
| + if (frame()->IsMaximized()) {
|
| + // In maximized mode the caption buttons appear only 19 pixels high, but
|
| + // their contents are aligned as if they were 20 pixels high and extended
|
| + // 1 pixel off the top of the screen. We position the profile switcher
|
| + // button the same way to match.
|
| + button_y -= 1;
|
| + }
|
| + profile_switcher_.view()->SetBounds(button_x, button_y, label_size.width(),
|
| + kProfileSwitcherButtonHeight);
|
| }
|
|
|
| void GlassBrowserFrameView::LayoutIncognitoIcon() {
|
| const bool md = ui::MaterialDesignController::IsModeMaterial();
|
| const gfx::Insets insets(GetLayoutInsets(AVATAR_ICON));
|
| const gfx::Size size(GetOTRAvatarIcon().size());
|
| - int x = NonClientBorderThickness(false);
|
| + int x = ClientBorderThickness(false);
|
| // In RTL, the icon needs to start after the caption buttons.
|
| - if (base::i18n::IsRTL()) {
|
| + if (CaptionButtonsOnLeadingEdge()) {
|
| x = width() - frame()->GetMinimizeButtonOffset() +
|
| - (profile_switcher_.view()
|
| - ? (profile_switcher_.view()->width() + kNewAvatarButtonOffset)
|
| - : 0);
|
| + (profile_switcher_.view() ? (profile_switcher_.view()->width() +
|
| + kProfileSwitcherButtonOffset)
|
| + : 0);
|
| } else if (!md && !avatar_button() && IsToolbarVisible() &&
|
| (base::win::GetVersion() < base::win::VERSION_WIN10)) {
|
| // In non-MD before Win 10, the toolbar has a rounded corner that we don't
|
| @@ -545,8 +563,9 @@ void GlassBrowserFrameView::LayoutIncognitoIcon() {
|
| }
|
| const int bottom = GetTopInset(false) + browser_view()->GetTabStripHeight() -
|
| insets.bottom();
|
| - const int y = (md || !frame()->IsMaximized()) ?
|
| - (bottom - size.height()) : FrameTopBorderHeight(false);
|
| + const int y = (md || !frame()->IsMaximized())
|
| + ? (bottom - size.height())
|
| + : FrameTopBorderThickness(false);
|
| incognito_bounds_.SetRect(x + (avatar_button() ? insets.left() : 0), y,
|
| avatar_button() ? size.width() : 0, bottom - y);
|
| if (avatar_button())
|
| @@ -561,8 +580,8 @@ gfx::Insets GlassBrowserFrameView::GetClientAreaInsets(bool restored) const {
|
| if (!browser_view()->IsTabStripVisible())
|
| return gfx::Insets();
|
|
|
| - const int top_height = NonClientTopBorderHeight(restored);
|
| - const int border_thickness = NonClientBorderThickness(restored);
|
| + const int top_height = TopAreaHeight(restored);
|
| + const int border_thickness = ClientBorderThickness(restored);
|
| return gfx::Insets(top_height,
|
| border_thickness,
|
| border_thickness,
|
|
|