summaryrefslogtreecommitdiffstats
path: root/widget/ThemeColors.h
blob: 739a7ca0f0ff4d1647c5c204b49ba7cc157c76fd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
/* -*- Mode: C++; tab-width: 40; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef mozilla_widget_ThemeColors_h
#define mozilla_widget_ThemeColors_h

#include "mozilla/dom/Document.h"
#include "mozilla/gfx/Types.h"
#include "mozilla/LookAndFeel.h"
#include "nsIFrame.h"

namespace mozilla::widget {

static constexpr gfx::sRGBColor sDefaultAccent(
    gfx::sRGBColor::UnusualFromARGB(0xff0060df));  // Luminance: 13.69346%
static constexpr gfx::sRGBColor sDefaultAccentText(
    gfx::sRGBColor::OpaqueWhite());

struct ColorPalette;

class ThemeAccentColor {
 protected:
  using sRGBColor = mozilla::gfx::sRGBColor;
  using ComputedStyle = mozilla::ComputedStyle;

  Maybe<nscolor> mAccentColor;
  const ColorPalette* mDefaultPalette = nullptr;

 public:
  explicit ThemeAccentColor(const ComputedStyle&, ColorScheme);
  virtual ~ThemeAccentColor() = default;

  sRGBColor Get() const;
  sRGBColor GetForeground() const;
  sRGBColor GetLight() const;
  sRGBColor GetDark() const;
  sRGBColor GetDarker() const;
};

// Widget color information associated to a particular frame.
class ThemeColors {
 protected:
  using Document = mozilla::dom::Document;
  using sRGBColor = mozilla::gfx::sRGBColor;
  using LookAndFeel = mozilla::LookAndFeel;
  using StyleSystemColor = mozilla::StyleSystemColor;
  using AccentColor = ThemeAccentColor;

  struct HighContrastInfo {
    bool mHighContrast = false;
    bool mMustUseLightSystemColors = false;
  };

  const Document& mDoc;
  const HighContrastInfo mHighContrastInfo;
  const ColorScheme mColorScheme;
  const AccentColor mAccentColor;

 public:
  explicit ThemeColors(const nsIFrame* aFrame, StyleAppearance aAppearance)
      : mDoc(*aFrame->PresContext()->Document()),
        mHighContrastInfo(ShouldBeHighContrast(*aFrame->PresContext())),
        mColorScheme(ColorSchemeForWidget(aFrame, aAppearance, mHighContrastInfo)),
        mAccentColor(*aFrame->Style(), mColorScheme) {}
  virtual ~ThemeColors() = default;

  [[nodiscard]] static float ScaleLuminanceBy(float aLuminance, float aFactor) {
    return aLuminance >= 0.18f ? aLuminance * aFactor : aLuminance / aFactor;
  }

  const AccentColor& Accent() const { return mAccentColor; }
  bool HighContrast() const { return mHighContrastInfo.mHighContrast; }
  bool IsDark() const { return mColorScheme == ColorScheme::Dark; }

  nscolor SystemNs(StyleSystemColor aColor) const {
    return LookAndFeel::Color(aColor, mColorScheme,
                              LookAndFeel::ShouldUseStandins(mDoc, aColor));
  }

  sRGBColor System(StyleSystemColor aColor) const {
    return sRGBColor::FromABGR(SystemNs(aColor));
  }

  template <typename Compute>
  sRGBColor SystemOrElse(StyleSystemColor aColor, Compute aCompute) const {
    if (auto color = LookAndFeel::GetColor(
            aColor, mColorScheme,
            LookAndFeel::ShouldUseStandins(mDoc, aColor))) {
      return sRGBColor::FromABGR(*color);
    }
    return aCompute();
  }

  std::pair<sRGBColor, sRGBColor> SystemPair(StyleSystemColor aFirst,
                                             StyleSystemColor aSecond) const {
    return std::make_pair(System(aFirst), System(aSecond));
  }

  // Whether we should use system colors (for high contrast mode).
  static HighContrastInfo ShouldBeHighContrast(const nsPresContext&);
  static ColorScheme ColorSchemeForWidget(const nsIFrame*, StyleAppearance,
                                          const HighContrastInfo&);

  static void RecomputeAccentColors();

  static nscolor ComputeCustomAccentForeground(nscolor aColor);

  static nscolor AdjustUnthemedScrollbarThumbColor(nscolor aFaceColor,
                                                   dom::ElementState aStates);
};

}  // namespace mozilla::widget

#endif