Bug 1627646 - Avoid creating a Port object when there are no listeners r=mixedpuppy
[gecko.git] / widget / nsXPLookAndFeel.cpp
blob0c99fe3db176e12acb145fcfa85026ab5815fb5d
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 "nsCRT.h"
14 #include "nsFont.h"
15 #include "mozilla/dom/ContentChild.h"
16 #include "mozilla/Preferences.h"
17 #include "mozilla/Services.h"
18 #include "mozilla/ServoStyleSet.h"
19 #include "mozilla/StaticPrefs_editor.h"
20 #include "mozilla/StaticPrefs_findbar.h"
21 #include "mozilla/StaticPrefs_fission.h"
22 #include "mozilla/StaticPrefs_ui.h"
23 #include "mozilla/gfx/2D.h"
24 #include "mozilla/widget/WidgetMessageUtils.h"
25 #include "mozilla/Telemetry.h"
26 #include "mozilla/TelemetryScalarEnums.h"
28 #include "gfxPlatform.h"
30 #include "qcms.h"
32 #ifdef DEBUG
33 # include "nsSize.h"
34 #endif
36 using namespace mozilla;
38 nsLookAndFeelIntPref nsXPLookAndFeel::sIntPrefs[] = {
39 {"ui.caretBlinkTime", eIntID_CaretBlinkTime, false, 0},
40 {"ui.caretWidth", eIntID_CaretWidth, false, 0},
41 {"ui.caretVisibleWithSelection", eIntID_ShowCaretDuringSelection, false, 0},
42 {"ui.submenuDelay", eIntID_SubmenuDelay, false, 0},
43 {"ui.dragThresholdX", eIntID_DragThresholdX, false, 0},
44 {"ui.dragThresholdY", eIntID_DragThresholdY, false, 0},
45 {"ui.useAccessibilityTheme", eIntID_UseAccessibilityTheme, false, 0},
46 {"ui.menusCanOverlapOSBar", eIntID_MenusCanOverlapOSBar, false, 0},
47 {"ui.useOverlayScrollbars", eIntID_UseOverlayScrollbars, false, 0},
48 {"ui.scrollbarDisplayOnMouseMove", eIntID_ScrollbarDisplayOnMouseMove,
49 false, 0},
50 {"ui.scrollbarFadeBeginDelay", eIntID_ScrollbarFadeBeginDelay, false, 0},
51 {"ui.scrollbarFadeDuration", eIntID_ScrollbarFadeDuration, false, 0},
52 {"ui.showHideScrollbars", eIntID_ShowHideScrollbars, false, 0},
53 {"ui.skipNavigatingDisabledMenuItem", eIntID_SkipNavigatingDisabledMenuItem,
54 false, 0},
55 {"ui.treeOpenDelay", eIntID_TreeOpenDelay, false, 0},
56 {"ui.treeCloseDelay", eIntID_TreeCloseDelay, false, 0},
57 {"ui.treeLazyScrollDelay", eIntID_TreeLazyScrollDelay, false, 0},
58 {"ui.treeScrollDelay", eIntID_TreeScrollDelay, false, 0},
59 {"ui.treeScrollLinesMax", eIntID_TreeScrollLinesMax, false, 0},
60 {"accessibility.tabfocus", eIntID_TabFocusModel, false, 0},
61 {"ui.alertNotificationOrigin", eIntID_AlertNotificationOrigin, false, 0},
62 {"ui.scrollToClick", eIntID_ScrollToClick, false, 0},
63 {"ui.IMERawInputUnderlineStyle", eIntID_IMERawInputUnderlineStyle, false,
64 0},
65 {"ui.IMESelectedRawTextUnderlineStyle",
66 eIntID_IMESelectedRawTextUnderlineStyle, false, 0},
67 {"ui.IMEConvertedTextUnderlineStyle", eIntID_IMEConvertedTextUnderlineStyle,
68 false, 0},
69 {"ui.IMESelectedConvertedTextUnderlineStyle",
70 eIntID_IMESelectedConvertedTextUnderline, false, 0},
71 {"ui.SpellCheckerUnderlineStyle", eIntID_SpellCheckerUnderlineStyle, false,
72 0},
73 {"ui.scrollbarButtonAutoRepeatBehavior",
74 eIntID_ScrollbarButtonAutoRepeatBehavior, false, 0},
75 {"ui.tooltipDelay", eIntID_TooltipDelay, false, 0},
76 {"ui.contextMenuOffsetVertical", eIntID_ContextMenuOffsetVertical, false,
77 0},
78 {"ui.contextMenuOffsetHorizontal", eIntID_ContextMenuOffsetHorizontal,
79 false, 0},
80 {"ui.GtkCSDAvailable", eIntID_GTKCSDAvailable, false, 0},
81 {"ui.GtkCSDHideTitlebarByDefault", eIntID_GTKCSDHideTitlebarByDefault,
82 false, 0},
83 {"ui.GtkCSDTransparentBackground", eIntID_GTKCSDTransparentBackground,
84 false, 0},
85 {"ui.GtkCSDMinimizeButton", eIntID_GTKCSDMinimizeButton, false, 0},
86 {"ui.GtkCSDMaximizeButton", eIntID_GTKCSDMaximizeButton, false, 0},
87 {"ui.GtkCSDCloseButton", eIntID_GTKCSDCloseButton, false, 0},
88 {"ui.systemUsesDarkTheme", eIntID_SystemUsesDarkTheme, false, 0},
89 {"ui.prefersReducedMotion", eIntID_PrefersReducedMotion, false, 0},
90 {"ui.primaryPointerCapabilities", eIntID_PrimaryPointerCapabilities, false,
91 6 /* fine and hover-capable pointer, i.e. mouse-type */},
92 {"ui.allPointerCapabilities", eIntID_AllPointerCapabilities, false,
93 6 /* fine and hover-capable pointer, i.e. mouse-type */},
96 nsLookAndFeelFloatPref nsXPLookAndFeel::sFloatPrefs[] = {
97 {"ui.IMEUnderlineRelativeSize", eFloatID_IMEUnderlineRelativeSize, false,
98 0},
99 {"ui.SpellCheckerUnderlineRelativeSize",
100 eFloatID_SpellCheckerUnderlineRelativeSize, false, 0},
101 {"ui.caretAspectRatio", eFloatID_CaretAspectRatio, false, 0},
104 // This array MUST be kept in the same order as the color list in
105 // specified/color.rs
106 /* XXX If you add any strings longer than
107 * "ui.-moz-mac-active-source-list-selection"
108 * to the following array then you MUST update the
109 * sizes of the sColorPrefs array in nsXPLookAndFeel.h
111 const char nsXPLookAndFeel::sColorPrefs[][41] = {
112 "ui.windowBackground",
113 "ui.windowForeground",
114 "ui.widgetBackground",
115 "ui.widgetForeground",
116 "ui.widgetSelectBackground",
117 "ui.widgetSelectForeground",
118 "ui.widget3DHighlight",
119 "ui.widget3DShadow",
120 "ui.textBackground",
121 "ui.textForeground",
122 "ui.textSelectBackground",
123 "ui.textSelectForeground",
124 "ui.textSelectForegroundCustom",
125 "ui.textSelectBackgroundDisabled",
126 "ui.textSelectBackgroundAttention",
127 "ui.textHighlightBackground",
128 "ui.textHighlightForeground",
129 "ui.IMERawInputBackground",
130 "ui.IMERawInputForeground",
131 "ui.IMERawInputUnderline",
132 "ui.IMESelectedRawTextBackground",
133 "ui.IMESelectedRawTextForeground",
134 "ui.IMESelectedRawTextUnderline",
135 "ui.IMEConvertedTextBackground",
136 "ui.IMEConvertedTextForeground",
137 "ui.IMEConvertedTextUnderline",
138 "ui.IMESelectedConvertedTextBackground",
139 "ui.IMESelectedConvertedTextForeground",
140 "ui.IMESelectedConvertedTextUnderline",
141 "ui.SpellCheckerUnderline",
142 "ui.activeborder",
143 "ui.activecaption",
144 "ui.appworkspace",
145 "ui.background",
146 "ui.buttonface",
147 "ui.buttonhighlight",
148 "ui.buttonshadow",
149 "ui.buttontext",
150 "ui.captiontext",
151 "ui.-moz-field",
152 "ui.-moz-fieldtext",
153 "ui.graytext",
154 "ui.highlight",
155 "ui.highlighttext",
156 "ui.inactiveborder",
157 "ui.inactivecaption",
158 "ui.inactivecaptiontext",
159 "ui.infobackground",
160 "ui.infotext",
161 "ui.menu",
162 "ui.menutext",
163 "ui.scrollbar",
164 "ui.threeddarkshadow",
165 "ui.threedface",
166 "ui.threedhighlight",
167 "ui.threedlightshadow",
168 "ui.threedshadow",
169 "ui.window",
170 "ui.windowframe",
171 "ui.windowtext",
172 "ui.-moz-buttondefault",
173 "ui.-moz-default-color",
174 "ui.-moz-default-background-color",
175 "ui.-moz-dialog",
176 "ui.-moz-dialogtext",
177 "ui.-moz-dragtargetzone",
178 "ui.-moz-cellhighlight",
179 "ui.-moz_cellhighlighttext",
180 "ui.-moz-html-cellhighlight",
181 "ui.-moz-html-cellhighlighttext",
182 "ui.-moz-buttonhoverface",
183 "ui.-moz_buttonhovertext",
184 "ui.-moz_menuhover",
185 "ui.-moz_menuhovertext",
186 "ui.-moz_menubartext",
187 "ui.-moz_menubarhovertext",
188 "ui.-moz_eventreerow",
189 "ui.-moz_oddtreerow",
190 "ui.-moz-gtk-buttonactivetext",
191 "ui.-moz-mac-buttonactivetext",
192 "ui.-moz_mac_chrome_active",
193 "ui.-moz_mac_chrome_inactive",
194 "ui.-moz-mac-defaultbuttontext",
195 "ui.-moz-mac-focusring",
196 "ui.-moz-mac-menuselect",
197 "ui.-moz-mac-menushadow",
198 "ui.-moz-mac-menutextdisable",
199 "ui.-moz-mac-menutextselect",
200 "ui.-moz_mac_disabledtoolbartext",
201 "ui.-moz-mac-secondaryhighlight",
202 "ui.-moz-mac-vibrancy-light",
203 "ui.-moz-mac-vibrancy-dark",
204 "ui.-moz-mac-vibrant-titlebar-light",
205 "ui.-moz-mac-vibrant-titlebar-dark",
206 "ui.-moz-mac-menupopup",
207 "ui.-moz-mac-menuitem",
208 "ui.-moz-mac-active-menuitem",
209 "ui.-moz-mac-source-list",
210 "ui.-moz-mac-source-list-selection",
211 "ui.-moz-mac-active-source-list-selection",
212 "ui.-moz-mac-tooltip",
213 "ui.-moz-win-accentcolor",
214 "ui.-moz-win-accentcolortext",
215 "ui.-moz-win-mediatext",
216 "ui.-moz-win-communicationstext",
217 "ui.-moz-nativehyperlinktext",
218 "ui.-moz-hyperlinktext",
219 "ui.-moz-activehyperlinktext",
220 "ui.-moz-visitedhyperlinktext",
221 "ui.-moz-comboboxtext",
222 "ui.-moz-combobox",
223 "ui.-moz-gtk-info-bar-text"};
225 int32_t nsXPLookAndFeel::sCachedColors[size_t(LookAndFeel::ColorID::End)] = {0};
226 int32_t nsXPLookAndFeel::sCachedColorBits[COLOR_CACHE_SIZE] = {0};
228 bool nsXPLookAndFeel::sInitialized = false;
230 nsXPLookAndFeel* nsXPLookAndFeel::sInstance = nullptr;
231 bool nsXPLookAndFeel::sShutdown = false;
233 // static
234 nsXPLookAndFeel* nsXPLookAndFeel::GetInstance() {
235 if (sInstance) {
236 return sInstance;
239 NS_ENSURE_TRUE(!sShutdown, nullptr);
241 if (gfxPlatform::IsHeadless()) {
242 sInstance = new widget::HeadlessLookAndFeel();
243 } else {
244 sInstance = new nsLookAndFeel();
246 return sInstance;
249 // static
250 void nsXPLookAndFeel::Shutdown() {
251 if (sShutdown) {
252 return;
254 sShutdown = true;
255 delete sInstance;
256 sInstance = nullptr;
259 // static
260 void nsXPLookAndFeel::IntPrefChanged(nsLookAndFeelIntPref* data) {
261 if (!data) {
262 return;
265 int32_t intpref;
266 nsresult rv = Preferences::GetInt(data->name, &intpref);
267 if (NS_FAILED(rv)) {
268 data->isSet = false;
270 #ifdef DEBUG_akkana
271 printf("====== Cleared int pref %s\n", data->name);
272 #endif
273 } else {
274 data->intVar = intpref;
275 data->isSet = true;
277 #ifdef DEBUG_akkana
278 printf("====== Changed int pref %s to %d\n", data->name, data->intVar);
279 #endif
282 NotifyPrefChanged();
285 // static
286 void nsXPLookAndFeel::FloatPrefChanged(nsLookAndFeelFloatPref* data) {
287 if (!data) {
288 return;
291 int32_t intpref;
292 nsresult rv = Preferences::GetInt(data->name, &intpref);
293 if (NS_FAILED(rv)) {
294 data->isSet = false;
296 #ifdef DEBUG_akkana
297 printf("====== Cleared float pref %s\n", data->name);
298 #endif
299 } else {
300 data->floatVar = (float)intpref / 100.0f;
301 data->isSet = true;
303 #ifdef DEBUG_akkana
304 printf("====== Changed float pref %s to %f\n", data->name);
305 #endif
308 NotifyPrefChanged();
311 // static
312 void nsXPLookAndFeel::ColorPrefChanged(unsigned int index,
313 const char* prefName) {
314 nsAutoString colorStr;
315 nsresult rv = Preferences::GetString(prefName, colorStr);
316 if (NS_SUCCEEDED(rv) && !colorStr.IsEmpty()) {
317 nscolor thecolor;
318 if (colorStr[0] == char16_t('#')) {
319 if (NS_HexToRGBA(nsDependentString(colorStr, 1), nsHexColorType::NoAlpha,
320 &thecolor)) {
321 int32_t id = NS_PTR_TO_INT32(index);
322 CACHE_COLOR(id, thecolor);
324 } else if (NS_ColorNameToRGB(colorStr, &thecolor)) {
325 int32_t id = NS_PTR_TO_INT32(index);
326 CACHE_COLOR(id, thecolor);
327 #ifdef DEBUG_akkana
328 printf("====== Changed color pref %s to 0x%lx\n", prefName, thecolor);
329 #endif
331 } else {
332 // Reset to the default color, by clearing the cache
333 // to force lookup when the color is next used
334 int32_t id = NS_PTR_TO_INT32(index);
335 CLEAR_COLOR_CACHE(id);
337 #ifdef DEBUG_akkana
338 printf("====== Cleared color pref %s\n", prefName);
339 #endif
342 NotifyPrefChanged();
345 // static
346 void nsXPLookAndFeel::NotifyPrefChanged() {
347 nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
348 if (obs) {
349 obs->NotifyObservers(nullptr, "look-and-feel-pref-changed", nullptr);
353 void nsXPLookAndFeel::InitFromPref(nsLookAndFeelIntPref* aPref) {
354 int32_t intpref;
355 nsresult rv = Preferences::GetInt(aPref->name, &intpref);
356 if (NS_SUCCEEDED(rv)) {
357 aPref->isSet = true;
358 aPref->intVar = intpref;
362 void nsXPLookAndFeel::InitFromPref(nsLookAndFeelFloatPref* aPref) {
363 int32_t intpref;
364 nsresult rv = Preferences::GetInt(aPref->name, &intpref);
365 if (NS_SUCCEEDED(rv)) {
366 aPref->isSet = true;
367 aPref->floatVar = (float)intpref / 100.0f;
371 void nsXPLookAndFeel::InitColorFromPref(int32_t i) {
372 static_assert(ArrayLength(sColorPrefs) == size_t(ColorID::End),
373 "Should have a pref for each color value");
375 nsAutoString colorStr;
376 nsresult rv = Preferences::GetString(sColorPrefs[i], colorStr);
377 if (NS_FAILED(rv) || colorStr.IsEmpty()) {
378 return;
380 nscolor thecolor;
381 if (colorStr[0] == char16_t('#')) {
382 nsAutoString hexString;
383 colorStr.Right(hexString, colorStr.Length() - 1);
384 if (NS_HexToRGBA(hexString, nsHexColorType::NoAlpha, &thecolor)) {
385 CACHE_COLOR(i, thecolor);
387 } else if (NS_ColorNameToRGB(colorStr, &thecolor)) {
388 CACHE_COLOR(i, thecolor);
392 // static
393 void nsXPLookAndFeel::OnPrefChanged(const char* aPref, void* aClosure) {
394 // looping in the same order as in ::Init
396 nsDependentCString prefName(aPref);
397 unsigned int i;
398 for (i = 0; i < ArrayLength(sIntPrefs); ++i) {
399 if (prefName.Equals(sIntPrefs[i].name)) {
400 IntPrefChanged(&sIntPrefs[i]);
401 return;
405 for (i = 0; i < ArrayLength(sFloatPrefs); ++i) {
406 if (prefName.Equals(sFloatPrefs[i].name)) {
407 FloatPrefChanged(&sFloatPrefs[i]);
408 return;
412 for (i = 0; i < ArrayLength(sColorPrefs); ++i) {
413 if (prefName.Equals(sColorPrefs[i])) {
414 ColorPrefChanged(i, sColorPrefs[i]);
415 return;
421 // Read values from the user's preferences.
422 // This is done once at startup, but since the user's preferences
423 // haven't actually been read yet at that time, we also have to
424 // set a callback to inform us of changes to each pref.
426 void nsXPLookAndFeel::Init() {
427 MOZ_RELEASE_ASSERT(NS_IsMainThread());
429 // Say we're already initialized, and take the chance that it might fail;
430 // protects against some other process writing to our static variables.
431 sInitialized = true;
433 // XXX If we could reorganize the pref names, we should separate the branch
434 // for each types. Then, we could reduce the unnecessary loop from
435 // nsXPLookAndFeel::OnPrefChanged().
436 Preferences::RegisterPrefixCallback(OnPrefChanged, "ui.");
437 // We really do just want the accessibility.tabfocus pref, not other prefs
438 // that start with that string.
439 Preferences::RegisterCallback(OnPrefChanged, "accessibility.tabfocus");
441 unsigned int i;
442 for (i = 0; i < ArrayLength(sIntPrefs); ++i) {
443 InitFromPref(&sIntPrefs[i]);
446 for (i = 0; i < ArrayLength(sFloatPrefs); ++i) {
447 InitFromPref(&sFloatPrefs[i]);
450 for (i = 0; i < ArrayLength(sColorPrefs); ++i) {
451 InitColorFromPref(i);
454 if (XRE_IsContentProcess()) {
455 mozilla::dom::ContentChild* cc = mozilla::dom::ContentChild::GetSingleton();
457 LookAndFeel::SetIntCache(cc->LookAndFeelCache());
458 // This is only ever used once during initialization, and can be cleared
459 // now.
460 cc->LookAndFeelCache().Clear();
464 nsXPLookAndFeel::~nsXPLookAndFeel() {
465 NS_ASSERTION(sInstance == this,
466 "This destroying instance isn't the singleton instance");
467 sInstance = nullptr;
470 bool nsXPLookAndFeel::IsSpecialColor(ColorID aID, nscolor& aColor) {
471 switch (aID) {
472 case ColorID::TextSelectForeground:
473 return (aColor == NS_DONT_CHANGE_COLOR);
474 case ColorID::IMESelectedRawTextBackground:
475 case ColorID::IMESelectedConvertedTextBackground:
476 case ColorID::IMERawInputBackground:
477 case ColorID::IMEConvertedTextBackground:
478 case ColorID::IMESelectedRawTextForeground:
479 case ColorID::IMESelectedConvertedTextForeground:
480 case ColorID::IMERawInputForeground:
481 case ColorID::IMEConvertedTextForeground:
482 case ColorID::IMERawInputUnderline:
483 case ColorID::IMEConvertedTextUnderline:
484 case ColorID::IMESelectedRawTextUnderline:
485 case ColorID::IMESelectedConvertedTextUnderline:
486 case ColorID::SpellCheckerUnderline:
487 return NS_IS_SELECTION_SPECIAL_COLOR(aColor);
488 default:
490 * In GetColor(), every color that is not a special color is color
491 * corrected. Use false to make other colors color corrected.
493 return false;
495 return false;
498 bool nsXPLookAndFeel::ColorIsNotCSSAccessible(ColorID aID) {
499 bool result = false;
501 switch (aID) {
502 case ColorID::WindowBackground:
503 case ColorID::WindowForeground:
504 case ColorID::WidgetBackground:
505 case ColorID::WidgetForeground:
506 case ColorID::WidgetSelectBackground:
507 case ColorID::WidgetSelectForeground:
508 case ColorID::Widget3DHighlight:
509 case ColorID::Widget3DShadow:
510 case ColorID::TextBackground:
511 case ColorID::TextForeground:
512 case ColorID::TextSelectBackground:
513 case ColorID::TextSelectForeground:
514 case ColorID::TextSelectBackgroundDisabled:
515 case ColorID::TextSelectBackgroundAttention:
516 case ColorID::TextHighlightBackground:
517 case ColorID::TextHighlightForeground:
518 case ColorID::IMERawInputBackground:
519 case ColorID::IMERawInputForeground:
520 case ColorID::IMERawInputUnderline:
521 case ColorID::IMESelectedRawTextBackground:
522 case ColorID::IMESelectedRawTextForeground:
523 case ColorID::IMESelectedRawTextUnderline:
524 case ColorID::IMEConvertedTextBackground:
525 case ColorID::IMEConvertedTextForeground:
526 case ColorID::IMEConvertedTextUnderline:
527 case ColorID::IMESelectedConvertedTextBackground:
528 case ColorID::IMESelectedConvertedTextForeground:
529 case ColorID::IMESelectedConvertedTextUnderline:
530 case ColorID::SpellCheckerUnderline:
531 result = true;
532 break;
533 default:
534 break;
537 return result;
540 nscolor nsXPLookAndFeel::GetStandinForNativeColor(ColorID aID) {
541 nscolor result = NS_RGB(0xFF, 0xFF, 0xFF);
543 // The stand-in colors are taken from the Windows 7 Aero theme
544 // except Mac-specific colors which are taken from Mac OS 10.7.
545 switch (aID) {
546 // CSS 2 colors:
547 case ColorID::Activeborder:
548 result = NS_RGB(0xB4, 0xB4, 0xB4);
549 break;
550 case ColorID::Activecaption:
551 result = NS_RGB(0x99, 0xB4, 0xD1);
552 break;
553 case ColorID::Appworkspace:
554 result = NS_RGB(0xAB, 0xAB, 0xAB);
555 break;
556 case ColorID::Background:
557 result = NS_RGB(0x00, 0x00, 0x00);
558 break;
559 case ColorID::Buttonface:
560 result = NS_RGB(0xF0, 0xF0, 0xF0);
561 break;
562 case ColorID::Buttonhighlight:
563 result = NS_RGB(0xFF, 0xFF, 0xFF);
564 break;
565 case ColorID::Buttonshadow:
566 result = NS_RGB(0xA0, 0xA0, 0xA0);
567 break;
568 case ColorID::Buttontext:
569 result = NS_RGB(0x00, 0x00, 0x00);
570 break;
571 case ColorID::Captiontext:
572 result = NS_RGB(0x00, 0x00, 0x00);
573 break;
574 case ColorID::Graytext:
575 result = NS_RGB(0x6D, 0x6D, 0x6D);
576 break;
577 case ColorID::Highlight:
578 result = NS_RGB(0x33, 0x99, 0xFF);
579 break;
580 case ColorID::Highlighttext:
581 result = NS_RGB(0xFF, 0xFF, 0xFF);
582 break;
583 case ColorID::Inactiveborder:
584 result = NS_RGB(0xF4, 0xF7, 0xFC);
585 break;
586 case ColorID::Inactivecaption:
587 result = NS_RGB(0xBF, 0xCD, 0xDB);
588 break;
589 case ColorID::Inactivecaptiontext:
590 result = NS_RGB(0x43, 0x4E, 0x54);
591 break;
592 case ColorID::Infobackground:
593 result = NS_RGB(0xFF, 0xFF, 0xE1);
594 break;
595 case ColorID::Infotext:
596 result = NS_RGB(0x00, 0x00, 0x00);
597 break;
598 case ColorID::Menu:
599 result = NS_RGB(0xF0, 0xF0, 0xF0);
600 break;
601 case ColorID::Menutext:
602 result = NS_RGB(0x00, 0x00, 0x00);
603 break;
604 case ColorID::Scrollbar:
605 result = NS_RGB(0xC8, 0xC8, 0xC8);
606 break;
607 case ColorID::Threeddarkshadow:
608 result = NS_RGB(0x69, 0x69, 0x69);
609 break;
610 case ColorID::Threedface:
611 result = NS_RGB(0xF0, 0xF0, 0xF0);
612 break;
613 case ColorID::Threedhighlight:
614 result = NS_RGB(0xFF, 0xFF, 0xFF);
615 break;
616 case ColorID::Threedlightshadow:
617 result = NS_RGB(0xE3, 0xE3, 0xE3);
618 break;
619 case ColorID::Threedshadow:
620 result = NS_RGB(0xA0, 0xA0, 0xA0);
621 break;
622 case ColorID::Window:
623 result = NS_RGB(0xFF, 0xFF, 0xFF);
624 break;
625 case ColorID::Windowframe:
626 result = NS_RGB(0x64, 0x64, 0x64);
627 break;
628 case ColorID::Windowtext:
629 result = NS_RGB(0x00, 0x00, 0x00);
630 break;
631 case ColorID::MozButtondefault:
632 result = NS_RGB(0x69, 0x69, 0x69);
633 break;
634 case ColorID::Field:
635 result = NS_RGB(0xFF, 0xFF, 0xFF);
636 break;
637 case ColorID::Fieldtext:
638 result = NS_RGB(0x00, 0x00, 0x00);
639 break;
640 case ColorID::MozDialog:
641 result = NS_RGB(0xF0, 0xF0, 0xF0);
642 break;
643 case ColorID::MozDialogtext:
644 result = NS_RGB(0x00, 0x00, 0x00);
645 break;
646 case ColorID::MozDragtargetzone:
647 result = NS_RGB(0xFF, 0xFF, 0xFF);
648 break;
649 case ColorID::MozCellhighlight:
650 result = NS_RGB(0xF0, 0xF0, 0xF0);
651 break;
652 case ColorID::MozCellhighlighttext:
653 result = NS_RGB(0x00, 0x00, 0x00);
654 break;
655 case ColorID::MozHtmlCellhighlight:
656 result = NS_RGB(0x33, 0x99, 0xFF);
657 break;
658 case ColorID::MozHtmlCellhighlighttext:
659 result = NS_RGB(0xFF, 0xFF, 0xFF);
660 break;
661 case ColorID::MozButtonhoverface:
662 result = NS_RGB(0xF0, 0xF0, 0xF0);
663 break;
664 case ColorID::MozButtonhovertext:
665 result = NS_RGB(0x00, 0x00, 0x00);
666 break;
667 case ColorID::MozMenuhover:
668 result = NS_RGB(0x33, 0x99, 0xFF);
669 break;
670 case ColorID::MozMenuhovertext:
671 result = NS_RGB(0x00, 0x00, 0x00);
672 break;
673 case ColorID::MozMenubartext:
674 result = NS_RGB(0x00, 0x00, 0x00);
675 break;
676 case ColorID::MozMenubarhovertext:
677 result = NS_RGB(0x00, 0x00, 0x00);
678 break;
679 case ColorID::MozOddtreerow:
680 case ColorID::MozGtkButtonactivetext:
681 result = NS_RGB(0xFF, 0xFF, 0xFF);
682 break;
683 case ColorID::MozMacChromeActive:
684 result = NS_RGB(0xB2, 0xB2, 0xB2);
685 break;
686 case ColorID::MozMacChromeInactive:
687 result = NS_RGB(0xE1, 0xE1, 0xE1);
688 break;
689 case ColorID::MozMacFocusring:
690 result = NS_RGB(0x60, 0x9D, 0xD7);
691 break;
692 case ColorID::MozMacMenuselect:
693 result = NS_RGB(0x38, 0x75, 0xD7);
694 break;
695 case ColorID::MozMacMenushadow:
696 result = NS_RGB(0xA3, 0xA3, 0xA3);
697 break;
698 case ColorID::MozMacMenutextdisable:
699 result = NS_RGB(0x88, 0x88, 0x88);
700 break;
701 case ColorID::MozMacMenutextselect:
702 result = NS_RGB(0xFF, 0xFF, 0xFF);
703 break;
704 case ColorID::MozMacDisabledtoolbartext:
705 result = NS_RGB(0x3F, 0x3F, 0x3F);
706 break;
707 case ColorID::MozMacSecondaryhighlight:
708 result = NS_RGB(0xD4, 0xD4, 0xD4);
709 break;
710 case ColorID::MozMacVibrancyLight:
711 case ColorID::MozMacVibrantTitlebarLight:
712 result = NS_RGB(0xf7, 0xf7, 0xf7);
713 break;
714 case ColorID::MozMacVibrancyDark:
715 case ColorID::MozMacVibrantTitlebarDark:
716 result = NS_RGB(0x28, 0x28, 0x28);
717 break;
718 case ColorID::MozMacMenupopup:
719 result = NS_RGB(0xe6, 0xe6, 0xe6);
720 break;
721 case ColorID::MozMacMenuitem:
722 result = NS_RGB(0xe6, 0xe6, 0xe6);
723 break;
724 case ColorID::MozMacActiveMenuitem:
725 result = NS_RGB(0x0a, 0x64, 0xdc);
726 break;
727 case ColorID::MozMacSourceList:
728 result = NS_RGB(0xf7, 0xf7, 0xf7);
729 break;
730 case ColorID::MozMacSourceListSelection:
731 result = NS_RGB(0xc8, 0xc8, 0xc8);
732 break;
733 case ColorID::MozMacActiveSourceListSelection:
734 result = NS_RGB(0x0a, 0x64, 0xdc);
735 break;
736 case ColorID::MozMacTooltip:
737 result = NS_RGB(0xf7, 0xf7, 0xf7);
738 break;
739 case ColorID::MozWinAccentcolor:
740 // Seems to be the default color (hardcoded because of bug 1065998)
741 result = NS_RGB(0x9E, 0x9E, 0x9E);
742 break;
743 case ColorID::MozWinAccentcolortext:
744 result = NS_RGB(0x00, 0x00, 0x00);
745 break;
746 case ColorID::MozWinMediatext:
747 result = NS_RGB(0xFF, 0xFF, 0xFF);
748 break;
749 case ColorID::MozWinCommunicationstext:
750 result = NS_RGB(0xFF, 0xFF, 0xFF);
751 break;
752 case ColorID::MozNativehyperlinktext:
753 result = NS_RGB(0x00, 0x66, 0xCC);
754 break;
755 case ColorID::MozComboboxtext:
756 result = NS_RGB(0x00, 0x00, 0x00);
757 break;
758 case ColorID::MozCombobox:
759 result = NS_RGB(0xFF, 0xFF, 0xFF);
760 break;
761 default:
762 break;
765 return result;
769 // All these routines will return NS_OK if they have a value,
770 // in which case the nsLookAndFeel should use that value;
771 // otherwise we'll return NS_ERROR_NOT_AVAILABLE, in which case, the
772 // platform-specific nsLookAndFeel should use its own values instead.
774 nsresult nsXPLookAndFeel::GetColorImpl(ColorID aID,
775 bool aUseStandinsForNativeColors,
776 nscolor& aResult) {
777 if (!sInitialized) Init();
779 // define DEBUG_SYSTEM_COLOR_USE if you want to debug system color
780 // use in a skin that uses them. When set, it will make all system
781 // color pairs that are appropriate for foreground/background
782 // pairing the same. This means if the skin is using system colors
783 // correctly you will not be able to see *any* text.
784 #undef DEBUG_SYSTEM_COLOR_USE
786 #ifdef DEBUG_SYSTEM_COLOR_USE
788 nsresult rv = NS_OK;
789 switch (aID) {
790 // css2 http://www.w3.org/TR/REC-CSS2/ui.html#system-colors
791 case ColorID::Activecaption:
792 // active window caption background
793 case ColorID::Captiontext:
794 // text in active window caption
795 aResult = NS_RGB(0xff, 0x00, 0x00);
796 break;
798 case ColorID::Highlight:
799 // background of selected item
800 case ColorID::Highlighttext:
801 // text of selected item
802 aResult = NS_RGB(0xff, 0xff, 0x00);
803 break;
805 case ColorID::Inactivecaption:
806 // inactive window caption
807 case ColorID::Inactivecaptiontext:
808 // text in inactive window caption
809 aResult = NS_RGB(0x66, 0x66, 0x00);
810 break;
812 case ColorID::Infobackground:
813 // tooltip background color
814 case ColorID::Infotext:
815 // tooltip text color
816 aResult = NS_RGB(0x00, 0xff, 0x00);
817 break;
819 case ColorID::Menu:
820 // menu background
821 case ColorID::Menutext:
822 // menu text
823 aResult = NS_RGB(0x00, 0xff, 0xff);
824 break;
826 case ColorID::Threedface:
827 case ColorID::Buttonface:
828 // 3-D face color
829 case ColorID::Buttontext:
830 // text on push buttons
831 aResult = NS_RGB(0x00, 0x66, 0x66);
832 break;
834 case ColorID::Window:
835 case ColorID::Windowtext:
836 aResult = NS_RGB(0x00, 0x00, 0xff);
837 break;
839 // from the CSS3 working draft (not yet finalized)
840 // http://www.w3.org/tr/2000/wd-css3-userint-20000216.html#color
842 case ColorID::Field:
843 case ColorID::Fieldtext:
844 aResult = NS_RGB(0xff, 0x00, 0xff);
845 break;
847 case ColorID::MozDialog:
848 case ColorID::MozDialogtext:
849 aResult = NS_RGB(0x66, 0x00, 0x66);
850 break;
852 default:
853 rv = NS_ERROR_NOT_AVAILABLE;
855 if (NS_SUCCEEDED(rv)) return rv;
857 #endif // DEBUG_SYSTEM_COLOR_USE
859 if (aUseStandinsForNativeColors &&
860 (ColorIsNotCSSAccessible(aID) ||
861 !nsContentUtils::UseStandinsForNativeColors())) {
862 aUseStandinsForNativeColors = false;
865 if (!aUseStandinsForNativeColors && IS_COLOR_CACHED(aID)) {
866 aResult = sCachedColors[uint32_t(aID)];
867 return NS_OK;
870 // There are no system color settings for these, so set them manually
871 #ifndef XP_MACOSX
872 if (aID == ColorID::TextSelectBackgroundDisabled) {
873 // This is used to gray out the selection when it's not focused
874 // Used with nsISelectionController::SELECTION_DISABLED
875 aResult = NS_RGB(0xb0, 0xb0, 0xb0);
876 return NS_OK;
878 #endif
880 if (aID == ColorID::TextSelectBackgroundAttention) {
881 if (StaticPrefs::findbar_modalHighlight() &&
882 !StaticPrefs::fission_autostart()) {
883 aResult = NS_RGBA(0, 0, 0, 0);
884 return NS_OK;
887 // This makes the selection stand out when typeaheadfind is on
888 // Used with nsISelectionController::SELECTION_ATTENTION
889 aResult = NS_RGB(0x38, 0xd8, 0x78);
890 return NS_OK;
893 if (aID == ColorID::TextHighlightBackground) {
894 // This makes the matched text stand out when findbar highlighting is on
895 // Used with nsISelectionController::SELECTION_FIND
896 aResult = NS_RGB(0xef, 0x0f, 0xff);
897 return NS_OK;
900 if (aID == ColorID::TextHighlightForeground) {
901 // The foreground color for the matched text in findbar highlighting
902 // Used with nsISelectionController::SELECTION_FIND
903 aResult = NS_RGB(0xff, 0xff, 0xff);
904 return NS_OK;
907 if (StaticPrefs::ui_use_native_colors() && aUseStandinsForNativeColors) {
908 aResult = GetStandinForNativeColor(aID);
909 return NS_OK;
912 if (StaticPrefs::ui_use_native_colors() &&
913 NS_SUCCEEDED(NativeGetColor(aID, aResult))) {
914 if (!mozilla::ServoStyleSet::IsInServoTraversal()) {
915 MOZ_ASSERT(NS_IsMainThread());
916 if ((gfxPlatform::GetCMSMode() == eCMSMode_All) &&
917 !IsSpecialColor(aID, aResult)) {
918 qcms_transform* transform = gfxPlatform::GetCMSInverseRGBTransform();
919 if (transform) {
920 uint8_t color[4];
921 color[0] = NS_GET_R(aResult);
922 color[1] = NS_GET_G(aResult);
923 color[2] = NS_GET_B(aResult);
924 color[3] = NS_GET_A(aResult);
925 qcms_transform_data(transform, color, color, 1);
926 aResult = NS_RGBA(color[0], color[1], color[2], color[3]);
930 CACHE_COLOR(aID, aResult);
932 return NS_OK;
935 return NS_ERROR_NOT_AVAILABLE;
938 nsresult nsXPLookAndFeel::GetIntImpl(IntID aID, int32_t& aResult) {
939 if (!sInitialized) Init();
941 // Set the default values for these prefs. but allow different platforms
942 // to override them in their nsLookAndFeel if desired.
943 switch (aID) {
944 case eIntID_ScrollButtonLeftMouseButtonAction:
945 aResult = 0;
946 return NS_OK;
947 case eIntID_ScrollButtonMiddleMouseButtonAction:
948 aResult = 3;
949 return NS_OK;
950 case eIntID_ScrollButtonRightMouseButtonAction:
951 aResult = 3;
952 return NS_OK;
953 default:
955 * The metrics above are hardcoded platform defaults. All the other
956 * metrics are stored in sIntPrefs and can be changed at runtime.
958 break;
961 for (unsigned int i = 0; i < ArrayLength(sIntPrefs); ++i) {
962 if (sIntPrefs[i].isSet && (sIntPrefs[i].id == aID)) {
963 aResult = sIntPrefs[i].intVar;
964 return NS_OK;
968 return NS_ERROR_NOT_AVAILABLE;
971 nsresult nsXPLookAndFeel::GetFloatImpl(FloatID aID, float& aResult) {
972 if (!sInitialized) Init();
974 for (unsigned int i = 0; i < ArrayLength(sFloatPrefs); ++i) {
975 if (sFloatPrefs[i].isSet && sFloatPrefs[i].id == aID) {
976 aResult = sFloatPrefs[i].floatVar;
977 return NS_OK;
981 return NS_ERROR_NOT_AVAILABLE;
984 void nsXPLookAndFeel::RefreshImpl() {
985 // Wipe out our color cache.
986 uint32_t i;
987 for (i = 0; i < uint32_t(ColorID::End); i++) {
988 sCachedColors[i] = 0;
990 for (i = 0; i < COLOR_CACHE_SIZE; i++) {
991 sCachedColorBits[i] = 0;
994 // Reinit color cache from prefs.
995 for (i = 0; i < uint32_t(ColorID::End); ++i) {
996 InitColorFromPref(i);
1000 nsTArray<LookAndFeelInt> nsXPLookAndFeel::GetIntCacheImpl() {
1001 return nsTArray<LookAndFeelInt>();
1004 static bool sRecordedLookAndFeelTelemetry = false;
1006 void nsXPLookAndFeel::RecordTelemetry() {
1007 if (sRecordedLookAndFeelTelemetry) {
1008 return;
1011 sRecordedLookAndFeelTelemetry = true;
1013 int32_t i;
1014 Telemetry::ScalarSet(
1015 Telemetry::ScalarID::WIDGET_DARK_MODE,
1016 NS_SUCCEEDED(GetIntImpl(eIntID_SystemUsesDarkTheme, i)) && i != 0);
1019 namespace mozilla {
1021 // static
1022 nsresult LookAndFeel::GetColor(ColorID aID, nscolor* aResult) {
1023 return nsLookAndFeel::GetInstance()->GetColorImpl(aID, false, *aResult);
1026 nsresult LookAndFeel::GetColor(ColorID aID, bool aUseStandinsForNativeColors,
1027 nscolor* aResult) {
1028 return nsLookAndFeel::GetInstance()->GetColorImpl(
1029 aID, aUseStandinsForNativeColors, *aResult);
1032 // static
1033 nsresult LookAndFeel::GetInt(IntID aID, int32_t* aResult) {
1034 return nsLookAndFeel::GetInstance()->GetIntImpl(aID, *aResult);
1037 // static
1038 nsresult LookAndFeel::GetFloat(FloatID aID, float* aResult) {
1039 return nsLookAndFeel::GetInstance()->GetFloatImpl(aID, *aResult);
1042 // static
1043 bool LookAndFeel::GetFont(FontID aID, nsString& aName, gfxFontStyle& aStyle) {
1044 return nsLookAndFeel::GetInstance()->GetFontImpl(aID, aName, aStyle);
1047 // static
1048 char16_t LookAndFeel::GetPasswordCharacter() {
1049 return nsLookAndFeel::GetInstance()->GetPasswordCharacterImpl();
1052 // static
1053 bool LookAndFeel::GetEchoPassword() {
1054 if (StaticPrefs::editor_password_mask_delay() >= 0) {
1055 return StaticPrefs::editor_password_mask_delay() > 0;
1057 return nsLookAndFeel::GetInstance()->GetEchoPasswordImpl();
1060 // static
1061 uint32_t LookAndFeel::GetPasswordMaskDelay() {
1062 int32_t delay = StaticPrefs::editor_password_mask_delay();
1063 if (delay < 0) {
1064 return nsLookAndFeel::GetInstance()->GetPasswordMaskDelayImpl();
1066 return delay;
1069 // static
1070 void LookAndFeel::Refresh() { nsLookAndFeel::GetInstance()->RefreshImpl(); }
1072 // static
1073 void LookAndFeel::NativeInit() { nsLookAndFeel::GetInstance()->NativeInit(); }
1075 // static
1076 nsTArray<LookAndFeelInt> LookAndFeel::GetIntCache() {
1077 return nsLookAndFeel::GetInstance()->GetIntCacheImpl();
1080 // static
1081 void LookAndFeel::SetIntCache(
1082 const nsTArray<LookAndFeelInt>& aLookAndFeelIntCache) {
1083 return nsLookAndFeel::GetInstance()->SetIntCacheImpl(aLookAndFeelIntCache);
1086 // static
1087 void LookAndFeel::SetShouldRetainCacheForTest(bool aValue) {
1088 nsLookAndFeel::GetInstance()->SetShouldRetainCacheImplForTest(aValue);
1091 // static
1092 void LookAndFeel::SetPrefersReducedMotionOverrideForTest(bool aValue) {
1093 // Tell that the cache value we are going to set isn't cleared via
1094 // nsPresContext::ThemeChangedInternal which is called right before
1095 // we queue the media feature value change for this prefers-reduced-motion
1096 // change.
1097 SetShouldRetainCacheForTest(true);
1099 int32_t value = aValue ? 1 : 0;
1101 AutoTArray<LookAndFeelInt, 1> lookAndFeelCache;
1102 lookAndFeelCache.AppendElement(
1103 LookAndFeelInt{.id = eIntID_PrefersReducedMotion, .value = value});
1105 SetIntCache(lookAndFeelCache);
1108 // static
1109 void LookAndFeel::ResetPrefersReducedMotionOverrideForTest() {
1110 SetShouldRetainCacheForTest(false);
1113 } // namespace mozilla