#ifndef UI_NATIVE_THEME_NATIVE_THEME_H_
#define UI_NATIVE_THEME_NATIVE_THEME_H_
#include <map>
#include "base/containers/flat_map.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/raw_ptr_exclusion.h"
#include "base/observer_list.h"
#include "base/sequence_checker.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/base/models/menu_separator_types.h"
#include "ui/color/color_provider_manager.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/native_theme/caption_style.h"
#include "ui/native_theme/native_theme_export.h"
#include "ui/native_theme/native_theme_observer.h"
namespace cc {
class PaintCanvas;
}
namespace gfx {
class Rect;
class Size;
}
namespace ui {
class NATIVE_THEME_EXPORT NativeTheme {
public:
enum Part {
kCheckbox,
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
kFrameTopArea,
#endif
kInnerSpinButton,
kMenuList,
kMenuPopupBackground,
#if BUILDFLAG(IS_WIN)
kMenuCheck,
kMenuCheckBackground,
kMenuPopupArrow,
kMenuPopupGutter,
#endif
kMenuPopupSeparator,
kMenuItemBackground,
kProgressBar,
kPushButton,
kRadio,
kScrollbarDownArrow,
kScrollbarLeftArrow,
kScrollbarRightArrow,
kScrollbarUpArrow,
kScrollbarHorizontalThumb,
kScrollbarVerticalThumb,
kScrollbarHorizontalTrack,
kScrollbarVerticalTrack,
kScrollbarHorizontalGripper,
kScrollbarVerticalGripper,
kScrollbarCorner,
kSliderTrack,
kSliderThumb,
kTabPanelBackground,
kTextField,
kTrackbarThumb,
kTrackbarTrack,
kWindowResizeGripper,
kMaxPart,
};
enum State {
kDisabled = 0,
kHovered = 1,
kNormal = 2,
kPressed = 3,
kNumStates = kPressed + 1,
};
enum PageColors {
kOff = 0,
kDusk = 1,
kDesert = 2,
kBlack = 3,
kWhite = 4,
kHighContrast = 5,
kMaxValue = kHighContrast,
};
enum class PreferredColorScheme {
kDark = 0,
kLight = 1,
kMaxValue = kLight,
};
enum class PreferredContrast {
kNoPreference = 0,
kMore = 1,
kLess = 2,
kCustom = 3,
kMaxValue = kCustom,
};
enum class PlatformHighContrastColorScheme {
kNone = 0,
kDark = 1,
kLight = 2,
kMaxValue = kLight,
};
enum class ColorScheme {
kDefault,
kLight,
kDark,
kPlatformHighContrast,
};
struct ButtonExtraParams {
bool checked;
bool indeterminate;
bool is_default;
bool is_focused;
bool has_border;
int classic_state;
SkColor background_color;
float zoom;
};
struct FrameTopAreaExtraParams {
bool is_active;
bool use_custom_frame;
SkColor default_background_color;
};
struct InnerSpinButtonExtraParams {
bool spin_up;
bool read_only;
int classic_state;
};
struct MenuArrowExtraParams {
bool pointing_right;
bool is_selected;
};
struct MenuCheckExtraParams {
bool is_radio;
bool is_selected;
};
struct MenuSeparatorExtraParams {
RAW_PTR_EXCLUSION const gfx::Rect* paint_rect;
MenuSeparatorType type;
};
struct MenuItemExtraParams {
bool is_selected;
int corner_radius;
};
struct MenuListExtraParams {
bool has_border;
bool has_border_radius;
int arrow_x;
int arrow_y;
int arrow_size;
SkColor arrow_color;
SkColor background_color;
int classic_state;
float zoom;
};
struct MenuBackgroundExtraParams {
int corner_radius;
};
struct ProgressBarExtraParams {
double animated_seconds;
bool determinate;
int value_rect_x;
int value_rect_y;
int value_rect_width;
int value_rect_height;
float zoom;
bool is_horizontal;
};
struct ScrollbarArrowExtraParams {
bool is_hovering;
float zoom;
bool right_to_left;
};
struct ScrollbarTrackExtraParams {
bool is_upper;
int track_x;
int track_y;
int track_width;
int track_height;
int classic_state;
};
enum class ScrollbarOverlayColorTheme {
kDefault = 0,
kLight = 1,
kDark = 2,
};
struct ScrollbarThumbExtraParams {
bool is_hovering;
#ifdef OHOS_SCROLLBAR
SkColor scrollbar_color;
#endif
ScrollbarOverlayColorTheme scrollbar_theme;
};
#if BUILDFLAG(IS_APPLE)
enum ScrollbarOrientation {
kVerticalOnRight,
kVerticalOnLeft,
kHorizontal,
};
struct ScrollbarExtraParams {
bool is_hovering;
bool is_overlay;
ScrollbarOverlayColorTheme scrollbar_theme;
ScrollbarOrientation orientation;
float scale_from_dip;
};
#endif
struct SliderExtraParams {
bool vertical;
bool in_drag;
int thumb_x;
int thumb_y;
float zoom;
bool right_to_left;
};
struct TextFieldExtraParams {
bool is_text_area;
bool is_listbox;
SkColor background_color;
bool is_read_only;
bool is_focused;
bool fill_content_area;
bool draw_edges;
int classic_state;
bool has_border;
bool auto_complete_active;
float zoom;
};
struct TrackbarExtraParams {
bool vertical;
int classic_state;
};
union NATIVE_THEME_EXPORT ExtraParams {
ExtraParams();
ExtraParams(const ExtraParams& other);
ButtonExtraParams button;
FrameTopAreaExtraParams frame_top_area;
InnerSpinButtonExtraParams inner_spin;
MenuArrowExtraParams menu_arrow;
MenuCheckExtraParams menu_check;
MenuItemExtraParams menu_item;
MenuSeparatorExtraParams menu_separator;
MenuListExtraParams menu_list;
MenuBackgroundExtraParams menu_background;
ProgressBarExtraParams progress_bar;
ScrollbarArrowExtraParams scrollbar_arrow;
#if BUILDFLAG(IS_APPLE)
ScrollbarExtraParams scrollbar_extra;
#endif
ScrollbarTrackExtraParams scrollbar_track;
ScrollbarThumbExtraParams scrollbar_thumb;
SliderExtraParams slider;
TextFieldExtraParams text_field;
TrackbarExtraParams trackbar;
};
NativeTheme(const NativeTheme&) = delete;
NativeTheme& operator=(const NativeTheme&) = delete;
virtual gfx::Size GetPartSize(Part part,
State state,
const ExtraParams& extra) const = 0;
virtual float GetBorderRadiusForPart(Part part,
float width,
float height) const;
virtual void Paint(
cc::PaintCanvas* canvas,
const ui::ColorProvider* color_provider,
Part part,
State state,
const gfx::Rect& rect,
const ExtraParams& extra,
ColorScheme color_scheme = ColorScheme::kDefault,
const absl::optional<SkColor>& accent_color = absl::nullopt) const = 0;
virtual bool SupportsNinePatch(Part part) const = 0;
virtual gfx::Size GetNinePatchCanvasSize(Part part) const = 0;
virtual gfx::Rect GetNinePatchAperture(Part part) const = 0;
enum class SystemThemeColor {
kNotSupported,
kButtonFace,
kButtonText,
kGrayText,
kHighlight,
kHighlightText,
kHotlight,
kMenuHighlight,
kScrollbar,
kWindow,
kWindowText,
kMaxValue = kWindowText,
};
ColorProviderManager::Key GetColorProviderKey(
scoped_refptr<ColorProviderManager::ThemeInitializerSupplier>
custom_theme,
bool use_custom_frame = true) const;
static NativeTheme* GetInstanceForWeb();
static NativeTheme* GetInstanceForNativeUi();
static NativeTheme* GetInstanceForDarkUI();
static bool SystemDarkModeSupported();
void AddObserver(NativeThemeObserver* observer);
void RemoveObserver(NativeThemeObserver* observer);
virtual void NotifyOnNativeThemeUpdated();
virtual void NotifyOnCaptionStyleUpdated();
virtual void NotifyOnPreferredContrastUpdated();
virtual bool UserHasContrastPreference() const;
bool InForcedColorsMode() const;
PlatformHighContrastColorScheme GetPlatformHighContrastColorScheme() const;
virtual bool ShouldUseDarkColors() const;
virtual PageColors GetPageColors() const;
virtual PreferredColorScheme GetPreferredColorScheme() const;
virtual PreferredContrast GetPreferredContrast() const;
virtual absl::optional<CaptionStyle> GetSystemCaptionStyle() const;
virtual ColorScheme GetDefaultSystemColorScheme() const;
virtual const std::map<SystemThemeColor, SkColor>& GetSystemColors() const;
absl::optional<SkColor> GetSystemThemeColor(
SystemThemeColor theme_color) const;
bool HasDifferentSystemColors(
const std::map<SystemThemeColor, SkColor>& colors) const;
void set_use_dark_colors(bool should_use_dark_colors) {
should_use_dark_colors_ = should_use_dark_colors;
}
void set_forced_colors(bool forced_colors) { forced_colors_ = forced_colors; }
void set_page_colors(PageColors page_colors) { page_colors_ = page_colors; }
void set_preferred_color_scheme(PreferredColorScheme preferred_color_scheme) {
preferred_color_scheme_ = preferred_color_scheme;
}
void SetPreferredContrast(PreferredContrast preferred_contrast);
void set_system_colors(const std::map<SystemThemeColor, SkColor>& colors);
ui::SystemTheme system_theme() const { return system_theme_; }
void set_user_color(absl::optional<SkColor> user_color) {
user_color_ = user_color;
}
absl::optional<SkColor> user_color() const { return user_color_; }
void set_scheme_variant(
absl::optional<ui::ColorProviderManager::SchemeVariant> scheme_variant) {
scheme_variant_ = scheme_variant;
}
absl::optional<ui::ColorProviderManager::SchemeVariant> scheme_variant() {
return scheme_variant_;
}
bool UpdateSystemColorInfo(
bool is_dark_mode,
bool forced_colors,
const base::flat_map<SystemThemeColor, uint32_t>& colors);
virtual SkColor GetSystemButtonPressedColor(SkColor base_color) const;
virtual SkColor4f FocusRingColorForBaseColor(SkColor4f base_color) const;
float AdjustBorderWidthByZoom(float border_width, float zoom_level) const;
float AdjustBorderRadiusByZoom(Part part,
float border_width,
float zoom_level) const;
static bool IsForcedHighContrast();
static bool IsForcedDarkMode();
protected:
explicit NativeTheme(
bool should_only_use_dark_colors,
ui::SystemTheme system_theme = ui::SystemTheme::kDefault);
virtual ~NativeTheme();
virtual PreferredColorScheme CalculatePreferredColorScheme() const;
virtual PreferredContrast CalculatePreferredContrast() const;
virtual void ConfigureWebInstance() {}
class NATIVE_THEME_EXPORT ColorSchemeNativeThemeObserver
: public NativeThemeObserver {
public:
ColorSchemeNativeThemeObserver(NativeTheme* theme_to_update);
ColorSchemeNativeThemeObserver(const ColorSchemeNativeThemeObserver&) =
delete;
ColorSchemeNativeThemeObserver& operator=(
const ColorSchemeNativeThemeObserver&) = delete;
~ColorSchemeNativeThemeObserver() override;
private:
void OnNativeThemeUpdated(ui::NativeTheme* observed_theme) override;
const raw_ptr<NativeTheme> theme_to_update_;
};
mutable std::map<SystemThemeColor, SkColor> system_colors_;
private:
base::ObserverList<NativeThemeObserver>::Unchecked native_theme_observers_;
absl::optional<SkColor> user_color_;
absl::optional<ui::ColorProviderManager::SchemeVariant> scheme_variant_;
bool should_use_dark_colors_ = false;
const ui::SystemTheme system_theme_;
bool forced_colors_ = false;
PageColors page_colors_ = PageColors::kOff;
PreferredColorScheme preferred_color_scheme_ = PreferredColorScheme::kLight;
PreferredContrast preferred_contrast_ = PreferredContrast::kNoPreference;
SEQUENCE_CHECKER(sequence_checker_);
};
}
#endif