native_theme.cc 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. // Copyright (c) 2012 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/native_theme/native_theme.h"
  5. #include <cstring>
  6. #include "base/bind.h"
  7. #include "base/command_line.h"
  8. #include "base/containers/fixed_flat_map.h"
  9. #include "base/logging.h"
  10. #include "base/observer_list.h"
  11. #include "build/build_config.h"
  12. #include "third_party/abseil-cpp/absl/types/optional.h"
  13. #include "ui/base/ui_base_switches.h"
  14. #include "ui/color/color_id.h"
  15. #include "ui/color/color_provider.h"
  16. #include "ui/color/color_provider_manager.h"
  17. #include "ui/color/color_provider_utils.h"
  18. #include "ui/native_theme/common_theme.h"
  19. #include "ui/native_theme/native_theme_utils.h"
  20. namespace ui {
  21. NativeTheme::ExtraParams::ExtraParams() {
  22. memset(this, 0, sizeof(*this));
  23. }
  24. NativeTheme::ExtraParams::ExtraParams(const ExtraParams& other) {
  25. memcpy(this, &other, sizeof(*this));
  26. }
  27. #if !BUILDFLAG(IS_WIN) && !BUILDFLAG(IS_APPLE)
  28. // static
  29. bool NativeTheme::SystemDarkModeSupported() {
  30. return false;
  31. }
  32. #endif
  33. ColorProviderManager::Key NativeTheme::GetColorProviderKey(
  34. scoped_refptr<ColorProviderManager::ThemeInitializerSupplier> custom_theme,
  35. bool use_custom_frame) const {
  36. return ColorProviderManager::Key(
  37. (GetDefaultSystemColorScheme() == ColorScheme::kDark)
  38. ? ColorProviderManager::ColorMode::kDark
  39. : ColorProviderManager::ColorMode::kLight,
  40. UserHasContrastPreference() ? ColorProviderManager::ContrastMode::kHigh
  41. : ColorProviderManager::ContrastMode::kNormal,
  42. is_custom_system_theme_ ? ColorProviderManager::SystemTheme::kCustom
  43. : ColorProviderManager::SystemTheme::kDefault,
  44. use_custom_frame ? ui::ColorProviderManager::FrameType::kChromium
  45. : ui::ColorProviderManager::FrameType::kNative,
  46. user_color_, std::move(custom_theme));
  47. }
  48. SkColor NativeTheme::GetSystemButtonPressedColor(SkColor base_color) const {
  49. return base_color;
  50. }
  51. SkColor NativeTheme::FocusRingColorForBaseColor(SkColor base_color) const {
  52. return base_color;
  53. }
  54. float NativeTheme::GetBorderRadiusForPart(Part part,
  55. float width,
  56. float height) const {
  57. return 0;
  58. }
  59. void NativeTheme::AddObserver(NativeThemeObserver* observer) {
  60. native_theme_observers_.AddObserver(observer);
  61. }
  62. void NativeTheme::RemoveObserver(NativeThemeObserver* observer) {
  63. native_theme_observers_.RemoveObserver(observer);
  64. }
  65. void NativeTheme::NotifyOnNativeThemeUpdated() {
  66. // This specific method is prone to being mistakenly called on the wrong
  67. // sequence, because it is often invoked from a platform-specific event
  68. // listener, and those events may be delivered on unexpected sequences.
  69. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  70. // Reset the ColorProviderManager's cache so that ColorProviders requested
  71. // from this point onwards incorporate the changes to the system theme.
  72. ui::ColorProviderManager::Get().ResetColorProviderCache();
  73. for (NativeThemeObserver& observer : native_theme_observers_)
  74. observer.OnNativeThemeUpdated(this);
  75. }
  76. void NativeTheme::NotifyOnCaptionStyleUpdated() {
  77. // This specific method is prone to being mistakenly called on the wrong
  78. // sequence, because it is often invoked from a platform-specific event
  79. // listener, and those events may be delivered on unexpected sequences.
  80. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  81. for (NativeThemeObserver& observer : native_theme_observers_)
  82. observer.OnCaptionStyleUpdated();
  83. }
  84. float NativeTheme::AdjustBorderWidthByZoom(float border_width,
  85. float zoom_level) const {
  86. float zoomed = floorf(border_width * zoom_level);
  87. return std::max(1.0f, zoomed);
  88. }
  89. float NativeTheme::AdjustBorderRadiusByZoom(Part part,
  90. float border_radius,
  91. float zoom) const {
  92. if (part == kCheckbox || part == kTextField || part == kPushButton) {
  93. float zoomed = floorf(border_radius * zoom);
  94. return std::max(1.0f, zoomed);
  95. }
  96. return border_radius;
  97. }
  98. NativeTheme::NativeTheme(bool should_use_dark_colors,
  99. bool is_custom_system_theme)
  100. : should_use_dark_colors_(should_use_dark_colors || IsForcedDarkMode()),
  101. is_custom_system_theme_(is_custom_system_theme),
  102. forced_colors_(IsForcedHighContrast()),
  103. preferred_color_scheme_(CalculatePreferredColorScheme()),
  104. preferred_contrast_(CalculatePreferredContrast()) {}
  105. NativeTheme::~NativeTheme() = default;
  106. bool NativeTheme::ShouldUseDarkColors() const {
  107. return should_use_dark_colors_;
  108. }
  109. bool NativeTheme::UserHasContrastPreference() const {
  110. return GetPreferredContrast() !=
  111. NativeTheme::PreferredContrast::kNoPreference;
  112. }
  113. bool NativeTheme::InForcedColorsMode() const {
  114. return forced_colors_;
  115. }
  116. NativeTheme::PlatformHighContrastColorScheme
  117. NativeTheme::GetPlatformHighContrastColorScheme() const {
  118. if (GetDefaultSystemColorScheme() != ColorScheme::kPlatformHighContrast)
  119. return PlatformHighContrastColorScheme::kNone;
  120. return (GetPreferredColorScheme() == PreferredColorScheme::kDark)
  121. ? PlatformHighContrastColorScheme::kDark
  122. : PlatformHighContrastColorScheme::kLight;
  123. }
  124. NativeTheme::PageColors NativeTheme::GetPageColors() const {
  125. return page_colors_;
  126. }
  127. NativeTheme::PreferredColorScheme NativeTheme::GetPreferredColorScheme() const {
  128. return preferred_color_scheme_;
  129. }
  130. NativeTheme::PreferredContrast NativeTheme::GetPreferredContrast() const {
  131. return preferred_contrast_;
  132. }
  133. bool NativeTheme::IsForcedDarkMode() const {
  134. static bool kIsForcedDarkMode =
  135. base::CommandLine::ForCurrentProcess()->HasSwitch(
  136. switches::kForceDarkMode);
  137. return kIsForcedDarkMode;
  138. }
  139. bool NativeTheme::IsForcedHighContrast() const {
  140. static bool kIsForcedHighContrast =
  141. base::CommandLine::ForCurrentProcess()->HasSwitch(
  142. switches::kForceHighContrast);
  143. return kIsForcedHighContrast;
  144. }
  145. NativeTheme::PreferredColorScheme NativeTheme::CalculatePreferredColorScheme()
  146. const {
  147. return ShouldUseDarkColors() ? NativeTheme::PreferredColorScheme::kDark
  148. : NativeTheme::PreferredColorScheme::kLight;
  149. }
  150. NativeTheme::PreferredContrast NativeTheme::CalculatePreferredContrast() const {
  151. return IsForcedHighContrast() ? PreferredContrast::kMore
  152. : PreferredContrast::kNoPreference;
  153. }
  154. absl::optional<CaptionStyle> NativeTheme::GetSystemCaptionStyle() const {
  155. return CaptionStyle::FromSystemSettings();
  156. }
  157. const std::map<NativeTheme::SystemThemeColor, SkColor>&
  158. NativeTheme::GetSystemColors() const {
  159. return system_colors_;
  160. }
  161. absl::optional<SkColor> NativeTheme::GetSystemThemeColor(
  162. SystemThemeColor theme_color) const {
  163. auto color = system_colors_.find(theme_color);
  164. if (color != system_colors_.end())
  165. return color->second;
  166. return absl::nullopt;
  167. }
  168. bool NativeTheme::HasDifferentSystemColors(
  169. const std::map<NativeTheme::SystemThemeColor, SkColor>& colors) const {
  170. return system_colors_ != colors;
  171. }
  172. void NativeTheme::set_system_colors(
  173. const std::map<NativeTheme::SystemThemeColor, SkColor>& colors) {
  174. system_colors_ = colors;
  175. }
  176. bool NativeTheme::UpdateSystemColorInfo(
  177. bool is_dark_mode,
  178. bool forced_colors,
  179. const base::flat_map<SystemThemeColor, uint32_t>& colors) {
  180. bool did_system_color_info_change = false;
  181. if (is_dark_mode != ShouldUseDarkColors()) {
  182. did_system_color_info_change = true;
  183. set_use_dark_colors(is_dark_mode);
  184. }
  185. if (forced_colors != InForcedColorsMode()) {
  186. did_system_color_info_change = true;
  187. set_forced_colors(forced_colors);
  188. }
  189. for (const auto& color : colors) {
  190. if (color.second != GetSystemThemeColor(color.first)) {
  191. did_system_color_info_change = true;
  192. system_colors_[color.first] = color.second;
  193. }
  194. }
  195. return did_system_color_info_change;
  196. }
  197. NativeTheme::ColorSchemeNativeThemeObserver::ColorSchemeNativeThemeObserver(
  198. NativeTheme* theme_to_update)
  199. : theme_to_update_(theme_to_update) {}
  200. NativeTheme::ColorSchemeNativeThemeObserver::~ColorSchemeNativeThemeObserver() =
  201. default;
  202. void NativeTheme::ColorSchemeNativeThemeObserver::OnNativeThemeUpdated(
  203. ui::NativeTheme* observed_theme) {
  204. bool should_use_dark_colors = observed_theme->ShouldUseDarkColors();
  205. bool forced_colors = observed_theme->InForcedColorsMode();
  206. PreferredColorScheme preferred_color_scheme =
  207. observed_theme->GetPreferredColorScheme();
  208. PreferredContrast preferred_contrast = observed_theme->GetPreferredContrast();
  209. bool notify_observers = false;
  210. if (theme_to_update_->ShouldUseDarkColors() != should_use_dark_colors) {
  211. theme_to_update_->set_use_dark_colors(should_use_dark_colors);
  212. notify_observers = true;
  213. }
  214. if (theme_to_update_->InForcedColorsMode() != forced_colors) {
  215. theme_to_update_->set_forced_colors(forced_colors);
  216. notify_observers = true;
  217. }
  218. if (theme_to_update_->GetPreferredColorScheme() != preferred_color_scheme) {
  219. theme_to_update_->set_preferred_color_scheme(preferred_color_scheme);
  220. notify_observers = true;
  221. }
  222. if (theme_to_update_->GetPreferredContrast() != preferred_contrast) {
  223. theme_to_update_->set_preferred_contrast(preferred_contrast);
  224. notify_observers = true;
  225. }
  226. const auto& system_colors = observed_theme->GetSystemColors();
  227. if (theme_to_update_->HasDifferentSystemColors(system_colors)) {
  228. theme_to_update_->set_system_colors(system_colors);
  229. notify_observers = true;
  230. }
  231. if (notify_observers) {
  232. DCHECK(theme_to_update_->UserHasContrastPreference() ||
  233. !theme_to_update_->InForcedColorsMode());
  234. theme_to_update_->NotifyOnNativeThemeUpdated();
  235. }
  236. }
  237. NativeTheme::ColorScheme NativeTheme::GetDefaultSystemColorScheme() const {
  238. return ShouldUseDarkColors() ? ColorScheme::kDark : ColorScheme::kLight;
  239. }
  240. } // namespace ui