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 "mozilla/dom/ContentChild.h"
19 #include "mozilla/Preferences.h"
20 #include "mozilla/Services.h"
21 #include "mozilla/ServoStyleSet.h"
22 #include "mozilla/StaticPrefs_editor.h"
23 #include "mozilla/StaticPrefs_findbar.h"
24 #include "mozilla/StaticPrefs_ui.h"
25 #include "mozilla/StaticPrefs_widget.h"
26 #include "mozilla/gfx/2D.h"
27 #include "mozilla/widget/WidgetMessageUtils.h"
28 #include "mozilla/Telemetry.h"
29 #include "mozilla/TelemetryScalarEnums.h"
31 #include "gfxPlatform.h"
39 using namespace mozilla
;
41 // To make one of these prefs toggleable from a reftest add a user
42 // pref in testing/profiles/reftest/user.js. For example, to make
43 // ui.useAccessibilityTheme toggleable, add:
45 // user_pref("ui.useAccessibilityTheme", 0);
47 nsLookAndFeelIntPref
nsXPLookAndFeel::sIntPrefs
[] = {
48 {"ui.caretBlinkTime", IntID::CaretBlinkTime
, false, 0},
49 {"ui.caretWidth", IntID::CaretWidth
, false, 0},
50 {"ui.caretVisibleWithSelection", IntID::ShowCaretDuringSelection
, false, 0},
51 {"ui.submenuDelay", IntID::SubmenuDelay
, false, 0},
52 {"ui.dragThresholdX", IntID::DragThresholdX
, false, 0},
53 {"ui.dragThresholdY", IntID::DragThresholdY
, false, 0},
54 {"ui.useAccessibilityTheme", IntID::UseAccessibilityTheme
, false, 0},
55 {"ui.menusCanOverlapOSBar", IntID::MenusCanOverlapOSBar
, false, 0},
56 {"ui.useOverlayScrollbars", IntID::UseOverlayScrollbars
, false, 0},
57 {"ui.scrollbarDisplayOnMouseMove", IntID::ScrollbarDisplayOnMouseMove
,
59 {"ui.scrollbarFadeBeginDelay", IntID::ScrollbarFadeBeginDelay
, false, 0},
60 {"ui.scrollbarFadeDuration", IntID::ScrollbarFadeDuration
, false, 0},
61 {"ui.showHideScrollbars", IntID::ShowHideScrollbars
, false, 0},
62 {"ui.skipNavigatingDisabledMenuItem", IntID::SkipNavigatingDisabledMenuItem
,
64 {"ui.treeOpenDelay", IntID::TreeOpenDelay
, false, 0},
65 {"ui.treeCloseDelay", IntID::TreeCloseDelay
, false, 0},
66 {"ui.treeLazyScrollDelay", IntID::TreeLazyScrollDelay
, false, 0},
67 {"ui.treeScrollDelay", IntID::TreeScrollDelay
, false, 0},
68 {"ui.treeScrollLinesMax", IntID::TreeScrollLinesMax
, false, 0},
69 {"accessibility.tabfocus", IntID::TabFocusModel
, false, 0},
70 {"ui.alertNotificationOrigin", IntID::AlertNotificationOrigin
, false, 0},
71 {"ui.scrollToClick", IntID::ScrollToClick
, false, 0},
72 {"ui.IMERawInputUnderlineStyle", IntID::IMERawInputUnderlineStyle
, false,
74 {"ui.IMESelectedRawTextUnderlineStyle",
75 IntID::IMESelectedRawTextUnderlineStyle
, false, 0},
76 {"ui.IMEConvertedTextUnderlineStyle", IntID::IMEConvertedTextUnderlineStyle
,
78 {"ui.IMESelectedConvertedTextUnderlineStyle",
79 IntID::IMESelectedConvertedTextUnderline
, false, 0},
80 {"ui.SpellCheckerUnderlineStyle", IntID::SpellCheckerUnderlineStyle
, false,
82 {"ui.scrollbarButtonAutoRepeatBehavior",
83 IntID::ScrollbarButtonAutoRepeatBehavior
, false, 0},
84 {"ui.tooltipDelay", IntID::TooltipDelay
, false, 0},
85 {"ui.contextMenuOffsetVertical", IntID::ContextMenuOffsetVertical
, false,
87 {"ui.contextMenuOffsetHorizontal", IntID::ContextMenuOffsetHorizontal
,
89 {"ui.GtkCSDAvailable", IntID::GTKCSDAvailable
, false, 0},
90 {"ui.GtkCSDHideTitlebarByDefault", IntID::GTKCSDHideTitlebarByDefault
,
92 {"ui.GtkCSDTransparentBackground", IntID::GTKCSDTransparentBackground
,
94 {"ui.GtkCSDMinimizeButton", IntID::GTKCSDMinimizeButton
, false, 0},
95 {"ui.GtkCSDMaximizeButton", IntID::GTKCSDMaximizeButton
, false, 0},
96 {"ui.GtkCSDCloseButton", IntID::GTKCSDCloseButton
, false, 0},
97 {"ui.systemUsesDarkTheme", IntID::SystemUsesDarkTheme
, false, 0},
98 {"ui.prefersReducedMotion", IntID::PrefersReducedMotion
, false, 0},
99 {"ui.primaryPointerCapabilities", IntID::PrimaryPointerCapabilities
, false,
100 6 /* fine and hover-capable pointer, i.e. mouse-type */},
101 {"ui.allPointerCapabilities", IntID::AllPointerCapabilities
, false,
102 6 /* fine and hover-capable pointer, i.e. mouse-type */},
103 {"ui.scrollArrowStyle", IntID::ScrollArrowStyle
, false, 0},
106 nsLookAndFeelFloatPref
nsXPLookAndFeel::sFloatPrefs
[] = {
107 {"ui.IMEUnderlineRelativeSize", FloatID::IMEUnderlineRelativeSize
, false,
109 {"ui.SpellCheckerUnderlineRelativeSize",
110 FloatID::SpellCheckerUnderlineRelativeSize
, false, 0},
111 {"ui.caretAspectRatio", FloatID::CaretAspectRatio
, false, 0},
114 // This array MUST be kept in the same order as the color list in
115 // specified/color.rs
116 /* XXX If you add any strings longer than
117 * "ui.-moz-mac-active-source-list-selection"
118 * to the following array then you MUST update the
119 * sizes of the sColorPrefs array in nsXPLookAndFeel.h
121 const char nsXPLookAndFeel::sColorPrefs
[][41] = {
122 "ui.windowBackground",
123 "ui.windowForeground",
124 "ui.widgetBackground",
125 "ui.widgetForeground",
126 "ui.widgetSelectBackground",
127 "ui.widgetSelectForeground",
128 "ui.widget3DHighlight",
132 "ui.textSelectBackground",
133 "ui.textSelectForeground",
134 "ui.textSelectForegroundCustom",
135 "ui.textSelectBackgroundDisabled",
136 "ui.textSelectBackgroundAttention",
137 "ui.textHighlightBackground",
138 "ui.textHighlightForeground",
139 "ui.IMERawInputBackground",
140 "ui.IMERawInputForeground",
141 "ui.IMERawInputUnderline",
142 "ui.IMESelectedRawTextBackground",
143 "ui.IMESelectedRawTextForeground",
144 "ui.IMESelectedRawTextUnderline",
145 "ui.IMEConvertedTextBackground",
146 "ui.IMEConvertedTextForeground",
147 "ui.IMEConvertedTextUnderline",
148 "ui.IMESelectedConvertedTextBackground",
149 "ui.IMESelectedConvertedTextForeground",
150 "ui.IMESelectedConvertedTextUnderline",
151 "ui.SpellCheckerUnderline",
152 "ui.themedScrollbar",
153 "ui.themedScrollbarInactive",
154 "ui.themedScrollbarThumb",
155 "ui.themedScrollbarThumbHover",
156 "ui.themedScrollbarThumbActive",
157 "ui.themedScrollbarThumbInactive",
163 "ui.buttonhighlight",
173 "ui.inactivecaption",
174 "ui.inactivecaptiontext",
180 "ui.threeddarkshadow",
182 "ui.threedhighlight",
183 "ui.threedlightshadow",
188 "ui.-moz-buttondefault",
189 "ui.-moz-default-color",
190 "ui.-moz-default-background-color",
192 "ui.-moz-dialogtext",
193 "ui.-moz-dragtargetzone",
194 "ui.-moz-cellhighlight",
195 "ui.-moz_cellhighlighttext",
196 "ui.-moz-html-cellhighlight",
197 "ui.-moz-html-cellhighlighttext",
198 "ui.-moz-buttonhoverface",
199 "ui.-moz_buttonhovertext",
201 "ui.-moz_menuhovertext",
202 "ui.-moz_menubartext",
203 "ui.-moz_menubarhovertext",
204 "ui.-moz_eventreerow",
205 "ui.-moz_oddtreerow",
206 "ui.-moz-gtk-buttonactivetext",
207 "ui.-moz-mac-buttonactivetext",
208 "ui.-moz_mac_chrome_active",
209 "ui.-moz_mac_chrome_inactive",
210 "ui.-moz-mac-defaultbuttontext",
211 "ui.-moz-mac-focusring",
212 "ui.-moz-mac-menuselect",
213 "ui.-moz-mac-menushadow",
214 "ui.-moz-mac-menutextdisable",
215 "ui.-moz-mac-menutextselect",
216 "ui.-moz_mac_disabledtoolbartext",
217 "ui.-moz-mac-secondaryhighlight",
218 "ui.-moz-mac-vibrancy-light",
219 "ui.-moz-mac-vibrancy-dark",
220 "ui.-moz-mac-vibrant-titlebar-light",
221 "ui.-moz-mac-vibrant-titlebar-dark",
222 "ui.-moz-mac-menupopup",
223 "ui.-moz-mac-menuitem",
224 "ui.-moz-mac-active-menuitem",
225 "ui.-moz-mac-source-list",
226 "ui.-moz-mac-source-list-selection",
227 "ui.-moz-mac-active-source-list-selection",
228 "ui.-moz-mac-tooltip",
229 "ui.-moz-win-accentcolor",
230 "ui.-moz-win-accentcolortext",
231 "ui.-moz-win-mediatext",
232 "ui.-moz-win-communicationstext",
233 "ui.-moz-nativehyperlinktext",
234 "ui.-moz-hyperlinktext",
235 "ui.-moz-activehyperlinktext",
236 "ui.-moz-visitedhyperlinktext",
237 "ui.-moz-comboboxtext",
239 "ui.-moz-gtk-info-bar-text",
240 "ui.-moz-colheadertext",
241 "ui.-moz-colheaderhovertext"};
243 int32_t nsXPLookAndFeel::sCachedColors
[size_t(LookAndFeel::ColorID::End
)] = {0};
244 int32_t nsXPLookAndFeel::sCachedColorBits
[COLOR_CACHE_SIZE
] = {0};
246 bool nsXPLookAndFeel::sInitialized
= false;
248 nsXPLookAndFeel
* nsXPLookAndFeel::sInstance
= nullptr;
249 bool nsXPLookAndFeel::sShutdown
= false;
252 nsXPLookAndFeel
* nsXPLookAndFeel::GetInstance() {
257 NS_ENSURE_TRUE(!sShutdown
, nullptr);
259 // If we're in a content process, then the parent process will have supplied
260 // us with an initial FullLookAndFeel object (for when the RemoteLookAndFeel
261 // is to be used) or an initial LookAndFeelCache object (for regular
262 // LookAndFeel implementations). We grab this data from the ContentChild,
263 // where it's been temporarily stashed, and initialize our new LookAndFeel
266 LookAndFeelCache
* lnfCache
= nullptr;
267 FullLookAndFeel
* fullLnf
= nullptr;
268 widget::LookAndFeelData
* lnfData
= nullptr;
270 if (auto* cc
= mozilla::dom::ContentChild::GetSingleton()) {
271 lnfData
= &cc
->BorrowLookAndFeelData();
272 switch (lnfData
->type()) {
273 case widget::LookAndFeelData::TLookAndFeelCache
:
274 lnfCache
= &lnfData
->get_LookAndFeelCache();
276 case widget::LookAndFeelData::TFullLookAndFeel
:
277 fullLnf
= &lnfData
->get_FullLookAndFeel();
280 MOZ_ASSERT_UNREACHABLE("unexpected LookAndFeelData type");
285 sInstance
= new widget::RemoteLookAndFeel(std::move(*fullLnf
));
286 } else if (gfxPlatform::IsHeadless()) {
287 sInstance
= new widget::HeadlessLookAndFeel(lnfCache
);
289 sInstance
= new nsLookAndFeel(lnfCache
);
292 // This is only ever used once during initialization, and can be cleared now.
294 *lnfData
= widget::LookAndFeelData
{};
301 void nsXPLookAndFeel::Shutdown() {
311 void nsXPLookAndFeel::IntPrefChanged(nsLookAndFeelIntPref
* data
) {
317 nsresult rv
= Preferences::GetInt(data
->name
, &intpref
);
322 printf("====== Cleared int pref %s\n", data
->name
);
325 data
->intVar
= intpref
;
329 printf("====== Changed int pref %s to %d\n", data
->name
, data
->intVar
);
333 // Int prefs can't change our system colors or fonts.
334 NotifyChangedAllWindows(widget::ThemeChangeKind::MediaQueriesOnly
);
338 void nsXPLookAndFeel::FloatPrefChanged(nsLookAndFeelFloatPref
* data
) {
344 nsresult rv
= Preferences::GetInt(data
->name
, &intpref
);
349 printf("====== Cleared float pref %s\n", data
->name
);
352 data
->floatVar
= (float)intpref
/ 100.0f
;
356 printf("====== Changed float pref %s to %f\n", data
->name
);
360 // Float prefs can't change our system colors or fonts.
361 NotifyChangedAllWindows(widget::ThemeChangeKind::MediaQueriesOnly
);
365 void nsXPLookAndFeel::ColorPrefChanged(unsigned int index
,
366 const char* prefName
) {
367 nsAutoString colorStr
;
368 nsresult rv
= Preferences::GetString(prefName
, colorStr
);
369 if (NS_SUCCEEDED(rv
) && !colorStr
.IsEmpty()) {
371 if (colorStr
[0] == char16_t('#')) {
372 if (NS_HexToRGBA(nsDependentString(colorStr
, 1), nsHexColorType::NoAlpha
,
374 int32_t id
= NS_PTR_TO_INT32(index
);
375 CACHE_COLOR(id
, thecolor
);
377 } else if (NS_ColorNameToRGB(colorStr
, &thecolor
)) {
378 int32_t id
= NS_PTR_TO_INT32(index
);
379 CACHE_COLOR(id
, thecolor
);
381 printf("====== Changed color pref %s to 0x%lx\n", prefName
, thecolor
);
385 // Reset to the default color, by clearing the cache
386 // to force lookup when the color is next used
387 int32_t id
= NS_PTR_TO_INT32(index
);
388 CLEAR_COLOR_CACHE(id
);
391 printf("====== Cleared color pref %s\n", prefName
);
395 // Color prefs affect style, because they by definition change system colors.
396 NotifyChangedAllWindows(widget::ThemeChangeKind::Style
);
399 void nsXPLookAndFeel::InitFromPref(nsLookAndFeelIntPref
* aPref
) {
401 nsresult rv
= Preferences::GetInt(aPref
->name
, &intpref
);
402 if (NS_SUCCEEDED(rv
)) {
404 aPref
->intVar
= intpref
;
408 void nsXPLookAndFeel::InitFromPref(nsLookAndFeelFloatPref
* aPref
) {
410 nsresult rv
= Preferences::GetInt(aPref
->name
, &intpref
);
411 if (NS_SUCCEEDED(rv
)) {
413 aPref
->floatVar
= (float)intpref
/ 100.0f
;
417 void nsXPLookAndFeel::InitColorFromPref(int32_t i
) {
418 static_assert(ArrayLength(sColorPrefs
) == size_t(ColorID::End
),
419 "Should have a pref for each color value");
421 nsAutoString colorStr
;
422 nsresult rv
= Preferences::GetString(sColorPrefs
[i
], colorStr
);
423 if (NS_FAILED(rv
) || colorStr
.IsEmpty()) {
427 if (colorStr
[0] == char16_t('#')) {
428 nsAutoString hexString
;
429 colorStr
.Right(hexString
, colorStr
.Length() - 1);
430 if (NS_HexToRGBA(hexString
, nsHexColorType::NoAlpha
, &thecolor
)) {
431 CACHE_COLOR(i
, thecolor
);
433 } else if (NS_ColorNameToRGB(colorStr
, &thecolor
)) {
434 CACHE_COLOR(i
, thecolor
);
439 void nsXPLookAndFeel::OnPrefChanged(const char* aPref
, void* aClosure
) {
440 // looping in the same order as in ::Init
442 nsDependentCString
prefName(aPref
);
444 for (i
= 0; i
< ArrayLength(sIntPrefs
); ++i
) {
445 if (prefName
.Equals(sIntPrefs
[i
].name
)) {
446 IntPrefChanged(&sIntPrefs
[i
]);
451 for (i
= 0; i
< ArrayLength(sFloatPrefs
); ++i
) {
452 if (prefName
.Equals(sFloatPrefs
[i
].name
)) {
453 FloatPrefChanged(&sFloatPrefs
[i
]);
458 for (i
= 0; i
< ArrayLength(sColorPrefs
); ++i
) {
459 if (prefName
.Equals(sColorPrefs
[i
])) {
460 ColorPrefChanged(i
, sColorPrefs
[i
]);
467 // Read values from the user's preferences.
468 // This is done once at startup, but since the user's preferences
469 // haven't actually been read yet at that time, we also have to
470 // set a callback to inform us of changes to each pref.
472 void nsXPLookAndFeel::Init() {
473 MOZ_RELEASE_ASSERT(NS_IsMainThread());
475 // Say we're already initialized, and take the chance that it might fail;
476 // protects against some other process writing to our static variables.
479 // XXX If we could reorganize the pref names, we should separate the branch
480 // for each types. Then, we could reduce the unnecessary loop from
481 // nsXPLookAndFeel::OnPrefChanged().
482 Preferences::RegisterPrefixCallback(OnPrefChanged
, "ui.");
483 // We really do just want the accessibility.tabfocus pref, not other prefs
484 // that start with that string.
485 Preferences::RegisterCallback(OnPrefChanged
, "accessibility.tabfocus");
488 for (i
= 0; i
< ArrayLength(sIntPrefs
); ++i
) {
489 InitFromPref(&sIntPrefs
[i
]);
492 for (i
= 0; i
< ArrayLength(sFloatPrefs
); ++i
) {
493 InitFromPref(&sFloatPrefs
[i
]);
496 for (i
= 0; i
< ArrayLength(sColorPrefs
); ++i
) {
497 InitColorFromPref(i
);
501 nsXPLookAndFeel::~nsXPLookAndFeel() {
502 NS_ASSERTION(sInstance
== this,
503 "This destroying instance isn't the singleton instance");
507 bool nsXPLookAndFeel::IsSpecialColor(ColorID aID
, nscolor
& aColor
) {
509 case ColorID::TextSelectForeground
:
510 return (aColor
== NS_DONT_CHANGE_COLOR
);
511 case ColorID::IMESelectedRawTextBackground
:
512 case ColorID::IMESelectedConvertedTextBackground
:
513 case ColorID::IMERawInputBackground
:
514 case ColorID::IMEConvertedTextBackground
:
515 case ColorID::IMESelectedRawTextForeground
:
516 case ColorID::IMESelectedConvertedTextForeground
:
517 case ColorID::IMERawInputForeground
:
518 case ColorID::IMEConvertedTextForeground
:
519 case ColorID::IMERawInputUnderline
:
520 case ColorID::IMEConvertedTextUnderline
:
521 case ColorID::IMESelectedRawTextUnderline
:
522 case ColorID::IMESelectedConvertedTextUnderline
:
523 case ColorID::SpellCheckerUnderline
:
524 return NS_IS_SELECTION_SPECIAL_COLOR(aColor
);
527 * In GetColor(), every color that is not a special color is color
528 * corrected. Use false to make other colors color corrected.
535 bool nsXPLookAndFeel::ColorIsNotCSSAccessible(ColorID aID
) {
539 case ColorID::WindowBackground
:
540 case ColorID::WindowForeground
:
541 case ColorID::WidgetBackground
:
542 case ColorID::WidgetForeground
:
543 case ColorID::WidgetSelectBackground
:
544 case ColorID::WidgetSelectForeground
:
545 case ColorID::Widget3DHighlight
:
546 case ColorID::Widget3DShadow
:
547 case ColorID::TextBackground
:
548 case ColorID::TextForeground
:
549 case ColorID::TextSelectBackground
:
550 case ColorID::TextSelectForeground
:
551 case ColorID::TextSelectBackgroundDisabled
:
552 case ColorID::TextSelectBackgroundAttention
:
553 case ColorID::TextHighlightBackground
:
554 case ColorID::TextHighlightForeground
:
555 case ColorID::IMERawInputBackground
:
556 case ColorID::IMERawInputForeground
:
557 case ColorID::IMERawInputUnderline
:
558 case ColorID::IMESelectedRawTextBackground
:
559 case ColorID::IMESelectedRawTextForeground
:
560 case ColorID::IMESelectedRawTextUnderline
:
561 case ColorID::IMEConvertedTextBackground
:
562 case ColorID::IMEConvertedTextForeground
:
563 case ColorID::IMEConvertedTextUnderline
:
564 case ColorID::IMESelectedConvertedTextBackground
:
565 case ColorID::IMESelectedConvertedTextForeground
:
566 case ColorID::IMESelectedConvertedTextUnderline
:
567 case ColorID::SpellCheckerUnderline
:
577 nscolor
nsXPLookAndFeel::GetStandinForNativeColor(ColorID aID
) {
578 nscolor result
= NS_RGB(0xFF, 0xFF, 0xFF);
580 // The stand-in colors are taken from the Windows 7 Aero theme
581 // except Mac-specific colors which are taken from Mac OS 10.7.
584 case ColorID::Activeborder
:
585 result
= NS_RGB(0xB4, 0xB4, 0xB4);
587 case ColorID::Activecaption
:
588 result
= NS_RGB(0x99, 0xB4, 0xD1);
590 case ColorID::Appworkspace
:
591 result
= NS_RGB(0xAB, 0xAB, 0xAB);
593 case ColorID::Background
:
594 result
= NS_RGB(0x00, 0x00, 0x00);
596 case ColorID::Buttonface
:
597 result
= NS_RGB(0xF0, 0xF0, 0xF0);
599 case ColorID::Buttonhighlight
:
600 result
= NS_RGB(0xFF, 0xFF, 0xFF);
602 case ColorID::Buttonshadow
:
603 result
= NS_RGB(0xA0, 0xA0, 0xA0);
605 case ColorID::Buttontext
:
606 result
= NS_RGB(0x00, 0x00, 0x00);
608 case ColorID::Captiontext
:
609 result
= NS_RGB(0x00, 0x00, 0x00);
611 case ColorID::Graytext
:
612 result
= NS_RGB(0x6D, 0x6D, 0x6D);
614 case ColorID::Highlight
:
615 result
= NS_RGB(0x33, 0x99, 0xFF);
617 case ColorID::Highlighttext
:
618 result
= NS_RGB(0xFF, 0xFF, 0xFF);
620 case ColorID::Inactiveborder
:
621 result
= NS_RGB(0xF4, 0xF7, 0xFC);
623 case ColorID::Inactivecaption
:
624 result
= NS_RGB(0xBF, 0xCD, 0xDB);
626 case ColorID::Inactivecaptiontext
:
627 result
= NS_RGB(0x43, 0x4E, 0x54);
629 case ColorID::Infobackground
:
630 result
= NS_RGB(0xFF, 0xFF, 0xE1);
632 case ColorID::Infotext
:
633 result
= NS_RGB(0x00, 0x00, 0x00);
636 result
= NS_RGB(0xF0, 0xF0, 0xF0);
638 case ColorID::Menutext
:
639 result
= NS_RGB(0x00, 0x00, 0x00);
641 case ColorID::Scrollbar
:
642 result
= NS_RGB(0xC8, 0xC8, 0xC8);
644 case ColorID::Threeddarkshadow
:
645 result
= NS_RGB(0x69, 0x69, 0x69);
647 case ColorID::Threedface
:
648 result
= NS_RGB(0xF0, 0xF0, 0xF0);
650 case ColorID::Threedhighlight
:
651 result
= NS_RGB(0xFF, 0xFF, 0xFF);
653 case ColorID::Threedlightshadow
:
654 result
= NS_RGB(0xE3, 0xE3, 0xE3);
656 case ColorID::Threedshadow
:
657 result
= NS_RGB(0xA0, 0xA0, 0xA0);
659 case ColorID::Window
:
660 result
= NS_RGB(0xFF, 0xFF, 0xFF);
662 case ColorID::Windowframe
:
663 result
= NS_RGB(0x64, 0x64, 0x64);
665 case ColorID::Windowtext
:
666 result
= NS_RGB(0x00, 0x00, 0x00);
668 case ColorID::MozButtondefault
:
669 result
= NS_RGB(0x69, 0x69, 0x69);
672 result
= NS_RGB(0xFF, 0xFF, 0xFF);
674 case ColorID::Fieldtext
:
675 result
= NS_RGB(0x00, 0x00, 0x00);
677 case ColorID::MozDialog
:
678 result
= NS_RGB(0xF0, 0xF0, 0xF0);
680 case ColorID::MozDialogtext
:
681 case ColorID::MozColheadertext
:
682 case ColorID::MozColheaderhovertext
:
683 result
= NS_RGB(0x00, 0x00, 0x00);
685 case ColorID::MozDragtargetzone
:
686 result
= NS_RGB(0xFF, 0xFF, 0xFF);
688 case ColorID::MozCellhighlight
:
689 result
= NS_RGB(0xF0, 0xF0, 0xF0);
691 case ColorID::MozCellhighlighttext
:
692 result
= NS_RGB(0x00, 0x00, 0x00);
694 case ColorID::MozHtmlCellhighlight
:
695 result
= NS_RGB(0x33, 0x99, 0xFF);
697 case ColorID::MozHtmlCellhighlighttext
:
698 result
= NS_RGB(0xFF, 0xFF, 0xFF);
700 case ColorID::MozButtonhoverface
:
701 result
= NS_RGB(0xF0, 0xF0, 0xF0);
703 case ColorID::MozButtonhovertext
:
704 result
= NS_RGB(0x00, 0x00, 0x00);
706 case ColorID::MozMenuhover
:
707 result
= NS_RGB(0x33, 0x99, 0xFF);
709 case ColorID::MozMenuhovertext
:
710 result
= NS_RGB(0x00, 0x00, 0x00);
712 case ColorID::MozMenubartext
:
713 result
= NS_RGB(0x00, 0x00, 0x00);
715 case ColorID::MozMenubarhovertext
:
716 result
= NS_RGB(0x00, 0x00, 0x00);
718 case ColorID::MozOddtreerow
:
719 case ColorID::MozGtkButtonactivetext
:
720 result
= NS_RGB(0xFF, 0xFF, 0xFF);
722 case ColorID::MozMacChromeActive
:
723 result
= NS_RGB(0xB2, 0xB2, 0xB2);
725 case ColorID::MozMacChromeInactive
:
726 result
= NS_RGB(0xE1, 0xE1, 0xE1);
728 case ColorID::MozMacFocusring
:
729 result
= NS_RGB(0x60, 0x9D, 0xD7);
731 case ColorID::MozMacMenuselect
:
732 result
= NS_RGB(0x38, 0x75, 0xD7);
734 case ColorID::MozMacMenushadow
:
735 result
= NS_RGB(0xA3, 0xA3, 0xA3);
737 case ColorID::MozMacMenutextdisable
:
738 result
= NS_RGB(0x88, 0x88, 0x88);
740 case ColorID::MozMacMenutextselect
:
741 result
= NS_RGB(0xFF, 0xFF, 0xFF);
743 case ColorID::MozMacDisabledtoolbartext
:
744 result
= NS_RGB(0x3F, 0x3F, 0x3F);
746 case ColorID::MozMacSecondaryhighlight
:
747 result
= NS_RGB(0xD4, 0xD4, 0xD4);
749 case ColorID::MozMacVibrancyLight
:
750 case ColorID::MozMacVibrantTitlebarLight
:
751 result
= NS_RGB(0xf7, 0xf7, 0xf7);
753 case ColorID::MozMacVibrancyDark
:
754 case ColorID::MozMacVibrantTitlebarDark
:
755 result
= NS_RGB(0x28, 0x28, 0x28);
757 case ColorID::MozMacMenupopup
:
758 result
= NS_RGB(0xe6, 0xe6, 0xe6);
760 case ColorID::MozMacMenuitem
:
761 result
= NS_RGB(0xe6, 0xe6, 0xe6);
763 case ColorID::MozMacActiveMenuitem
:
764 result
= NS_RGB(0x0a, 0x64, 0xdc);
766 case ColorID::MozMacSourceList
:
767 result
= NS_RGB(0xf7, 0xf7, 0xf7);
769 case ColorID::MozMacSourceListSelection
:
770 result
= NS_RGB(0xc8, 0xc8, 0xc8);
772 case ColorID::MozMacActiveSourceListSelection
:
773 result
= NS_RGB(0x0a, 0x64, 0xdc);
775 case ColorID::MozMacTooltip
:
776 result
= NS_RGB(0xf7, 0xf7, 0xf7);
778 case ColorID::MozWinAccentcolor
:
779 // Seems to be the default color (hardcoded because of bug 1065998)
780 result
= NS_RGB(0x9E, 0x9E, 0x9E);
782 case ColorID::MozWinAccentcolortext
:
783 result
= NS_RGB(0x00, 0x00, 0x00);
785 case ColorID::MozWinMediatext
:
786 result
= NS_RGB(0xFF, 0xFF, 0xFF);
788 case ColorID::MozWinCommunicationstext
:
789 result
= NS_RGB(0xFF, 0xFF, 0xFF);
791 case ColorID::MozNativehyperlinktext
:
792 result
= NS_RGB(0x00, 0x66, 0xCC);
794 case ColorID::MozComboboxtext
:
795 result
= NS_RGB(0x00, 0x00, 0x00);
797 case ColorID::MozCombobox
:
798 result
= NS_RGB(0xFF, 0xFF, 0xFF);
808 // All these routines will return NS_OK if they have a value,
809 // in which case the nsLookAndFeel should use that value;
810 // otherwise we'll return NS_ERROR_NOT_AVAILABLE, in which case, the
811 // platform-specific nsLookAndFeel should use its own values instead.
813 nsresult
nsXPLookAndFeel::GetColorValue(ColorID aID
,
814 bool aUseStandinsForNativeColors
,
816 if (!sInitialized
) Init();
818 // define DEBUG_SYSTEM_COLOR_USE if you want to debug system color
819 // use in a skin that uses them. When set, it will make all system
820 // color pairs that are appropriate for foreground/background
821 // pairing the same. This means if the skin is using system colors
822 // correctly you will not be able to see *any* text.
823 #undef DEBUG_SYSTEM_COLOR_USE
825 #ifdef DEBUG_SYSTEM_COLOR_USE
829 // css2 http://www.w3.org/TR/REC-CSS2/ui.html#system-colors
830 case ColorID::Activecaption
:
831 // active window caption background
832 case ColorID::Captiontext
:
833 // text in active window caption
834 aResult
= NS_RGB(0xff, 0x00, 0x00);
837 case ColorID::Highlight
:
838 // background of selected item
839 case ColorID::Highlighttext
:
840 // text of selected item
841 aResult
= NS_RGB(0xff, 0xff, 0x00);
844 case ColorID::Inactivecaption
:
845 // inactive window caption
846 case ColorID::Inactivecaptiontext
:
847 // text in inactive window caption
848 aResult
= NS_RGB(0x66, 0x66, 0x00);
851 case ColorID::Infobackground
:
852 // tooltip background color
853 case ColorID::Infotext
:
854 // tooltip text color
855 aResult
= NS_RGB(0x00, 0xff, 0x00);
860 case ColorID::Menutext
:
862 aResult
= NS_RGB(0x00, 0xff, 0xff);
865 case ColorID::Threedface
:
866 case ColorID::Buttonface
:
868 case ColorID::Buttontext
:
869 // text on push buttons
870 aResult
= NS_RGB(0x00, 0x66, 0x66);
873 case ColorID::Window
:
874 case ColorID::Windowtext
:
875 aResult
= NS_RGB(0x00, 0x00, 0xff);
878 // from the CSS3 working draft (not yet finalized)
879 // http://www.w3.org/tr/2000/wd-css3-userint-20000216.html#color
882 case ColorID::Fieldtext
:
883 aResult
= NS_RGB(0xff, 0x00, 0xff);
886 case ColorID::MozDialog
:
887 case ColorID::MozDialogtext
:
888 aResult
= NS_RGB(0x66, 0x00, 0x66);
892 rv
= NS_ERROR_NOT_AVAILABLE
;
894 if (NS_SUCCEEDED(rv
)) return rv
;
896 #endif // DEBUG_SYSTEM_COLOR_USE
898 if (aUseStandinsForNativeColors
&&
899 (ColorIsNotCSSAccessible(aID
) ||
900 !nsContentUtils::UseStandinsForNativeColors())) {
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 (StaticPrefs::ui_use_native_colors() && aUseStandinsForNativeColors
) {
946 aResult
= GetStandinForNativeColor(aID
);
950 if (StaticPrefs::ui_use_native_colors() &&
951 NS_SUCCEEDED(NativeGetColor(aID
, aResult
))) {
952 if (!mozilla::ServoStyleSet::IsInServoTraversal()) {
953 MOZ_ASSERT(NS_IsMainThread());
954 if ((gfxPlatform::GetCMSMode() == eCMSMode_All
) &&
955 !IsSpecialColor(aID
, aResult
)) {
956 qcms_transform
* transform
= gfxPlatform::GetCMSInverseRGBTransform();
959 color
[0] = NS_GET_R(aResult
);
960 color
[1] = NS_GET_G(aResult
);
961 color
[2] = NS_GET_B(aResult
);
962 color
[3] = NS_GET_A(aResult
);
963 qcms_transform_data(transform
, color
, color
, 1);
964 aResult
= NS_RGBA(color
[0], color
[1], color
[2], color
[3]);
968 CACHE_COLOR(aID
, aResult
);
973 return NS_ERROR_NOT_AVAILABLE
;
976 nsresult
nsXPLookAndFeel::GetIntValue(IntID aID
, int32_t& aResult
) {
977 if (!sInitialized
) Init();
979 for (unsigned int i
= 0; i
< ArrayLength(sIntPrefs
); ++i
) {
980 if (sIntPrefs
[i
].isSet
&& (sIntPrefs
[i
].id
== aID
)) {
981 aResult
= sIntPrefs
[i
].intVar
;
986 return NativeGetInt(aID
, aResult
);
989 nsresult
nsXPLookAndFeel::GetFloatValue(FloatID aID
, float& aResult
) {
990 if (!sInitialized
) Init();
992 for (unsigned int i
= 0; i
< ArrayLength(sFloatPrefs
); ++i
) {
993 if (sFloatPrefs
[i
].isSet
&& sFloatPrefs
[i
].id
== aID
) {
994 aResult
= sFloatPrefs
[i
].floatVar
;
999 return NativeGetFloat(aID
, aResult
);
1002 void nsXPLookAndFeel::RefreshImpl() {
1003 // Wipe out our color cache.
1005 for (i
= 0; i
< uint32_t(ColorID::End
); i
++) {
1006 sCachedColors
[i
] = 0;
1008 for (i
= 0; i
< COLOR_CACHE_SIZE
; i
++) {
1009 sCachedColorBits
[i
] = 0;
1012 // Reinit color cache from prefs.
1013 for (i
= 0; i
< uint32_t(ColorID::End
); ++i
) {
1014 InitColorFromPref(i
);
1017 // Clear any cached FullLookAndFeel data, which is now invalid.
1018 if (XRE_IsParentProcess()) {
1019 widget::RemoteLookAndFeel::ClearCachedData();
1023 widget::LookAndFeelCache
nsXPLookAndFeel::GetCacheImpl() {
1024 return LookAndFeelCache
{};
1027 static bool sRecordedLookAndFeelTelemetry
= false;
1029 void nsXPLookAndFeel::RecordTelemetry() {
1030 if (!XRE_IsParentProcess()) {
1034 if (sRecordedLookAndFeelTelemetry
) {
1038 sRecordedLookAndFeelTelemetry
= true;
1041 Telemetry::ScalarSet(
1042 Telemetry::ScalarID::WIDGET_DARK_MODE
,
1043 NS_SUCCEEDED(GetIntValue(IntID::SystemUsesDarkTheme
, i
)) && i
!= 0);
1045 RecordLookAndFeelSpecificTelemetry();
1051 void LookAndFeel::NotifyChangedAllWindows(widget::ThemeChangeKind aKind
) {
1052 if (nsCOMPtr
<nsIObserverService
> obs
= services::GetObserverService()) {
1053 obs
->NotifyObservers(nullptr, "look-and-feel-changed",
1054 reinterpret_cast<char16_t
*>(uintptr_t(aKind
)));
1059 nsresult
LookAndFeel::GetColor(ColorID aID
, nscolor
* aResult
) {
1060 return nsLookAndFeel::GetInstance()->GetColorValue(aID
, false, *aResult
);
1063 nsresult
LookAndFeel::GetColor(ColorID aID
, bool aUseStandinsForNativeColors
,
1065 return nsLookAndFeel::GetInstance()->GetColorValue(
1066 aID
, aUseStandinsForNativeColors
, *aResult
);
1070 nsresult
LookAndFeel::GetInt(IntID aID
, int32_t* aResult
) {
1071 return nsLookAndFeel::GetInstance()->GetIntValue(aID
, *aResult
);
1075 nsresult
LookAndFeel::GetFloat(FloatID aID
, float* aResult
) {
1076 return nsLookAndFeel::GetInstance()->GetFloatValue(aID
, *aResult
);
1080 bool LookAndFeel::GetFont(FontID aID
, nsString
& aName
, gfxFontStyle
& aStyle
) {
1081 return nsLookAndFeel::GetInstance()->GetFontValue(aID
, aName
, aStyle
);
1085 char16_t
LookAndFeel::GetPasswordCharacter() {
1086 return nsLookAndFeel::GetInstance()->GetPasswordCharacterImpl();
1090 bool LookAndFeel::GetEchoPassword() {
1091 if (StaticPrefs::editor_password_mask_delay() >= 0) {
1092 return StaticPrefs::editor_password_mask_delay() > 0;
1094 return nsLookAndFeel::GetInstance()->GetEchoPasswordImpl();
1098 uint32_t LookAndFeel::GetPasswordMaskDelay() {
1099 int32_t delay
= StaticPrefs::editor_password_mask_delay();
1101 return nsLookAndFeel::GetInstance()->GetPasswordMaskDelayImpl();
1107 void LookAndFeel::Refresh() { nsLookAndFeel::GetInstance()->RefreshImpl(); }
1110 void LookAndFeel::NativeInit() { nsLookAndFeel::GetInstance()->NativeInit(); }
1113 widget::LookAndFeelCache
LookAndFeel::GetCache() {
1114 return nsLookAndFeel::GetInstance()->GetCacheImpl();
1118 void LookAndFeel::SetCache(const widget::LookAndFeelCache
& aCache
) {
1119 nsLookAndFeel::GetInstance()->SetCacheImpl(aCache
);
1123 void LookAndFeel::SetData(widget::FullLookAndFeel
&& aTables
) {
1124 nsLookAndFeel::GetInstance()->SetDataImpl(std::move(aTables
));
1127 } // namespace mozilla