Bug 1649121: part 26) Move `CollectTopMostChildContentsCompletelyInRange`. r=masayuki
[gecko.git] / widget / nsXPLookAndFeel.cpp
blob2c7f444ba71019e47a1718c279668c42d9772afa
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 "nsIXULRuntime.h"
16 #include "mozilla/dom/ContentChild.h"
17 #include "mozilla/Preferences.h"
18 #include "mozilla/Services.h"
19 #include "mozilla/ServoStyleSet.h"
20 #include "mozilla/StaticPrefs_editor.h"
21 #include "mozilla/StaticPrefs_findbar.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", IntID::CaretBlinkTime, false, 0},
40 {"ui.caretWidth", IntID::CaretWidth, false, 0},
41 {"ui.caretVisibleWithSelection", IntID::ShowCaretDuringSelection, false, 0},
42 {"ui.submenuDelay", IntID::SubmenuDelay, false, 0},
43 {"ui.dragThresholdX", IntID::DragThresholdX, false, 0},
44 {"ui.dragThresholdY", IntID::DragThresholdY, false, 0},
45 {"ui.useAccessibilityTheme", IntID::UseAccessibilityTheme, false, 0},
46 {"ui.menusCanOverlapOSBar", IntID::MenusCanOverlapOSBar, false, 0},
47 {"ui.useOverlayScrollbars", IntID::UseOverlayScrollbars, false, 0},
48 {"ui.scrollbarDisplayOnMouseMove", IntID::ScrollbarDisplayOnMouseMove,
49 false, 0},
50 {"ui.scrollbarFadeBeginDelay", IntID::ScrollbarFadeBeginDelay, false, 0},
51 {"ui.scrollbarFadeDuration", IntID::ScrollbarFadeDuration, false, 0},
52 {"ui.showHideScrollbars", IntID::ShowHideScrollbars, false, 0},
53 {"ui.skipNavigatingDisabledMenuItem", IntID::SkipNavigatingDisabledMenuItem,
54 false, 0},
55 {"ui.treeOpenDelay", IntID::TreeOpenDelay, false, 0},
56 {"ui.treeCloseDelay", IntID::TreeCloseDelay, false, 0},
57 {"ui.treeLazyScrollDelay", IntID::TreeLazyScrollDelay, false, 0},
58 {"ui.treeScrollDelay", IntID::TreeScrollDelay, false, 0},
59 {"ui.treeScrollLinesMax", IntID::TreeScrollLinesMax, false, 0},
60 {"accessibility.tabfocus", IntID::TabFocusModel, false, 0},
61 {"ui.alertNotificationOrigin", IntID::AlertNotificationOrigin, false, 0},
62 {"ui.scrollToClick", IntID::ScrollToClick, false, 0},
63 {"ui.IMERawInputUnderlineStyle", IntID::IMERawInputUnderlineStyle, false,
64 0},
65 {"ui.IMESelectedRawTextUnderlineStyle",
66 IntID::IMESelectedRawTextUnderlineStyle, false, 0},
67 {"ui.IMEConvertedTextUnderlineStyle", IntID::IMEConvertedTextUnderlineStyle,
68 false, 0},
69 {"ui.IMESelectedConvertedTextUnderlineStyle",
70 IntID::IMESelectedConvertedTextUnderline, false, 0},
71 {"ui.SpellCheckerUnderlineStyle", IntID::SpellCheckerUnderlineStyle, false,
72 0},
73 {"ui.scrollbarButtonAutoRepeatBehavior",
74 IntID::ScrollbarButtonAutoRepeatBehavior, false, 0},
75 {"ui.tooltipDelay", IntID::TooltipDelay, false, 0},
76 {"ui.contextMenuOffsetVertical", IntID::ContextMenuOffsetVertical, false,
77 0},
78 {"ui.contextMenuOffsetHorizontal", IntID::ContextMenuOffsetHorizontal,
79 false, 0},
80 {"ui.GtkCSDAvailable", IntID::GTKCSDAvailable, false, 0},
81 {"ui.GtkCSDHideTitlebarByDefault", IntID::GTKCSDHideTitlebarByDefault,
82 false, 0},
83 {"ui.GtkCSDTransparentBackground", IntID::GTKCSDTransparentBackground,
84 false, 0},
85 {"ui.GtkCSDMinimizeButton", IntID::GTKCSDMinimizeButton, false, 0},
86 {"ui.GtkCSDMaximizeButton", IntID::GTKCSDMaximizeButton, false, 0},
87 {"ui.GtkCSDCloseButton", IntID::GTKCSDCloseButton, false, 0},
88 {"ui.systemUsesDarkTheme", IntID::SystemUsesDarkTheme, false, 0},
89 {"ui.prefersReducedMotion", IntID::PrefersReducedMotion, false, 0},
90 {"ui.primaryPointerCapabilities", IntID::PrimaryPointerCapabilities, false,
91 6 /* fine and hover-capable pointer, i.e. mouse-type */},
92 {"ui.allPointerCapabilities", IntID::AllPointerCapabilities, false,
93 6 /* fine and hover-capable pointer, i.e. mouse-type */},
96 nsLookAndFeelFloatPref nsXPLookAndFeel::sFloatPrefs[] = {
97 {"ui.IMEUnderlineRelativeSize", FloatID::IMEUnderlineRelativeSize, false,
98 0},
99 {"ui.SpellCheckerUnderlineRelativeSize",
100 FloatID::SpellCheckerUnderlineRelativeSize, false, 0},
101 {"ui.caretAspectRatio", FloatID::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",
224 "ui.-moz-colheadertext",
225 "ui.-moz-colheaderhovertext"};
227 int32_t nsXPLookAndFeel::sCachedColors[size_t(LookAndFeel::ColorID::End)] = {0};
228 int32_t nsXPLookAndFeel::sCachedColorBits[COLOR_CACHE_SIZE] = {0};
230 bool nsXPLookAndFeel::sInitialized = false;
232 nsXPLookAndFeel* nsXPLookAndFeel::sInstance = nullptr;
233 bool nsXPLookAndFeel::sShutdown = false;
235 // static
236 nsXPLookAndFeel* nsXPLookAndFeel::GetInstance() {
237 if (sInstance) {
238 return sInstance;
241 NS_ENSURE_TRUE(!sShutdown, nullptr);
243 if (gfxPlatform::IsHeadless()) {
244 sInstance = new widget::HeadlessLookAndFeel();
245 } else {
246 sInstance = new nsLookAndFeel();
248 return sInstance;
251 // static
252 void nsXPLookAndFeel::Shutdown() {
253 if (sShutdown) {
254 return;
256 sShutdown = true;
257 delete sInstance;
258 sInstance = nullptr;
261 // static
262 void nsXPLookAndFeel::IntPrefChanged(nsLookAndFeelIntPref* data) {
263 if (!data) {
264 return;
267 int32_t intpref;
268 nsresult rv = Preferences::GetInt(data->name, &intpref);
269 if (NS_FAILED(rv)) {
270 data->isSet = false;
272 #ifdef DEBUG_akkana
273 printf("====== Cleared int pref %s\n", data->name);
274 #endif
275 } else {
276 data->intVar = intpref;
277 data->isSet = true;
279 #ifdef DEBUG_akkana
280 printf("====== Changed int pref %s to %d\n", data->name, data->intVar);
281 #endif
284 NotifyChangedAllWindows();
287 // static
288 void nsXPLookAndFeel::FloatPrefChanged(nsLookAndFeelFloatPref* data) {
289 if (!data) {
290 return;
293 int32_t intpref;
294 nsresult rv = Preferences::GetInt(data->name, &intpref);
295 if (NS_FAILED(rv)) {
296 data->isSet = false;
298 #ifdef DEBUG_akkana
299 printf("====== Cleared float pref %s\n", data->name);
300 #endif
301 } else {
302 data->floatVar = (float)intpref / 100.0f;
303 data->isSet = true;
305 #ifdef DEBUG_akkana
306 printf("====== Changed float pref %s to %f\n", data->name);
307 #endif
310 NotifyChangedAllWindows();
313 // static
314 void nsXPLookAndFeel::ColorPrefChanged(unsigned int index,
315 const char* prefName) {
316 nsAutoString colorStr;
317 nsresult rv = Preferences::GetString(prefName, colorStr);
318 if (NS_SUCCEEDED(rv) && !colorStr.IsEmpty()) {
319 nscolor thecolor;
320 if (colorStr[0] == char16_t('#')) {
321 if (NS_HexToRGBA(nsDependentString(colorStr, 1), nsHexColorType::NoAlpha,
322 &thecolor)) {
323 int32_t id = NS_PTR_TO_INT32(index);
324 CACHE_COLOR(id, thecolor);
326 } else if (NS_ColorNameToRGB(colorStr, &thecolor)) {
327 int32_t id = NS_PTR_TO_INT32(index);
328 CACHE_COLOR(id, thecolor);
329 #ifdef DEBUG_akkana
330 printf("====== Changed color pref %s to 0x%lx\n", prefName, thecolor);
331 #endif
333 } else {
334 // Reset to the default color, by clearing the cache
335 // to force lookup when the color is next used
336 int32_t id = NS_PTR_TO_INT32(index);
337 CLEAR_COLOR_CACHE(id);
339 #ifdef DEBUG_akkana
340 printf("====== Cleared color pref %s\n", prefName);
341 #endif
344 NotifyChangedAllWindows();
347 void nsXPLookAndFeel::InitFromPref(nsLookAndFeelIntPref* aPref) {
348 int32_t intpref;
349 nsresult rv = Preferences::GetInt(aPref->name, &intpref);
350 if (NS_SUCCEEDED(rv)) {
351 aPref->isSet = true;
352 aPref->intVar = intpref;
356 void nsXPLookAndFeel::InitFromPref(nsLookAndFeelFloatPref* aPref) {
357 int32_t intpref;
358 nsresult rv = Preferences::GetInt(aPref->name, &intpref);
359 if (NS_SUCCEEDED(rv)) {
360 aPref->isSet = true;
361 aPref->floatVar = (float)intpref / 100.0f;
365 void nsXPLookAndFeel::InitColorFromPref(int32_t i) {
366 static_assert(ArrayLength(sColorPrefs) == size_t(ColorID::End),
367 "Should have a pref for each color value");
369 nsAutoString colorStr;
370 nsresult rv = Preferences::GetString(sColorPrefs[i], colorStr);
371 if (NS_FAILED(rv) || colorStr.IsEmpty()) {
372 return;
374 nscolor thecolor;
375 if (colorStr[0] == char16_t('#')) {
376 nsAutoString hexString;
377 colorStr.Right(hexString, colorStr.Length() - 1);
378 if (NS_HexToRGBA(hexString, nsHexColorType::NoAlpha, &thecolor)) {
379 CACHE_COLOR(i, thecolor);
381 } else if (NS_ColorNameToRGB(colorStr, &thecolor)) {
382 CACHE_COLOR(i, thecolor);
386 // static
387 void nsXPLookAndFeel::OnPrefChanged(const char* aPref, void* aClosure) {
388 // looping in the same order as in ::Init
390 nsDependentCString prefName(aPref);
391 unsigned int i;
392 for (i = 0; i < ArrayLength(sIntPrefs); ++i) {
393 if (prefName.Equals(sIntPrefs[i].name)) {
394 IntPrefChanged(&sIntPrefs[i]);
395 return;
399 for (i = 0; i < ArrayLength(sFloatPrefs); ++i) {
400 if (prefName.Equals(sFloatPrefs[i].name)) {
401 FloatPrefChanged(&sFloatPrefs[i]);
402 return;
406 for (i = 0; i < ArrayLength(sColorPrefs); ++i) {
407 if (prefName.Equals(sColorPrefs[i])) {
408 ColorPrefChanged(i, sColorPrefs[i]);
409 return;
415 // Read values from the user's preferences.
416 // This is done once at startup, but since the user's preferences
417 // haven't actually been read yet at that time, we also have to
418 // set a callback to inform us of changes to each pref.
420 void nsXPLookAndFeel::Init() {
421 MOZ_RELEASE_ASSERT(NS_IsMainThread());
423 // Say we're already initialized, and take the chance that it might fail;
424 // protects against some other process writing to our static variables.
425 sInitialized = true;
427 // XXX If we could reorganize the pref names, we should separate the branch
428 // for each types. Then, we could reduce the unnecessary loop from
429 // nsXPLookAndFeel::OnPrefChanged().
430 Preferences::RegisterPrefixCallback(OnPrefChanged, "ui.");
431 // We really do just want the accessibility.tabfocus pref, not other prefs
432 // that start with that string.
433 Preferences::RegisterCallback(OnPrefChanged, "accessibility.tabfocus");
435 unsigned int i;
436 for (i = 0; i < ArrayLength(sIntPrefs); ++i) {
437 InitFromPref(&sIntPrefs[i]);
440 for (i = 0; i < ArrayLength(sFloatPrefs); ++i) {
441 InitFromPref(&sFloatPrefs[i]);
444 for (i = 0; i < ArrayLength(sColorPrefs); ++i) {
445 InitColorFromPref(i);
448 if (XRE_IsContentProcess()) {
449 mozilla::dom::ContentChild* cc = mozilla::dom::ContentChild::GetSingleton();
451 LookAndFeel::SetIntCache(cc->LookAndFeelCache());
452 // This is only ever used once during initialization, and can be cleared
453 // now.
454 cc->LookAndFeelCache().Clear();
458 nsXPLookAndFeel::~nsXPLookAndFeel() {
459 NS_ASSERTION(sInstance == this,
460 "This destroying instance isn't the singleton instance");
461 sInstance = nullptr;
464 bool nsXPLookAndFeel::IsSpecialColor(ColorID aID, nscolor& aColor) {
465 switch (aID) {
466 case ColorID::TextSelectForeground:
467 return (aColor == NS_DONT_CHANGE_COLOR);
468 case ColorID::IMESelectedRawTextBackground:
469 case ColorID::IMESelectedConvertedTextBackground:
470 case ColorID::IMERawInputBackground:
471 case ColorID::IMEConvertedTextBackground:
472 case ColorID::IMESelectedRawTextForeground:
473 case ColorID::IMESelectedConvertedTextForeground:
474 case ColorID::IMERawInputForeground:
475 case ColorID::IMEConvertedTextForeground:
476 case ColorID::IMERawInputUnderline:
477 case ColorID::IMEConvertedTextUnderline:
478 case ColorID::IMESelectedRawTextUnderline:
479 case ColorID::IMESelectedConvertedTextUnderline:
480 case ColorID::SpellCheckerUnderline:
481 return NS_IS_SELECTION_SPECIAL_COLOR(aColor);
482 default:
484 * In GetColor(), every color that is not a special color is color
485 * corrected. Use false to make other colors color corrected.
487 return false;
489 return false;
492 bool nsXPLookAndFeel::ColorIsNotCSSAccessible(ColorID aID) {
493 bool result = false;
495 switch (aID) {
496 case ColorID::WindowBackground:
497 case ColorID::WindowForeground:
498 case ColorID::WidgetBackground:
499 case ColorID::WidgetForeground:
500 case ColorID::WidgetSelectBackground:
501 case ColorID::WidgetSelectForeground:
502 case ColorID::Widget3DHighlight:
503 case ColorID::Widget3DShadow:
504 case ColorID::TextBackground:
505 case ColorID::TextForeground:
506 case ColorID::TextSelectBackground:
507 case ColorID::TextSelectForeground:
508 case ColorID::TextSelectBackgroundDisabled:
509 case ColorID::TextSelectBackgroundAttention:
510 case ColorID::TextHighlightBackground:
511 case ColorID::TextHighlightForeground:
512 case ColorID::IMERawInputBackground:
513 case ColorID::IMERawInputForeground:
514 case ColorID::IMERawInputUnderline:
515 case ColorID::IMESelectedRawTextBackground:
516 case ColorID::IMESelectedRawTextForeground:
517 case ColorID::IMESelectedRawTextUnderline:
518 case ColorID::IMEConvertedTextBackground:
519 case ColorID::IMEConvertedTextForeground:
520 case ColorID::IMEConvertedTextUnderline:
521 case ColorID::IMESelectedConvertedTextBackground:
522 case ColorID::IMESelectedConvertedTextForeground:
523 case ColorID::IMESelectedConvertedTextUnderline:
524 case ColorID::SpellCheckerUnderline:
525 result = true;
526 break;
527 default:
528 break;
531 return result;
534 nscolor nsXPLookAndFeel::GetStandinForNativeColor(ColorID aID) {
535 nscolor result = NS_RGB(0xFF, 0xFF, 0xFF);
537 // The stand-in colors are taken from the Windows 7 Aero theme
538 // except Mac-specific colors which are taken from Mac OS 10.7.
539 switch (aID) {
540 // CSS 2 colors:
541 case ColorID::Activeborder:
542 result = NS_RGB(0xB4, 0xB4, 0xB4);
543 break;
544 case ColorID::Activecaption:
545 result = NS_RGB(0x99, 0xB4, 0xD1);
546 break;
547 case ColorID::Appworkspace:
548 result = NS_RGB(0xAB, 0xAB, 0xAB);
549 break;
550 case ColorID::Background:
551 result = NS_RGB(0x00, 0x00, 0x00);
552 break;
553 case ColorID::Buttonface:
554 result = NS_RGB(0xF0, 0xF0, 0xF0);
555 break;
556 case ColorID::Buttonhighlight:
557 result = NS_RGB(0xFF, 0xFF, 0xFF);
558 break;
559 case ColorID::Buttonshadow:
560 result = NS_RGB(0xA0, 0xA0, 0xA0);
561 break;
562 case ColorID::Buttontext:
563 result = NS_RGB(0x00, 0x00, 0x00);
564 break;
565 case ColorID::Captiontext:
566 result = NS_RGB(0x00, 0x00, 0x00);
567 break;
568 case ColorID::Graytext:
569 result = NS_RGB(0x6D, 0x6D, 0x6D);
570 break;
571 case ColorID::Highlight:
572 result = NS_RGB(0x33, 0x99, 0xFF);
573 break;
574 case ColorID::Highlighttext:
575 result = NS_RGB(0xFF, 0xFF, 0xFF);
576 break;
577 case ColorID::Inactiveborder:
578 result = NS_RGB(0xF4, 0xF7, 0xFC);
579 break;
580 case ColorID::Inactivecaption:
581 result = NS_RGB(0xBF, 0xCD, 0xDB);
582 break;
583 case ColorID::Inactivecaptiontext:
584 result = NS_RGB(0x43, 0x4E, 0x54);
585 break;
586 case ColorID::Infobackground:
587 result = NS_RGB(0xFF, 0xFF, 0xE1);
588 break;
589 case ColorID::Infotext:
590 result = NS_RGB(0x00, 0x00, 0x00);
591 break;
592 case ColorID::Menu:
593 result = NS_RGB(0xF0, 0xF0, 0xF0);
594 break;
595 case ColorID::Menutext:
596 result = NS_RGB(0x00, 0x00, 0x00);
597 break;
598 case ColorID::Scrollbar:
599 result = NS_RGB(0xC8, 0xC8, 0xC8);
600 break;
601 case ColorID::Threeddarkshadow:
602 result = NS_RGB(0x69, 0x69, 0x69);
603 break;
604 case ColorID::Threedface:
605 result = NS_RGB(0xF0, 0xF0, 0xF0);
606 break;
607 case ColorID::Threedhighlight:
608 result = NS_RGB(0xFF, 0xFF, 0xFF);
609 break;
610 case ColorID::Threedlightshadow:
611 result = NS_RGB(0xE3, 0xE3, 0xE3);
612 break;
613 case ColorID::Threedshadow:
614 result = NS_RGB(0xA0, 0xA0, 0xA0);
615 break;
616 case ColorID::Window:
617 result = NS_RGB(0xFF, 0xFF, 0xFF);
618 break;
619 case ColorID::Windowframe:
620 result = NS_RGB(0x64, 0x64, 0x64);
621 break;
622 case ColorID::Windowtext:
623 result = NS_RGB(0x00, 0x00, 0x00);
624 break;
625 case ColorID::MozButtondefault:
626 result = NS_RGB(0x69, 0x69, 0x69);
627 break;
628 case ColorID::Field:
629 result = NS_RGB(0xFF, 0xFF, 0xFF);
630 break;
631 case ColorID::Fieldtext:
632 result = NS_RGB(0x00, 0x00, 0x00);
633 break;
634 case ColorID::MozDialog:
635 result = NS_RGB(0xF0, 0xF0, 0xF0);
636 break;
637 case ColorID::MozDialogtext:
638 case ColorID::MozColheadertext:
639 case ColorID::MozColheaderhovertext:
640 result = NS_RGB(0x00, 0x00, 0x00);
641 break;
642 case ColorID::MozDragtargetzone:
643 result = NS_RGB(0xFF, 0xFF, 0xFF);
644 break;
645 case ColorID::MozCellhighlight:
646 result = NS_RGB(0xF0, 0xF0, 0xF0);
647 break;
648 case ColorID::MozCellhighlighttext:
649 result = NS_RGB(0x00, 0x00, 0x00);
650 break;
651 case ColorID::MozHtmlCellhighlight:
652 result = NS_RGB(0x33, 0x99, 0xFF);
653 break;
654 case ColorID::MozHtmlCellhighlighttext:
655 result = NS_RGB(0xFF, 0xFF, 0xFF);
656 break;
657 case ColorID::MozButtonhoverface:
658 result = NS_RGB(0xF0, 0xF0, 0xF0);
659 break;
660 case ColorID::MozButtonhovertext:
661 result = NS_RGB(0x00, 0x00, 0x00);
662 break;
663 case ColorID::MozMenuhover:
664 result = NS_RGB(0x33, 0x99, 0xFF);
665 break;
666 case ColorID::MozMenuhovertext:
667 result = NS_RGB(0x00, 0x00, 0x00);
668 break;
669 case ColorID::MozMenubartext:
670 result = NS_RGB(0x00, 0x00, 0x00);
671 break;
672 case ColorID::MozMenubarhovertext:
673 result = NS_RGB(0x00, 0x00, 0x00);
674 break;
675 case ColorID::MozOddtreerow:
676 case ColorID::MozGtkButtonactivetext:
677 result = NS_RGB(0xFF, 0xFF, 0xFF);
678 break;
679 case ColorID::MozMacChromeActive:
680 result = NS_RGB(0xB2, 0xB2, 0xB2);
681 break;
682 case ColorID::MozMacChromeInactive:
683 result = NS_RGB(0xE1, 0xE1, 0xE1);
684 break;
685 case ColorID::MozMacFocusring:
686 result = NS_RGB(0x60, 0x9D, 0xD7);
687 break;
688 case ColorID::MozMacMenuselect:
689 result = NS_RGB(0x38, 0x75, 0xD7);
690 break;
691 case ColorID::MozMacMenushadow:
692 result = NS_RGB(0xA3, 0xA3, 0xA3);
693 break;
694 case ColorID::MozMacMenutextdisable:
695 result = NS_RGB(0x88, 0x88, 0x88);
696 break;
697 case ColorID::MozMacMenutextselect:
698 result = NS_RGB(0xFF, 0xFF, 0xFF);
699 break;
700 case ColorID::MozMacDisabledtoolbartext:
701 result = NS_RGB(0x3F, 0x3F, 0x3F);
702 break;
703 case ColorID::MozMacSecondaryhighlight:
704 result = NS_RGB(0xD4, 0xD4, 0xD4);
705 break;
706 case ColorID::MozMacVibrancyLight:
707 case ColorID::MozMacVibrantTitlebarLight:
708 result = NS_RGB(0xf7, 0xf7, 0xf7);
709 break;
710 case ColorID::MozMacVibrancyDark:
711 case ColorID::MozMacVibrantTitlebarDark:
712 result = NS_RGB(0x28, 0x28, 0x28);
713 break;
714 case ColorID::MozMacMenupopup:
715 result = NS_RGB(0xe6, 0xe6, 0xe6);
716 break;
717 case ColorID::MozMacMenuitem:
718 result = NS_RGB(0xe6, 0xe6, 0xe6);
719 break;
720 case ColorID::MozMacActiveMenuitem:
721 result = NS_RGB(0x0a, 0x64, 0xdc);
722 break;
723 case ColorID::MozMacSourceList:
724 result = NS_RGB(0xf7, 0xf7, 0xf7);
725 break;
726 case ColorID::MozMacSourceListSelection:
727 result = NS_RGB(0xc8, 0xc8, 0xc8);
728 break;
729 case ColorID::MozMacActiveSourceListSelection:
730 result = NS_RGB(0x0a, 0x64, 0xdc);
731 break;
732 case ColorID::MozMacTooltip:
733 result = NS_RGB(0xf7, 0xf7, 0xf7);
734 break;
735 case ColorID::MozWinAccentcolor:
736 // Seems to be the default color (hardcoded because of bug 1065998)
737 result = NS_RGB(0x9E, 0x9E, 0x9E);
738 break;
739 case ColorID::MozWinAccentcolortext:
740 result = NS_RGB(0x00, 0x00, 0x00);
741 break;
742 case ColorID::MozWinMediatext:
743 result = NS_RGB(0xFF, 0xFF, 0xFF);
744 break;
745 case ColorID::MozWinCommunicationstext:
746 result = NS_RGB(0xFF, 0xFF, 0xFF);
747 break;
748 case ColorID::MozNativehyperlinktext:
749 result = NS_RGB(0x00, 0x66, 0xCC);
750 break;
751 case ColorID::MozComboboxtext:
752 result = NS_RGB(0x00, 0x00, 0x00);
753 break;
754 case ColorID::MozCombobox:
755 result = NS_RGB(0xFF, 0xFF, 0xFF);
756 break;
757 default:
758 break;
761 return result;
765 // All these routines will return NS_OK if they have a value,
766 // in which case the nsLookAndFeel should use that value;
767 // otherwise we'll return NS_ERROR_NOT_AVAILABLE, in which case, the
768 // platform-specific nsLookAndFeel should use its own values instead.
770 nsresult nsXPLookAndFeel::GetColorImpl(ColorID aID,
771 bool aUseStandinsForNativeColors,
772 nscolor& aResult) {
773 if (!sInitialized) Init();
775 // define DEBUG_SYSTEM_COLOR_USE if you want to debug system color
776 // use in a skin that uses them. When set, it will make all system
777 // color pairs that are appropriate for foreground/background
778 // pairing the same. This means if the skin is using system colors
779 // correctly you will not be able to see *any* text.
780 #undef DEBUG_SYSTEM_COLOR_USE
782 #ifdef DEBUG_SYSTEM_COLOR_USE
784 nsresult rv = NS_OK;
785 switch (aID) {
786 // css2 http://www.w3.org/TR/REC-CSS2/ui.html#system-colors
787 case ColorID::Activecaption:
788 // active window caption background
789 case ColorID::Captiontext:
790 // text in active window caption
791 aResult = NS_RGB(0xff, 0x00, 0x00);
792 break;
794 case ColorID::Highlight:
795 // background of selected item
796 case ColorID::Highlighttext:
797 // text of selected item
798 aResult = NS_RGB(0xff, 0xff, 0x00);
799 break;
801 case ColorID::Inactivecaption:
802 // inactive window caption
803 case ColorID::Inactivecaptiontext:
804 // text in inactive window caption
805 aResult = NS_RGB(0x66, 0x66, 0x00);
806 break;
808 case ColorID::Infobackground:
809 // tooltip background color
810 case ColorID::Infotext:
811 // tooltip text color
812 aResult = NS_RGB(0x00, 0xff, 0x00);
813 break;
815 case ColorID::Menu:
816 // menu background
817 case ColorID::Menutext:
818 // menu text
819 aResult = NS_RGB(0x00, 0xff, 0xff);
820 break;
822 case ColorID::Threedface:
823 case ColorID::Buttonface:
824 // 3-D face color
825 case ColorID::Buttontext:
826 // text on push buttons
827 aResult = NS_RGB(0x00, 0x66, 0x66);
828 break;
830 case ColorID::Window:
831 case ColorID::Windowtext:
832 aResult = NS_RGB(0x00, 0x00, 0xff);
833 break;
835 // from the CSS3 working draft (not yet finalized)
836 // http://www.w3.org/tr/2000/wd-css3-userint-20000216.html#color
838 case ColorID::Field:
839 case ColorID::Fieldtext:
840 aResult = NS_RGB(0xff, 0x00, 0xff);
841 break;
843 case ColorID::MozDialog:
844 case ColorID::MozDialogtext:
845 aResult = NS_RGB(0x66, 0x00, 0x66);
846 break;
848 default:
849 rv = NS_ERROR_NOT_AVAILABLE;
851 if (NS_SUCCEEDED(rv)) return rv;
853 #endif // DEBUG_SYSTEM_COLOR_USE
855 if (aUseStandinsForNativeColors &&
856 (ColorIsNotCSSAccessible(aID) ||
857 !nsContentUtils::UseStandinsForNativeColors())) {
858 aUseStandinsForNativeColors = false;
861 if (!aUseStandinsForNativeColors && IS_COLOR_CACHED(aID)) {
862 aResult = sCachedColors[uint32_t(aID)];
863 return NS_OK;
866 // There are no system color settings for these, so set them manually
867 #ifndef XP_MACOSX
868 if (aID == ColorID::TextSelectBackgroundDisabled) {
869 // This is used to gray out the selection when it's not focused
870 // Used with nsISelectionController::SELECTION_DISABLED
871 aResult = NS_RGB(0xb0, 0xb0, 0xb0);
872 return NS_OK;
874 #endif
876 if (aID == ColorID::TextSelectBackgroundAttention) {
877 if (StaticPrefs::findbar_modalHighlight() && !mozilla::FissionAutostart()) {
878 aResult = NS_RGBA(0, 0, 0, 0);
879 return NS_OK;
882 // This makes the selection stand out when typeaheadfind is on
883 // Used with nsISelectionController::SELECTION_ATTENTION
884 aResult = NS_RGB(0x38, 0xd8, 0x78);
885 return NS_OK;
888 if (aID == ColorID::TextHighlightBackground) {
889 // This makes the matched text stand out when findbar highlighting is on
890 // Used with nsISelectionController::SELECTION_FIND
891 aResult = NS_RGB(0xef, 0x0f, 0xff);
892 return NS_OK;
895 if (aID == ColorID::TextHighlightForeground) {
896 // The foreground color for the matched text in findbar highlighting
897 // Used with nsISelectionController::SELECTION_FIND
898 aResult = NS_RGB(0xff, 0xff, 0xff);
899 return NS_OK;
902 if (StaticPrefs::ui_use_native_colors() && aUseStandinsForNativeColors) {
903 aResult = GetStandinForNativeColor(aID);
904 return NS_OK;
907 if (StaticPrefs::ui_use_native_colors() &&
908 NS_SUCCEEDED(NativeGetColor(aID, aResult))) {
909 if (!mozilla::ServoStyleSet::IsInServoTraversal()) {
910 MOZ_ASSERT(NS_IsMainThread());
911 if ((gfxPlatform::GetCMSMode() == eCMSMode_All) &&
912 !IsSpecialColor(aID, aResult)) {
913 qcms_transform* transform = gfxPlatform::GetCMSInverseRGBTransform();
914 if (transform) {
915 uint8_t color[4];
916 color[0] = NS_GET_R(aResult);
917 color[1] = NS_GET_G(aResult);
918 color[2] = NS_GET_B(aResult);
919 color[3] = NS_GET_A(aResult);
920 qcms_transform_data(transform, color, color, 1);
921 aResult = NS_RGBA(color[0], color[1], color[2], color[3]);
925 CACHE_COLOR(aID, aResult);
927 return NS_OK;
930 return NS_ERROR_NOT_AVAILABLE;
933 nsresult nsXPLookAndFeel::GetIntImpl(IntID aID, int32_t& aResult) {
934 if (!sInitialized) Init();
936 // Set the default values for these prefs. but allow different platforms
937 // to override them in their nsLookAndFeel if desired.
938 switch (aID) {
939 case IntID::ScrollButtonLeftMouseButtonAction:
940 aResult = 0;
941 return NS_OK;
942 case IntID::ScrollButtonMiddleMouseButtonAction:
943 aResult = 3;
944 return NS_OK;
945 case IntID::ScrollButtonRightMouseButtonAction:
946 aResult = 3;
947 return NS_OK;
948 default:
950 * The metrics above are hardcoded platform defaults. All the other
951 * metrics are stored in sIntPrefs and can be changed at runtime.
953 break;
956 for (unsigned int i = 0; i < ArrayLength(sIntPrefs); ++i) {
957 if (sIntPrefs[i].isSet && (sIntPrefs[i].id == aID)) {
958 aResult = sIntPrefs[i].intVar;
959 return NS_OK;
963 return NS_ERROR_NOT_AVAILABLE;
966 nsresult nsXPLookAndFeel::GetFloatImpl(FloatID aID, float& aResult) {
967 if (!sInitialized) Init();
969 for (unsigned int i = 0; i < ArrayLength(sFloatPrefs); ++i) {
970 if (sFloatPrefs[i].isSet && sFloatPrefs[i].id == aID) {
971 aResult = sFloatPrefs[i].floatVar;
972 return NS_OK;
976 return NS_ERROR_NOT_AVAILABLE;
979 void nsXPLookAndFeel::RefreshImpl() {
980 // Wipe out our color cache.
981 uint32_t i;
982 for (i = 0; i < uint32_t(ColorID::End); i++) {
983 sCachedColors[i] = 0;
985 for (i = 0; i < COLOR_CACHE_SIZE; i++) {
986 sCachedColorBits[i] = 0;
989 // Reinit color cache from prefs.
990 for (i = 0; i < uint32_t(ColorID::End); ++i) {
991 InitColorFromPref(i);
995 nsTArray<LookAndFeelInt> nsXPLookAndFeel::GetIntCacheImpl() {
996 return nsTArray<LookAndFeelInt>();
999 static bool sRecordedLookAndFeelTelemetry = false;
1001 void nsXPLookAndFeel::RecordTelemetry() {
1002 if (sRecordedLookAndFeelTelemetry) {
1003 return;
1006 sRecordedLookAndFeelTelemetry = true;
1008 int32_t i;
1009 Telemetry::ScalarSet(
1010 Telemetry::ScalarID::WIDGET_DARK_MODE,
1011 NS_SUCCEEDED(GetIntImpl(IntID::SystemUsesDarkTheme, i)) && i != 0);
1014 namespace mozilla {
1016 // static
1017 void LookAndFeel::NotifyChangedAllWindows() {
1018 if (nsCOMPtr<nsIObserverService> obs = services::GetObserverService()) {
1019 obs->NotifyObservers(nullptr, "look-and-feel-changed", nullptr);
1023 // static
1024 nsresult LookAndFeel::GetColor(ColorID aID, nscolor* aResult) {
1025 return nsLookAndFeel::GetInstance()->GetColorImpl(aID, false, *aResult);
1028 nsresult LookAndFeel::GetColor(ColorID aID, bool aUseStandinsForNativeColors,
1029 nscolor* aResult) {
1030 return nsLookAndFeel::GetInstance()->GetColorImpl(
1031 aID, aUseStandinsForNativeColors, *aResult);
1034 // static
1035 nsresult LookAndFeel::GetInt(IntID aID, int32_t* aResult) {
1036 return nsLookAndFeel::GetInstance()->GetIntImpl(aID, *aResult);
1039 // static
1040 nsresult LookAndFeel::GetFloat(FloatID aID, float* aResult) {
1041 return nsLookAndFeel::GetInstance()->GetFloatImpl(aID, *aResult);
1044 // static
1045 bool LookAndFeel::GetFont(FontID aID, nsString& aName, gfxFontStyle& aStyle) {
1046 return nsLookAndFeel::GetInstance()->GetFontImpl(aID, aName, aStyle);
1049 // static
1050 char16_t LookAndFeel::GetPasswordCharacter() {
1051 return nsLookAndFeel::GetInstance()->GetPasswordCharacterImpl();
1054 // static
1055 bool LookAndFeel::GetEchoPassword() {
1056 if (StaticPrefs::editor_password_mask_delay() >= 0) {
1057 return StaticPrefs::editor_password_mask_delay() > 0;
1059 return nsLookAndFeel::GetInstance()->GetEchoPasswordImpl();
1062 // static
1063 uint32_t LookAndFeel::GetPasswordMaskDelay() {
1064 int32_t delay = StaticPrefs::editor_password_mask_delay();
1065 if (delay < 0) {
1066 return nsLookAndFeel::GetInstance()->GetPasswordMaskDelayImpl();
1068 return delay;
1071 // static
1072 void LookAndFeel::Refresh() { nsLookAndFeel::GetInstance()->RefreshImpl(); }
1074 // static
1075 void LookAndFeel::NativeInit() { nsLookAndFeel::GetInstance()->NativeInit(); }
1077 // static
1078 nsTArray<LookAndFeelInt> LookAndFeel::GetIntCache() {
1079 return nsLookAndFeel::GetInstance()->GetIntCacheImpl();
1082 // static
1083 void LookAndFeel::SetIntCache(
1084 const nsTArray<LookAndFeelInt>& aLookAndFeelIntCache) {
1085 return nsLookAndFeel::GetInstance()->SetIntCacheImpl(aLookAndFeelIntCache);
1088 } // namespace mozilla