Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5928)

Unified Diff: chrome/browser/ui/views/frame/opaque_browser_frame_view.cc

Issue 1431303002: Make windows caption buttons look natural on windows 10 (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebased Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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;
}

Powered by Google App Engine
This is Rietveld 408576698