Bug 1737746 - Use Permission spec's PermissionState r=mt,peterv
[gecko.git] / widget / nsXPLookAndFeel.cpp
blobcf0967fc5e349f1b12adf9950af4d40e6bf1300d
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.enabled"_ns},
428 {"browser.proton.places-tooltip.enabled"_ns},
429 {"layout.css.prefers-color-scheme.content-override"_ns},
430 // This affects not only the media query, but also the native theme, so we
431 // need to re-layout.
432 {"browser.theme.toolbar-theme"_ns, widget::ThemeChangeKind::AllBits},
433 {"browser.theme.content-theme"_ns},
434 {"layout.css.color-scheme.content-override"_ns},
437 // Read values from the user's preferences.
438 // This is done once at startup, but since the user's preferences
439 // haven't actually been read yet at that time, we also have to
440 // set a callback to inform us of changes to each pref.
441 void nsXPLookAndFeel::Init() {
442 MOZ_RELEASE_ASSERT(NS_IsMainThread());
444 // Say we're already initialized, and take the chance that it might fail;
445 // protects against some other process writing to our static variables.
446 sInitialized = true;
448 RecomputeColorSchemes();
450 // XXX If we could reorganize the pref names, we should separate the branch
451 // for each types. Then, we could reduce the unnecessary loop from
452 // nsXPLookAndFeel::OnPrefChanged().
453 Preferences::RegisterPrefixCallback(OnPrefChanged, "ui.");
454 // We really do just want the accessibility.tabfocus pref, not other prefs
455 // that start with that string.
456 Preferences::RegisterCallback(OnPrefChanged, "accessibility.tabfocus");
458 for (auto& pref : kMediaQueryPrefs) {
459 Preferences::RegisterCallback(
460 [](const char*, void* aChangeKind) {
461 auto changeKind =
462 widget::ThemeChangeKind(reinterpret_cast<uintptr_t>(aChangeKind));
463 LookAndFeel::NotifyChangedAllWindows(changeKind);
465 pref.mName, reinterpret_cast<void*>(uintptr_t(pref.mChangeKind)));
469 nsXPLookAndFeel::~nsXPLookAndFeel() {
470 NS_ASSERTION(sInstance == this,
471 "This destroying instance isn't the singleton instance");
472 sInstance = nullptr;
475 static bool IsSpecialColor(LookAndFeel::ColorID aID, nscolor aColor) {
476 using ColorID = LookAndFeel::ColorID;
478 if (aColor == NS_SAME_AS_FOREGROUND_COLOR) {
479 return true;
482 switch (aID) {
483 case ColorID::IMESelectedRawTextBackground:
484 case ColorID::IMESelectedConvertedTextBackground:
485 case ColorID::IMERawInputBackground:
486 case ColorID::IMEConvertedTextBackground:
487 case ColorID::IMESelectedRawTextForeground:
488 case ColorID::IMESelectedConvertedTextForeground:
489 case ColorID::IMERawInputForeground:
490 case ColorID::IMEConvertedTextForeground:
491 case ColorID::IMERawInputUnderline:
492 case ColorID::IMEConvertedTextUnderline:
493 case ColorID::IMESelectedRawTextUnderline:
494 case ColorID::IMESelectedConvertedTextUnderline:
495 case ColorID::SpellCheckerUnderline:
496 return NS_IS_SELECTION_SPECIAL_COLOR(aColor);
497 default:
498 break;
501 * In GetColor(), every color that is not a special color is color
502 * corrected. Use false to make other colors color corrected.
504 return false;
507 nscolor nsXPLookAndFeel::GetStandinForNativeColor(ColorID aID,
508 ColorScheme aScheme) {
509 if (aScheme == ColorScheme::Dark) {
510 if (auto color = GenericDarkColor(aID)) {
511 return *color;
515 // The stand-in colors are taken from what the non-native theme needs (for
516 // field/button colors), the Windows 7 Aero theme except Mac-specific colors
517 // which are taken from Mac OS 10.7.
519 #define COLOR(name_, r, g, b) \
520 case ColorID::name_: \
521 return NS_RGB(r, g, b);
523 #define COLORA(name_, r, g, b, a) \
524 case ColorID::name_: \
525 return NS_RGBA(r, g, b, a);
527 switch (aID) {
528 // CSS 2 colors:
529 COLOR(Activeborder, 0xB4, 0xB4, 0xB4)
530 COLOR(Activecaption, 0x99, 0xB4, 0xD1)
531 COLOR(Appworkspace, 0xAB, 0xAB, 0xAB)
532 COLOR(Background, 0x00, 0x00, 0x00)
533 COLOR(Buttonhighlight, 0xFF, 0xFF, 0xFF)
534 COLOR(Buttonshadow, 0xA0, 0xA0, 0xA0)
536 // Buttons and comboboxes should be kept in sync since they are drawn with
537 // the same colors by the non-native theme.
538 COLOR(Buttonface, 0xe9, 0xe9, 0xed)
539 COLORA(MozButtondisabledface, 0xe9, 0xe9, 0xed, 128)
541 COLOR(MozCombobox, 0xe9, 0xe9, 0xed)
543 COLOR(Buttontext, 0x00, 0x00, 0x00)
544 COLOR(MozComboboxtext, 0x00, 0x00, 0x00)
546 COLOR(Captiontext, 0x00, 0x00, 0x00)
547 COLOR(Graytext, 0x6D, 0x6D, 0x6D)
548 COLOR(Highlight, 0x33, 0x99, 0xFF)
549 COLOR(Highlighttext, 0xFF, 0xFF, 0xFF)
550 COLOR(Inactiveborder, 0xF4, 0xF7, 0xFC)
551 COLOR(Inactivecaption, 0xBF, 0xCD, 0xDB)
552 COLOR(Inactivecaptiontext, 0x43, 0x4E, 0x54)
553 COLOR(Infobackground, 0xFF, 0xFF, 0xE1)
554 COLOR(Infotext, 0x00, 0x00, 0x00)
555 COLOR(Menu, 0xF0, 0xF0, 0xF0)
556 COLOR(Menutext, 0x00, 0x00, 0x00)
557 COLOR(Scrollbar, 0xC8, 0xC8, 0xC8)
558 COLOR(Threeddarkshadow, 0x69, 0x69, 0x69)
559 COLOR(Threedface, 0xF0, 0xF0, 0xF0)
560 COLOR(Threedhighlight, 0xFF, 0xFF, 0xFF)
561 COLOR(Threedlightshadow, 0xE3, 0xE3, 0xE3)
562 COLOR(Threedshadow, 0xA0, 0xA0, 0xA0)
563 COLOR(Window, 0xFF, 0xFF, 0xFF)
564 COLOR(Windowframe, 0x64, 0x64, 0x64)
565 COLOR(Windowtext, 0x00, 0x00, 0x00)
566 COLOR(MozButtondefault, 0x69, 0x69, 0x69)
567 COLOR(Field, 0xFF, 0xFF, 0xFF)
568 COLORA(MozDisabledfield, 0xFF, 0xFF, 0xFF, 128)
569 COLOR(Fieldtext, 0x00, 0x00, 0x00)
570 COLOR(MozDialog, 0xF0, 0xF0, 0xF0)
571 COLOR(MozDialogtext, 0x00, 0x00, 0x00)
572 COLOR(MozColheadertext, 0x00, 0x00, 0x00)
573 COLOR(MozColheaderhovertext, 0x00, 0x00, 0x00)
574 COLOR(MozDragtargetzone, 0xFF, 0xFF, 0xFF)
575 COLOR(MozCellhighlight, 0xF0, 0xF0, 0xF0)
576 COLOR(MozCellhighlighttext, 0x00, 0x00, 0x00)
577 COLOR(Selecteditem, 0x33, 0x99, 0xFF)
578 COLOR(Selecteditemtext, 0xFF, 0xFF, 0xFF)
579 COLOR(MozButtonhoverface, 0xd0, 0xd0, 0xd7)
580 COLOR(MozButtonhovertext, 0x00, 0x00, 0x00)
581 COLOR(MozButtonactiveface, 0xb1, 0xb1, 0xb9)
582 COLOR(MozButtonactivetext, 0x00, 0x00, 0x00)
583 COLOR(MozMenuhover, 0x33, 0x99, 0xFF)
584 COLOR(MozMenuhovertext, 0x00, 0x00, 0x00)
585 COLOR(MozMenubartext, 0x00, 0x00, 0x00)
586 COLOR(MozMenubarhovertext, 0x00, 0x00, 0x00)
587 COLOR(MozOddtreerow, 0xFF, 0xFF, 0xFF)
588 COLOR(MozMacChromeActive, 0xB2, 0xB2, 0xB2)
589 COLOR(MozMacChromeInactive, 0xE1, 0xE1, 0xE1)
590 COLOR(MozMacFocusring, 0x60, 0x9D, 0xD7)
591 COLOR(MozMacMenuselect, 0x38, 0x75, 0xD7)
592 COLOR(MozMacMenushadow, 0xA3, 0xA3, 0xA3)
593 COLOR(MozMacMenutextdisable, 0x88, 0x88, 0x88)
594 COLOR(MozMacMenutextselect, 0xFF, 0xFF, 0xFF)
595 COLOR(MozMacDisabledtoolbartext, 0x3F, 0x3F, 0x3F)
596 COLOR(MozMacSecondaryhighlight, 0xD4, 0xD4, 0xD4)
597 COLOR(MozMacVibrantTitlebarLight, 0xf7, 0xf7, 0xf7)
598 COLOR(MozMacVibrantTitlebarDark, 0x28, 0x28, 0x28)
599 COLOR(MozMacMenupopup, 0xe6, 0xe6, 0xe6)
600 COLOR(MozMacMenuitem, 0xe6, 0xe6, 0xe6)
601 COLOR(MozMacActiveMenuitem, 0x0a, 0x64, 0xdc)
602 COLOR(MozMacSourceList, 0xf7, 0xf7, 0xf7)
603 COLOR(MozMacSourceListSelection, 0xc8, 0xc8, 0xc8)
604 COLOR(MozMacActiveSourceListSelection, 0x0a, 0x64, 0xdc)
605 COLOR(MozMacTooltip, 0xf7, 0xf7, 0xf7)
606 // Seems to be the default color (hardcoded because of bug 1065998)
607 COLOR(MozWinMediatext, 0xFF, 0xFF, 0xFF)
608 COLOR(MozWinCommunicationstext, 0xFF, 0xFF, 0xFF)
609 COLOR(MozNativehyperlinktext, 0x00, 0x66, 0xCC)
610 COLOR(MozNativevisitedhyperlinktext, 0x55, 0x1A, 0x8B)
611 default:
612 break;
614 return NS_RGB(0xFF, 0xFF, 0xFF);
617 #undef COLOR
618 #undef COLORA
620 // Taken from in-content/common.inc.css's dark theme.
621 Maybe<nscolor> nsXPLookAndFeel::GenericDarkColor(ColorID aID) {
622 nscolor color = NS_RGB(0, 0, 0);
623 static constexpr nscolor kWindowBackground = NS_RGB(28, 27, 34);
624 static constexpr nscolor kWindowText = NS_RGB(251, 251, 254);
625 switch (aID) {
626 case ColorID::Window: // --in-content-page-background
627 case ColorID::Background:
628 case ColorID::Menu:
629 color = kWindowBackground;
630 break;
631 case ColorID::MozOddtreerow:
632 case ColorID::MozDialog: // --in-content-box-background
633 color = NS_RGB(35, 34, 43);
634 break;
635 case ColorID::Windowtext: // --in-content-page-color
636 case ColorID::Menutext:
637 case ColorID::MozDialogtext:
638 case ColorID::Fieldtext:
639 case ColorID::Buttontext: // --in-content-button-text-color (via
640 // --in-content-page-color)
641 case ColorID::MozComboboxtext:
642 case ColorID::MozButtonhovertext:
643 case ColorID::MozButtonactivetext:
644 color = kWindowText;
645 break;
646 case ColorID::Threedlightshadow: // --in-content-box-border-color computed
647 // with kWindowText above
648 // kWindowBackground.
649 case ColorID::Graytext: // opacity: 0.4 of kWindowText blended over the
650 // "Window" background color, which happens to be
651 // the same :-)
652 color = NS_ComposeColors(kWindowBackground, NS_RGBA(251, 251, 254, 102));
653 break;
654 case ColorID::MozCellhighlight:
655 case ColorID::Selecteditem: // --in-content-primary-button-background /
656 // --in-content-item-selected
657 color = NS_RGB(0, 221, 255);
658 break;
659 case ColorID::Field:
660 case ColorID::Buttonface: // --in-content-button-background
661 case ColorID::MozCombobox:
662 case ColorID::MozCellhighlighttext:
663 case ColorID::Selecteditemtext: // --in-content-primary-button-text-color /
664 // --in-content-item-selected-text
665 color = NS_RGB(43, 42, 51);
666 break;
667 case ColorID::Threeddarkshadow: // Same as Threedlightshadow but with the
668 // background.
669 case ColorID::MozDisabledfield: // opacity: 0.4 of the face above blended
670 // over the "Window" background color.
671 case ColorID::MozButtondisabledface:
672 color = NS_ComposeColors(kWindowBackground, NS_RGBA(43, 42, 51, 102));
673 break;
674 case ColorID::MozButtonhoverface: // --in-content-button-background-hover
675 color = NS_RGB(82, 82, 94);
676 break;
677 case ColorID::MozButtonactiveface: // --in-content-button-background-active
678 color = NS_RGB(91, 91, 102);
679 break;
680 case ColorID::Highlight:
681 color = NS_RGBA(0, 221, 255, 153);
682 break;
683 case ColorID::Highlighttext:
684 color = NS_SAME_AS_FOREGROUND_COLOR;
685 break;
686 case ColorID::MozNativehyperlinktext:
687 // If you change this color, you probably also want to change the default
688 // value of browser.anchor_color.dark.
689 color = NS_RGB(0x8c, 0x8c, 0xff);
690 break;
691 case ColorID::MozNativevisitedhyperlinktext:
692 // If you change this color, you probably also want to change the default
693 // value of browser.visited_color.dark.
694 color = NS_RGB(0xff, 0xad, 0xff);
695 break;
697 default:
698 return Nothing();
700 return Some(color);
703 // Uncomment the #define below if you want to debug system color use in a skin
704 // that uses them. When set, it will make all system color pairs that are
705 // appropriate for foreground/background pairing the same. This means if the
706 // skin is using system colors correctly you will not be able to see *any* text.
708 // #define DEBUG_SYSTEM_COLOR_USE
710 #ifdef DEBUG_SYSTEM_COLOR_USE
711 static nsresult SystemColorUseDebuggingColor(LookAndFeel::ColorID aID,
712 nscolor& aResult) {
713 using ColorID = LookAndFeel::ColorID;
715 switch (aID) {
716 // css2 http://www.w3.org/TR/REC-CSS2/ui.html#system-colors
717 case ColorID::Activecaption:
718 // active window caption background
719 case ColorID::Captiontext:
720 // text in active window caption
721 aResult = NS_RGB(0xff, 0x00, 0x00);
722 break;
724 case ColorID::Highlight:
725 // background of selected item
726 case ColorID::Highlighttext:
727 // text of selected item
728 aResult = NS_RGB(0xff, 0xff, 0x00);
729 break;
731 case ColorID::Inactivecaption:
732 // inactive window caption
733 case ColorID::Inactivecaptiontext:
734 // text in inactive window caption
735 aResult = NS_RGB(0x66, 0x66, 0x00);
736 break;
738 case ColorID::Infobackground:
739 // tooltip background color
740 case ColorID::Infotext:
741 // tooltip text color
742 aResult = NS_RGB(0x00, 0xff, 0x00);
743 break;
745 case ColorID::Menu:
746 // menu background
747 case ColorID::Menutext:
748 // menu text
749 aResult = NS_RGB(0x00, 0xff, 0xff);
750 break;
752 case ColorID::Threedface:
753 case ColorID::Buttonface:
754 // 3-D face color
755 case ColorID::Buttontext:
756 // text on push buttons
757 aResult = NS_RGB(0x00, 0x66, 0x66);
758 break;
760 case ColorID::Window:
761 case ColorID::Windowtext:
762 aResult = NS_RGB(0x00, 0x00, 0xff);
763 break;
765 // from the CSS3 working draft (not yet finalized)
766 // http://www.w3.org/tr/2000/wd-css3-userint-20000216.html#color
768 case ColorID::Field:
769 case ColorID::Fieldtext:
770 aResult = NS_RGB(0xff, 0x00, 0xff);
771 break;
773 case ColorID::MozDialog:
774 case ColorID::MozDialogtext:
775 aResult = NS_RGB(0x66, 0x00, 0x66);
776 break;
778 default:
779 return NS_ERROR_NOT_AVAILABLE;
782 return NS_OK;
784 #endif
786 static nsresult GetPrefColor(const char* aPref, nscolor& aResult) {
787 nsAutoCString colorStr;
788 MOZ_TRY(Preferences::GetCString(aPref, colorStr));
789 if (!ServoCSSParser::ComputeColor(nullptr, NS_RGB(0, 0, 0), colorStr,
790 &aResult)) {
791 return NS_ERROR_FAILURE;
793 return NS_OK;
796 static nsresult GetColorFromPref(LookAndFeel::ColorID aID, ColorScheme aScheme,
797 nscolor& aResult) {
798 const char* prefName = sColorPrefs[size_t(aID)];
799 if (aScheme == ColorScheme::Dark) {
800 nsAutoCString darkPrefName(prefName);
801 darkPrefName.Append(".dark");
802 if (NS_SUCCEEDED(GetPrefColor(darkPrefName.get(), aResult))) {
803 return NS_OK;
806 return GetPrefColor(prefName, aResult);
809 // All these routines will return NS_OK if they have a value,
810 // in which case the nsLookAndFeel should use that value;
811 // otherwise we'll return NS_ERROR_NOT_AVAILABLE, in which case, the
812 // platform-specific nsLookAndFeel should use its own values instead.
813 nsresult nsXPLookAndFeel::GetColorValue(ColorID aID, ColorScheme aScheme,
814 UseStandins aUseStandins,
815 nscolor& aResult) {
816 if (!sInitialized) {
817 Init();
820 #ifdef DEBUG_SYSTEM_COLOR_USE
821 if (NS_SUCCEEDED(SystemColorUseDebuggingColor(aID, aResult))) {
822 return NS_OK;
824 #endif
826 if (aUseStandins == UseStandins::Yes) {
827 aResult = GetStandinForNativeColor(aID, aScheme);
828 return NS_OK;
831 auto& cache =
832 aScheme == ColorScheme::Light ? sLightColorCache : sDarkColorCache;
833 if (const auto* cached = cache.Get(aID)) {
834 if (cached->isNothing()) {
835 return NS_ERROR_FAILURE;
837 aResult = cached->value();
838 return NS_OK;
841 if (NS_SUCCEEDED(GetColorFromPref(aID, aScheme, aResult))) {
842 cache.Insert(aID, Some(aResult));
843 return NS_OK;
846 if (NS_SUCCEEDED(NativeGetColor(aID, aScheme, aResult))) {
847 if (gfxPlatform::GetCMSMode() == CMSMode::All &&
848 !IsSpecialColor(aID, aResult)) {
849 qcms_transform* transform = gfxPlatform::GetCMSInverseRGBTransform();
850 if (transform) {
851 uint8_t color[4];
852 color[0] = NS_GET_R(aResult);
853 color[1] = NS_GET_G(aResult);
854 color[2] = NS_GET_B(aResult);
855 color[3] = NS_GET_A(aResult);
856 qcms_transform_data(transform, color, color, 1);
857 aResult = NS_RGBA(color[0], color[1], color[2], color[3]);
861 // NOTE: Servo holds a lock and the main thread is paused, so writing to the
862 // global cache here is fine.
863 cache.Insert(aID, Some(aResult));
864 return NS_OK;
867 cache.Insert(aID, Nothing());
868 return NS_ERROR_FAILURE;
871 nsresult nsXPLookAndFeel::GetIntValue(IntID aID, int32_t& aResult) {
872 if (!sInitialized) {
873 Init();
876 if (const auto* cached = sIntCache.Get(aID)) {
877 if (cached->isNothing()) {
878 return NS_ERROR_FAILURE;
880 aResult = cached->value();
881 return NS_OK;
884 if (NS_SUCCEEDED(Preferences::GetInt(sIntPrefs[size_t(aID)], &aResult))) {
885 sIntCache.Insert(aID, Some(aResult));
886 return NS_OK;
889 if (NS_FAILED(NativeGetInt(aID, aResult))) {
890 sIntCache.Insert(aID, Nothing());
891 return NS_ERROR_FAILURE;
894 sIntCache.Insert(aID, Some(aResult));
895 return NS_OK;
898 nsresult nsXPLookAndFeel::GetFloatValue(FloatID aID, float& aResult) {
899 if (!sInitialized) {
900 Init();
903 if (const auto* cached = sFloatCache.Get(aID)) {
904 if (cached->isNothing()) {
905 return NS_ERROR_FAILURE;
907 aResult = cached->value();
908 return NS_OK;
911 int32_t pref = 0;
912 if (NS_SUCCEEDED(Preferences::GetInt(sFloatPrefs[size_t(aID)], &pref))) {
913 aResult = float(pref) / 100.0f;
914 sFloatCache.Insert(aID, Some(aResult));
915 return NS_OK;
918 if (NS_FAILED(NativeGetFloat(aID, aResult))) {
919 sFloatCache.Insert(aID, Nothing());
920 return NS_ERROR_FAILURE;
923 sFloatCache.Insert(aID, Some(aResult));
924 return NS_OK;
927 bool nsXPLookAndFeel::LookAndFeelFontToStyle(const LookAndFeelFont& aFont,
928 nsString& aName,
929 gfxFontStyle& aStyle) {
930 if (!aFont.haveFont()) {
931 return false;
933 aName = aFont.name();
934 aStyle = gfxFontStyle();
935 aStyle.size = aFont.size();
936 aStyle.weight = FontWeight(aFont.weight());
937 aStyle.style =
938 aFont.italic() ? FontSlantStyle::Italic() : FontSlantStyle::Normal();
939 aStyle.systemFont = true;
940 return true;
943 widget::LookAndFeelFont nsXPLookAndFeel::StyleToLookAndFeelFont(
944 const nsAString& aName, const gfxFontStyle& aStyle) {
945 LookAndFeelFont font;
946 font.haveFont() = true;
947 font.name() = aName;
948 font.size() = aStyle.size;
949 font.weight() = aStyle.weight.ToFloat();
950 font.italic() = aStyle.style.IsItalic();
951 MOZ_ASSERT(aStyle.style.IsNormal() || aStyle.style.IsItalic(),
952 "Cannot handle oblique font style");
953 #ifdef DEBUG
955 // Assert that all the remaining font style properties have their
956 // default values.
957 gfxFontStyle candidate = aStyle;
958 gfxFontStyle defaults{};
959 candidate.size = defaults.size;
960 candidate.weight = defaults.weight;
961 candidate.style = defaults.style;
962 MOZ_ASSERT(candidate.Equals(defaults),
963 "Some font style properties not supported");
965 #endif
966 return font;
969 bool nsXPLookAndFeel::GetFontValue(FontID aID, nsString& aName,
970 gfxFontStyle& aStyle) {
971 if (const LookAndFeelFont* cached = sFontCache.Get(aID)) {
972 return LookAndFeelFontToStyle(*cached, aName, aStyle);
974 LookAndFeelFont font;
975 const bool haveFont = NativeGetFont(aID, aName, aStyle);
976 font.haveFont() = haveFont;
977 if (haveFont) {
978 font = StyleToLookAndFeelFont(aName, aStyle);
980 sFontCache.Insert(aID, std::move(font));
981 return haveFont;
984 void nsXPLookAndFeel::RefreshImpl() {
985 // Wipe out our caches.
986 sLightColorCache.Clear();
987 sDarkColorCache.Clear();
988 sFontCache.Clear();
989 sFloatCache.Clear();
990 sIntCache.Clear();
991 RecomputeColorSchemes();
993 // Clear any cached FullLookAndFeel data, which is now invalid.
994 if (XRE_IsParentProcess()) {
995 widget::RemoteLookAndFeel::ClearCachedData();
999 static bool sRecordedLookAndFeelTelemetry = false;
1001 void nsXPLookAndFeel::RecordTelemetry() {
1002 if (!XRE_IsParentProcess()) {
1003 return;
1006 if (sRecordedLookAndFeelTelemetry) {
1007 return;
1010 sRecordedLookAndFeelTelemetry = true;
1012 int32_t i;
1013 Telemetry::ScalarSet(
1014 Telemetry::ScalarID::WIDGET_DARK_MODE,
1015 NS_SUCCEEDED(GetIntValue(IntID::SystemUsesDarkTheme, i)) && i != 0);
1017 RecordLookAndFeelSpecificTelemetry();
1020 namespace mozilla {
1022 // static
1023 void LookAndFeel::NotifyChangedAllWindows(widget::ThemeChangeKind aKind) {
1024 if (nsCOMPtr<nsIObserverService> obs = services::GetObserverService()) {
1025 const char16_t kind[] = {char16_t(aKind), 0};
1026 obs->NotifyObservers(nullptr, "internal-look-and-feel-changed", kind);
1030 static bool ShouldUseStandinsForNativeColorForNonNativeTheme(
1031 const dom::Document& aDoc, LookAndFeel::ColorID aColor) {
1032 using ColorID = LookAndFeel::ColorID;
1033 if (!aDoc.ShouldAvoidNativeTheme()) {
1034 return false;
1037 // The native theme doesn't use native system colors backgrounds etc, except
1038 // when in high-contrast mode, so spoof some of the colors with stand-ins to
1039 // prevent lack of contrast.
1040 switch (aColor) {
1041 case ColorID::Buttonface:
1042 case ColorID::Buttontext:
1043 case ColorID::MozButtonhoverface:
1044 case ColorID::MozButtonhovertext:
1045 case ColorID::MozButtonactiveface:
1046 case ColorID::MozButtonactivetext:
1047 case ColorID::MozButtondisabledface:
1049 case ColorID::Threedlightshadow:
1050 case ColorID::Threeddarkshadow:
1051 case ColorID::Threedface:
1053 case ColorID::MozCombobox:
1054 case ColorID::MozComboboxtext:
1056 case ColorID::Field:
1057 case ColorID::MozDisabledfield:
1058 case ColorID::Fieldtext:
1060 case ColorID::Graytext:
1062 return !PreferenceSheet::PrefsFor(aDoc)
1063 .NonNativeThemeShouldBeHighContrast();
1065 default:
1066 break;
1069 return false;
1072 ColorScheme LookAndFeel::sChromeColorScheme;
1073 ColorScheme LookAndFeel::sContentColorScheme;
1075 auto LookAndFeel::ColorSchemeSettingForChrome() -> ChromeColorSchemeSetting {
1076 switch (StaticPrefs::browser_theme_toolbar_theme()) {
1077 case 0: // Dark
1078 return ChromeColorSchemeSetting::Dark;
1079 case 1: // Light
1080 return ChromeColorSchemeSetting::Light;
1081 default:
1082 return ChromeColorSchemeSetting::System;
1086 void LookAndFeel::RecomputeColorSchemes() {
1087 sChromeColorScheme = [] {
1088 switch (ColorSchemeSettingForChrome()) {
1089 case ChromeColorSchemeSetting::Light:
1090 return ColorScheme::Light;
1091 case ChromeColorSchemeSetting::Dark:
1092 return ColorScheme::Dark;
1093 case ChromeColorSchemeSetting::System:
1094 break;
1096 return SystemColorScheme();
1097 }();
1099 sContentColorScheme = [] {
1100 switch (StaticPrefs::layout_css_prefers_color_scheme_content_override()) {
1101 case 0:
1102 return ColorScheme::Dark;
1103 case 1:
1104 return ColorScheme::Light;
1105 case 2:
1106 return SystemColorScheme();
1107 default:
1108 break; // Use the browser theme.
1111 switch (StaticPrefs::browser_theme_content_theme()) {
1112 case 0: // Dark
1113 return ColorScheme::Dark;
1114 case 1: // Light
1115 return ColorScheme::Light;
1116 default:
1117 return ColorSchemeForChrome();
1119 }();
1122 ColorScheme LookAndFeel::ColorSchemeForStyle(
1123 const dom::Document& aDoc, const StyleColorSchemeFlags& aFlags) {
1124 StyleColorSchemeFlags style(aFlags);
1125 if (!style) {
1126 style.bits = aDoc.GetColorSchemeBits();
1128 const bool supportsDark = bool(style & StyleColorSchemeFlags::DARK);
1129 const bool supportsLight = bool(style & StyleColorSchemeFlags::LIGHT);
1130 if (supportsLight && supportsDark) {
1131 // Both color-schemes are explicitly supported, use the preferred one.
1132 return aDoc.PreferredColorScheme();
1134 if (supportsDark || supportsLight) {
1135 // One color-scheme is explicitly supported and one isn't, so use the one
1136 // the content supports.
1137 return supportsDark ? ColorScheme::Dark : ColorScheme::Light;
1139 // No value specified. Chrome docs always supports both, so use the preferred
1140 // color-scheme.
1141 if (nsContentUtils::IsChromeDoc(&aDoc)) {
1142 return aDoc.PreferredColorScheme();
1144 // As an special-case, use the system color-scheme if allow-gtk-dark-theme is
1145 // set.
1147 // TODO(emilio): Once we ship the color-scheme property and meta tag I think
1148 // this can go. The use case for this is sidebars and such (bug 1721359),
1149 // which will be able to just use <meta name=color-scheme value="light dark">
1150 // to state that they support light and dark color schemes (taking the
1151 // PreferredColorScheme codepath above).
1152 #ifdef MOZ_WIDGET_GTK
1153 if (StaticPrefs::widget_content_allow_gtk_dark_theme()) {
1154 return SystemColorScheme();
1156 #endif
1157 // Default content to light.
1158 return ColorScheme::Light;
1161 LookAndFeel::ColorScheme LookAndFeel::ColorSchemeForFrame(
1162 const nsIFrame* aFrame) {
1163 return ColorSchemeForStyle(*aFrame->PresContext()->Document(),
1164 aFrame->StyleUI()->mColorScheme.bits);
1167 // static
1168 Maybe<nscolor> LookAndFeel::GetColor(ColorID aId, ColorScheme aScheme,
1169 UseStandins aUseStandins) {
1170 nscolor result;
1171 nsresult rv = nsLookAndFeel::GetInstance()->GetColorValue(
1172 aId, aScheme, aUseStandins, result);
1173 if (NS_FAILED(rv)) {
1174 return Nothing();
1176 return Some(result);
1179 // Returns whether there is a CSS color name for this color.
1180 static bool ColorIsCSSAccessible(LookAndFeel::ColorID aId) {
1181 using ColorID = LookAndFeel::ColorID;
1183 switch (aId) {
1184 case ColorID::TextSelectDisabledBackground:
1185 case ColorID::TextSelectAttentionBackground:
1186 case ColorID::TextSelectAttentionForeground:
1187 case ColorID::TextHighlightBackground:
1188 case ColorID::TextHighlightForeground:
1189 case ColorID::ThemedScrollbar:
1190 case ColorID::ThemedScrollbarInactive:
1191 case ColorID::ThemedScrollbarThumb:
1192 case ColorID::ThemedScrollbarThumbActive:
1193 case ColorID::ThemedScrollbarThumbInactive:
1194 case ColorID::ThemedScrollbarThumbHover:
1195 case ColorID::IMERawInputBackground:
1196 case ColorID::IMERawInputForeground:
1197 case ColorID::IMERawInputUnderline:
1198 case ColorID::IMESelectedRawTextBackground:
1199 case ColorID::IMESelectedRawTextForeground:
1200 case ColorID::IMESelectedRawTextUnderline:
1201 case ColorID::IMEConvertedTextBackground:
1202 case ColorID::IMEConvertedTextForeground:
1203 case ColorID::IMEConvertedTextUnderline:
1204 case ColorID::IMESelectedConvertedTextBackground:
1205 case ColorID::IMESelectedConvertedTextForeground:
1206 case ColorID::IMESelectedConvertedTextUnderline:
1207 case ColorID::SpellCheckerUnderline:
1208 return false;
1209 default:
1210 break;
1213 return true;
1216 LookAndFeel::UseStandins LookAndFeel::ShouldUseStandins(
1217 const dom::Document& aDoc, ColorID aId) {
1218 if (ShouldUseStandinsForNativeColorForNonNativeTheme(aDoc, aId)) {
1219 return UseStandins::Yes;
1221 if (nsContentUtils::UseStandinsForNativeColors() &&
1222 ColorIsCSSAccessible(aId) && !nsContentUtils::IsChromeDoc(&aDoc)) {
1223 return UseStandins::Yes;
1225 if (aDoc.IsStaticDocument() &&
1226 !PreferenceSheet::ContentPrefs().mUseDocumentColors) {
1227 return UseStandins::Yes;
1229 return UseStandins::No;
1232 Maybe<nscolor> LookAndFeel::GetColor(ColorID aId, const nsIFrame* aFrame) {
1233 const auto* doc = aFrame->PresContext()->Document();
1234 return GetColor(aId, ColorSchemeForFrame(aFrame),
1235 ShouldUseStandins(*doc, aId));
1238 // static
1239 nsresult LookAndFeel::GetInt(IntID aID, int32_t* aResult) {
1240 return nsLookAndFeel::GetInstance()->GetIntValue(aID, *aResult);
1243 // static
1244 nsresult LookAndFeel::GetFloat(FloatID aID, float* aResult) {
1245 return nsLookAndFeel::GetInstance()->GetFloatValue(aID, *aResult);
1248 // static
1249 bool LookAndFeel::GetFont(FontID aID, nsString& aName, gfxFontStyle& aStyle) {
1250 return nsLookAndFeel::GetInstance()->GetFontValue(aID, aName, aStyle);
1253 // static
1254 char16_t LookAndFeel::GetPasswordCharacter() {
1255 return nsLookAndFeel::GetInstance()->GetPasswordCharacterImpl();
1258 // static
1259 bool LookAndFeel::GetEchoPassword() {
1260 if (StaticPrefs::editor_password_mask_delay() >= 0) {
1261 return StaticPrefs::editor_password_mask_delay() > 0;
1263 return nsLookAndFeel::GetInstance()->GetEchoPasswordImpl();
1266 // static
1267 uint32_t LookAndFeel::GetPasswordMaskDelay() {
1268 int32_t delay = StaticPrefs::editor_password_mask_delay();
1269 if (delay < 0) {
1270 return nsLookAndFeel::GetInstance()->GetPasswordMaskDelayImpl();
1272 return delay;
1275 bool LookAndFeel::DrawInTitlebar() {
1276 switch (StaticPrefs::browser_tabs_inTitlebar()) {
1277 case 0:
1278 return false;
1279 case 1:
1280 return true;
1281 default:
1282 break;
1284 return nsLookAndFeel::GetInstance()->GetDefaultDrawInTitlebar();
1287 void LookAndFeel::GetThemeInfo(nsACString& aOut) {
1288 nsLookAndFeel::GetInstance()->GetThemeInfo(aOut);
1291 // static
1292 void LookAndFeel::Refresh() {
1293 nsLookAndFeel::GetInstance()->RefreshImpl();
1294 nsNativeBasicTheme::LookAndFeelChanged();
1297 // static
1298 void LookAndFeel::NativeInit() { nsLookAndFeel::GetInstance()->NativeInit(); }
1300 // static
1301 void LookAndFeel::SetData(widget::FullLookAndFeel&& aTables) {
1302 nsLookAndFeel::GetInstance()->SetDataImpl(std::move(aTables));
1305 } // namespace mozilla