Skip to content

Commit

Permalink
feat: enable customizing symbolColor
Browse files Browse the repository at this point in the history
  • Loading branch information
codebytere committed Apr 5, 2024
1 parent b0230d2 commit 852dcea
Show file tree
Hide file tree
Showing 5 changed files with 148 additions and 10 deletions.
7 changes: 3 additions & 4 deletions docs/api/base-window.md
Expand Up @@ -1374,13 +1374,12 @@ removed in future Electron releases.

* `options` Object
* `color` String (optional) - The CSS color of the Window Controls Overlay when enabled.
* `symbolColor` String (optional) _Windows_ - The CSS color of the symbols on the Window Controls Overlay when enabled.
* `symbolColor` String (optional) - The CSS color of the symbols on the Window Controls Overlay when enabled.
* `height` Integer (optional) - The height of the title bar and Window Controls Overlay in pixels.

On a Window with Window Controls Overlay already enabled, this method updates
the style of the title bar overlay.
On a Window with Window Controls Overlay already enabled, this method updates the style of the title bar overlay.

On Linux, the `symbolColor` is automatically calculated to have minimum accessible contrast to the `color`.
On Linux, the `symbolColor` is automatically calculated to have minimum accessible contrast to the `color` if not explicitly set.

[quick-look]: https://en.wikipedia.org/wiki/Quick_Look
[vibrancy-docs]: https://developer.apple.com/documentation/appkit/nsvisualeffectview?preferredLanguage=objc
Expand Down
7 changes: 3 additions & 4 deletions docs/api/browser-window.md
Expand Up @@ -1645,13 +1645,12 @@ with `addBrowserView` or `setBrowserView`. The top-most BrowserView is the last

* `options` Object
* `color` String (optional) - The CSS color of the Window Controls Overlay when enabled.
* `symbolColor` String (optional) _Windows_ - The CSS color of the symbols on the Window Controls Overlay when enabled.
* `symbolColor` String (optional) - The CSS color of the symbols on the Window Controls Overlay when enabled.
* `height` Integer (optional) - The height of the title bar and Window Controls Overlay in pixels.

On a window with Window Controls Overlay already enabled, this method updates
the style of the title bar overlay.
On a window with Window Controls Overlay already enabled, this method updates the style of the title bar overlay.

On Linux, the `symbolColor` is automatically calculated to have minimum accessible contrast to the `color`.
On Linux, the `symbolColor` is automatically calculated to have minimum accessible contrast to the `color` if not explicitly set.

[page-visibility-api]: https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API
[quick-look]: https://en.wikipedia.org/wiki/Quick_Look
Expand Down
1 change: 1 addition & 0 deletions patches/chromium/.patches
Expand Up @@ -129,3 +129,4 @@ build_run_reclient_cfg_generator_after_chrome.patch
fix_suppress_clang_-wimplicit-const-int-float-conversion_in.patch
fix_getcursorscreenpoint_wrongly_returns_0_0.patch
fix_add_support_for_skipping_first_2_no-op_refreshes_in_thumb_cap.patch
feat_enable_customizing_symbol_color_in_framecaptionbutton.patch
@@ -0,0 +1,137 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Shelley Vohr <shelley.vohr@gmail.com>
Date: Fri, 5 Apr 2024 11:07:22 +0200
Subject: feat: enable customizing symbol color in FrameCaptionButton

This enables customizing the symbol color on a given FrameCaptionButton
for the Window Controls Overlay API on Linux. By default, the symbol color
is dynamically calculated based on the background color of the button to
ensure it has minimum contrast required to be accessible.

This should be upstreamed to Chromium if possible.

diff --git a/ui/views/window/frame_caption_button.cc b/ui/views/window/frame_caption_button.cc
index 73e6020e3b9b6e0d12a8dea991f189b3ddeab14c..52c273b3dee06bf996bbc997e3c8ca266c1994ba 100644
--- a/ui/views/window/frame_caption_button.cc
+++ b/ui/views/window/frame_caption_button.cc
@@ -108,6 +108,10 @@ FrameCaptionButton::~FrameCaptionButton() = default;

// static
SkColor FrameCaptionButton::GetButtonColor(SkColor background_color) {
+ // If the button color has been overridden, return that.
+ if (button_color_ != SkColor())
+ return button_color_;
+
// Use IsDark() to change target colors instead of PickContrastingColor(), so
// that DefaultFrameHeader::GetTitleColor() (which uses different target
// colors) can change between light/dark targets at the same time. It looks
@@ -124,6 +128,11 @@ SkColor FrameCaptionButton::GetButtonColor(SkColor background_color) {
.color;
}

+// static
+SkColor FrameCaptionButton::SetButtonColor(SkColor button_color) {
+ button_color_ = button_color;
+}
+
// static
float FrameCaptionButton::GetInactiveButtonColorAlphaRatio() {
return 0.38f;
@@ -135,10 +144,10 @@ void FrameCaptionButton::SetImage(CaptionButtonIcon icon,
// If the button is not yet in a widget, OnThemeChanged() will call back
// here once it is, updating the color as needed.
SkColor icon_color = gfx::kPlaceholderColor;
- if (absl::holds_alternative<SkColor>(color_)) {
- icon_color = GetButtonColor(absl::get<SkColor>(color_));
+ if (absl::holds_alternative<SkColor>(background_color_)) {
+ icon_color = GetButtonColor(absl::get<SkColor>(background_color_));
} else if (const auto* color_provider = GetColorProvider()) {
- icon_color = color_provider->GetColor(absl::get<ui::ColorId>(color_));
+ icon_color = color_provider->GetColor(absl::get<ui::ColorId>(background_color_));
}

gfx::ImageSkia new_icon_image =
@@ -213,27 +222,27 @@ views::PaintInfo::ScaleType FrameCaptionButton::GetPaintScaleType() const {
}

void FrameCaptionButton::SetBackgroundColor(SkColor background_color) {
- if (absl::holds_alternative<SkColor>(color_) &&
- absl::get<SkColor>(color_) == background_color) {
+ if (absl::holds_alternative<SkColor>(background_color_) &&
+ absl::get<SkColor>(background_color_) == background_color) {
return;
}

- color_ = background_color;
+ background_color_ = background_color;
MaybeRefreshIconAndInkdropBaseColor();
}

void FrameCaptionButton::SetIconColorId(ui::ColorId icon_color_id) {
- if (absl::holds_alternative<ui::ColorId>(color_) &&
- absl::get<ui::ColorId>(color_) == icon_color_id) {
+ if (absl::holds_alternative<ui::ColorId>(background_color_) &&
+ absl::get<ui::ColorId>(background_color_) == icon_color_id) {
return;
}

- color_ = icon_color_id;
+ background_color_ = icon_color_id;
MaybeRefreshIconAndInkdropBaseColor();
}

SkColor FrameCaptionButton::GetBackgroundColor() const {
- return absl::get<SkColor>(color_);
+ return absl::get<SkColor>(background_color_);
}

void FrameCaptionButton::SetInkDropCornerRadius(int ink_drop_corner_radius) {
@@ -250,7 +259,7 @@ int FrameCaptionButton::GetInkDropCornerRadius() const {
base::CallbackListSubscription
FrameCaptionButton::AddBackgroundColorChangedCallback(
PropertyChangedCallback callback) {
- return AddPropertyChangedCallback(&color_, callback);
+ return AddPropertyChangedCallback(&background_color_, callback);
}

void FrameCaptionButton::SetPaintAsActive(bool paint_as_active) {
@@ -394,9 +403,9 @@ void FrameCaptionButton::UpdateInkDropBaseColor() {
// TODO(pkasting): It would likely be better to make the button glyph always
// be an alpha-blended version of GetColorWithMaxContrast(background_color_).
const SkColor button_color =
- absl::holds_alternative<ui::ColorId>(color_)
- ? GetColorProvider()->GetColor(absl::get<ui::ColorId>(color_))
- : GetButtonColor(absl::get<SkColor>(color_));
+ absl::holds_alternative<ui::ColorId>(background_color_)
+ ? GetColorProvider()->GetColor(absl::get<ui::ColorId>(background_color_))
+ : GetButtonColor(absl::get<SkColor>(background_color_));

InkDrop::Get(this)->SetBaseColor(
GetColorWithMaxContrast(GetColorWithMaxContrast(button_color)));
diff --git a/ui/views/window/frame_caption_button.h b/ui/views/window/frame_caption_button.h
index 0d20ec5891d08187b4dae7a6b46a9a6de2f7c39c..a7db2a33319cd60d8017d1e617c963781d8d0243 100644
--- a/ui/views/window/frame_caption_button.h
+++ b/ui/views/window/frame_caption_button.h
@@ -46,6 +46,12 @@ class VIEWS_EXPORT FrameCaptionButton : public Button {
// Gets the color to use for a frame caption button.
static SkColor GetButtonColor(SkColor background_color);

+ // Sets the color to use for a frame caption button.
+ // The color is by default calculated to be an accessible contrast
+ // to the background color, so you should keep that in mind when
+ // overriding that behavior.
+ static SkColor SetButtonColor(SkColor button_color);
+
// Gets the alpha ratio for the colors of inactive frame caption buttons.
static float GetInactiveButtonColorAlphaRatio();

@@ -132,7 +138,8 @@ class VIEWS_EXPORT FrameCaptionButton : public Button {
// id.
// TODO(b/292154873): Store the foreground color instead of the background
// color for the SkColor type.
- absl::variant<ui::ColorId, SkColor> color_ = gfx::kPlaceholderColor;
+ absl::variant<ui::ColorId, SkColor> background_color_ = gfx::kPlaceholderColor;
+ SkColor button_color_ = SkColor();

// Whether the button should be painted as active.
bool paint_as_active_ = false;
6 changes: 4 additions & 2 deletions shell/browser/ui/views/opaque_frame_view.cc
Expand Up @@ -205,9 +205,10 @@ void OpaqueFrameView::OnPaint(gfx::Canvas* canvas) {
return;

const bool active = ShouldPaintAsActive();
const SkColor symbol_color = window()->overlay_button_color();
const SkColor symbol_color = window()->overlay_symbol_color();
const SkColor background_color = window()->overlay_button_color();
SkColor frame_color =
symbol_color == SkColor() ? GetFrameColor() : symbol_color;
background_color == SkColor() ? GetFrameColor() : background_color;

for (views::Button* button :
{minimize_button_, maximize_button_, restore_button_, close_button_}) {
Expand All @@ -217,6 +218,7 @@ void OpaqueFrameView::OnPaint(gfx::Canvas* canvas) {
static_cast<views::FrameCaptionButton*>(button);
frame_caption_button->SetPaintAsActive(active);
frame_caption_button->SetBackgroundColor(frame_color);
frame_caption_button->SetButtonColor(symbol_color);
}
}

Expand Down

0 comments on commit 852dcea

Please sign in to comment.