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"
10 #include "nsXPLookAndFeel.h"
11 #include "nsLookAndFeel.h"
12 #include "HeadlessLookAndFeel.h"
13 #include "RemoteLookAndFeel.h"
14 #include "nsContentUtils.h"
17 #include "nsIXULRuntime.h"
18 #include "nsNativeBasicTheme.h"
19 #include "mozilla/dom/ContentChild.h"
20 #include "mozilla/Preferences.h"
21 #include "mozilla/Services.h"
22 #include "mozilla/ServoStyleSet.h"
23 #include "mozilla/StaticPrefs_editor.h"
24 #include "mozilla/StaticPrefs_findbar.h"
25 #include "mozilla/StaticPrefs_ui.h"
26 #include "mozilla/StaticPrefs_widget.h"
27 #include "mozilla/gfx/2D.h"
28 #include "mozilla/widget/WidgetMessageUtils.h"
29 #include "mozilla/Telemetry.h"
30 #include "mozilla/TelemetryScalarEnums.h"
32 #include "gfxPlatform.h"
40 using namespace mozilla
;
42 // To make one of these prefs toggleable from a reftest add a user
43 // pref in testing/profiles/reftest/user.js. For example, to make
44 // ui.useAccessibilityTheme toggleable, add:
46 // user_pref("ui.useAccessibilityTheme", 0);
48 nsLookAndFeelIntPref
nsXPLookAndFeel::sIntPrefs
[] = {
49 {"ui.caretBlinkTime", IntID::CaretBlinkTime
, false, 0},
50 {"ui.caretWidth", IntID::CaretWidth
, false, 0},
51 {"ui.caretVisibleWithSelection", IntID::ShowCaretDuringSelection
, false, 0},
52 {"ui.submenuDelay", IntID::SubmenuDelay
, false, 0},
53 {"ui.dragThresholdX", IntID::DragThresholdX
, false, 0},
54 {"ui.dragThresholdY", IntID::DragThresholdY
, false, 0},
55 {"ui.useAccessibilityTheme", IntID::UseAccessibilityTheme
, false, 0},
56 {"ui.menusCanOverlapOSBar", IntID::MenusCanOverlapOSBar
, false, 0},
57 {"ui.useOverlayScrollbars", IntID::UseOverlayScrollbars
, false, 0},
58 {"ui.scrollbarDisplayOnMouseMove", IntID::ScrollbarDisplayOnMouseMove
,
60 {"ui.scrollbarFadeBeginDelay", IntID::ScrollbarFadeBeginDelay
, false, 0},
61 {"ui.scrollbarFadeDuration", IntID::ScrollbarFadeDuration
, false, 0},
62 {"ui.showHideScrollbars", IntID::ShowHideScrollbars
, false, 0},
63 {"ui.skipNavigatingDisabledMenuItem", IntID::SkipNavigatingDisabledMenuItem
,
65 {"ui.treeOpenDelay", IntID::TreeOpenDelay
, false, 0},
66 {"ui.treeCloseDelay", IntID::TreeCloseDelay
, false, 0},
67 {"ui.treeLazyScrollDelay", IntID::TreeLazyScrollDelay
, false, 0},
68 {"ui.treeScrollDelay", IntID::TreeScrollDelay
, false, 0},
69 {"ui.treeScrollLinesMax", IntID::TreeScrollLinesMax
, false, 0},
70 {"accessibility.tabfocus", IntID::TabFocusModel
, false, 0},
71 {"ui.alertNotificationOrigin", IntID::AlertNotificationOrigin
, false, 0},
72 {"ui.scrollToClick", IntID::ScrollToClick
, false, 0},
73 {"ui.IMERawInputUnderlineStyle", IntID::IMERawInputUnderlineStyle
, false,
75 {"ui.IMESelectedRawTextUnderlineStyle",
76 IntID::IMESelectedRawTextUnderlineStyle
, false, 0},
77 {"ui.IMEConvertedTextUnderlineStyle", IntID::IMEConvertedTextUnderlineStyle
,
79 {"ui.IMESelectedConvertedTextUnderlineStyle",
80 IntID::IMESelectedConvertedTextUnderline
, false, 0},
81 {"ui.SpellCheckerUnderlineStyle", IntID::SpellCheckerUnderlineStyle
, false,
83 {"ui.scrollbarButtonAutoRepeatBehavior",
84 IntID::ScrollbarButtonAutoRepeatBehavior
, false, 0},
85 {"ui.tooltipDelay", IntID::TooltipDelay
, false, 0},
86 {"ui.contextMenuOffsetVertical", IntID::ContextMenuOffsetVertical
, false,
88 {"ui.contextMenuOffsetHorizontal", IntID::ContextMenuOffsetHorizontal
,
90 {"ui.GtkCSDAvailable", IntID::GTKCSDAvailable
, false, 0},
91 {"ui.GtkCSDHideTitlebarByDefault", IntID::GTKCSDHideTitlebarByDefault
,
93 {"ui.GtkCSDTransparentBackground", IntID::GTKCSDTransparentBackground
,
95 {"ui.GtkCSDMinimizeButton", IntID::GTKCSDMinimizeButton
, false, 0},
96 {"ui.GtkCSDMaximizeButton", IntID::GTKCSDMaximizeButton
, false, 0},
97 {"ui.GtkCSDCloseButton", IntID::GTKCSDCloseButton
, false, 0},
98 {"ui.systemUsesDarkTheme", IntID::SystemUsesDarkTheme
, false, 0},
99 {"ui.prefersReducedMotion", IntID::PrefersReducedMotion
, false, 0},
100 {"ui.primaryPointerCapabilities", IntID::PrimaryPointerCapabilities
, false,
101 6 /* fine and hover-capable pointer, i.e. mouse-type */},
102 {"ui.allPointerCapabilities", IntID::AllPointerCapabilities
, false,
103 6 /* fine and hover-capable pointer, i.e. mouse-type */},
104 {"ui.scrollArrowStyle", IntID::ScrollArrowStyle
, false, 0},
107 nsLookAndFeelFloatPref
nsXPLookAndFeel::sFloatPrefs
[] = {
108 {"ui.IMEUnderlineRelativeSize", FloatID::IMEUnderlineRelativeSize
, false,
110 {"ui.SpellCheckerUnderlineRelativeSize",
111 FloatID::SpellCheckerUnderlineRelativeSize
, false, 0},
112 {"ui.caretAspectRatio", FloatID::CaretAspectRatio
, false, 0},
115 // This array MUST be kept in the same order as the color list in
116 // specified/color.rs
117 /* XXX If you add any strings longer than
118 * "ui.-moz-mac-active-source-list-selection"
119 * to the following array then you MUST update the
120 * sizes of the sColorPrefs array in nsXPLookAndFeel.h
122 const char nsXPLookAndFeel::sColorPrefs
[][41] = {
123 "ui.windowBackground",
124 "ui.windowForeground",
125 "ui.widgetBackground",
126 "ui.widgetForeground",
127 "ui.widgetSelectBackground",
128 "ui.widgetSelectForeground",
129 "ui.widget3DHighlight",
133 "ui.textSelectBackground",
134 "ui.textSelectForeground",
135 "ui.textSelectForegroundCustom",
136 "ui.textSelectBackgroundDisabled",
137 "ui.textSelectBackgroundAttention",
138 "ui.textHighlightBackground",
139 "ui.textHighlightForeground",
140 "ui.IMERawInputBackground",
141 "ui.IMERawInputForeground",
142 "ui.IMERawInputUnderline",
143 "ui.IMESelectedRawTextBackground",
144 "ui.IMESelectedRawTextForeground",
145 "ui.IMESelectedRawTextUnderline",
146 "ui.IMEConvertedTextBackground",
147 "ui.IMEConvertedTextForeground",
148 "ui.IMEConvertedTextUnderline",
149 "ui.IMESelectedConvertedTextBackground",
150 "ui.IMESelectedConvertedTextForeground",
151 "ui.IMESelectedConvertedTextUnderline",
152 "ui.SpellCheckerUnderline",
153 "ui.themedScrollbar",
154 "ui.themedScrollbarInactive",
155 "ui.themedScrollbarThumb",
156 "ui.themedScrollbarThumbHover",
157 "ui.themedScrollbarThumbActive",
158 "ui.themedScrollbarThumbInactive",
164 "ui.buttonhighlight",
174 "ui.inactivecaption",
175 "ui.inactivecaptiontext",
181 "ui.threeddarkshadow",
183 "ui.threedhighlight",
184 "ui.threedlightshadow",
189 "ui.-moz-buttondefault",
190 "ui.-moz-default-color",
191 "ui.-moz-default-background-color",
193 "ui.-moz-dialogtext",
194 "ui.-moz-dragtargetzone",
195 "ui.-moz-cellhighlight",
196 "ui.-moz_cellhighlighttext",
197 "ui.-moz-html-cellhighlight",
198 "ui.-moz-html-cellhighlighttext",
199 "ui.-moz-buttonhoverface",
200 "ui.-moz_buttonhovertext",
202 "ui.-moz_menuhovertext",
203 "ui.-moz_menubartext",
204 "ui.-moz_menubarhovertext",
205 "ui.-moz_eventreerow",
206 "ui.-moz_oddtreerow",
207 "ui.-moz-gtk-buttonactivetext",
208 "ui.-moz-mac-buttonactivetext",
209 "ui.-moz_mac_chrome_active",
210 "ui.-moz_mac_chrome_inactive",
211 "ui.-moz-mac-defaultbuttontext",
212 "ui.-moz-mac-focusring",
213 "ui.-moz-mac-menuselect",
214 "ui.-moz-mac-menushadow",
215 "ui.-moz-mac-menutextdisable",
216 "ui.-moz-mac-menutextselect",
217 "ui.-moz_mac_disabledtoolbartext",
218 "ui.-moz-mac-secondaryhighlight",
219 "ui.-moz-mac-vibrancy-light",
220 "ui.-moz-mac-vibrancy-dark",
221 "ui.-moz-mac-vibrant-titlebar-light",
222 "ui.-moz-mac-vibrant-titlebar-dark",
223 "ui.-moz-mac-menupopup",
224 "ui.-moz-mac-menuitem",
225 "ui.-moz-mac-active-menuitem",
226 "ui.-moz-mac-source-list",
227 "ui.-moz-mac-source-list-selection",
228 "ui.-moz-mac-active-source-list-selection",
229 "ui.-moz-mac-tooltip",
230 "ui.-moz-accent-color",
231 "ui.-moz-accent-color-foreground",
232 "ui.-moz-win-accentcolor",
233 "ui.-moz-win-accentcolortext",
234 "ui.-moz-win-mediatext",
235 "ui.-moz-win-communicationstext",
236 "ui.-moz-nativehyperlinktext",
237 "ui.-moz-hyperlinktext",
238 "ui.-moz-activehyperlinktext",
239 "ui.-moz-visitedhyperlinktext",
240 "ui.-moz-comboboxtext",
242 "ui.-moz-gtk-info-bar-text",
243 "ui.-moz-colheadertext",
244 "ui.-moz-colheaderhovertext"};
246 int32_t nsXPLookAndFeel::sCachedColors
[size_t(LookAndFeel::ColorID::End
)] = {0};
247 int32_t nsXPLookAndFeel::sCachedColorBits
[COLOR_CACHE_SIZE
] = {0};
249 bool nsXPLookAndFeel::sInitialized
= false;
251 nsXPLookAndFeel
* nsXPLookAndFeel::sInstance
= nullptr;
252 bool nsXPLookAndFeel::sShutdown
= false;
255 nsXPLookAndFeel
* nsXPLookAndFeel::GetInstance() {
260 NS_ENSURE_TRUE(!sShutdown
, nullptr);
262 // If we're in a content process, then the parent process will have supplied
263 // us with an initial FullLookAndFeel object (for when the RemoteLookAndFeel
264 // is to be used) or an initial LookAndFeelCache object (for regular
265 // LookAndFeel implementations). We grab this data from the ContentChild,
266 // where it's been temporarily stashed, and initialize our new LookAndFeel
269 LookAndFeelCache
* lnfCache
= nullptr;
270 FullLookAndFeel
* fullLnf
= nullptr;
271 widget::LookAndFeelData
* lnfData
= nullptr;
273 if (auto* cc
= mozilla::dom::ContentChild::GetSingleton()) {
274 lnfData
= &cc
->BorrowLookAndFeelData();
275 switch (lnfData
->type()) {
276 case widget::LookAndFeelData::TLookAndFeelCache
:
277 lnfCache
= &lnfData
->get_LookAndFeelCache();
279 case widget::LookAndFeelData::TFullLookAndFeel
:
280 fullLnf
= &lnfData
->get_FullLookAndFeel();
283 MOZ_ASSERT_UNREACHABLE("unexpected LookAndFeelData type");
288 sInstance
= new widget::RemoteLookAndFeel(std::move(*fullLnf
));
289 } else if (gfxPlatform::IsHeadless()) {
290 sInstance
= new widget::HeadlessLookAndFeel(lnfCache
);
292 sInstance
= new nsLookAndFeel(lnfCache
);
295 // This is only ever used once during initialization, and can be cleared now.
297 *lnfData
= widget::LookAndFeelData
{};
300 nsNativeBasicTheme::Init();
305 void nsXPLookAndFeel::Shutdown() {
312 nsNativeBasicTheme::Shutdown();
316 void nsXPLookAndFeel::IntPrefChanged(nsLookAndFeelIntPref
* data
) {
322 nsresult rv
= Preferences::GetInt(data
->name
, &intpref
);
327 printf("====== Cleared int pref %s\n", data
->name
);
330 data
->intVar
= intpref
;
334 printf("====== Changed int pref %s to %d\n", data
->name
, data
->intVar
);
338 // Int prefs can't change our system colors or fonts.
339 NotifyChangedAllWindows(widget::ThemeChangeKind::MediaQueriesOnly
);
343 void nsXPLookAndFeel::FloatPrefChanged(nsLookAndFeelFloatPref
* data
) {
349 nsresult rv
= Preferences::GetInt(data
->name
, &intpref
);
354 printf("====== Cleared float pref %s\n", data
->name
);
357 data
->floatVar
= (float)intpref
/ 100.0f
;
361 printf("====== Changed float pref %s to %f\n", data
->name
);
365 // Float prefs can't change our system colors or fonts.
366 NotifyChangedAllWindows(widget::ThemeChangeKind::MediaQueriesOnly
);
370 void nsXPLookAndFeel::ColorPrefChanged(unsigned int index
,
371 const char* prefName
) {
372 nsAutoString colorStr
;
373 nsresult rv
= Preferences::GetString(prefName
, colorStr
);
374 if (NS_SUCCEEDED(rv
) && !colorStr
.IsEmpty()) {
376 if (colorStr
[0] == char16_t('#')) {
377 if (NS_HexToRGBA(nsDependentString(colorStr
, 1), nsHexColorType::NoAlpha
,
379 int32_t id
= NS_PTR_TO_INT32(index
);
380 CACHE_COLOR(id
, thecolor
);
382 } else if (NS_ColorNameToRGB(colorStr
, &thecolor
)) {
383 int32_t id
= NS_PTR_TO_INT32(index
);
384 CACHE_COLOR(id
, thecolor
);
386 printf("====== Changed color pref %s to 0x%lx\n", prefName
, thecolor
);
390 // Reset to the default color, by clearing the cache
391 // to force lookup when the color is next used
392 int32_t id
= NS_PTR_TO_INT32(index
);
393 CLEAR_COLOR_CACHE(id
);
396 printf("====== Cleared color pref %s\n", prefName
);
400 // Color prefs affect style, because they by definition change system colors.
401 NotifyChangedAllWindows(widget::ThemeChangeKind::Style
);
404 void nsXPLookAndFeel::InitFromPref(nsLookAndFeelIntPref
* aPref
) {
406 nsresult rv
= Preferences::GetInt(aPref
->name
, &intpref
);
407 if (NS_SUCCEEDED(rv
)) {
409 aPref
->intVar
= intpref
;
413 void nsXPLookAndFeel::InitFromPref(nsLookAndFeelFloatPref
* aPref
) {
415 nsresult rv
= Preferences::GetInt(aPref
->name
, &intpref
);
416 if (NS_SUCCEEDED(rv
)) {
418 aPref
->floatVar
= (float)intpref
/ 100.0f
;
422 void nsXPLookAndFeel::InitColorFromPref(int32_t i
) {
423 static_assert(ArrayLength(sColorPrefs
) == size_t(ColorID::End
),
424 "Should have a pref for each color value");
426 nsAutoString colorStr
;
427 nsresult rv
= Preferences::GetString(sColorPrefs
[i
], colorStr
);
428 if (NS_FAILED(rv
) || colorStr
.IsEmpty()) {
432 if (colorStr
[0] == char16_t('#')) {
433 nsAutoString hexString
;
434 colorStr
.Right(hexString
, colorStr
.Length() - 1);
435 if (NS_HexToRGBA(hexString
, nsHexColorType::NoAlpha
, &thecolor
)) {
436 CACHE_COLOR(i
, thecolor
);
438 } else if (NS_ColorNameToRGB(colorStr
, &thecolor
)) {
439 CACHE_COLOR(i
, thecolor
);
444 void nsXPLookAndFeel::OnPrefChanged(const char* aPref
, void* aClosure
) {
445 // looping in the same order as in ::Init
447 nsDependentCString
prefName(aPref
);
449 for (i
= 0; i
< ArrayLength(sIntPrefs
); ++i
) {
450 if (prefName
.Equals(sIntPrefs
[i
].name
)) {
451 IntPrefChanged(&sIntPrefs
[i
]);
456 for (i
= 0; i
< ArrayLength(sFloatPrefs
); ++i
) {
457 if (prefName
.Equals(sFloatPrefs
[i
].name
)) {
458 FloatPrefChanged(&sFloatPrefs
[i
]);
463 for (i
= 0; i
< ArrayLength(sColorPrefs
); ++i
) {
464 if (prefName
.Equals(sColorPrefs
[i
])) {
465 ColorPrefChanged(i
, sColorPrefs
[i
]);
472 // Read values from the user's preferences.
473 // This is done once at startup, but since the user's preferences
474 // haven't actually been read yet at that time, we also have to
475 // set a callback to inform us of changes to each pref.
477 void nsXPLookAndFeel::Init() {
478 MOZ_RELEASE_ASSERT(NS_IsMainThread());
480 // Say we're already initialized, and take the chance that it might fail;
481 // protects against some other process writing to our static variables.
484 // XXX If we could reorganize the pref names, we should separate the branch
485 // for each types. Then, we could reduce the unnecessary loop from
486 // nsXPLookAndFeel::OnPrefChanged().
487 Preferences::RegisterPrefixCallback(OnPrefChanged
, "ui.");
488 // We really do just want the accessibility.tabfocus pref, not other prefs
489 // that start with that string.
490 Preferences::RegisterCallback(OnPrefChanged
, "accessibility.tabfocus");
493 for (i
= 0; i
< ArrayLength(sIntPrefs
); ++i
) {
494 InitFromPref(&sIntPrefs
[i
]);
497 for (i
= 0; i
< ArrayLength(sFloatPrefs
); ++i
) {
498 InitFromPref(&sFloatPrefs
[i
]);
501 for (i
= 0; i
< ArrayLength(sColorPrefs
); ++i
) {
502 InitColorFromPref(i
);
506 nsXPLookAndFeel::~nsXPLookAndFeel() {
507 NS_ASSERTION(sInstance
== this,
508 "This destroying instance isn't the singleton instance");
512 bool nsXPLookAndFeel::IsSpecialColor(ColorID aID
, nscolor
& aColor
) {
514 case ColorID::TextSelectForeground
:
515 return (aColor
== NS_DONT_CHANGE_COLOR
);
516 case ColorID::IMESelectedRawTextBackground
:
517 case ColorID::IMESelectedConvertedTextBackground
:
518 case ColorID::IMERawInputBackground
:
519 case ColorID::IMEConvertedTextBackground
:
520 case ColorID::IMESelectedRawTextForeground
:
521 case ColorID::IMESelectedConvertedTextForeground
:
522 case ColorID::IMERawInputForeground
:
523 case ColorID::IMEConvertedTextForeground
:
524 case ColorID::IMERawInputUnderline
:
525 case ColorID::IMEConvertedTextUnderline
:
526 case ColorID::IMESelectedRawTextUnderline
:
527 case ColorID::IMESelectedConvertedTextUnderline
:
528 case ColorID::SpellCheckerUnderline
:
529 return NS_IS_SELECTION_SPECIAL_COLOR(aColor
);
532 * In GetColor(), every color that is not a special color is color
533 * corrected. Use false to make other colors color corrected.
540 bool nsXPLookAndFeel::ColorIsNotCSSAccessible(ColorID aID
) {
542 case ColorID::WindowBackground
:
543 case ColorID::WindowForeground
:
544 case ColorID::WidgetBackground
:
545 case ColorID::WidgetForeground
:
546 case ColorID::WidgetSelectBackground
:
547 case ColorID::WidgetSelectForeground
:
548 case ColorID::Widget3DHighlight
:
549 case ColorID::Widget3DShadow
:
550 case ColorID::TextBackground
:
551 case ColorID::TextForeground
:
552 case ColorID::TextSelectBackground
:
553 case ColorID::TextSelectForeground
:
554 case ColorID::TextSelectBackgroundDisabled
:
555 case ColorID::TextSelectBackgroundAttention
:
556 case ColorID::TextHighlightBackground
:
557 case ColorID::TextHighlightForeground
:
558 case ColorID::IMERawInputBackground
:
559 case ColorID::IMERawInputForeground
:
560 case ColorID::IMERawInputUnderline
:
561 case ColorID::IMESelectedRawTextBackground
:
562 case ColorID::IMESelectedRawTextForeground
:
563 case ColorID::IMESelectedRawTextUnderline
:
564 case ColorID::IMEConvertedTextBackground
:
565 case ColorID::IMEConvertedTextForeground
:
566 case ColorID::IMEConvertedTextUnderline
:
567 case ColorID::IMESelectedConvertedTextBackground
:
568 case ColorID::IMESelectedConvertedTextForeground
:
569 case ColorID::IMESelectedConvertedTextUnderline
:
570 case ColorID::SpellCheckerUnderline
:
579 nscolor
nsXPLookAndFeel::GetStandinForNativeColor(ColorID aID
) {
580 nscolor result
= NS_RGB(0xFF, 0xFF, 0xFF);
582 // The stand-in colors are taken from the Windows 7 Aero theme
583 // except Mac-specific colors which are taken from Mac OS 10.7.
586 case ColorID::Activeborder
:
587 result
= NS_RGB(0xB4, 0xB4, 0xB4);
589 case ColorID::Activecaption
:
590 result
= NS_RGB(0x99, 0xB4, 0xD1);
592 case ColorID::Appworkspace
:
593 result
= NS_RGB(0xAB, 0xAB, 0xAB);
595 case ColorID::Background
:
596 result
= NS_RGB(0x00, 0x00, 0x00);
598 case ColorID::Buttonface
:
599 result
= NS_RGB(0xF0, 0xF0, 0xF0);
601 case ColorID::Buttonhighlight
:
602 result
= NS_RGB(0xFF, 0xFF, 0xFF);
604 case ColorID::Buttonshadow
:
605 result
= NS_RGB(0xA0, 0xA0, 0xA0);
607 case ColorID::Buttontext
:
608 result
= NS_RGB(0x00, 0x00, 0x00);
610 case ColorID::Captiontext
:
611 result
= NS_RGB(0x00, 0x00, 0x00);
613 case ColorID::Graytext
:
614 result
= NS_RGB(0x6D, 0x6D, 0x6D);
616 case ColorID::Highlight
:
617 result
= NS_RGB(0x33, 0x99, 0xFF);
619 case ColorID::Highlighttext
:
620 result
= NS_RGB(0xFF, 0xFF, 0xFF);
622 case ColorID::Inactiveborder
:
623 result
= NS_RGB(0xF4, 0xF7, 0xFC);
625 case ColorID::Inactivecaption
:
626 result
= NS_RGB(0xBF, 0xCD, 0xDB);
628 case ColorID::Inactivecaptiontext
:
629 result
= NS_RGB(0x43, 0x4E, 0x54);
631 case ColorID::Infobackground
:
632 result
= NS_RGB(0xFF, 0xFF, 0xE1);
634 case ColorID::Infotext
:
635 result
= NS_RGB(0x00, 0x00, 0x00);
638 result
= NS_RGB(0xF0, 0xF0, 0xF0);
640 case ColorID::Menutext
:
641 result
= NS_RGB(0x00, 0x00, 0x00);
643 case ColorID::Scrollbar
:
644 result
= NS_RGB(0xC8, 0xC8, 0xC8);
646 case ColorID::Threeddarkshadow
:
647 result
= NS_RGB(0x69, 0x69, 0x69);
649 case ColorID::Threedface
:
650 result
= NS_RGB(0xF0, 0xF0, 0xF0);
652 case ColorID::Threedhighlight
:
653 result
= NS_RGB(0xFF, 0xFF, 0xFF);
655 case ColorID::Threedlightshadow
:
656 result
= NS_RGB(0xE3, 0xE3, 0xE3);
658 case ColorID::Threedshadow
:
659 result
= NS_RGB(0xA0, 0xA0, 0xA0);
661 case ColorID::Window
:
662 result
= NS_RGB(0xFF, 0xFF, 0xFF);
664 case ColorID::Windowframe
:
665 result
= NS_RGB(0x64, 0x64, 0x64);
667 case ColorID::Windowtext
:
668 result
= NS_RGB(0x00, 0x00, 0x00);
670 case ColorID::MozButtondefault
:
671 result
= NS_RGB(0x69, 0x69, 0x69);
674 result
= NS_RGB(0xFF, 0xFF, 0xFF);
676 case ColorID::Fieldtext
:
677 result
= NS_RGB(0x00, 0x00, 0x00);
679 case ColorID::MozDialog
:
680 result
= NS_RGB(0xF0, 0xF0, 0xF0);
682 case ColorID::MozDialogtext
:
683 case ColorID::MozColheadertext
:
684 case ColorID::MozColheaderhovertext
:
685 result
= NS_RGB(0x00, 0x00, 0x00);
687 case ColorID::MozDragtargetzone
:
688 result
= NS_RGB(0xFF, 0xFF, 0xFF);
690 case ColorID::MozCellhighlight
:
691 result
= NS_RGB(0xF0, 0xF0, 0xF0);
693 case ColorID::MozCellhighlighttext
:
694 result
= NS_RGB(0x00, 0x00, 0x00);
696 case ColorID::MozHtmlCellhighlight
:
697 result
= NS_RGB(0x33, 0x99, 0xFF);
699 case ColorID::MozHtmlCellhighlighttext
:
700 result
= NS_RGB(0xFF, 0xFF, 0xFF);
702 case ColorID::MozButtonhoverface
:
703 result
= NS_RGB(0xF0, 0xF0, 0xF0);
705 case ColorID::MozGtkButtonactivetext
:
706 case ColorID::MozButtonhovertext
:
707 result
= NS_RGB(0x00, 0x00, 0x00);
709 case ColorID::MozMenuhover
:
710 result
= NS_RGB(0x33, 0x99, 0xFF);
712 case ColorID::MozMenuhovertext
:
713 result
= NS_RGB(0x00, 0x00, 0x00);
715 case ColorID::MozMenubartext
:
716 result
= NS_RGB(0x00, 0x00, 0x00);
718 case ColorID::MozMenubarhovertext
:
719 result
= NS_RGB(0x00, 0x00, 0x00);
721 case ColorID::MozOddtreerow
:
722 result
= NS_RGB(0xFF, 0xFF, 0xFF);
724 case ColorID::MozMacChromeActive
:
725 result
= NS_RGB(0xB2, 0xB2, 0xB2);
727 case ColorID::MozMacChromeInactive
:
728 result
= NS_RGB(0xE1, 0xE1, 0xE1);
730 case ColorID::MozMacFocusring
:
731 result
= NS_RGB(0x60, 0x9D, 0xD7);
733 case ColorID::MozMacMenuselect
:
734 result
= NS_RGB(0x38, 0x75, 0xD7);
736 case ColorID::MozMacMenushadow
:
737 result
= NS_RGB(0xA3, 0xA3, 0xA3);
739 case ColorID::MozMacMenutextdisable
:
740 result
= NS_RGB(0x88, 0x88, 0x88);
742 case ColorID::MozMacMenutextselect
:
743 result
= NS_RGB(0xFF, 0xFF, 0xFF);
745 case ColorID::MozMacDisabledtoolbartext
:
746 result
= NS_RGB(0x3F, 0x3F, 0x3F);
748 case ColorID::MozMacSecondaryhighlight
:
749 result
= NS_RGB(0xD4, 0xD4, 0xD4);
751 case ColorID::MozMacVibrancyLight
:
752 case ColorID::MozMacVibrantTitlebarLight
:
753 result
= NS_RGB(0xf7, 0xf7, 0xf7);
755 case ColorID::MozMacVibrancyDark
:
756 case ColorID::MozMacVibrantTitlebarDark
:
757 result
= NS_RGB(0x28, 0x28, 0x28);
759 case ColorID::MozMacMenupopup
:
760 result
= NS_RGB(0xe6, 0xe6, 0xe6);
762 case ColorID::MozMacMenuitem
:
763 result
= NS_RGB(0xe6, 0xe6, 0xe6);
765 case ColorID::MozMacActiveMenuitem
:
766 result
= NS_RGB(0x0a, 0x64, 0xdc);
768 case ColorID::MozMacSourceList
:
769 result
= NS_RGB(0xf7, 0xf7, 0xf7);
771 case ColorID::MozMacSourceListSelection
:
772 result
= NS_RGB(0xc8, 0xc8, 0xc8);
774 case ColorID::MozMacActiveSourceListSelection
:
775 result
= NS_RGB(0x0a, 0x64, 0xdc);
777 case ColorID::MozMacTooltip
:
778 result
= NS_RGB(0xf7, 0xf7, 0xf7);
780 case ColorID::MozWinAccentcolor
:
781 // Seems to be the default color (hardcoded because of bug 1065998)
782 result
= NS_RGB(0x9E, 0x9E, 0x9E);
784 case ColorID::MozWinAccentcolortext
:
785 result
= NS_RGB(0x00, 0x00, 0x00);
787 case ColorID::MozWinMediatext
:
788 result
= NS_RGB(0xFF, 0xFF, 0xFF);
790 case ColorID::MozWinCommunicationstext
:
791 result
= NS_RGB(0xFF, 0xFF, 0xFF);
793 case ColorID::MozNativehyperlinktext
:
794 result
= NS_RGB(0x00, 0x66, 0xCC);
796 case ColorID::MozComboboxtext
:
797 result
= NS_RGB(0x00, 0x00, 0x00);
799 case ColorID::MozCombobox
:
800 result
= NS_RGB(0xFF, 0xFF, 0xFF);
810 // All these routines will return NS_OK if they have a value,
811 // in which case the nsLookAndFeel should use that value;
812 // otherwise we'll return NS_ERROR_NOT_AVAILABLE, in which case, the
813 // platform-specific nsLookAndFeel should use its own values instead.
815 nsresult
nsXPLookAndFeel::GetColorValue(ColorID aID
,
816 bool aUseStandinsForNativeColors
,
818 if (!sInitialized
) Init();
820 // define DEBUG_SYSTEM_COLOR_USE if you want to debug system color
821 // use in a skin that uses them. When set, it will make all system
822 // color pairs that are appropriate for foreground/background
823 // pairing the same. This means if the skin is using system colors
824 // correctly you will not be able to see *any* text.
825 #undef DEBUG_SYSTEM_COLOR_USE
827 #ifdef DEBUG_SYSTEM_COLOR_USE
831 // css2 http://www.w3.org/TR/REC-CSS2/ui.html#system-colors
832 case ColorID::Activecaption
:
833 // active window caption background
834 case ColorID::Captiontext
:
835 // text in active window caption
836 aResult
= NS_RGB(0xff, 0x00, 0x00);
839 case ColorID::Highlight
:
840 // background of selected item
841 case ColorID::Highlighttext
:
842 // text of selected item
843 aResult
= NS_RGB(0xff, 0xff, 0x00);
846 case ColorID::Inactivecaption
:
847 // inactive window caption
848 case ColorID::Inactivecaptiontext
:
849 // text in inactive window caption
850 aResult
= NS_RGB(0x66, 0x66, 0x00);
853 case ColorID::Infobackground
:
854 // tooltip background color
855 case ColorID::Infotext
:
856 // tooltip text color
857 aResult
= NS_RGB(0x00, 0xff, 0x00);
862 case ColorID::Menutext
:
864 aResult
= NS_RGB(0x00, 0xff, 0xff);
867 case ColorID::Threedface
:
868 case ColorID::Buttonface
:
870 case ColorID::Buttontext
:
871 // text on push buttons
872 aResult
= NS_RGB(0x00, 0x66, 0x66);
875 case ColorID::Window
:
876 case ColorID::Windowtext
:
877 aResult
= NS_RGB(0x00, 0x00, 0xff);
880 // from the CSS3 working draft (not yet finalized)
881 // http://www.w3.org/tr/2000/wd-css3-userint-20000216.html#color
884 case ColorID::Fieldtext
:
885 aResult
= NS_RGB(0xff, 0x00, 0xff);
888 case ColorID::MozDialog
:
889 case ColorID::MozDialogtext
:
890 aResult
= NS_RGB(0x66, 0x00, 0x66);
894 rv
= NS_ERROR_NOT_AVAILABLE
;
896 if (NS_SUCCEEDED(rv
)) return rv
;
898 #endif // DEBUG_SYSTEM_COLOR_USE
900 if (aUseStandinsForNativeColors
&& ColorIsNotCSSAccessible(aID
)) {
901 aUseStandinsForNativeColors
= false;
904 if (!aUseStandinsForNativeColors
&& IS_COLOR_CACHED(aID
)) {
905 aResult
= sCachedColors
[uint32_t(aID
)];
909 // There are no system color settings for these, so set them manually
911 if (aID
== ColorID::TextSelectBackgroundDisabled
) {
912 // This is used to gray out the selection when it's not focused
913 // Used with nsISelectionController::SELECTION_DISABLED
914 aResult
= NS_RGB(0xb0, 0xb0, 0xb0);
919 if (aID
== ColorID::TextSelectBackgroundAttention
) {
920 if (StaticPrefs::findbar_modalHighlight() && !mozilla::FissionAutostart()) {
921 aResult
= NS_RGBA(0, 0, 0, 0);
925 // This makes the selection stand out when typeaheadfind is on
926 // Used with nsISelectionController::SELECTION_ATTENTION
927 aResult
= NS_RGB(0x38, 0xd8, 0x78);
931 if (aID
== ColorID::TextHighlightBackground
) {
932 // This makes the matched text stand out when findbar highlighting is on
933 // Used with nsISelectionController::SELECTION_FIND
934 aResult
= NS_RGB(0xef, 0x0f, 0xff);
938 if (aID
== ColorID::TextHighlightForeground
) {
939 // The foreground color for the matched text in findbar highlighting
940 // Used with nsISelectionController::SELECTION_FIND
941 aResult
= NS_RGB(0xff, 0xff, 0xff);
945 if (aUseStandinsForNativeColors
) {
946 aResult
= GetStandinForNativeColor(aID
);
950 if (NS_SUCCEEDED(NativeGetColor(aID
, aResult
))) {
951 if (!mozilla::ServoStyleSet::IsInServoTraversal()) {
952 MOZ_ASSERT(NS_IsMainThread());
953 if ((gfxPlatform::GetCMSMode() == eCMSMode_All
) &&
954 !IsSpecialColor(aID
, aResult
)) {
955 qcms_transform
* transform
= gfxPlatform::GetCMSInverseRGBTransform();
958 color
[0] = NS_GET_R(aResult
);
959 color
[1] = NS_GET_G(aResult
);
960 color
[2] = NS_GET_B(aResult
);
961 color
[3] = NS_GET_A(aResult
);
962 qcms_transform_data(transform
, color
, color
, 1);
963 aResult
= NS_RGBA(color
[0], color
[1], color
[2], color
[3]);
967 CACHE_COLOR(aID
, aResult
);
972 return NS_ERROR_NOT_AVAILABLE
;
975 nsresult
nsXPLookAndFeel::GetIntValue(IntID aID
, int32_t& aResult
) {
976 if (!sInitialized
) Init();
978 for (unsigned int i
= 0; i
< ArrayLength(sIntPrefs
); ++i
) {
979 if (sIntPrefs
[i
].isSet
&& (sIntPrefs
[i
].id
== aID
)) {
980 aResult
= sIntPrefs
[i
].intVar
;
985 return NativeGetInt(aID
, aResult
);
988 nsresult
nsXPLookAndFeel::GetFloatValue(FloatID aID
, float& aResult
) {
989 if (!sInitialized
) Init();
991 for (unsigned int i
= 0; i
< ArrayLength(sFloatPrefs
); ++i
) {
992 if (sFloatPrefs
[i
].isSet
&& sFloatPrefs
[i
].id
== aID
) {
993 aResult
= sFloatPrefs
[i
].floatVar
;
998 return NativeGetFloat(aID
, aResult
);
1001 void nsXPLookAndFeel::RefreshImpl() {
1002 // Wipe out our color cache.
1004 for (i
= 0; i
< uint32_t(ColorID::End
); i
++) {
1005 sCachedColors
[i
] = 0;
1007 for (i
= 0; i
< COLOR_CACHE_SIZE
; i
++) {
1008 sCachedColorBits
[i
] = 0;
1011 // Reinit color cache from prefs.
1012 for (i
= 0; i
< uint32_t(ColorID::End
); ++i
) {
1013 InitColorFromPref(i
);
1016 // Clear any cached FullLookAndFeel data, which is now invalid.
1017 if (XRE_IsParentProcess()) {
1018 widget::RemoteLookAndFeel::ClearCachedData();
1022 widget::LookAndFeelCache
nsXPLookAndFeel::GetCacheImpl() {
1023 return LookAndFeelCache
{};
1026 static bool sRecordedLookAndFeelTelemetry
= false;
1028 void nsXPLookAndFeel::RecordTelemetry() {
1029 if (!XRE_IsParentProcess()) {
1033 if (sRecordedLookAndFeelTelemetry
) {
1037 sRecordedLookAndFeelTelemetry
= true;
1040 Telemetry::ScalarSet(
1041 Telemetry::ScalarID::WIDGET_DARK_MODE
,
1042 NS_SUCCEEDED(GetIntValue(IntID::SystemUsesDarkTheme
, i
)) && i
!= 0);
1044 RecordLookAndFeelSpecificTelemetry();
1050 void LookAndFeel::NotifyChangedAllWindows(widget::ThemeChangeKind aKind
) {
1051 if (nsCOMPtr
<nsIObserverService
> obs
= services::GetObserverService()) {
1052 obs
->NotifyObservers(nullptr, "look-and-feel-changed",
1053 reinterpret_cast<char16_t
*>(uintptr_t(aKind
)));
1058 nsresult
LookAndFeel::GetColor(ColorID aID
, nscolor
* aResult
) {
1059 return nsLookAndFeel::GetInstance()->GetColorValue(aID
, false, *aResult
);
1062 nsresult
LookAndFeel::GetColor(ColorID aID
, bool aUseStandinsForNativeColors
,
1064 return nsLookAndFeel::GetInstance()->GetColorValue(
1065 aID
, aUseStandinsForNativeColors
, *aResult
);
1069 nsresult
LookAndFeel::GetInt(IntID aID
, int32_t* aResult
) {
1070 return nsLookAndFeel::GetInstance()->GetIntValue(aID
, *aResult
);
1074 nsresult
LookAndFeel::GetFloat(FloatID aID
, float* aResult
) {
1075 return nsLookAndFeel::GetInstance()->GetFloatValue(aID
, *aResult
);
1079 bool LookAndFeel::GetFont(FontID aID
, nsString
& aName
, gfxFontStyle
& aStyle
) {
1080 return nsLookAndFeel::GetInstance()->GetFontValue(aID
, aName
, aStyle
);
1084 char16_t
LookAndFeel::GetPasswordCharacter() {
1085 return nsLookAndFeel::GetInstance()->GetPasswordCharacterImpl();
1089 bool LookAndFeel::GetEchoPassword() {
1090 if (StaticPrefs::editor_password_mask_delay() >= 0) {
1091 return StaticPrefs::editor_password_mask_delay() > 0;
1093 return nsLookAndFeel::GetInstance()->GetEchoPasswordImpl();
1097 uint32_t LookAndFeel::GetPasswordMaskDelay() {
1098 int32_t delay
= StaticPrefs::editor_password_mask_delay();
1100 return nsLookAndFeel::GetInstance()->GetPasswordMaskDelayImpl();
1106 void LookAndFeel::Refresh() {
1107 nsLookAndFeel::GetInstance()->RefreshImpl();
1108 nsNativeBasicTheme::LookAndFeelChanged();
1112 void LookAndFeel::NativeInit() { nsLookAndFeel::GetInstance()->NativeInit(); }
1115 widget::LookAndFeelCache
LookAndFeel::GetCache() {
1116 return nsLookAndFeel::GetInstance()->GetCacheImpl();
1120 void LookAndFeel::SetCache(const widget::LookAndFeelCache
& aCache
) {
1121 nsLookAndFeel::GetInstance()->SetCacheImpl(aCache
);
1125 void LookAndFeel::SetData(widget::FullLookAndFeel
&& aTables
) {
1126 nsLookAndFeel::GetInstance()->SetDataImpl(std::move(aTables
));
1129 } // namespace mozilla