| Index: chrome/browser/ui/views/frame/opaque_browser_frame_view.cc
|
| diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc b/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc
|
| index f9cfccafac849e4aa4dc0a587bce4988ce3a9f06..244321b0aa357f45d9cc44a5a8cd8222165f6681 100644
|
| --- a/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc
|
| +++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc
|
| @@ -35,7 +35,9 @@
|
| #include "ui/base/l10n/l10n_util.h"
|
| #include "ui/base/material_design/material_design_controller.h"
|
| #include "ui/base/theme_provider.h"
|
| +#include "ui/gfx/animation/throb_animation.h"
|
| #include "ui/gfx/canvas.h"
|
| +#include "ui/gfx/color_utils.h"
|
| #include "ui/gfx/font_list.h"
|
| #include "ui/gfx/geometry/rect_conversions.h"
|
| #include "ui/gfx/image/image.h"
|
| @@ -57,6 +59,10 @@
|
| #include "ui/views/controls/menu/menu_runner.h"
|
| #endif
|
|
|
| +#if defined(OS_WIN)
|
| +#include "base/win/windows_version.h"
|
| +#endif
|
| +
|
| using content::WebContents;
|
|
|
| namespace {
|
| @@ -70,6 +76,219 @@ const int kResizeAreaCornerSize = 16;
|
| const int kIconMinimumSize = 16;
|
| #endif
|
|
|
| +// This draws button that look like win10 window caption buttons. The
|
| +// foreground colour is taken from the theme itself, so that it is guaranteed
|
| +// to provide good contrast with the background.
|
| +class OpaqueWin10CaptionButton : public views::CustomButton {
|
| + public:
|
| + OpaqueWin10CaptionButton(OpaqueBrowserFrameView* parent, ViewID view_id);
|
| +
|
| + // The width and height of a caption button. The button is slightly shorter
|
| + // when the browser window is maximized since there is less vertical space.
|
| + const int kWidth = 46;
|
| + const int kHeightNormal = 28;
|
| + const int kHeightMaximized = 20;
|
| +
|
| + private:
|
| + // Overridden from View:
|
| + gfx::Size GetPreferredSize() const override;
|
| + void OnBoundsChanged(const gfx::Rect& previous_bounds) override;
|
| + void OnPaint(gfx::Canvas* canvas) override;
|
| +
|
| + OpaqueBrowserFrameView* parent_;
|
| + gfx::Size preferred_size_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(OpaqueWin10CaptionButton);
|
| +};
|
| +
|
| +OpaqueWin10CaptionButton::OpaqueWin10CaptionButton(
|
| + OpaqueBrowserFrameView* parent,
|
| + ViewID view_id)
|
| + : views::CustomButton(parent),
|
| + parent_(parent),
|
| + preferred_size_(kWidth, kHeightNormal) {
|
| + set_id(view_id);
|
| +}
|
| +
|
| +gfx::Size OpaqueWin10CaptionButton::GetPreferredSize() const {
|
| + return preferred_size_;
|
| +}
|
| +
|
| +void OpaqueWin10CaptionButton::OnBoundsChanged(
|
| + const gfx::Rect& previous_bounds) {
|
| + views::Widget* widget = GetWidget();
|
| + if (!widget)
|
| + return;
|
| +
|
| + preferred_size_.set_height(
|
| + widget->IsMaximized() ? kHeightMaximized : kHeightNormal);
|
| + PreferredSizeChanged();
|
| +}
|
| +
|
| +void OpaqueWin10CaptionButton::OnPaint(gfx::Canvas* canvas) {
|
| + gfx::Rect rect(GetLocalBounds());
|
| +
|
| + // Determine the foreground colour. The colour is chosen to most contrast
|
| + // with the frame's background colour.
|
| + SkColor foreground = SK_ColorTRANSPARENT;
|
| + SkColor foreground_secondary = SK_ColorTRANSPARENT;
|
| + SkColor frame_color = parent_->GetFrameColor();
|
| + if (color_utils::GetContrastRatio(frame_color, SK_ColorBLACK) >
|
| + color_utils::kMinimumReadableContrastRatio) {
|
| + foreground = SK_ColorBLACK;
|
| + foreground_secondary = SkColorSetA(SK_ColorWHITE, 100);
|
| + } else {
|
| + foreground = SK_ColorWHITE;
|
| + foreground_secondary = SkColorSetA(SK_ColorBLACK, 100);
|
| + }
|
| +
|
| + // Determine the background colour depending on which caption button is being
|
| + // painted and its current state.
|
| + SkColor background = SK_ColorTRANSPARENT;
|
| + if (id() == VIEW_ID_CLOSE_BUTTON) {
|
| + // The close button has an opaque red background on hover, slightly
|
| + // less saturated on press.
|
| + SkAlpha alpha = 0;
|
| + if (state() == STATE_HOVERED) {
|
| + foreground = SK_ColorWHITE;
|
| + foreground_secondary = SK_ColorTRANSPARENT;
|
| + alpha = hover_animation_->is_animating() ?
|
| + hover_animation_->CurrentValueBetween(0, 255) : 255;
|
| + background = SkColorSetARGB(alpha, 232, 17, 35);
|
| + } else if (state() == STATE_PRESSED) {
|
| + foreground = SK_ColorWHITE;
|
| + foreground_secondary = SK_ColorTRANSPARENT;
|
| + background = SkColorSetARGB(255, 241, 112, 122);
|
| + }
|
| + } else {
|
| + if (state() == STATE_HOVERED) {
|
| + int alpha = hover_animation_->is_animating() ?
|
| + hover_animation_->CurrentValueBetween(0, 50) : 50;
|
| + if (foreground == SK_ColorWHITE) {
|
| + // Background is dark, so lighten it.
|
| + background = SkColorSetA(SK_ColorWHITE, alpha);
|
| + } else {
|
| + // Background is light, so darken it.
|
| + background = SkColorSetA(SK_ColorBLACK, alpha);
|
| + }
|
| + } else if (state() == STATE_PRESSED) {
|
| + if (foreground == SK_ColorWHITE) {
|
| + // Background is dark, so lighten it.
|
| + background = SkColorSetA(SK_ColorWHITE, 70);
|
| + } else {
|
| + // Background is light, so darken it.
|
| + background = SkColorSetA(SK_ColorBLACK, 70);
|
| + }
|
| + }
|
| + }
|
| +
|
| + // Fill the background of the button if needed.
|
| + //if (background != SK_ColorTRANSPARENT)
|
| + // canvas->FillRect(GetLocalBounds(), background);
|
| +
|
| + SkPaint paint;
|
| + paint.setStyle(SkPaint::kStroke_Style);
|
| + paint.setStrokeWidth(SkIntToScalar(1));
|
| + paint.setStrokeCap(SkPaint::kSquare_Cap);
|
| + paint.setColor(foreground);
|
| +
|
| + SkPaint paint_secondary;
|
| + paint_secondary.setStyle(SkPaint::kStroke_Style);
|
| + paint_secondary.setStrokeWidth(SkIntToScalar(3));
|
| + paint_secondary.setStrokeCap(SkPaint::kSquare_Cap);
|
| + paint_secondary.setColor(foreground_secondary);
|
| +
|
| + ui::NativeTheme::Part native_part = ui::NativeTheme::kCaptionMin;
|
| + switch(id()) {
|
| + case VIEW_ID_MINIMIZE_BUTTON:
|
| + break;
|
| + case VIEW_ID_MAXIMIZE_BUTTON:
|
| + native_part = ui::NativeTheme::kCaptionMax;
|
| + break;
|
| + case VIEW_ID_RESTORE_BUTTON:
|
| + native_part = ui::NativeTheme::kCaptionRestore;
|
| + break;
|
| + case VIEW_ID_CLOSE_BUTTON:
|
| + native_part = ui::NativeTheme::kCaptionClose;
|
| + break;
|
| + default:
|
| + NOTREACHED();
|
| + break;
|
| + }
|
| +
|
| + ui::NativeTheme::State native_state = ui::NativeTheme::kNormal;
|
| + switch(state()) {
|
| + case STATE_NORMAL:
|
| + break;
|
| + case STATE_HOVERED:
|
| + native_state = ui::NativeTheme::kHovered;
|
| + break;
|
| + case STATE_PRESSED:
|
| + native_state = ui::NativeTheme::kPressed;
|
| + break;
|
| + case STATE_DISABLED:
|
| + native_state = ui::NativeTheme::kDisabled;
|
| + break;
|
| + default:
|
| + NOTREACHED();
|
| + break;
|
| + }
|
| +
|
| + ui::NativeTheme::ExtraParams extra;
|
| + GetNativeTheme()->Paint(canvas->sk_canvas(),
|
| + native_part,
|
| + native_state,
|
| + rect,
|
| + extra);
|
| + // Draw the button's icon.
|
| + /*switch (id()) {
|
| + case VIEW_ID_MINIMIZE_BUTTON: {
|
| + rect.ClampToCenteredSize(gfx::Size(9, 9));
|
| + int mid_y = rect.CenterPoint().y();
|
| + gfx::Point p1(rect.x(), mid_y);
|
| + gfx::Point p2(rect.right(), mid_y);
|
| + canvas->DrawLine(p1, p2, paint_secondary);
|
| + canvas->DrawLine(p1, p2, paint);
|
| + break;
|
| + }
|
| + case VIEW_ID_MAXIMIZE_BUTTON:
|
| + rect.ClampToCenteredSize(gfx::Size(9, 9));
|
| + canvas->DrawRect(rect, paint_secondary);
|
| + canvas->DrawRect(rect, paint);
|
| + break;
|
| + case VIEW_ID_RESTORE_BUTTON: {
|
| + rect.ClampToCenteredSize(gfx::Size(7, 7));
|
| + rect.Offset(1, -1);
|
| + gfx::Point start(rect.origin());
|
| + start.Offset(0, 2);
|
| + gfx::Point stop(rect.bottom_right());
|
| + stop.Offset(-2, 0);
|
| +
|
| + canvas->DrawLine(rect.origin(), rect.top_right(), paint_secondary);
|
| + canvas->DrawLine(rect.top_right(), rect.bottom_right(), paint_secondary);
|
| +
|
| + canvas->DrawLine(start, rect.origin(), paint);
|
| + canvas->DrawLine(rect.origin(), rect.top_right(), paint);
|
| + canvas->DrawLine(rect.top_right(), rect.bottom_right(), paint);
|
| + canvas->DrawLine(rect.bottom_right(), stop, paint);
|
| +
|
| + rect.Offset(-2, 2);
|
| + canvas->DrawRect(rect, paint_secondary);
|
| + canvas->DrawRect(rect, paint);
|
| + break;
|
| + }
|
| + case VIEW_ID_CLOSE_BUTTON:
|
| + rect.ClampToCenteredSize(gfx::Size(9, 9));
|
| + paint.setAntiAlias(true);
|
| + paint_secondary.setAntiAlias(true);
|
| + canvas->DrawLine(rect.origin(), rect.bottom_right(), paint_secondary);
|
| + canvas->DrawLine(rect.bottom_left(), rect.top_right(), paint_secondary);
|
| + canvas->DrawLine(rect.origin(), rect.bottom_right(), paint);
|
| + canvas->DrawLine(rect.bottom_left(), rect.top_right(), paint);
|
| + break;
|
| + }*/
|
| +}
|
| +
|
| } // namespace
|
|
|
| ///////////////////////////////////////////////////////////////////////////////
|
| @@ -517,30 +736,44 @@ bool OpaqueBrowserFrameView::DoesIntersectRect(const views::View* target,
|
| return true;
|
| }
|
|
|
| -views::ImageButton* OpaqueBrowserFrameView::InitWindowCaptionButton(
|
| +views::CustomButton* OpaqueBrowserFrameView::InitWindowCaptionButton(
|
| int normal_image_id,
|
| int hot_image_id,
|
| int pushed_image_id,
|
| int mask_image_id,
|
| int accessibility_string_id,
|
| ViewID view_id) {
|
| - views::ImageButton* button = new views::ImageButton(this);
|
| + views::CustomButton* button = nullptr;
|
| const ui::ThemeProvider* tp = frame()->GetThemeProvider();
|
| - button->SetImage(views::CustomButton::STATE_NORMAL,
|
| - tp->GetImageSkiaNamed(normal_image_id));
|
| - button->SetImage(views::CustomButton::STATE_HOVERED,
|
| - tp->GetImageSkiaNamed(hot_image_id));
|
| - button->SetImage(views::CustomButton::STATE_PRESSED,
|
| - tp->GetImageSkiaNamed(pushed_image_id));
|
| - if (browser_view()->IsBrowserTypeNormal()) {
|
| - button->SetBackground(
|
| - tp->GetColor(ThemeProperties::COLOR_BUTTON_BACKGROUND),
|
| - tp->GetImageSkiaNamed(IDR_THEME_WINDOW_CONTROL_BACKGROUND),
|
| - tp->GetImageSkiaNamed(mask_image_id));
|
| +
|
| +#if defined(OS_WIN)
|
| + if (base::win::GetVersion() <= base::win::VERSION_VISTA) {//base::win::VERSION_WIN10) {
|
| +#endif
|
| + views::ImageButton* image_button = new views::ImageButton(this);
|
| + image_button->SetImage(views::CustomButton::STATE_NORMAL,
|
| + tp->GetImageSkiaNamed(normal_image_id));
|
| + image_button->SetImage(views::CustomButton::STATE_HOVERED,
|
| + tp->GetImageSkiaNamed(hot_image_id));
|
| + image_button->SetImage(views::CustomButton::STATE_PRESSED,
|
| + tp->GetImageSkiaNamed(pushed_image_id));
|
| + if (browser_view()->IsBrowserTypeNormal()) {
|
| + image_button->SetBackground(
|
| + tp->GetColor(ThemeProperties::COLOR_BUTTON_BACKGROUND),
|
| + tp->GetImageSkiaNamed(IDR_THEME_WINDOW_CONTROL_BACKGROUND),
|
| + tp->GetImageSkiaNamed(mask_image_id));
|
| + }
|
| + image_button->SetAccessibleName(
|
| + l10n_util::GetStringUTF16(accessibility_string_id));
|
| + image_button->set_id(view_id);
|
| + button = image_button;
|
| +#if defined(OS_WIN)
|
| + } else {
|
| + OpaqueWin10CaptionButton* opaque_button =
|
| + new OpaqueWin10CaptionButton(this, view_id);
|
| + button = opaque_button;
|
| }
|
| - button->SetAccessibleName(
|
| - l10n_util::GetStringUTF16(accessibility_string_id));
|
| - button->set_id(view_id);
|
| +#endif
|
| +
|
| AddChildView(button);
|
| return button;
|
| }
|
|
|