Bug 1705532 use async/await instead of callbacks r=annyG
[gecko.git] / widget / nsXPLookAndFeel.cpp
blob431b4c06f743a59ea50c63e0b285b15e06190860
1 /* -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "mozilla/ArrayUtils.h"
8 #include "nscore.h"
10 #include "nsXPLookAndFeel.h"
11 #include "nsLookAndFeel.h"
12 #include "HeadlessLookAndFeel.h"
13 #include "RemoteLookAndFeel.h"
14 #include "nsContentUtils.h"
15 #include "nsCRT.h"
16 #include "nsFont.h"
17 #include "nsIFrame.h"
18 #include "nsIXULRuntime.h"
19 #include "nsNativeBasicTheme.h"
20 #include "mozilla/dom/ContentChild.h"
21 #include "mozilla/Preferences.h"
22 #include "mozilla/Services.h"
23 #include "mozilla/ServoStyleSet.h"
24 #include "mozilla/ServoCSSParser.h"
25 #include "mozilla/StaticPrefs_browser.h"
26 #include "mozilla/StaticPrefs_editor.h"
27 #include "mozilla/StaticPrefs_findbar.h"
28 #include "mozilla/StaticPrefs_ui.h"
29 #include "mozilla/StaticPrefs_widget.h"
30 #include "mozilla/dom/Document.h"
31 #include "mozilla/PreferenceSheet.h"
32 #include "mozilla/gfx/2D.h"
33 #include "mozilla/widget/WidgetMessageUtils.h"
34 #include "mozilla/Telemetry.h"
35 #include "mozilla/TelemetryScalarEnums.h"
37 #include "gfxPlatform.h"
38 #include "gfxFont.h"
40 #include "qcms.h"
42 #ifdef DEBUG
43 # include "nsSize.h"
44 #endif
46 using namespace mozilla;
48 using IntID = mozilla::LookAndFeel::IntID;
49 using FloatID = mozilla::LookAndFeel::FloatID;
50 using ColorID = mozilla::LookAndFeel::ColorID;
51 using FontID = mozilla::LookAndFeel::FontID;
53 template <typename Index, typename Value, Index kEnd>
54 class EnumeratedCache {
55 static constexpr uint32_t ChunkFor(Index aIndex) {
56 return uint32_t(aIndex) >> 5; // >> 5 is the same as / 32.
58 static constexpr uint32_t BitFor(Index aIndex) {
59 return 1u << (uint32_t(aIndex) & 31);
61 static constexpr uint32_t kChunks = ChunkFor(kEnd) + 1;
63 mozilla::EnumeratedArray<Index, kEnd, Value> mEntries;
64 uint32_t mValidity[kChunks] = {0};
66 public:
67 constexpr EnumeratedCache() = default;
69 bool IsValid(Index aIndex) const {
70 return mValidity[ChunkFor(aIndex)] & BitFor(aIndex);
73 const Value* Get(Index aIndex) const {
74 return IsValid(aIndex) ? &mEntries[aIndex] : nullptr;
77 void Insert(Index aIndex, Value aValue) {
78 mValidity[ChunkFor(aIndex)] |= BitFor(aIndex);
79 mEntries[aIndex] = aValue;
82 void Remove(Index aIndex) {
83 mValidity[ChunkFor(aIndex)] &= ~BitFor(aIndex);
84 mEntries[aIndex] = Value();
87 void Clear() {
88 for (auto& chunk : mValidity) {
89 chunk = 0;
91 for (auto& entry : mEntries) {
92 entry = Value();
97 static EnumeratedCache<ColorID, Maybe<nscolor>, ColorID::End> sLightColorCache;
98 static EnumeratedCache<ColorID, Maybe<nscolor>, ColorID::End> sDarkColorCache;
99 static EnumeratedCache<FloatID, Maybe<float>, FloatID::End> sFloatCache;
100 static EnumeratedCache<IntID, Maybe<int32_t>, IntID::End> sIntCache;
101 static EnumeratedCache<FontID, widget::LookAndFeelFont, FontID::End> sFontCache;
103 // To make one of these prefs toggleable from a reftest add a user
104 // pref in testing/profiles/reftest/user.js. For example, to make
105 // ui.useAccessibilityTheme toggleable, add:
107 // user_pref("ui.useAccessibilityTheme", 0);
109 // This needs to be of the same length and in the same order as
110 // LookAndFeel::IntID values.
111 static const char sIntPrefs[][43] = {
112 "ui.caretBlinkTime",
113 "ui.caretBlinkCount",
114 "ui.caretWidth",
115 "ui.caretVisibleWithSelection",
116 "ui.selectTextfieldsOnKeyFocus",
117 "ui.submenuDelay",
118 "ui.menusCanOverlapOSBar",
119 "ui.useOverlayScrollbars",
120 "ui.allowOverlayScrollbarsOverlap",
121 "ui.skipNavigatingDisabledMenuItem",
122 "ui.dragThresholdX",
123 "ui.dragThresholdY",
124 "ui.useAccessibilityTheme",
125 "ui.scrollArrowStyle",
126 "ui.scrollSliderStyle",
127 "ui.scrollButtonLeftMouseButtonAction",
128 "ui.scrollButtonMiddleMouseButtonAction",
129 "ui.scrollButtonRightMouseButtonAction",
130 "ui.treeOpenDelay",
131 "ui.treeCloseDelay",
132 "ui.treeLazyScrollDelay",
133 "ui.treeScrollDelay",
134 "ui.treeScrollLinesMax",
135 "accessibility.tabfocus", // Weird one...
136 "ui.chosenMenuItemsShouldBlink",
137 "ui.windowsAccentColorInTitlebar",
138 "ui.windowsDefaultTheme",
139 "ui.dwmCompositor",
140 "ui.windowsClassic",
141 "ui.windowsGlass",
142 "ui.macGraphiteTheme",
143 "ui.macBigSurTheme",
144 "ui.macRTL",
145 "ui.alertNotificationOrigin",
146 "ui.scrollToClick",
147 "ui.IMERawInputUnderlineStyle",
148 "ui.IMESelectedRawTextUnderlineStyle",
149 "ui.IMEConvertedTextUnderlineStyle",
150 "ui.IMESelectedConvertedTextUnderlineStyle",
151 "ui.SpellCheckerUnderlineStyle",
152 "ui.menuBarDrag",
153 "ui.operatingSystemVersionIdentifier",
154 "ui.scrollbarButtonAutoRepeatBehavior",
155 "ui.tooltipDelay",
156 "ui.swipeAnimationEnabled",
157 "ui.scrollbarDisplayOnMouseMove",
158 "ui.scrollbarFadeBeginDelay",
159 "ui.scrollbarFadeDuration",
160 "ui.contextMenuOffsetVertical",
161 "ui.contextMenuOffsetHorizontal",
162 "ui.GtkCSDAvailable",
163 "ui.GtkCSDMinimizeButton",
164 "ui.GtkCSDMaximizeButton",
165 "ui.GtkCSDCloseButton",
166 "ui.GtkCSDMinimizeButtonPosition",
167 "ui.GtkCSDMaximizeButtonPosition",
168 "ui.GtkCSDCloseButtonPosition",
169 "ui.GtkCSDReversedPlacement",
170 "ui.systemUsesDarkTheme",
171 "ui.prefersReducedMotion",
172 "ui.primaryPointerCapabilities",
173 "ui.allPointerCapabilities",
174 "ui.systemVerticalScrollbarWidth",
175 "ui.systemHorizontalScrollbarHeight",
176 "ui.touchDeviceSupportPresent",
177 "ui.titlebarRadius",
178 "ui.GtkMenuRadius",
181 static_assert(ArrayLength(sIntPrefs) == size_t(LookAndFeel::IntID::End),
182 "Should have a pref for each int value");
184 // This array MUST be kept in the same order as the float id list in
185 // LookAndFeel.h
186 // clang-format off
187 static const char sFloatPrefs[][37] = {
188 "ui.IMEUnderlineRelativeSize",
189 "ui.SpellCheckerUnderlineRelativeSize",
190 "ui.caretAspectRatio",
191 "ui.textScaleFactor",
192 "ui.cursorScale",
194 // clang-format on
196 static_assert(ArrayLength(sFloatPrefs) == size_t(LookAndFeel::FloatID::End),
197 "Should have a pref for each float value");
199 // This array MUST be kept in the same order as the color list in
200 // specified/color.rs
201 static const char sColorPrefs[][41] = {
202 "ui.textSelectDisabledBackground",
203 "ui.textSelectAttentionBackground",
204 "ui.textSelectAttentionForeground",
205 "ui.textHighlightBackground",
206 "ui.textHighlightForeground",
207 "ui.IMERawInputBackground",
208 "ui.IMERawInputForeground",
209 "ui.IMERawInputUnderline",
210 "ui.IMESelectedRawTextBackground",
211 "ui.IMESelectedRawTextForeground",
212 "ui.IMESelectedRawTextUnderline",
213 "ui.IMEConvertedTextBackground",
214 "ui.IMEConvertedTextForeground",
215 "ui.IMEConvertedTextUnderline",
216 "ui.IMESelectedConvertedTextBackground",
217 "ui.IMESelectedConvertedTextForeground",
218 "ui.IMESelectedConvertedTextUnderline",
219 "ui.SpellCheckerUnderline",
220 "ui.themedScrollbar",
221 "ui.themedScrollbarInactive",
222 "ui.themedScrollbarThumb",
223 "ui.themedScrollbarThumbHover",
224 "ui.themedScrollbarThumbActive",
225 "ui.themedScrollbarThumbInactive",
226 "ui.activeborder",
227 "ui.activecaption",
228 "ui.appworkspace",
229 "ui.background",
230 "ui.buttonface",
231 "ui.buttonhighlight",
232 "ui.buttonshadow",
233 "ui.buttontext",
234 "ui.captiontext",
235 "ui.-moz-field",
236 "ui.-moz-disabledfield",
237 "ui.-moz-fieldtext",
238 "ui.graytext",
239 "ui.highlight",
240 "ui.highlighttext",
241 "ui.inactiveborder",
242 "ui.inactivecaption",
243 "ui.inactivecaptiontext",
244 "ui.infobackground",
245 "ui.infotext",
246 "ui.menu",
247 "ui.menutext",
248 "ui.scrollbar",
249 "ui.threeddarkshadow",
250 "ui.threedface",
251 "ui.threedhighlight",
252 "ui.threedlightshadow",
253 "ui.threedshadow",
254 "ui.window",
255 "ui.windowframe",
256 "ui.windowtext",
257 "ui.-moz-buttondefault",
258 "ui.-moz-default-color",
259 "ui.-moz-default-background-color",
260 "ui.-moz-dialog",
261 "ui.-moz-dialogtext",
262 "ui.-moz-dragtargetzone",
263 "ui.-moz-cellhighlight",
264 "ui.-moz_cellhighlighttext",
265 "ui.selecteditem",
266 "ui.selecteditemtext",
267 "ui.-moz-buttonhoverface",
268 "ui.-moz_buttonhovertext",
269 "ui.-moz_menuhover",
270 "ui.-moz_menuhovertext",
271 "ui.-moz_menubartext",
272 "ui.-moz_menubarhovertext",
273 "ui.-moz_eventreerow",
274 "ui.-moz_oddtreerow",
275 "ui.-moz-buttonactivetext",
276 "ui.-moz-buttonactiveface",
277 "ui.-moz-buttondisabledface",
278 "ui.-moz_mac_chrome_active",
279 "ui.-moz_mac_chrome_inactive",
280 "ui.-moz-mac-defaultbuttontext",
281 "ui.-moz-mac-focusring",
282 "ui.-moz-mac-menuselect",
283 "ui.-moz-mac-menushadow",
284 "ui.-moz-mac-menutextdisable",
285 "ui.-moz-mac-menutextselect",
286 "ui.-moz_mac_disabledtoolbartext",
287 "ui.-moz-mac-secondaryhighlight",
288 "ui.-moz-mac-vibrant-titlebar-light",
289 "ui.-moz-mac-vibrant-titlebar-dark",
290 "ui.-moz-mac-menupopup",
291 "ui.-moz-mac-menuitem",
292 "ui.-moz-mac-active-menuitem",
293 "ui.-moz-mac-source-list",
294 "ui.-moz-mac-source-list-selection",
295 "ui.-moz-mac-active-source-list-selection",
296 "ui.-moz-mac-tooltip",
297 "ui.-moz-accent-color",
298 "ui.-moz-accent-color-foreground",
299 "ui.-moz-autofill-background",
300 "ui.-moz-win-mediatext",
301 "ui.-moz-win-communicationstext",
302 "ui.-moz-nativehyperlinktext",
303 "ui.-moz-nativevisitedhyperlinktext",
304 "ui.-moz-hyperlinktext",
305 "ui.-moz-activehyperlinktext",
306 "ui.-moz-visitedhyperlinktext",
307 "ui.-moz-comboboxtext",
308 "ui.-moz-combobox",
309 "ui.-moz-colheadertext",
310 "ui.-moz-colheaderhovertext",
313 static_assert(ArrayLength(sColorPrefs) == size_t(LookAndFeel::ColorID::End),
314 "Should have a pref for each color value");
316 const char* nsXPLookAndFeel::GetColorPrefName(ColorID aId) {
317 return sColorPrefs[size_t(aId)];
320 bool nsXPLookAndFeel::sInitialized = false;
322 nsXPLookAndFeel* nsXPLookAndFeel::sInstance = nullptr;
323 bool nsXPLookAndFeel::sShutdown = false;
325 // static
326 nsXPLookAndFeel* nsXPLookAndFeel::GetInstance() {
327 if (sInstance) {
328 return sInstance;
331 NS_ENSURE_TRUE(!sShutdown, nullptr);
333 // If we're in a content process, then the parent process will have supplied
334 // us with an initial FullLookAndFeel object.
335 // We grab this data from the ContentChild,
336 // where it's been temporarily stashed, and initialize our new LookAndFeel
337 // object with it.
339 FullLookAndFeel* lnf = nullptr;
341 if (auto* cc = mozilla::dom::ContentChild::GetSingleton()) {
342 lnf = &cc->BorrowLookAndFeelData();
345 if (lnf) {
346 sInstance = new widget::RemoteLookAndFeel(std::move(*lnf));
347 } else if (gfxPlatform::IsHeadless()) {
348 sInstance = new widget::HeadlessLookAndFeel();
349 } else {
350 sInstance = new nsLookAndFeel();
353 // This is only ever used once during initialization, and can be cleared now.
354 if (lnf) {
355 *lnf = {};
358 nsNativeBasicTheme::Init();
359 return sInstance;
362 // static
363 void nsXPLookAndFeel::Shutdown() {
364 if (sShutdown) {
365 return;
368 sShutdown = true;
369 delete sInstance;
370 sInstance = nullptr;
372 // This keeps strings alive, so need to clear to make leak checking happy.
373 sFontCache.Clear();
375 nsNativeBasicTheme::Shutdown();
378 static void IntPrefChanged() {
379 // Int prefs can't change our system colors or fonts.
380 LookAndFeel::NotifyChangedAllWindows(
381 widget::ThemeChangeKind::MediaQueriesOnly);
384 static void FloatPrefChanged() {
385 // Float prefs can't change our system colors or fonts.
386 LookAndFeel::NotifyChangedAllWindows(
387 widget::ThemeChangeKind::MediaQueriesOnly);
390 static void ColorPrefChanged() {
391 // Color prefs affect style, because they by definition change system colors.
392 LookAndFeel::NotifyChangedAllWindows(widget::ThemeChangeKind::Style);
395 // static
396 void nsXPLookAndFeel::OnPrefChanged(const char* aPref, void* aClosure) {
397 nsDependentCString prefName(aPref);
398 for (const char* pref : sIntPrefs) {
399 if (prefName.Equals(pref)) {
400 IntPrefChanged();
401 return;
405 for (const char* pref : sFloatPrefs) {
406 if (prefName.Equals(pref)) {
407 FloatPrefChanged();
408 return;
412 for (const char* pref : sColorPrefs) {
413 // We use StringBeginsWith to handle .dark prefs too.
414 if (StringBeginsWith(prefName, nsDependentCString(pref))) {
415 ColorPrefChanged();
416 return;
421 static constexpr struct {
422 nsLiteralCString mName;
423 widget::ThemeChangeKind mChangeKind =
424 widget::ThemeChangeKind::MediaQueriesOnly;
425 } kMediaQueryPrefs[] = {
426 {"browser.display.windows.native_menus"_ns},
427 {"browser.proton.places-tooltip.enabled"_ns},
428 {"layout.css.prefers-color-scheme.content-override"_ns},
429 // This affects not only the media query, but also the native theme, so we
430 // need to re-layout.
431 {"browser.theme.toolbar-theme"_ns, widget::ThemeChangeKind::AllBits},
432 {"browser.theme.content-theme"_ns},
433 {"layout.css.color-scheme.content-override"_ns},
436 // Read values from the user's preferences.
437 // This is done once at startup, but since the user's preferences
438 // haven't actually been read yet at that time, we also have to
439 // set a callback to inform us of changes to each pref.
440 void nsXPLookAndFeel::Init() {
441 MOZ_RELEASE_ASSERT(NS_IsMainThread());
443 // Say we're already initialized, and take the chance that it might fail;
444 // protects against some other process writing to our static variables.
445 sInitialized = true;
447 RecomputeColorSchemes();
449 // XXX If we could reorganize the pref names, we should separate the branch
450 // for each types. Then, we could reduce the unnecessary loop from
451 // nsXPLookAndFeel::OnPrefChanged().
452 Preferences::RegisterPrefixCallback(OnPrefChanged, "ui.");
453 // We really do just want the accessibility.tabfocus pref, not other prefs
454 // that start with that string.
455 Preferences::RegisterCallback(OnPrefChanged, "accessibility.tabfocus");
457 for (auto& pref : kMediaQueryPrefs) {
458 Preferences::RegisterCallback(
459 [](const char*, void* aChangeKind) {
460 auto changeKind =
461 widget::ThemeChangeKind(reinterpret_cast<uintptr_t>(aChangeKind));
462 LookAndFeel::NotifyChangedAllWindows(changeKind);
464 pref.mName, reinterpret_cast<void*>(uintptr_t(pref.mChangeKind)));
468 nsXPLookAndFeel::~nsXPLookAndFeel() {
469 NS_ASSERTION(sInstance == this,
470 "This destroying instance isn't the singleton instance");
471 sInstance = nullptr;
474 static bool IsSpecialColor(LookAndFeel::ColorID aID, nscolor aColor) {
475 using ColorID = LookAndFeel::ColorID;
477 if (aColor == NS_SAME_AS_FOREGROUND_COLOR) {
478 return true;
481 switch (aID) {
482 case ColorID::IMESelectedRawTextBackground:
483 case ColorID::IMESelectedConvertedTextBackground:
484 case ColorID::IMERawInputBackground:
485 case ColorID::IMEConvertedTextBackground:
486 case ColorID::IMESelectedRawTextForeground:
487 case ColorID::IMESelectedConvertedTextForeground:
488 case ColorID::IMERawInputForeground:
489 case ColorID::IMEConvertedTextForeground:
490 case ColorID::IMERawInputUnderline:
491 case ColorID::IMEConvertedTextUnderline:
492 case ColorID::IMESelectedRawTextUnderline:
493 case ColorID::IMESelectedConvertedTextUnderline:
494 case ColorID::SpellCheckerUnderline:
495 return NS_IS_SELECTION_SPECIAL_COLOR(aColor);
496 default:
497 break;
500 * In GetColor(), every color that is not a special color is color
501 * corrected. Use false to make other colors color corrected.
503 return false;
506 nscolor nsXPLookAndFeel::GetStandinForNativeColor(ColorID aID,
507 ColorScheme aScheme) {
508 if (aScheme == ColorScheme::Dark) {
509 if (auto color = GenericDarkColor(aID)) {
510 return *color;
514 // The stand-in colors are taken from what the non-native theme needs (for
515 // field/button colors), the Windows 7 Aero theme except Mac-specific colors
516 // which are taken from Mac OS 10.7.
518 #define COLOR(name_, r, g, b) \
519 case ColorID::name_: \
520 return NS_RGB(r, g, b);
522 #define COLORA(name_, r, g, b, a) \
523 case ColorID::name_: \
524 return NS_RGBA(r, g, b, a);
526 switch (aID) {
527 // These are here for the purposes of headless mode.
528 case ColorID::IMESelectedRawTextBackground:
529 case ColorID::IMESelectedConvertedTextBackground:
530 case ColorID::IMERawInputBackground:
531 case ColorID::IMEConvertedTextBackground:
532 return NS_TRANSPARENT;
533 case ColorID::IMESelectedRawTextForeground:
534 case ColorID::IMESelectedConvertedTextForeground:
535 case ColorID::IMERawInputForeground:
536 case ColorID::IMEConvertedTextForeground:
537 return NS_SAME_AS_FOREGROUND_COLOR;
538 case ColorID::IMERawInputUnderline:
539 case ColorID::IMEConvertedTextUnderline:
540 return NS_40PERCENT_FOREGROUND_COLOR;
541 COLOR(MozAccentColor, 53, 132, 228)
542 COLOR(MozAccentColorForeground, 0xff, 0xff, 0xff)
543 COLOR(SpellCheckerUnderline, 0xff, 0x00, 0x00)
544 COLOR(TextSelectDisabledBackground, 0xaa, 0xaa, 0xaa)
546 // CSS 2 colors:
547 COLOR(Activeborder, 0xB4, 0xB4, 0xB4)
548 COLOR(Activecaption, 0x99, 0xB4, 0xD1)
549 COLOR(Appworkspace, 0xAB, 0xAB, 0xAB)
550 COLOR(Background, 0x00, 0x00, 0x00)
551 COLOR(Buttonhighlight, 0xFF, 0xFF, 0xFF)
552 COLOR(Buttonshadow, 0xA0, 0xA0, 0xA0)
554 // Buttons and comboboxes should be kept in sync since they are drawn with
555 // the same colors by the non-native theme.
556 COLOR(Buttonface, 0xe9, 0xe9, 0xed)
557 COLORA(MozButtondisabledface, 0xe9, 0xe9, 0xed, 128)
559 COLOR(MozCombobox, 0xe9, 0xe9, 0xed)
561 COLOR(Buttontext, 0x00, 0x00, 0x00)
562 COLOR(MozComboboxtext, 0x00, 0x00, 0x00)
564 COLOR(Captiontext, 0x00, 0x00, 0x00)
565 COLOR(Graytext, 0x6D, 0x6D, 0x6D)
566 COLOR(Highlight, 0x33, 0x99, 0xFF)
567 COLOR(Highlighttext, 0xFF, 0xFF, 0xFF)
568 COLOR(Inactiveborder, 0xF4, 0xF7, 0xFC)
569 COLOR(Inactivecaption, 0xBF, 0xCD, 0xDB)
570 COLOR(Inactivecaptiontext, 0x43, 0x4E, 0x54)
571 COLOR(Infobackground, 0xFF, 0xFF, 0xE1)
572 COLOR(Infotext, 0x00, 0x00, 0x00)
573 COLOR(Menu, 0xF0, 0xF0, 0xF0)
574 COLOR(Menutext, 0x00, 0x00, 0x00)
575 COLOR(Scrollbar, 0xC8, 0xC8, 0xC8)
576 COLOR(Threeddarkshadow, 0x69, 0x69, 0x69)
577 COLOR(Threedface, 0xF0, 0xF0, 0xF0)
578 COLOR(Threedhighlight, 0xFF, 0xFF, 0xFF)
579 COLOR(Threedlightshadow, 0xE3, 0xE3, 0xE3)
580 COLOR(Threedshadow, 0xA0, 0xA0, 0xA0)
581 COLOR(Window, 0xFF, 0xFF, 0xFF)
582 COLOR(Windowframe, 0x64, 0x64, 0x64)
583 COLOR(Windowtext, 0x00, 0x00, 0x00)
584 COLOR(MozButtondefault, 0x69, 0x69, 0x69)
585 COLOR(Field, 0xFF, 0xFF, 0xFF)
586 COLORA(MozDisabledfield, 0xFF, 0xFF, 0xFF, 128)
587 COLOR(Fieldtext, 0x00, 0x00, 0x00)
588 COLOR(MozDialog, 0xF0, 0xF0, 0xF0)
589 COLOR(MozDialogtext, 0x00, 0x00, 0x00)
590 COLOR(MozColheadertext, 0x00, 0x00, 0x00)
591 COLOR(MozColheaderhovertext, 0x00, 0x00, 0x00)
592 COLOR(MozDragtargetzone, 0xFF, 0xFF, 0xFF)
593 COLOR(MozCellhighlight, 0xF0, 0xF0, 0xF0)
594 COLOR(MozCellhighlighttext, 0x00, 0x00, 0x00)
595 COLOR(Selecteditem, 0x33, 0x99, 0xFF)
596 COLOR(Selecteditemtext, 0xFF, 0xFF, 0xFF)
597 COLOR(MozButtonhoverface, 0xd0, 0xd0, 0xd7)
598 COLOR(MozButtonhovertext, 0x00, 0x00, 0x00)
599 COLOR(MozButtonactiveface, 0xb1, 0xb1, 0xb9)
600 COLOR(MozButtonactivetext, 0x00, 0x00, 0x00)
601 COLOR(MozMenuhover, 0x33, 0x99, 0xFF)
602 COLOR(MozMenuhovertext, 0x00, 0x00, 0x00)
603 COLOR(MozMenubartext, 0x00, 0x00, 0x00)
604 COLOR(MozMenubarhovertext, 0x00, 0x00, 0x00)
605 COLOR(MozEventreerow, 0xFF, 0xFF, 0xFF)
606 COLOR(MozOddtreerow, 0xFF, 0xFF, 0xFF)
607 COLOR(MozMacChromeActive, 0xB2, 0xB2, 0xB2)
608 COLOR(MozMacChromeInactive, 0xE1, 0xE1, 0xE1)
609 COLOR(MozMacFocusring, 0x60, 0x9D, 0xD7)
610 COLOR(MozMacMenuselect, 0x38, 0x75, 0xD7)
611 COLOR(MozMacMenushadow, 0xA3, 0xA3, 0xA3)
612 COLOR(MozMacMenutextdisable, 0x88, 0x88, 0x88)
613 COLOR(MozMacMenutextselect, 0xFF, 0xFF, 0xFF)
614 COLOR(MozMacDisabledtoolbartext, 0x3F, 0x3F, 0x3F)
615 COLOR(MozMacSecondaryhighlight, 0xD4, 0xD4, 0xD4)
616 COLOR(MozMacVibrantTitlebarLight, 0xf7, 0xf7, 0xf7)
617 COLOR(MozMacVibrantTitlebarDark, 0x28, 0x28, 0x28)
618 COLOR(MozMacMenupopup, 0xe6, 0xe6, 0xe6)
619 COLOR(MozMacMenuitem, 0xe6, 0xe6, 0xe6)
620 COLOR(MozMacActiveMenuitem, 0x0a, 0x64, 0xdc)
621 COLOR(MozMacSourceList, 0xf7, 0xf7, 0xf7)
622 COLOR(MozMacSourceListSelection, 0xc8, 0xc8, 0xc8)
623 COLOR(MozMacActiveSourceListSelection, 0x0a, 0x64, 0xdc)
624 COLOR(MozMacTooltip, 0xf7, 0xf7, 0xf7)
625 // Seems to be the default color (hardcoded because of bug 1065998)
626 COLOR(MozWinMediatext, 0xFF, 0xFF, 0xFF)
627 COLOR(MozWinCommunicationstext, 0xFF, 0xFF, 0xFF)
628 COLOR(MozNativehyperlinktext, 0x00, 0x66, 0xCC)
629 COLOR(MozNativevisitedhyperlinktext, 0x55, 0x1A, 0x8B)
630 default:
631 break;
633 return NS_RGB(0xFF, 0xFF, 0xFF);
636 #undef COLOR
637 #undef COLORA
639 // Taken from in-content/common.inc.css's dark theme.
640 Maybe<nscolor> nsXPLookAndFeel::GenericDarkColor(ColorID aID) {
641 nscolor color = NS_RGB(0, 0, 0);
642 static constexpr nscolor kWindowBackground = NS_RGB(28, 27, 34);
643 static constexpr nscolor kWindowText = NS_RGB(251, 251, 254);
644 switch (aID) {
645 case ColorID::Window: // --in-content-page-background
646 case ColorID::Background:
647 case ColorID::Menu:
648 color = kWindowBackground;
649 break;
650 case ColorID::MozOddtreerow:
651 case ColorID::MozDialog: // --in-content-box-background
652 color = NS_RGB(35, 34, 43);
653 break;
654 case ColorID::Windowtext: // --in-content-page-color
655 case ColorID::Menutext:
656 case ColorID::MozDialogtext:
657 case ColorID::Fieldtext:
658 case ColorID::Buttontext: // --in-content-button-text-color (via
659 // --in-content-page-color)
660 case ColorID::MozComboboxtext:
661 case ColorID::MozButtonhovertext:
662 case ColorID::MozButtonactivetext:
663 color = kWindowText;
664 break;
665 case ColorID::Threedlightshadow: // --in-content-box-border-color computed
666 // with kWindowText above
667 // kWindowBackground.
668 case ColorID::Graytext: // opacity: 0.4 of kWindowText blended over the
669 // "Window" background color, which happens to be
670 // the same :-)
671 color = NS_ComposeColors(kWindowBackground, NS_RGBA(251, 251, 254, 102));
672 break;
673 case ColorID::MozCellhighlight:
674 case ColorID::Selecteditem: // --in-content-primary-button-background /
675 // --in-content-item-selected
676 color = NS_RGB(0, 221, 255);
677 break;
678 case ColorID::Field:
679 case ColorID::Buttonface: // --in-content-button-background
680 case ColorID::MozCombobox:
681 case ColorID::MozCellhighlighttext:
682 case ColorID::Selecteditemtext: // --in-content-primary-button-text-color /
683 // --in-content-item-selected-text
684 color = NS_RGB(43, 42, 51);
685 break;
686 case ColorID::Threeddarkshadow: // Same as Threedlightshadow but with the
687 // background.
688 case ColorID::MozDisabledfield: // opacity: 0.4 of the face above blended
689 // over the "Window" background color.
690 case ColorID::MozButtondisabledface:
691 color = NS_ComposeColors(kWindowBackground, NS_RGBA(43, 42, 51, 102));
692 break;
693 case ColorID::MozButtonhoverface: // --in-content-button-background-hover
694 color = NS_RGB(82, 82, 94);
695 break;
696 case ColorID::MozButtonactiveface: // --in-content-button-background-active
697 color = NS_RGB(91, 91, 102);
698 break;
699 case ColorID::Highlight:
700 color = NS_RGBA(0, 221, 255, 78);
701 break;
702 case ColorID::Highlighttext:
703 color = NS_SAME_AS_FOREGROUND_COLOR;
704 break;
705 case ColorID::MozNativehyperlinktext:
706 // If you change this color, you probably also want to change the default
707 // value of browser.anchor_color.dark.
708 color = NS_RGB(0x8c, 0x8c, 0xff);
709 break;
710 case ColorID::MozNativevisitedhyperlinktext:
711 // If you change this color, you probably also want to change the default
712 // value of browser.visited_color.dark.
713 color = NS_RGB(0xff, 0xad, 0xff);
714 break;
716 default:
717 return Nothing();
719 return Some(color);
722 // Uncomment the #define below if you want to debug system color use in a skin
723 // that uses them. When set, it will make all system color pairs that are
724 // appropriate for foreground/background pairing the same. This means if the
725 // skin is using system colors correctly you will not be able to see *any* text.
727 // #define DEBUG_SYSTEM_COLOR_USE
729 #ifdef DEBUG_SYSTEM_COLOR_USE
730 static nsresult SystemColorUseDebuggingColor(LookAndFeel::ColorID aID,
731 nscolor& aResult) {
732 using ColorID = LookAndFeel::ColorID;
734 switch (aID) {
735 // css2 http://www.w3.org/TR/REC-CSS2/ui.html#system-colors
736 case ColorID::Activecaption:
737 // active window caption background
738 case ColorID::Captiontext:
739 // text in active window caption
740 aResult = NS_RGB(0xff, 0x00, 0x00);
741 break;
743 case ColorID::Highlight:
744 // background of selected item
745 case ColorID::Highlighttext:
746 // text of selected item
747 aResult = NS_RGB(0xff, 0xff, 0x00);
748 break;
750 case ColorID::Inactivecaption:
751 // inactive window caption
752 case ColorID::Inactivecaptiontext:
753 // text in inactive window caption
754 aResult = NS_RGB(0x66, 0x66, 0x00);
755 break;
757 case ColorID::Infobackground:
758 // tooltip background color
759 case ColorID::Infotext:
760 // tooltip text color
761 aResult = NS_RGB(0x00, 0xff, 0x00);
762 break;
764 case ColorID::Menu:
765 // menu background
766 case ColorID::Menutext:
767 // menu text
768 aResult = NS_RGB(0x00, 0xff, 0xff);
769 break;
771 case ColorID::Threedface:
772 case ColorID::Buttonface:
773 // 3-D face color
774 case ColorID::Buttontext:
775 // text on push buttons
776 aResult = NS_RGB(0x00, 0x66, 0x66);
777 break;
779 case ColorID::Window:
780 case ColorID::Windowtext:
781 aResult = NS_RGB(0x00, 0x00, 0xff);
782 break;
784 // from the CSS3 working draft (not yet finalized)
785 // http://www.w3.org/tr/2000/wd-css3-userint-20000216.html#color
787 case ColorID::Field:
788 case ColorID::Fieldtext:
789 aResult = NS_RGB(0xff, 0x00, 0xff);
790 break;
792 case ColorID::MozDialog:
793 case ColorID::MozDialogtext:
794 aResult = NS_RGB(0x66, 0x00, 0x66);
795 break;
797 default:
798 return NS_ERROR_NOT_AVAILABLE;
801 return NS_OK;
803 #endif
805 static nsresult GetPrefColor(const char* aPref, nscolor& aResult) {
806 nsAutoCString colorStr;
807 MOZ_TRY(Preferences::GetCString(aPref, colorStr));
808 if (!ServoCSSParser::ComputeColor(nullptr, NS_RGB(0, 0, 0), colorStr,
809 &aResult)) {
810 return NS_ERROR_FAILURE;
812 return NS_OK;
815 static nsresult GetColorFromPref(LookAndFeel::ColorID aID, ColorScheme aScheme,
816 nscolor& aResult) {
817 const char* prefName = sColorPrefs[size_t(aID)];
818 if (aScheme == ColorScheme::Dark) {
819 nsAutoCString darkPrefName(prefName);
820 darkPrefName.Append(".dark");
821 if (NS_SUCCEEDED(GetPrefColor(darkPrefName.get(), aResult))) {
822 return NS_OK;
825 return GetPrefColor(prefName, aResult);
828 // All these routines will return NS_OK if they have a value,
829 // in which case the nsLookAndFeel should use that value;
830 // otherwise we'll return NS_ERROR_NOT_AVAILABLE, in which case, the
831 // platform-specific nsLookAndFeel should use its own values instead.
832 nsresult nsXPLookAndFeel::GetColorValue(ColorID aID, ColorScheme aScheme,
833 UseStandins aUseStandins,
834 nscolor& aResult) {
835 if (!sInitialized) {
836 Init();
839 #ifdef DEBUG_SYSTEM_COLOR_USE
840 if (NS_SUCCEEDED(SystemColorUseDebuggingColor(aID, aResult))) {
841 return NS_OK;
843 #endif
845 if (aUseStandins == UseStandins::Yes) {
846 aResult = GetStandinForNativeColor(aID, aScheme);
847 return NS_OK;
850 auto& cache =
851 aScheme == ColorScheme::Light ? sLightColorCache : sDarkColorCache;
852 if (const auto* cached = cache.Get(aID)) {
853 if (cached->isNothing()) {
854 return NS_ERROR_FAILURE;
856 aResult = cached->value();
857 return NS_OK;
860 if (NS_SUCCEEDED(GetColorFromPref(aID, aScheme, aResult))) {
861 cache.Insert(aID, Some(aResult));
862 return NS_OK;
865 if (NS_SUCCEEDED(NativeGetColor(aID, aScheme, aResult))) {
866 if (gfxPlatform::GetCMSMode() == CMSMode::All &&
867 !IsSpecialColor(aID, aResult)) {
868 qcms_transform* transform = gfxPlatform::GetCMSInverseRGBTransform();
869 if (transform) {
870 uint8_t color[4];
871 color[0] = NS_GET_R(aResult);
872 color[1] = NS_GET_G(aResult);
873 color[2] = NS_GET_B(aResult);
874 color[3] = NS_GET_A(aResult);
875 qcms_transform_data(transform, color, color, 1);
876 aResult = NS_RGBA(color[0], color[1], color[2], color[3]);
880 // NOTE: Servo holds a lock and the main thread is paused, so writing to the
881 // global cache here is fine.
882 cache.Insert(aID, Some(aResult));
883 return NS_OK;
886 cache.Insert(aID, Nothing());
887 return NS_ERROR_FAILURE;
890 nsresult nsXPLookAndFeel::GetIntValue(IntID aID, int32_t& aResult) {
891 if (!sInitialized) {
892 Init();
895 if (const auto* cached = sIntCache.Get(aID)) {
896 if (cached->isNothing()) {
897 return NS_ERROR_FAILURE;
899 aResult = cached->value();
900 return NS_OK;
903 if (NS_SUCCEEDED(Preferences::GetInt(sIntPrefs[size_t(aID)], &aResult))) {
904 sIntCache.Insert(aID, Some(aResult));
905 return NS_OK;
908 if (NS_FAILED(NativeGetInt(aID, aResult))) {
909 sIntCache.Insert(aID, Nothing());
910 return NS_ERROR_FAILURE;
913 sIntCache.Insert(aID, Some(aResult));
914 return NS_OK;
917 nsresult nsXPLookAndFeel::GetFloatValue(FloatID aID, float& aResult) {
918 if (!sInitialized) {
919 Init();
922 if (const auto* cached = sFloatCache.Get(aID)) {
923 if (cached->isNothing()) {
924 return NS_ERROR_FAILURE;
926 aResult = cached->value();
927 return NS_OK;
930 int32_t pref = 0;
931 if (NS_SUCCEEDED(Preferences::GetInt(sFloatPrefs[size_t(aID)], &pref))) {
932 aResult = float(pref) / 100.0f;
933 sFloatCache.Insert(aID, Some(aResult));
934 return NS_OK;
937 if (NS_FAILED(NativeGetFloat(aID, aResult))) {
938 sFloatCache.Insert(aID, Nothing());
939 return NS_ERROR_FAILURE;
942 sFloatCache.Insert(aID, Some(aResult));
943 return NS_OK;
946 bool nsXPLookAndFeel::LookAndFeelFontToStyle(const LookAndFeelFont& aFont,
947 nsString& aName,
948 gfxFontStyle& aStyle) {
949 if (!aFont.haveFont()) {
950 return false;
952 aName = aFont.name();
953 aStyle = gfxFontStyle();
954 aStyle.size = aFont.size();
955 aStyle.weight = FontWeight(aFont.weight());
956 aStyle.style =
957 aFont.italic() ? FontSlantStyle::Italic() : FontSlantStyle::Normal();
958 aStyle.systemFont = true;
959 return true;
962 widget::LookAndFeelFont nsXPLookAndFeel::StyleToLookAndFeelFont(
963 const nsAString& aName, const gfxFontStyle& aStyle) {
964 LookAndFeelFont font;
965 font.haveFont() = true;
966 font.name() = aName;
967 font.size() = aStyle.size;
968 font.weight() = aStyle.weight.ToFloat();
969 font.italic() = aStyle.style.IsItalic();
970 MOZ_ASSERT(aStyle.style.IsNormal() || aStyle.style.IsItalic(),
971 "Cannot handle oblique font style");
972 #ifdef DEBUG
974 // Assert that all the remaining font style properties have their
975 // default values.
976 gfxFontStyle candidate = aStyle;
977 gfxFontStyle defaults{};
978 candidate.size = defaults.size;
979 candidate.weight = defaults.weight;
980 candidate.style = defaults.style;
981 MOZ_ASSERT(candidate.Equals(defaults),
982 "Some font style properties not supported");
984 #endif
985 return font;
988 bool nsXPLookAndFeel::GetFontValue(FontID aID, nsString& aName,
989 gfxFontStyle& aStyle) {
990 if (const LookAndFeelFont* cached = sFontCache.Get(aID)) {
991 return LookAndFeelFontToStyle(*cached, aName, aStyle);
993 LookAndFeelFont font;
994 const bool haveFont = NativeGetFont(aID, aName, aStyle);
995 font.haveFont() = haveFont;
996 if (haveFont) {
997 font = StyleToLookAndFeelFont(aName, aStyle);
999 sFontCache.Insert(aID, std::move(font));
1000 return haveFont;
1003 void nsXPLookAndFeel::RefreshImpl() {
1004 // Wipe out our caches.
1005 sLightColorCache.Clear();
1006 sDarkColorCache.Clear();
1007 sFontCache.Clear();
1008 sFloatCache.Clear();
1009 sIntCache.Clear();
1010 RecomputeColorSchemes();
1012 // Clear any cached FullLookAndFeel data, which is now invalid.
1013 if (XRE_IsParentProcess()) {
1014 widget::RemoteLookAndFeel::ClearCachedData();
1018 static bool sRecordedLookAndFeelTelemetry = false;
1020 void nsXPLookAndFeel::RecordTelemetry() {
1021 if (!XRE_IsParentProcess()) {
1022 return;
1025 if (sRecordedLookAndFeelTelemetry) {
1026 return;
1029 sRecordedLookAndFeelTelemetry = true;
1031 int32_t i;
1032 Telemetry::ScalarSet(
1033 Telemetry::ScalarID::WIDGET_DARK_MODE,
1034 NS_SUCCEEDED(GetIntValue(IntID::SystemUsesDarkTheme, i)) && i != 0);
1036 RecordLookAndFeelSpecificTelemetry();
1039 namespace mozilla {
1041 // static
1042 void LookAndFeel::NotifyChangedAllWindows(widget::ThemeChangeKind aKind) {
1043 if (nsCOMPtr<nsIObserverService> obs = services::GetObserverService()) {
1044 const char16_t kind[] = {char16_t(aKind), 0};
1045 obs->NotifyObservers(nullptr, "internal-look-and-feel-changed", kind);
1049 static bool ShouldUseStandinsForNativeColorForNonNativeTheme(
1050 const dom::Document& aDoc, LookAndFeel::ColorID aColor) {
1051 using ColorID = LookAndFeel::ColorID;
1052 if (!aDoc.ShouldAvoidNativeTheme()) {
1053 return false;
1056 // The native theme doesn't use native system colors backgrounds etc, except
1057 // when in high-contrast mode, so spoof some of the colors with stand-ins to
1058 // prevent lack of contrast.
1059 switch (aColor) {
1060 case ColorID::Buttonface:
1061 case ColorID::Buttontext:
1062 case ColorID::MozButtonhoverface:
1063 case ColorID::MozButtonhovertext:
1064 case ColorID::MozButtonactiveface:
1065 case ColorID::MozButtonactivetext:
1066 case ColorID::MozButtondisabledface:
1068 case ColorID::Threedlightshadow:
1069 case ColorID::Threeddarkshadow:
1070 case ColorID::Threedface:
1072 case ColorID::MozCombobox:
1073 case ColorID::MozComboboxtext:
1075 case ColorID::Field:
1076 case ColorID::MozDisabledfield:
1077 case ColorID::Fieldtext:
1079 case ColorID::Graytext:
1081 return !PreferenceSheet::PrefsFor(aDoc)
1082 .NonNativeThemeShouldBeHighContrast();
1084 default:
1085 break;
1088 return false;
1091 ColorScheme LookAndFeel::sChromeColorScheme;
1092 ColorScheme LookAndFeel::sContentColorScheme;
1093 bool LookAndFeel::sColorSchemeInitialized;
1095 auto LookAndFeel::ColorSchemeSettingForChrome() -> ChromeColorSchemeSetting {
1096 switch (StaticPrefs::browser_theme_toolbar_theme()) {
1097 case 0: // Dark
1098 return ChromeColorSchemeSetting::Dark;
1099 case 1: // Light
1100 return ChromeColorSchemeSetting::Light;
1101 default:
1102 return ChromeColorSchemeSetting::System;
1106 void LookAndFeel::RecomputeColorSchemes() {
1107 sColorSchemeInitialized = true;
1109 sChromeColorScheme = [] {
1110 switch (ColorSchemeSettingForChrome()) {
1111 case ChromeColorSchemeSetting::Light:
1112 return ColorScheme::Light;
1113 case ChromeColorSchemeSetting::Dark:
1114 return ColorScheme::Dark;
1115 case ChromeColorSchemeSetting::System:
1116 break;
1118 return SystemColorScheme();
1119 }();
1121 sContentColorScheme = [] {
1122 switch (StaticPrefs::layout_css_prefers_color_scheme_content_override()) {
1123 case 0:
1124 return ColorScheme::Dark;
1125 case 1:
1126 return ColorScheme::Light;
1127 case 2:
1128 return SystemColorScheme();
1129 default:
1130 break; // Use the browser theme.
1133 switch (StaticPrefs::browser_theme_content_theme()) {
1134 case 0: // Dark
1135 return ColorScheme::Dark;
1136 case 1: // Light
1137 return ColorScheme::Light;
1138 default:
1139 return ColorSchemeForChrome();
1141 }();
1144 ColorScheme LookAndFeel::ColorSchemeForStyle(
1145 const dom::Document& aDoc, const StyleColorSchemeFlags& aFlags) {
1146 if (PreferenceSheet::MayForceColors()) {
1147 auto& prefs = PreferenceSheet::PrefsFor(aDoc);
1148 if (!prefs.mUseDocumentColors) {
1149 // When forcing colors, we can use our preferred color-scheme. Do this
1150 // only if we're using system colors, as dark preference colors are not
1151 // exposed on the UI.
1153 // Also, use light if we're using a high-contrast-theme on Windows, since
1154 // Windows overrides the light colors with HCM colors when HCM is active.
1155 #ifdef XP_WIN
1156 if (prefs.mUseAccessibilityTheme) {
1157 return ColorScheme::Light;
1159 #endif
1160 if (StaticPrefs::browser_display_use_system_colors()) {
1161 return aDoc.PreferredColorScheme();
1163 return ColorScheme::Light;
1167 StyleColorSchemeFlags style(aFlags);
1168 if (!style) {
1169 style.bits = aDoc.GetColorSchemeBits();
1171 const bool supportsDark = bool(style & StyleColorSchemeFlags::DARK);
1172 const bool supportsLight = bool(style & StyleColorSchemeFlags::LIGHT);
1173 if (supportsLight && supportsDark) {
1174 // Both color-schemes are explicitly supported, use the preferred one.
1175 return aDoc.PreferredColorScheme();
1177 if (supportsDark || supportsLight) {
1178 // One color-scheme is explicitly supported and one isn't, so use the one
1179 // the content supports.
1180 return supportsDark ? ColorScheme::Dark : ColorScheme::Light;
1182 // No value specified. Chrome docs always supports both, so use the preferred
1183 // color-scheme.
1184 if (nsContentUtils::IsChromeDoc(&aDoc)) {
1185 return aDoc.PreferredColorScheme();
1187 // Default content to light.
1188 return ColorScheme::Light;
1191 LookAndFeel::ColorScheme LookAndFeel::ColorSchemeForFrame(
1192 const nsIFrame* aFrame) {
1193 return ColorSchemeForStyle(*aFrame->PresContext()->Document(),
1194 aFrame->StyleUI()->mColorScheme.bits);
1197 // static
1198 Maybe<nscolor> LookAndFeel::GetColor(ColorID aId, ColorScheme aScheme,
1199 UseStandins aUseStandins) {
1200 nscolor result;
1201 nsresult rv = nsLookAndFeel::GetInstance()->GetColorValue(
1202 aId, aScheme, aUseStandins, result);
1203 if (NS_FAILED(rv)) {
1204 return Nothing();
1206 return Some(result);
1209 // Returns whether there is a CSS color name for this color.
1210 static bool ColorIsCSSAccessible(LookAndFeel::ColorID aId) {
1211 using ColorID = LookAndFeel::ColorID;
1213 switch (aId) {
1214 case ColorID::TextSelectDisabledBackground:
1215 case ColorID::TextSelectAttentionBackground:
1216 case ColorID::TextSelectAttentionForeground:
1217 case ColorID::TextHighlightBackground:
1218 case ColorID::TextHighlightForeground:
1219 case ColorID::ThemedScrollbar:
1220 case ColorID::ThemedScrollbarInactive:
1221 case ColorID::ThemedScrollbarThumb:
1222 case ColorID::ThemedScrollbarThumbActive:
1223 case ColorID::ThemedScrollbarThumbInactive:
1224 case ColorID::ThemedScrollbarThumbHover:
1225 case ColorID::IMERawInputBackground:
1226 case ColorID::IMERawInputForeground:
1227 case ColorID::IMERawInputUnderline:
1228 case ColorID::IMESelectedRawTextBackground:
1229 case ColorID::IMESelectedRawTextForeground:
1230 case ColorID::IMESelectedRawTextUnderline:
1231 case ColorID::IMEConvertedTextBackground:
1232 case ColorID::IMEConvertedTextForeground:
1233 case ColorID::IMEConvertedTextUnderline:
1234 case ColorID::IMESelectedConvertedTextBackground:
1235 case ColorID::IMESelectedConvertedTextForeground:
1236 case ColorID::IMESelectedConvertedTextUnderline:
1237 case ColorID::SpellCheckerUnderline:
1238 return false;
1239 default:
1240 break;
1243 return true;
1246 LookAndFeel::UseStandins LookAndFeel::ShouldUseStandins(
1247 const dom::Document& aDoc, ColorID aId) {
1248 if (ShouldUseStandinsForNativeColorForNonNativeTheme(aDoc, aId)) {
1249 return UseStandins::Yes;
1251 if (nsContentUtils::UseStandinsForNativeColors() &&
1252 ColorIsCSSAccessible(aId) && !nsContentUtils::IsChromeDoc(&aDoc)) {
1253 return UseStandins::Yes;
1255 if (aDoc.IsStaticDocument() &&
1256 !PreferenceSheet::ContentPrefs().mUseDocumentColors) {
1257 return UseStandins::Yes;
1259 return UseStandins::No;
1262 Maybe<nscolor> LookAndFeel::GetColor(ColorID aId, const nsIFrame* aFrame) {
1263 const auto* doc = aFrame->PresContext()->Document();
1264 return GetColor(aId, ColorSchemeForFrame(aFrame),
1265 ShouldUseStandins(*doc, aId));
1268 // static
1269 nsresult LookAndFeel::GetInt(IntID aID, int32_t* aResult) {
1270 return nsLookAndFeel::GetInstance()->GetIntValue(aID, *aResult);
1273 // static
1274 nsresult LookAndFeel::GetFloat(FloatID aID, float* aResult) {
1275 return nsLookAndFeel::GetInstance()->GetFloatValue(aID, *aResult);
1278 // static
1279 bool LookAndFeel::GetFont(FontID aID, nsString& aName, gfxFontStyle& aStyle) {
1280 return nsLookAndFeel::GetInstance()->GetFontValue(aID, aName, aStyle);
1283 // static
1284 char16_t LookAndFeel::GetPasswordCharacter() {
1285 return nsLookAndFeel::GetInstance()->GetPasswordCharacterImpl();
1288 // static
1289 bool LookAndFeel::GetEchoPassword() {
1290 if (StaticPrefs::editor_password_mask_delay() >= 0) {
1291 return StaticPrefs::editor_password_mask_delay() > 0;
1293 return nsLookAndFeel::GetInstance()->GetEchoPasswordImpl();
1296 // static
1297 uint32_t LookAndFeel::GetPasswordMaskDelay() {
1298 int32_t delay = StaticPrefs::editor_password_mask_delay();
1299 if (delay < 0) {
1300 return nsLookAndFeel::GetInstance()->GetPasswordMaskDelayImpl();
1302 return delay;
1305 bool LookAndFeel::DrawInTitlebar() {
1306 switch (StaticPrefs::browser_tabs_inTitlebar()) {
1307 case 0:
1308 return false;
1309 case 1:
1310 return true;
1311 default:
1312 break;
1314 return nsLookAndFeel::GetInstance()->GetDefaultDrawInTitlebar();
1317 void LookAndFeel::GetThemeInfo(nsACString& aOut) {
1318 nsLookAndFeel::GetInstance()->GetThemeInfo(aOut);
1321 // static
1322 void LookAndFeel::Refresh() {
1323 nsLookAndFeel::GetInstance()->RefreshImpl();
1324 nsNativeBasicTheme::LookAndFeelChanged();
1327 // static
1328 void LookAndFeel::NativeInit() { nsLookAndFeel::GetInstance()->NativeInit(); }
1330 // static
1331 void LookAndFeel::SetData(widget::FullLookAndFeel&& aTables) {
1332 nsLookAndFeel::GetInstance()->SetDataImpl(std::move(aTables));
1335 } // namespace mozilla