gtk_color_mixers.cc 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. // Copyright 2021 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "ui/gtk/gtk_color_mixers.h"
  5. #include "base/strings/strcat.h"
  6. #include "third_party/skia/include/core/SkColor.h"
  7. #include "ui/color/color_id.h"
  8. #include "ui/color/color_mixer.h"
  9. #include "ui/color/color_provider.h"
  10. #include "ui/color/color_recipe.h"
  11. #include "ui/color/color_transform.h"
  12. #include "ui/gfx/color_palette.h"
  13. #include "ui/gtk/gtk_util.h"
  14. namespace gtk {
  15. void AddGtkNativeColorMixer(ui::ColorProvider* provider,
  16. const ui::ColorProviderManager::Key& key) {
  17. if (key.system_theme == ui::ColorProviderManager::SystemTheme::kDefault)
  18. return;
  19. ui::ColorMixer& mixer = provider->AddMixer();
  20. const std::string header_selector =
  21. key.frame_type == ui::ColorProviderManager::FrameType::kChromium
  22. ? "#headerbar.header-bar.titlebar"
  23. : "GtkMenuBar#menubar";
  24. const std::string header_selector_inactive = header_selector + ":backdrop";
  25. const auto tooltip_context = AppendCssNodeToStyleContext(
  26. {}, GtkCheckVersion(3, 20) ? "#tooltip.background"
  27. : "GtkWindow#window.background.tooltip");
  28. const SkColor primary_bg = GetBgColor("");
  29. const SkColor button_bg_disabled =
  30. GetBgColor("GtkButton#button.text-button:disabled");
  31. const SkColor button_border = GetBorderColor("GtkButton#button");
  32. const SkColor frame_color =
  33. SkColorSetA(GetBgColor(header_selector), SK_AlphaOPAQUE);
  34. const SkColor frame_color_inactive =
  35. SkColorSetA(GetBgColor(header_selector_inactive), SK_AlphaOPAQUE);
  36. const SkColor label_fg = GetFgColor("GtkLabel#label");
  37. const SkColor label_fg_disabled = GetFgColor("GtkLabel#label:disabled");
  38. const SkColor entry_border = GetBorderColor("GtkEntry#entry");
  39. const SkColor toolbar_color =
  40. color_utils::GetResultingPaintColor(primary_bg, frame_color);
  41. const SkColor accent = GetFgColor(
  42. "GtkTreeView#treeview.view "
  43. "GtkTreeView#treeview.view.cell:selected:focus GtkLabel#label");
  44. // Core colors
  45. mixer[ui::kColorAccent] = {
  46. GetBgColor("GtkTreeView#treeview.view "
  47. "GtkTreeView#treeview.view.cell:selected:focus")};
  48. mixer[ui::kColorAlertHighSeverity] = {SelectBasedOnDarkInput(
  49. ui::kColorPrimaryBackground, gfx::kGoogleRed300, gfx::kGoogleRed600)};
  50. mixer[ui::kColorAlertLowSeverity] = {SelectBasedOnDarkInput(
  51. ui::kColorPrimaryBackground, gfx::kGoogleGreen300, gfx::kGoogleGreen700)};
  52. mixer[ui::kColorAlertMediumSeverity] = {
  53. SelectBasedOnDarkInput(ui::kColorPrimaryBackground, gfx::kGoogleYellow300,
  54. gfx::kGoogleYellow700)};
  55. mixer[ui::kColorDisabledForeground] = {label_fg_disabled};
  56. mixer[ui::kColorItemHighlight] = {GetBorderColor("GtkEntry#entry:focus")};
  57. mixer[ui::kColorItemSelectionBackground] = {ui::kColorAccent};
  58. mixer[ui::kColorMenuSelectionBackground] = {GetBgColor(
  59. base::StrCat({GtkCssMenu(), " ", GtkCssMenuItem(), ":hover"}))};
  60. mixer[ui::kColorMidground] = {
  61. GetSeparatorColor("GtkSeparator#separator.horizontal")};
  62. mixer[ui::kColorPrimaryBackground] = {primary_bg};
  63. mixer[ui::kColorPrimaryForeground] = {label_fg};
  64. mixer[ui::kColorSecondaryForeground] = {label_fg_disabled};
  65. mixer[ui::kColorTextSelectionBackground] = {
  66. GetSelectionBgColor(GtkCheckVersion(3, 20) ? "GtkLabel#label #selection"
  67. : "GtkLabel#label:selected")};
  68. mixer[ui::kColorTextSelectionForeground] = {
  69. GetFgColor(GtkCheckVersion(3, 20) ? "GtkLabel#label #selection"
  70. : "GtkLabel#label:selected")};
  71. // UI element colors
  72. mixer[ui::kColorAvatarHeaderArt] =
  73. AlphaBlend(ui::kColorPrimaryForeground, ui::kColorPrimaryBackground,
  74. gfx::kGoogleGreyAlpha300);
  75. mixer[ui::kColorAvatarIconGuest] =
  76. DeriveDefaultIconColor(ui::kColorPrimaryForeground);
  77. mixer[ui::kColorButtonBackground] = {GetBgColor("GtkButton#button")};
  78. mixer[ui::kColorButtonBackgroundProminentDisabled] = {button_bg_disabled};
  79. mixer[ui::kColorButtonBorder] = {button_border};
  80. mixer[ui::kColorButtonBorderDisabled] = {button_bg_disabled};
  81. mixer[ui::kColorButtonForeground] = {
  82. GetFgColor("GtkButton#button.text-button GtkLabel#label")};
  83. mixer[ui::kColorButtonForegroundChecked] = {ui::kColorAccent};
  84. mixer[ui::kColorButtonForegroundDisabled] = {
  85. GetFgColor("GtkButton#button.text-button:disabled GtkLabel#label")};
  86. mixer[ui::kColorButtonForegroundProminent] = {accent};
  87. mixer[ui::kColorButtonForegroundUnchecked] = {ui::kColorButtonForeground};
  88. mixer[ui::kColorDialogForeground] = {ui::kColorPrimaryForeground};
  89. mixer[ui::kColorDropdownBackground] = {GetBgColor(base::StrCat(
  90. {"GtkComboBoxText#combobox GtkWindow#window.background.popup ",
  91. "GtkTreeMenu#menu(gtk-combobox-popup-menu) ", GtkCssMenuItem(), " ",
  92. "GtkCellView#cellview"}))};
  93. mixer[ui::kColorDropdownBackgroundSelected] = {GetBgColor(base::StrCat(
  94. {"GtkComboBoxText#combobox GtkWindow#window.background.popup ",
  95. "GtkTreeMenu#menu(gtk-combobox-popup-menu) ", GtkCssMenuItem(),
  96. ":hover GtkCellView#cellview"}))};
  97. mixer[ui::kColorDropdownForeground] = {GetFgColor(base::StrCat(
  98. {"GtkComboBoxText#combobox GtkWindow#window.background.popup ",
  99. "GtkTreeMenu#menu(gtk-combobox-popup-menu) ", GtkCssMenuItem(), " ",
  100. "GtkCellView#cellview"}))};
  101. mixer[ui::kColorDropdownForegroundSelected] = {GetFgColor(base::StrCat(
  102. {"GtkComboBoxText#combobox GtkWindow#window.background.popup ",
  103. "GtkTreeMenu#menu(gtk-combobox-popup-menu) ", GtkCssMenuItem(),
  104. ":hover GtkCellView#cellview"}))};
  105. mixer[ui::kColorFrameActive] = {frame_color};
  106. mixer[ui::kColorFrameInactive] = {frame_color_inactive};
  107. mixer[ui::kColorFocusableBorderUnfocused] = {entry_border};
  108. mixer[ui::kColorHelpIconActive] = {
  109. GetFgColor("GtkButton#button.image-button:hover")};
  110. mixer[ui::kColorIcon] = {
  111. GetFgColor("GtkButton#button.flat.scale GtkImage#image")};
  112. mixer[ui::kColorHelpIconInactive] = {
  113. GetFgColor("GtkButton#button.image-button")};
  114. if (GtkCheckVersion(3, 12)) {
  115. mixer[ui::kColorLinkForeground] = {GetFgColor("GtkLabel#label.link:link")};
  116. mixer[ui::kColorLinkForegroundDisabled] = {
  117. GetFgColor("GtkLabel#label.link:link:disabled")};
  118. mixer[ui::kColorLinkForegroundPressed] = {
  119. GetFgColor("GtkLabel#label.link:link:hover:active")};
  120. } else {
  121. auto link_context = GetStyleContextFromCss("GtkLabel#label.view");
  122. GdkColor* gdk_color = nullptr;
  123. GtkStyleContextGetStyle(link_context, "link-color", &gdk_color, nullptr);
  124. SkColor color = SkColorSetRGB(0x00, 0x00, 0xEE); // From gtklinkbutton.c.
  125. if (gdk_color) {
  126. color = SkColorSetRGB(gdk_color->red >> 8, gdk_color->green >> 8,
  127. gdk_color->blue >> 8);
  128. // gdk_color_free() was deprecated in Gtk3.14. This code path is only
  129. // taken on versions earlier than Gtk3.12, but the compiler doesn't know
  130. // that, so silence the deprecation warnings.
  131. G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
  132. gdk_color_free(gdk_color);
  133. G_GNUC_END_IGNORE_DEPRECATIONS;
  134. }
  135. mixer[ui::kColorLinkForeground] = {color};
  136. mixer[ui::kColorLinkForegroundDisabled] = {color};
  137. mixer[ui::kColorLinkForegroundPressed] = {color};
  138. }
  139. mixer[ui::kColorMenuBackground] = {GetBgColor(GtkCssMenu())};
  140. mixer[ui::kColorMenuBorder] = {GetBorderColor(GtkCssMenu())};
  141. mixer[ui::kColorMenuDropmarker] = {ui::kColorMenuItemForeground};
  142. mixer[ui::kColorMenuIcon] = {GetFgColor(
  143. base::StrCat({GtkCssMenu(), " ", GtkCssMenuItem(),
  144. GtkCheckVersion(3, 20) ? " #radio" : ".radio"}))};
  145. mixer[ui::kColorMenuItemBackgroundHighlighted] = {ui::kColorMenuBackground};
  146. mixer[ui::kColorMenuItemForeground] = {GetFgColor(
  147. base::StrCat({GtkCssMenu(), " ", GtkCssMenuItem(), " GtkLabel#label"}))};
  148. mixer[ui::kColorMenuItemForegroundHighlighted] = {
  149. ui::kColorMenuItemForeground};
  150. mixer[ui::kColorMenuItemForegroundDisabled] = {GetFgColor(base::StrCat(
  151. {GtkCssMenu(), " ", GtkCssMenuItem(), ":disabled GtkLabel#label"}))};
  152. mixer[ui::kColorMenuItemForegroundSecondary] = {GetFgColor(
  153. base::StrCat({GtkCssMenu(), " ", GtkCssMenuItem(),
  154. GtkCheckVersion(3, 20) ? " #accelerator"
  155. : " GtkLabel#label.accelerator"}))};
  156. mixer[ui::kColorMenuItemForegroundSelected] = {GetFgColor(base::StrCat(
  157. {GtkCssMenu(), " ", GtkCssMenuItem(), ":hover GtkLabel#label"}))};
  158. mixer[ui::kColorMenuSeparator] = {GetSeparatorColor(
  159. GtkCheckVersion(3, 20)
  160. ? base::StrCat({GtkCssMenu(), " GtkSeparator#separator.horizontal"})
  161. : base::StrCat({GtkCssMenu(), " ", GtkCssMenuItem(), ".separator"}))};
  162. mixer[ui::kColorNotificationInputForeground] = {accent};
  163. mixer[ui::kColorOverlayScrollbarFill] = {
  164. GetBgColor("#GtkScrollbar#scrollbar #slider")};
  165. mixer[ui::kColorOverlayScrollbarFillHovered] = {
  166. GetBgColor("#GtkScrollbar#scrollbar #slider:hover")};
  167. mixer[ui::kColorOverlayScrollbarStroke] = {
  168. GetBgColor("#GtkScrollbar#scrollbar #trough")};
  169. mixer[ui::kColorOverlayScrollbarStrokeHovered] = {
  170. GetBgColor("#GtkScrollbar#scrollbar #trough:hover")};
  171. mixer[ui::kColorSliderThumb] = {GetBgColor("GtkScale#scale #highlight")};
  172. mixer[ui::kColorSliderThumbMinimal] = {
  173. GetBgColor("GtkScale#scale:disabled #highlight")};
  174. mixer[ui::kColorSliderTrack] = {GetBgColor("GtkScale#scale #trough")};
  175. mixer[ui::kColorSliderTrackMinimal] = {
  176. GetBgColor("GtkScale#scale:disabled #trough")};
  177. mixer[ui::kColorSyncInfoBackground] = {GetBgColor("#statusbar")};
  178. mixer[ui::kColorTabBackgroundHighlighted] = {
  179. GetBgColor("GtkNotebook#notebook #tab:checked")};
  180. mixer[ui::kColorTabBackgroundHighlightedFocused] = {
  181. GetBgColor("GtkNotebook#notebook:focus #tab:checked")};
  182. mixer[ui::kColorTabContentSeparator] = {GetBorderColor(
  183. GtkCheckVersion(3, 20) ? "GtkFrame#frame #border" : "GtkFrame#frame")};
  184. mixer[ui::kColorTabForegroundSelected] = {ui::kColorPrimaryForeground};
  185. mixer[ui::kColorTableBackground] = {ui::kColorTreeBackground};
  186. mixer[ui::kColorTableBackgroundAlternate] = {ui::kColorTreeBackground};
  187. mixer[ui::kColorTableBackgroundSelectedUnfocused] = {
  188. ui::kColorTreeNodeBackgroundSelectedUnfocused};
  189. mixer[ui::kColorTableForeground] = {ui::kColorTreeNodeForeground};
  190. mixer[ui::kColorTableForegroundSelectedFocused] = {
  191. ui::kColorTreeNodeForegroundSelectedFocused};
  192. mixer[ui::kColorTableForegroundSelectedUnfocused] = {
  193. ui::kColorTreeNodeForegroundSelectedUnfocused};
  194. mixer[ui::kColorTableGroupingIndicator] = {ui::kColorTableForeground};
  195. mixer[ui::kColorTableHeaderBackground] = {
  196. GetBgColor("GtkTreeView#treeview.view GtkButton#button")};
  197. mixer[ui::kColorTableHeaderForeground] = {
  198. GetFgColor("GtkTreeView#treeview.view GtkButton#button GtkLabel#label")};
  199. mixer[ui::kColorTableHeaderSeparator] = {
  200. GetBorderColor("GtkTreeView#treeview.view GtkButton#button")};
  201. mixer[ui::kColorTextfieldBackground] = {
  202. GetBgColor(GtkCheckVersion(3, 20) ? "GtkTextView#textview.view"
  203. : "GtkTextView.view")};
  204. mixer[ui::kColorTextfieldBackgroundDisabled] = {
  205. GetBgColor(GtkCheckVersion(3, 20) ? "GtkTextView#textview.view:disabled"
  206. : "GtkTextView.view:disabled")};
  207. mixer[ui::kColorTextfieldForeground] = {
  208. GetFgColor(GtkCheckVersion(3, 20) ? "GtkTextView#textview.view #text"
  209. : "GtkTextView.view")};
  210. mixer[ui::kColorTextfieldForegroundDisabled] = {GetFgColor(
  211. GtkCheckVersion(3, 20) ? "GtkTextView#textview.view:disabled #text"
  212. : "GtkTextView.view:disabled")};
  213. mixer[ui::kColorTextfieldForegroundPlaceholder] = {GtkCheckVersion(4)};
  214. mixer[ui::kColorTextfieldSelectionBackground] = {GetSelectionBgColor(
  215. GtkCheckVersion(3, 20) ? "GtkTextView#textview.view #text #selection"
  216. : "GtkTextView.view:selected")};
  217. mixer[ui::kColorTextfieldSelectionForeground] = {GetFgColor(
  218. GtkCheckVersion(3, 20) ? "GtkTextView#textview.view #text #selection"
  219. : "GtkTextView.view:selected")};
  220. mixer[ui::kColorThrobber] = {GetFgColor("GtkSpinner#spinner")};
  221. mixer[ui::kColorThrobberPreconnect] = {
  222. GetFgColor("GtkSpinner#spinner:disabled")};
  223. mixer[ui::kColorToggleButtonTrackOff] = {
  224. GetBgColor("GtkButton#button.text-button.toggle")};
  225. mixer[ui::kColorToggleButtonTrackOn] = {
  226. GetBgColor("GtkButton#button.text-button.toggle:checked")};
  227. mixer[ui::kColorTooltipBackground] = {
  228. GetBgColorFromStyleContext(tooltip_context)};
  229. mixer[ui::kColorTooltipForeground] = {GtkStyleContextGetColor(
  230. AppendCssNodeToStyleContext(tooltip_context, "GtkLabel#label"))};
  231. mixer[ui::kColorTreeBackground] = {
  232. GetBgColor("GtkTreeView#treeview.view GtkTreeView#treeview.view.cell")};
  233. mixer[ui::kColorTreeNodeForeground] = {
  234. GetFgColor("GtkTreeView#treeview.view GtkTreeView#treeview.view.cell "
  235. "GtkLabel#label")};
  236. mixer[ui::kColorTreeNodeForegroundSelectedFocused] = {accent};
  237. mixer[ui::kColorTreeNodeBackgroundSelectedUnfocused] = {
  238. GetBgColor("GtkTreeView#treeview.view "
  239. "GtkTreeView#treeview.view.cell:selected")};
  240. mixer[ui::kColorTreeNodeForegroundSelectedUnfocused] = {
  241. GetFgColor("GtkTreeView#treeview.view "
  242. "GtkTreeView#treeview.view.cell:selected GtkLabel#label")};
  243. // Platform-specific UI elements
  244. mixer[ui::kColorNativeHeaderButtonBorderActive] = {
  245. GetBorderColor(header_selector + " GtkButton#button")};
  246. mixer[ui::kColorNativeHeaderButtonBorderInactive] = {
  247. GetBorderColor(header_selector + ":backdrop GtkButton#button")};
  248. mixer[ui::kColorNativeHeaderSeparatorBorderActive] = {GetBorderColor(
  249. header_selector + " GtkSeparator#separator.vertical.titlebutton")};
  250. mixer[ui::kColorNativeHeaderSeparatorBorderInactive] = {
  251. GetBorderColor(header_selector +
  252. ":backdrop GtkSeparator#separator.vertical.titlebutton")};
  253. mixer[ui::kColorNativeTabForegroundInactiveFrameActive] = {
  254. GetFgColor(header_selector + " GtkLabel#label.title")};
  255. mixer[ui::kColorNativeTabForegroundInactiveFrameInactive] = {
  256. GetFgColor(header_selector_inactive + " GtkLabel#label.title")};
  257. mixer[ui::kColorNativeToolbarBackground] = {toolbar_color};
  258. mixer[ui::kColorNativeTextfieldBorderUnfocused] = {entry_border};
  259. mixer[ui::kColorNativeButtonBorder] = {button_border};
  260. mixer[ui::kColorNativeLabelForeground] = {label_fg};
  261. }
  262. } // namespace gtk