| // Copyright 2021 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "ui/gtk/gtk_color_mixers.h" |
| |
| #include "base/strings/strcat.h" |
| #include "third_party/skia/include/core/SkColor.h" |
| #include "ui/color/color_id.h" |
| #include "ui/color/color_mixer.h" |
| #include "ui/color/color_provider.h" |
| #include "ui/color/color_recipe.h" |
| #include "ui/color/color_transform.h" |
| #include "ui/gfx/color_palette.h" |
| #include "ui/gtk/gtk_util.h" |
| |
| namespace gtk { |
| |
| void AddGtkNativeColorMixer(ui::ColorProvider* provider, |
| const ui::ColorProviderManager::Key& key) { |
| if (key.system_theme == ui::ColorProviderManager::SystemTheme::kDefault) |
| return; |
| |
| ui::ColorMixer& mixer = provider->AddMixer(); |
| |
| const std::string header_selector = |
| key.frame_type == ui::ColorProviderManager::FrameType::kChromium |
| ? "#headerbar.header-bar.titlebar" |
| : "GtkMenuBar#menubar"; |
| const std::string header_selector_inactive = header_selector + ":backdrop"; |
| const auto tooltip_context = AppendCssNodeToStyleContext( |
| {}, GtkCheckVersion(3, 20) ? "#tooltip.background" |
| : "GtkWindow#window.background.tooltip"); |
| |
| const SkColor primary_bg = GetBgColor(""); |
| const SkColor button_bg_disabled = |
| GetBgColor("GtkButton#button.text-button:disabled"); |
| const SkColor button_border = GetBorderColor("GtkButton#button"); |
| const SkColor frame_color = |
| SkColorSetA(GetBgColor(header_selector), SK_AlphaOPAQUE); |
| const SkColor frame_color_inactive = |
| SkColorSetA(GetBgColor(header_selector_inactive), SK_AlphaOPAQUE); |
| const SkColor label_fg = GetFgColor("GtkLabel#label"); |
| const SkColor label_fg_disabled = GetFgColor("GtkLabel#label:disabled"); |
| const SkColor entry_border = GetBorderColor("GtkEntry#entry"); |
| const SkColor toolbar_color = |
| color_utils::GetResultingPaintColor(primary_bg, frame_color); |
| const SkColor accent = GetFgColor( |
| "GtkTreeView#treeview.view " |
| "GtkTreeView#treeview.view.cell:selected:focus GtkLabel#label"); |
| |
| // Core colors |
| mixer[ui::kColorAccent] = { |
| GetBgColor("GtkTreeView#treeview.view " |
| "GtkTreeView#treeview.view.cell:selected:focus")}; |
| mixer[ui::kColorAlertHighSeverity] = {SelectBasedOnDarkInput( |
| ui::kColorPrimaryBackground, gfx::kGoogleRed300, gfx::kGoogleRed600)}; |
| mixer[ui::kColorAlertLowSeverity] = {SelectBasedOnDarkInput( |
| ui::kColorPrimaryBackground, gfx::kGoogleGreen300, gfx::kGoogleGreen700)}; |
| mixer[ui::kColorAlertMediumSeverity] = { |
| SelectBasedOnDarkInput(ui::kColorPrimaryBackground, gfx::kGoogleYellow300, |
| gfx::kGoogleYellow700)}; |
| mixer[ui::kColorDisabledForeground] = {label_fg_disabled}; |
| mixer[ui::kColorItemHighlight] = {GetBorderColor("GtkEntry#entry:focus")}; |
| mixer[ui::kColorItemSelectionBackground] = {ui::kColorAccent}; |
| mixer[ui::kColorMenuSelectionBackground] = {GetBgColor( |
| base::StrCat({GtkCssMenu(), " ", GtkCssMenuItem(), ":hover"}))}; |
| mixer[ui::kColorMidground] = { |
| GetSeparatorColor("GtkSeparator#separator.horizontal")}; |
| mixer[ui::kColorPrimaryBackground] = {primary_bg}; |
| mixer[ui::kColorPrimaryForeground] = {label_fg}; |
| mixer[ui::kColorSecondaryForeground] = {label_fg_disabled}; |
| mixer[ui::kColorTextSelectionBackground] = { |
| GetSelectionBgColor(GtkCheckVersion(3, 20) ? "GtkLabel#label #selection" |
| : "GtkLabel#label:selected")}; |
| mixer[ui::kColorTextSelectionForeground] = { |
| GetFgColor(GtkCheckVersion(3, 20) ? "GtkLabel#label #selection" |
| : "GtkLabel#label:selected")}; |
| |
| // UI element colors |
| mixer[ui::kColorAvatarHeaderArt] = |
| AlphaBlend(ui::kColorPrimaryForeground, ui::kColorPrimaryBackground, |
| gfx::kGoogleGreyAlpha300); |
| mixer[ui::kColorAvatarIconGuest] = |
| DeriveDefaultIconColor(ui::kColorPrimaryForeground); |
| mixer[ui::kColorButtonBackground] = {GetBgColor("GtkButton#button")}; |
| mixer[ui::kColorButtonBackgroundProminentDisabled] = {button_bg_disabled}; |
| mixer[ui::kColorButtonBorder] = {button_border}; |
| mixer[ui::kColorButtonBorderDisabled] = {button_bg_disabled}; |
| mixer[ui::kColorButtonForeground] = { |
| GetFgColor("GtkButton#button.text-button GtkLabel#label")}; |
| mixer[ui::kColorButtonForegroundChecked] = {ui::kColorAccent}; |
| mixer[ui::kColorButtonForegroundDisabled] = { |
| GetFgColor("GtkButton#button.text-button:disabled GtkLabel#label")}; |
| mixer[ui::kColorButtonForegroundProminent] = {accent}; |
| mixer[ui::kColorButtonForegroundUnchecked] = {ui::kColorButtonForeground}; |
| mixer[ui::kColorDialogForeground] = {ui::kColorPrimaryForeground}; |
| mixer[ui::kColorDropdownBackground] = {GetBgColor(base::StrCat( |
| {"GtkComboBoxText#combobox GtkWindow#window.background.popup ", |
| "GtkTreeMenu#menu(gtk-combobox-popup-menu) ", GtkCssMenuItem(), " ", |
| "GtkCellView#cellview"}))}; |
| mixer[ui::kColorDropdownBackgroundSelected] = {GetBgColor(base::StrCat( |
| {"GtkComboBoxText#combobox GtkWindow#window.background.popup ", |
| "GtkTreeMenu#menu(gtk-combobox-popup-menu) ", GtkCssMenuItem(), |
| ":hover GtkCellView#cellview"}))}; |
| mixer[ui::kColorDropdownForeground] = {GetFgColor(base::StrCat( |
| {"GtkComboBoxText#combobox GtkWindow#window.background.popup ", |
| "GtkTreeMenu#menu(gtk-combobox-popup-menu) ", GtkCssMenuItem(), " ", |
| "GtkCellView#cellview"}))}; |
| mixer[ui::kColorDropdownForegroundSelected] = {GetFgColor(base::StrCat( |
| {"GtkComboBoxText#combobox GtkWindow#window.background.popup ", |
| "GtkTreeMenu#menu(gtk-combobox-popup-menu) ", GtkCssMenuItem(), |
| ":hover GtkCellView#cellview"}))}; |
| mixer[ui::kColorFrameActive] = {frame_color}; |
| mixer[ui::kColorFrameInactive] = {frame_color_inactive}; |
| mixer[ui::kColorFocusableBorderUnfocused] = {entry_border}; |
| mixer[ui::kColorHelpIconActive] = { |
| GetFgColor("GtkButton#button.image-button:hover")}; |
| mixer[ui::kColorIcon] = { |
| GetFgColor("GtkButton#button.flat.scale GtkImage#image")}; |
| mixer[ui::kColorHelpIconInactive] = { |
| GetFgColor("GtkButton#button.image-button")}; |
| if (GtkCheckVersion(3, 12)) { |
| mixer[ui::kColorLinkForeground] = {GetFgColor("GtkLabel#label.link:link")}; |
| mixer[ui::kColorLinkForegroundDisabled] = { |
| GetFgColor("GtkLabel#label.link:link:disabled")}; |
| mixer[ui::kColorLinkForegroundPressed] = { |
| GetFgColor("GtkLabel#label.link:link:hover:active")}; |
| } else { |
| auto link_context = GetStyleContextFromCss("GtkLabel#label.view"); |
| GdkColor* gdk_color = nullptr; |
| GtkStyleContextGetStyle(link_context, "link-color", &gdk_color, nullptr); |
| SkColor color = SkColorSetRGB(0x00, 0x00, 0xEE); // From gtklinkbutton.c. |
| if (gdk_color) { |
| color = SkColorSetRGB(gdk_color->red >> 8, gdk_color->green >> 8, |
| gdk_color->blue >> 8); |
| // gdk_color_free() was deprecated in Gtk3.14. This code path is only |
| // taken on versions earlier than Gtk3.12, but the compiler doesn't know |
| // that, so silence the deprecation warnings. |
| G_GNUC_BEGIN_IGNORE_DEPRECATIONS; |
| gdk_color_free(gdk_color); |
| G_GNUC_END_IGNORE_DEPRECATIONS; |
| } |
| mixer[ui::kColorLinkForeground] = {color}; |
| mixer[ui::kColorLinkForegroundDisabled] = {color}; |
| mixer[ui::kColorLinkForegroundPressed] = {color}; |
| } |
| mixer[ui::kColorMenuBackground] = {GetBgColor(GtkCssMenu())}; |
| mixer[ui::kColorMenuBorder] = {GetBorderColor(GtkCssMenu())}; |
| mixer[ui::kColorMenuDropmarker] = {ui::kColorMenuItemForeground}; |
| mixer[ui::kColorMenuIcon] = {GetFgColor( |
| base::StrCat({GtkCssMenu(), " ", GtkCssMenuItem(), |
| GtkCheckVersion(3, 20) ? " #radio" : ".radio"}))}; |
| mixer[ui::kColorMenuItemBackgroundHighlighted] = {ui::kColorMenuBackground}; |
| mixer[ui::kColorMenuItemForeground] = {GetFgColor( |
| base::StrCat({GtkCssMenu(), " ", GtkCssMenuItem(), " GtkLabel#label"}))}; |
| mixer[ui::kColorMenuItemForegroundHighlighted] = { |
| ui::kColorMenuItemForeground}; |
| mixer[ui::kColorMenuItemForegroundDisabled] = {GetFgColor(base::StrCat( |
| {GtkCssMenu(), " ", GtkCssMenuItem(), ":disabled GtkLabel#label"}))}; |
| mixer[ui::kColorMenuItemForegroundSecondary] = {GetFgColor( |
| base::StrCat({GtkCssMenu(), " ", GtkCssMenuItem(), |
| GtkCheckVersion(3, 20) ? " #accelerator" |
| : " GtkLabel#label.accelerator"}))}; |
| mixer[ui::kColorMenuItemForegroundSelected] = {GetFgColor(base::StrCat( |
| {GtkCssMenu(), " ", GtkCssMenuItem(), ":hover GtkLabel#label"}))}; |
| mixer[ui::kColorMenuSeparator] = {GetSeparatorColor( |
| GtkCheckVersion(3, 20) |
| ? base::StrCat({GtkCssMenu(), " GtkSeparator#separator.horizontal"}) |
| : base::StrCat({GtkCssMenu(), " ", GtkCssMenuItem(), ".separator"}))}; |
| mixer[ui::kColorNotificationInputForeground] = {accent}; |
| mixer[ui::kColorOverlayScrollbarFill] = { |
| GetBgColor("#GtkScrollbar#scrollbar #slider")}; |
| mixer[ui::kColorOverlayScrollbarFillHovered] = { |
| GetBgColor("#GtkScrollbar#scrollbar #slider:hover")}; |
| mixer[ui::kColorOverlayScrollbarStroke] = { |
| GetBgColor("#GtkScrollbar#scrollbar #trough")}; |
| mixer[ui::kColorOverlayScrollbarStrokeHovered] = { |
| GetBgColor("#GtkScrollbar#scrollbar #trough:hover")}; |
| mixer[ui::kColorSliderThumb] = {GetBgColor("GtkScale#scale #highlight")}; |
| mixer[ui::kColorSliderThumbMinimal] = { |
| GetBgColor("GtkScale#scale:disabled #highlight")}; |
| mixer[ui::kColorSliderTrack] = {GetBgColor("GtkScale#scale #trough")}; |
| mixer[ui::kColorSliderTrackMinimal] = { |
| GetBgColor("GtkScale#scale:disabled #trough")}; |
| mixer[ui::kColorSyncInfoBackground] = {GetBgColor("#statusbar")}; |
| mixer[ui::kColorTabBackgroundHighlighted] = { |
| GetBgColor("GtkNotebook#notebook #tab:checked")}; |
| mixer[ui::kColorTabBackgroundHighlightedFocused] = { |
| GetBgColor("GtkNotebook#notebook:focus #tab:checked")}; |
| mixer[ui::kColorTabContentSeparator] = {GetBorderColor( |
| GtkCheckVersion(3, 20) ? "GtkFrame#frame #border" : "GtkFrame#frame")}; |
| mixer[ui::kColorTabForegroundSelected] = {ui::kColorPrimaryForeground}; |
| mixer[ui::kColorTableBackground] = {ui::kColorTreeBackground}; |
| mixer[ui::kColorTableBackgroundAlternate] = {ui::kColorTreeBackground}; |
| mixer[ui::kColorTableBackgroundSelectedUnfocused] = { |
| ui::kColorTreeNodeBackgroundSelectedUnfocused}; |
| mixer[ui::kColorTableForeground] = {ui::kColorTreeNodeForeground}; |
| mixer[ui::kColorTableForegroundSelectedFocused] = { |
| ui::kColorTreeNodeForegroundSelectedFocused}; |
| mixer[ui::kColorTableForegroundSelectedUnfocused] = { |
| ui::kColorTreeNodeForegroundSelectedUnfocused}; |
| mixer[ui::kColorTableGroupingIndicator] = {ui::kColorTableForeground}; |
| mixer[ui::kColorTableHeaderBackground] = { |
| GetBgColor("GtkTreeView#treeview.view GtkButton#button")}; |
| mixer[ui::kColorTableHeaderForeground] = { |
| GetFgColor("GtkTreeView#treeview.view GtkButton#button GtkLabel#label")}; |
| mixer[ui::kColorTableHeaderSeparator] = { |
| GetBorderColor("GtkTreeView#treeview.view GtkButton#button")}; |
| mixer[ui::kColorTextfieldBackground] = { |
| GetBgColor(GtkCheckVersion(3, 20) ? "GtkTextView#textview.view" |
| : "GtkTextView.view")}; |
| mixer[ui::kColorTextfieldBackgroundDisabled] = { |
| GetBgColor(GtkCheckVersion(3, 20) ? "GtkTextView#textview.view:disabled" |
| : "GtkTextView.view:disabled")}; |
| mixer[ui::kColorTextfieldForeground] = { |
| GetFgColor(GtkCheckVersion(3, 20) ? "GtkTextView#textview.view #text" |
| : "GtkTextView.view")}; |
| mixer[ui::kColorTextfieldForegroundDisabled] = {GetFgColor( |
| GtkCheckVersion(3, 20) ? "GtkTextView#textview.view:disabled #text" |
| : "GtkTextView.view:disabled")}; |
| mixer[ui::kColorTextfieldForegroundPlaceholder] = {GtkCheckVersion(4)}; |
| mixer[ui::kColorTextfieldSelectionBackground] = {GetSelectionBgColor( |
| GtkCheckVersion(3, 20) ? "GtkTextView#textview.view #text #selection" |
| : "GtkTextView.view:selected")}; |
| mixer[ui::kColorTextfieldSelectionForeground] = {GetFgColor( |
| GtkCheckVersion(3, 20) ? "GtkTextView#textview.view #text #selection" |
| : "GtkTextView.view:selected")}; |
| mixer[ui::kColorThrobber] = {GetFgColor("GtkSpinner#spinner")}; |
| mixer[ui::kColorThrobberPreconnect] = { |
| GetFgColor("GtkSpinner#spinner:disabled")}; |
| mixer[ui::kColorToggleButtonTrackOff] = { |
| GetBgColor("GtkButton#button.text-button.toggle")}; |
| mixer[ui::kColorToggleButtonTrackOn] = { |
| GetBgColor("GtkButton#button.text-button.toggle:checked")}; |
| mixer[ui::kColorTooltipBackground] = { |
| GetBgColorFromStyleContext(tooltip_context)}; |
| mixer[ui::kColorTooltipForeground] = {GtkStyleContextGetColor( |
| AppendCssNodeToStyleContext(tooltip_context, "GtkLabel#label"))}; |
| mixer[ui::kColorTreeBackground] = { |
| GetBgColor("GtkTreeView#treeview.view GtkTreeView#treeview.view.cell")}; |
| mixer[ui::kColorTreeNodeForeground] = { |
| GetFgColor("GtkTreeView#treeview.view GtkTreeView#treeview.view.cell " |
| "GtkLabel#label")}; |
| mixer[ui::kColorTreeNodeForegroundSelectedFocused] = {accent}; |
| mixer[ui::kColorTreeNodeBackgroundSelectedUnfocused] = { |
| GetBgColor("GtkTreeView#treeview.view " |
| "GtkTreeView#treeview.view.cell:selected")}; |
| mixer[ui::kColorTreeNodeForegroundSelectedUnfocused] = { |
| GetFgColor("GtkTreeView#treeview.view " |
| "GtkTreeView#treeview.view.cell:selected GtkLabel#label")}; |
| |
| // Platform-specific UI elements |
| mixer[ui::kColorNativeHeaderButtonBorderActive] = { |
| GetBorderColor(header_selector + " GtkButton#button")}; |
| mixer[ui::kColorNativeHeaderButtonBorderInactive] = { |
| GetBorderColor(header_selector + ":backdrop GtkButton#button")}; |
| mixer[ui::kColorNativeHeaderSeparatorBorderActive] = {GetBorderColor( |
| header_selector + " GtkSeparator#separator.vertical.titlebutton")}; |
| mixer[ui::kColorNativeHeaderSeparatorBorderInactive] = { |
| GetBorderColor(header_selector + |
| ":backdrop GtkSeparator#separator.vertical.titlebutton")}; |
| mixer[ui::kColorNativeTabForegroundInactiveFrameActive] = { |
| GetFgColor(header_selector + " GtkLabel#label.title")}; |
| mixer[ui::kColorNativeTabForegroundInactiveFrameInactive] = { |
| GetFgColor(header_selector_inactive + " GtkLabel#label.title")}; |
| mixer[ui::kColorNativeToolbarBackground] = {toolbar_color}; |
| mixer[ui::kColorNativeTextfieldBorderUnfocused] = {entry_border}; |
| mixer[ui::kColorNativeButtonBorder] = {button_border}; |
| mixer[ui::kColorNativeLabelForeground] = {label_fg}; |
| } |
| |
| } // namespace gtk |