fix: default to system accent color on invalid user color (#47800)

fix: default to system accent color on invalid user color"
This commit is contained in:
Shelley Vohr 2025-07-31 11:10:24 +02:00 committed by GitHub
commit e17cbc96e2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 38 additions and 41 deletions

View file

@ -656,7 +656,7 @@ bool BaseWindow::IsTabletMode() const {
} }
void BaseWindow::SetBackgroundColor(const std::string& color_name) { void BaseWindow::SetBackgroundColor(const std::string& color_name) {
SkColor color = ParseCSSColor(color_name); SkColor color = ParseCSSColor(color_name).value_or(SK_ColorWHITE);
window_->SetBackgroundColor(color); window_->SetBackgroundColor(color);
} }

View file

@ -234,7 +234,7 @@ void BrowserWindow::Blur() {
void BrowserWindow::SetBackgroundColor(const std::string& color_name) { void BrowserWindow::SetBackgroundColor(const std::string& color_name) {
BaseWindow::SetBackgroundColor(color_name); BaseWindow::SetBackgroundColor(color_name);
SkColor color = ParseCSSColor(color_name); SkColor color = ParseCSSColor(color_name).value_or(SK_ColorWHITE);
if (api_web_contents_) { if (api_web_contents_) {
api_web_contents_->SetBackgroundColor(color); api_web_contents_->SetBackgroundColor(color);
// Also update the web preferences object otherwise the view will be reset // Also update the web preferences object otherwise the view will be reset
@ -242,7 +242,7 @@ void BrowserWindow::SetBackgroundColor(const std::string& color_name) {
auto* web_preferences = auto* web_preferences =
WebContentsPreferences::From(api_web_contents_->web_contents()); WebContentsPreferences::From(api_web_contents_->web_contents());
if (web_preferences) { if (web_preferences) {
web_preferences->SetBackgroundColor(ParseCSSColor(color_name)); web_preferences->SetBackgroundColor(color);
} }
} }
} }

View file

@ -864,9 +864,10 @@ WebContents::WebContents(v8::Isolate* isolate,
// webPreferences does not have a transparent option, so if the window needs // webPreferences does not have a transparent option, so if the window needs
// to be transparent, that will be set at electron_api_browser_window.cc#L57 // to be transparent, that will be set at electron_api_browser_window.cc#L57
// and we then need to pull it back out and check it here. // and we then need to pull it back out and check it here.
std::string background_color; std::string background_color_str;
options.GetHidden(options::kBackgroundColor, &background_color); options.GetHidden(options::kBackgroundColor, &background_color_str);
bool transparent = ParseCSSColor(background_color) == SK_ColorTRANSPARENT; SkColor bc = ParseCSSColor(background_color_str).value_or(SK_ColorWHITE);
bool transparent = bc == SK_ColorTRANSPARENT;
content::WebContents::CreateParams params(session->browser_context()); content::WebContents::CreateParams params(session->browser_context());
auto* view = new OffScreenWebContentsView( auto* view = new OffScreenWebContentsView(

View file

@ -233,7 +233,7 @@ void NativeWindow::InitFromOptions(const gin_helper::Dictionary& options) {
SkColor background_color = SK_ColorWHITE; SkColor background_color = SK_ColorWHITE;
if (std::string color; options.Get(options::kBackgroundColor, &color)) { if (std::string color; options.Get(options::kBackgroundColor, &color)) {
background_color = ParseCSSColor(color); background_color = ParseCSSColor(color).value_or(SK_ColorWHITE);
} else if (IsTranslucent()) { } else if (IsTranslucent()) {
background_color = SK_ColorTRANSPARENT; background_color = SK_ColorTRANSPARENT;
} }

View file

@ -216,7 +216,9 @@ NativeWindowViews::NativeWindowViews(const gin_helper::Dictionary& options,
overlay_symbol_color_ = color_utils::GetSysSkColor(COLOR_BTNTEXT); overlay_symbol_color_ = color_utils::GetSysSkColor(COLOR_BTNTEXT);
if (std::string str; options.Get(options::kAccentColor, &str)) { if (std::string str; options.Get(options::kAccentColor, &str)) {
accent_color_ = ParseCSSColor(str); std::optional<SkColor> parsed_color = ParseCSSColor(str);
if (parsed_color.has_value())
accent_color_ = parsed_color.value();
} else if (bool flag; options.Get(options::kAccentColor, &flag)) { } else if (bool flag; options.Get(options::kAccentColor, &flag)) {
accent_color_ = flag; accent_color_ = flag;
} }

View file

@ -574,43 +574,36 @@ void NativeWindowViews::UpdateWindowAccentColor() {
if (base::win::GetVersion() < base::win::Version::WIN11) if (base::win::GetVersion() < base::win::Version::WIN11)
return; return;
COLORREF border_color; std::optional<COLORREF> border_color;
bool should_apply_accent = false; bool should_apply_accent = false;
if (std::holds_alternative<bool>(accent_color_)) { if (std::holds_alternative<SkColor>(accent_color_)) {
bool force_accent = std::get<bool>(accent_color_); // If the user has explicitly set an accent color, use it
if (!force_accent) { // regardless of whether the system accent color is enabled.
should_apply_accent = false;
} else {
std::optional<DWORD> accent_color = GetAccentColor();
if (accent_color.has_value()) {
border_color = RGB(GetRValue(accent_color.value()),
GetGValue(accent_color.value()),
GetBValue(accent_color.value()));
should_apply_accent = true;
}
}
} else if (std::holds_alternative<SkColor>(accent_color_)) {
SkColor color = std::get<SkColor>(accent_color_); SkColor color = std::get<SkColor>(accent_color_);
border_color = border_color =
RGB(SkColorGetR(color), SkColorGetG(color), SkColorGetB(color)); RGB(SkColorGetR(color), SkColorGetG(color), SkColorGetB(color));
should_apply_accent = true; should_apply_accent = true;
} else if (std::holds_alternative<bool>(accent_color_)) {
// Allow the user to optionally force system color on/off.
should_apply_accent = std::get<bool>(accent_color_);
} else if (std::holds_alternative<std::monostate>(accent_color_)) { } else if (std::holds_alternative<std::monostate>(accent_color_)) {
if (IsAccentColorOnTitleBarsEnabled()) { // If no explicit color was set, default to the system accent color.
std::optional<DWORD> accent_color = GetAccentColor(); should_apply_accent = IsAccentColorOnTitleBarsEnabled();
if (accent_color.has_value()) { }
border_color = RGB(GetRValue(accent_color.value()),
GetGValue(accent_color.value()), // Use system accent color as fallback if no explicit color was set.
GetBValue(accent_color.value())); if (!border_color.has_value() && should_apply_accent) {
should_apply_accent = true; std::optional<DWORD> system_accent_color = GetAccentColor();
} if (system_accent_color.has_value()) {
border_color = RGB(GetRValue(system_accent_color.value()),
GetGValue(system_accent_color.value()),
GetBValue(system_accent_color.value()));
} }
} }
// Reset to default system colors when accent color should not be applied. COLORREF final_color = border_color.value_or(DWMWA_COLOR_DEFAULT);
if (!should_apply_accent) SetWindowBorderAndCaptionColor(GetAcceleratedWidget(), final_color);
border_color = DWMWA_COLOR_DEFAULT;
SetWindowBorderAndCaptionColor(GetAcceleratedWidget(), border_color);
} }
void NativeWindowViews::ResetWindowControls() { void NativeWindowViews::ResetWindowControls() {

View file

@ -338,7 +338,7 @@ static NSString* const ImageScrubberItemIdentifier = @"scrubber.image.item";
} }
- (NSColor*)colorFromHexColorString:(const std::string&)colorString { - (NSColor*)colorFromHexColorString:(const std::string&)colorString {
SkColor color = electron::ParseCSSColor(colorString); SkColor color = electron::ParseCSSColor(colorString).value_or(SK_ColorWHITE);
return skia::SkColorToDeviceNSColor(color); return skia::SkColorToDeviceNSColor(color);
} }

View file

@ -215,7 +215,7 @@ void WebContentsPreferences::SetFromDictionary(
} }
std::string background_color; std::string background_color;
if (web_preferences.GetHidden(options::kBackgroundColor, &background_color)) if (web_preferences.GetHidden(options::kBackgroundColor, &background_color))
background_color_ = ParseCSSColor(background_color); background_color_ = ParseCSSColor(background_color).value_or(SK_ColorWHITE);
std::string safe_dialogs_message; std::string safe_dialogs_message;
if (web_preferences.Get("safeDialogsMessage", &safe_dialogs_message)) if (web_preferences.Get("safeDialogsMessage", &safe_dialogs_message))
safe_dialogs_message_ = safe_dialogs_message; safe_dialogs_message_ = safe_dialogs_message;

View file

@ -28,7 +28,7 @@ bool IsHexFormatWithAlpha(const std::string& str) {
namespace electron { namespace electron {
SkColor ParseCSSColor(const std::string& color_string) { std::optional<SkColor> ParseCSSColor(const std::string& color_string) {
// ParseCssColorString expects RGBA and we historically use ARGB // ParseCssColorString expects RGBA and we historically use ARGB
// so we need to convert before passing to ParseCssColorString. // so we need to convert before passing to ParseCssColorString.
std::string converted_color_str; std::string converted_color_str;
@ -42,7 +42,7 @@ SkColor ParseCSSColor(const std::string& color_string) {
SkColor color; SkColor color;
if (!content::ParseCssColorString(converted_color_str, &color)) if (!content::ParseCssColorString(converted_color_str, &color))
color = SK_ColorWHITE; return std::nullopt;
return color; return color;
} }

View file

@ -5,6 +5,7 @@
#ifndef ELECTRON_SHELL_COMMON_COLOR_UTIL_H_ #ifndef ELECTRON_SHELL_COMMON_COLOR_UTIL_H_
#define ELECTRON_SHELL_COMMON_COLOR_UTIL_H_ #define ELECTRON_SHELL_COMMON_COLOR_UTIL_H_
#include <optional>
#include <string> #include <string>
#include "third_party/skia/include/core/SkColor.h" #include "third_party/skia/include/core/SkColor.h"
@ -22,7 +23,7 @@ namespace electron {
// Parses a CSS-style color string from hex, rgb(), rgba(), // Parses a CSS-style color string from hex, rgb(), rgba(),
// hsl(), hsla(), or color name formats. // hsl(), hsla(), or color name formats.
SkColor ParseCSSColor(const std::string& color_string); std::optional<SkColor> ParseCSSColor(const std::string& color_string);
// Convert color to RGB hex value like "#RRGGBB". // Convert color to RGB hex value like "#RRGGBB".
std::string ToRGBHex(SkColor color); std::string ToRGBHex(SkColor color);

View file

@ -226,7 +226,7 @@ bool Converter<WrappedSkColor>::FromV8(v8::Isolate* isolate,
std::string str; std::string str;
if (!gin::ConvertFromV8(isolate, val, &str)) if (!gin::ConvertFromV8(isolate, val, &str))
return false; return false;
*out = electron::ParseCSSColor(str); *out = electron::ParseCSSColor(str).value_or(SK_ColorWHITE);
return true; return true;
} }