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 f70d810e5c316a0dfee0b12a0972679f5f56b22b..5a5b2b3e1a70c7365a4d6deb90c183f8392c8c9f 100644
--- a/ui/views/window/frame_caption_button.cc
+++ b/ui/views/window/frame_caption_button.cc
@@ -108,7 +108,7 @@ FrameCaptionButton::FrameCaptionButton(PressedCallback callback,
 FrameCaptionButton::~FrameCaptionButton() = default;
 
 // static
-SkColor FrameCaptionButton::GetButtonColor(SkColor background_color) {
+SkColor FrameCaptionButton::GetAccessibleButtonColor(SkColor background_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
@@ -125,6 +125,22 @@ SkColor FrameCaptionButton::GetButtonColor(SkColor background_color) {
       .color;
 }
 
+SkColor FrameCaptionButton::GetButtonColor(SkColor background_color) {
+  // If the button color has been overridden, return that.
+  if (button_color_ != SkColor())
+    return button_color_;
+
+  return GetAccessibleButtonColor(background_color);
+}
+
+void FrameCaptionButton::SetButtonColor(SkColor button_color) {
+  if (button_color_ == button_color)
+    return;
+
+  button_color_ = button_color;
+  MaybeRefreshIconAndInkdropBaseColor();
+}
+
 // static
 float FrameCaptionButton::GetInactiveButtonColorAlphaRatio() {
   return 0.38f;
diff --git a/ui/views/window/frame_caption_button.h b/ui/views/window/frame_caption_button.h
index e74917399d3306e6557069d85fe90d153cecf585..738965e15ea4a5c3d71a5bf79ea0df78dac9cd73 100644
--- a/ui/views/window/frame_caption_button.h
+++ b/ui/views/window/frame_caption_button.h
@@ -45,8 +45,18 @@ class VIEWS_EXPORT FrameCaptionButton : public Button {
   FrameCaptionButton& operator=(const FrameCaptionButton&) = delete;
   ~FrameCaptionButton() override;
 
+  // Gets the color to use for a frame caption button with accessible contrast
+  // to the given background color.
+  static SkColor GetAccessibleButtonColor(SkColor background_color);
+
   // Gets the color to use for a frame caption button.
-  static SkColor GetButtonColor(SkColor background_color);
+  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.
+  void SetButtonColor(SkColor button_color);
 
   // Gets the alpha ratio for the colors of inactive frame caption buttons.
   static float GetInactiveButtonColorAlphaRatio();
@@ -135,6 +145,7 @@ class VIEWS_EXPORT FrameCaptionButton : public Button {
   // TODO(b/292154873): Store the foreground color instead of the background
   // color for the SkColor type.
   std::variant<ui::ColorId, SkColor> color_ = gfx::kPlaceholderColor;
+  SkColor button_color_ = SkColor();
 
   // Whether the button should be painted as active.
   bool paint_as_active_ = false;
