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; |
} |