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/. */
5 
6 #include "mozilla/ArrayUtils.h"
7 
8 #include "nscore.h"
9 
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/ServoStyleSet.h"
18 #include "mozilla/gfx/2D.h"
19 #include "mozilla/widget/WidgetMessageUtils.h"
20 
21 #include "gfxPlatform.h"
22 #include "gfxPrefs.h"
23 #include "qcms.h"
24 
25 #ifdef DEBUG
26 #include "nsSize.h"
27 #endif
28 
29 using namespace mozilla;
30 
31 nsLookAndFeelIntPref nsXPLookAndFeel::sIntPrefs[] = {
32     {"ui.caretBlinkTime", eIntID_CaretBlinkTime, false, 0},
33     {"ui.caretWidth", eIntID_CaretWidth, false, 0},
34     {"ui.caretVisibleWithSelection", eIntID_ShowCaretDuringSelection, false, 0},
35     {"ui.submenuDelay", eIntID_SubmenuDelay, false, 0},
36     {"ui.dragThresholdX", eIntID_DragThresholdX, false, 0},
37     {"ui.dragThresholdY", eIntID_DragThresholdY, false, 0},
38     {"ui.useAccessibilityTheme", eIntID_UseAccessibilityTheme, false, 0},
39     {"ui.menusCanOverlapOSBar", eIntID_MenusCanOverlapOSBar, false, 0},
40     {"ui.useOverlayScrollbars", eIntID_UseOverlayScrollbars, false, 0},
41     {"ui.scrollbarDisplayOnMouseMove", eIntID_ScrollbarDisplayOnMouseMove,
42      false, 0},
43     {"ui.scrollbarFadeBeginDelay", eIntID_ScrollbarFadeBeginDelay, false, 0},
44     {"ui.scrollbarFadeDuration", eIntID_ScrollbarFadeDuration, false, 0},
45     {"ui.showHideScrollbars", eIntID_ShowHideScrollbars, false, 0},
46     {"ui.skipNavigatingDisabledMenuItem", eIntID_SkipNavigatingDisabledMenuItem,
47      false, 0},
48     {"ui.treeOpenDelay", eIntID_TreeOpenDelay, false, 0},
49     {"ui.treeCloseDelay", eIntID_TreeCloseDelay, false, 0},
50     {"ui.treeLazyScrollDelay", eIntID_TreeLazyScrollDelay, false, 0},
51     {"ui.treeScrollDelay", eIntID_TreeScrollDelay, false, 0},
52     {"ui.treeScrollLinesMax", eIntID_TreeScrollLinesMax, false, 0},
53     {"accessibility.tabfocus", eIntID_TabFocusModel, false, 0},
54     {"ui.alertNotificationOrigin", eIntID_AlertNotificationOrigin, false, 0},
55     {"ui.scrollToClick", eIntID_ScrollToClick, false, 0},
56     {"ui.IMERawInputUnderlineStyle", eIntID_IMERawInputUnderlineStyle, false,
57      0},
58     {"ui.IMESelectedRawTextUnderlineStyle",
59      eIntID_IMESelectedRawTextUnderlineStyle, false, 0},
60     {"ui.IMEConvertedTextUnderlineStyle", eIntID_IMEConvertedTextUnderlineStyle,
61      false, 0},
62     {"ui.IMESelectedConvertedTextUnderlineStyle",
63      eIntID_IMESelectedConvertedTextUnderline, false, 0},
64     {"ui.SpellCheckerUnderlineStyle", eIntID_SpellCheckerUnderlineStyle, false,
65      0},
66     {"ui.scrollbarButtonAutoRepeatBehavior",
67      eIntID_ScrollbarButtonAutoRepeatBehavior, false, 0},
68     {"ui.tooltipDelay", eIntID_TooltipDelay, false, 0},
69     {"ui.contextMenuOffsetVertical", eIntID_ContextMenuOffsetVertical, false,
70      0},
71     {"ui.contextMenuOffsetHorizontal", eIntID_ContextMenuOffsetHorizontal,
72      false, 0},
73     {"ui.GtkCSDAvailable", eIntID_GTKCSDAvailable, false, 0},
74     {"ui.GtkCSDMinimizeButton", eIntID_GTKCSDMinimizeButton, false, 0},
75     {"ui.GtkCSDMaximizeButton", eIntID_GTKCSDMaximizeButton, false, 0},
76     {"ui.GtkCSDCloseButton", eIntID_GTKCSDCloseButton, false, 0}};
77 
78 nsLookAndFeelFloatPref nsXPLookAndFeel::sFloatPrefs[] = {
79     {"ui.IMEUnderlineRelativeSize", eFloatID_IMEUnderlineRelativeSize, false,
80      0},
81     {"ui.SpellCheckerUnderlineRelativeSize",
82      eFloatID_SpellCheckerUnderlineRelativeSize, false, 0},
83     {"ui.caretAspectRatio", eFloatID_CaretAspectRatio, false, 0},
84 };
85 
86 // This array MUST be kept in the same order as the color list in LookAndFeel.h.
87 /* XXX If you add any strings longer than
88  * "ui.-moz-mac-active-source-list-selection"
89  * to the following array then you MUST update the
90  * sizes of the sColorPrefs array in nsXPLookAndFeel.h
91  */
92 const char nsXPLookAndFeel::sColorPrefs[][41] = {
93     "ui.windowBackground",
94     "ui.windowForeground",
95     "ui.widgetBackground",
96     "ui.widgetForeground",
97     "ui.widgetSelectBackground",
98     "ui.widgetSelectForeground",
99     "ui.widget3DHighlight",
100     "ui.widget3DShadow",
101     "ui.textBackground",
102     "ui.textForeground",
103     "ui.textSelectBackground",
104     "ui.textSelectForeground",
105     "ui.textSelectForegroundCustom",
106     "ui.textSelectBackgroundDisabled",
107     "ui.textSelectBackgroundAttention",
108     "ui.textHighlightBackground",
109     "ui.textHighlightForeground",
110     "ui.IMERawInputBackground",
111     "ui.IMERawInputForeground",
112     "ui.IMERawInputUnderline",
113     "ui.IMESelectedRawTextBackground",
114     "ui.IMESelectedRawTextForeground",
115     "ui.IMESelectedRawTextUnderline",
116     "ui.IMEConvertedTextBackground",
117     "ui.IMEConvertedTextForeground",
118     "ui.IMEConvertedTextUnderline",
119     "ui.IMESelectedConvertedTextBackground",
120     "ui.IMESelectedConvertedTextForeground",
121     "ui.IMESelectedConvertedTextUnderline",
122     "ui.SpellCheckerUnderline",
123     "ui.activeborder",
124     "ui.activecaption",
125     "ui.appworkspace",
126     "ui.background",
127     "ui.buttonface",
128     "ui.buttonhighlight",
129     "ui.buttonshadow",
130     "ui.buttontext",
131     "ui.captiontext",
132     "ui.graytext",
133     "ui.highlight",
134     "ui.highlighttext",
135     "ui.inactiveborder",
136     "ui.inactivecaption",
137     "ui.inactivecaptiontext",
138     "ui.infobackground",
139     "ui.infotext",
140     "ui.menu",
141     "ui.menutext",
142     "ui.scrollbar",
143     "ui.threeddarkshadow",
144     "ui.threedface",
145     "ui.threedhighlight",
146     "ui.threedlightshadow",
147     "ui.threedshadow",
148     "ui.window",
149     "ui.windowframe",
150     "ui.windowtext",
151     "ui.-moz-buttondefault",
152     "ui.-moz-field",
153     "ui.-moz-fieldtext",
154     "ui.-moz-dialog",
155     "ui.-moz-dialogtext",
156     "ui.-moz-dragtargetzone",
157     "ui.-moz-cellhighlight",
158     "ui.-moz_cellhighlighttext",
159     "ui.-moz-html-cellhighlight",
160     "ui.-moz-html-cellhighlighttext",
161     "ui.-moz-buttonhoverface",
162     "ui.-moz_buttonhovertext",
163     "ui.-moz_menuhover",
164     "ui.-moz_menuhovertext",
165     "ui.-moz_menubartext",
166     "ui.-moz_menubarhovertext",
167     "ui.-moz_eventreerow",
168     "ui.-moz_oddtreerow",
169     "ui.-moz-mac-buttonactivetext",
170     "ui.-moz_mac_chrome_active",
171     "ui.-moz_mac_chrome_inactive",
172     "ui.-moz-mac-defaultbuttontext",
173     "ui.-moz-mac-focusring",
174     "ui.-moz-mac-menuselect",
175     "ui.-moz-mac-menushadow",
176     "ui.-moz-mac-menutextdisable",
177     "ui.-moz-mac-menutextselect",
178     "ui.-moz_mac_disabledtoolbartext",
179     "ui.-moz-mac-secondaryhighlight",
180     "ui.-moz-mac-vibrancy-light",
181     "ui.-moz-mac-vibrancy-dark",
182     "ui.-moz-mac-vibrant-titlebar-light",
183     "ui.-moz-mac-vibrant-titlebar-dark",
184     "ui.-moz-mac-menupopup",
185     "ui.-moz-mac-menuitem",
186     "ui.-moz-mac-active-menuitem",
187     "ui.-moz-mac-source-list",
188     "ui.-moz-mac-source-list-selection",
189     "ui.-moz-mac-active-source-list-selection",
190     "ui.-moz-mac-tooltip",
191     "ui.-moz-win-mediatext",
192     "ui.-moz-win-communicationstext",
193     "ui.-moz-nativehyperlinktext",
194     "ui.-moz-comboboxtext",
195     "ui.-moz-combobox"};
196 
197 int32_t nsXPLookAndFeel::sCachedColors[LookAndFeel::eColorID_LAST_COLOR] = {0};
198 int32_t nsXPLookAndFeel::sCachedColorBits[COLOR_CACHE_SIZE] = {0};
199 
200 bool nsXPLookAndFeel::sInitialized = false;
201 bool nsXPLookAndFeel::sUseNativeColors = true;
202 bool nsXPLookAndFeel::sUseStandinsForNativeColors = false;
203 bool nsXPLookAndFeel::sFindbarModalHighlight = false;
204 
205 nsXPLookAndFeel* nsXPLookAndFeel::sInstance = nullptr;
206 bool nsXPLookAndFeel::sShutdown = false;
207 
208 // static
GetInstance()209 nsXPLookAndFeel* nsXPLookAndFeel::GetInstance() {
210   if (sInstance) {
211     return sInstance;
212   }
213 
214   NS_ENSURE_TRUE(!sShutdown, nullptr);
215 
216   if (gfxPlatform::IsHeadless()) {
217     sInstance = new widget::HeadlessLookAndFeel();
218   } else {
219     sInstance = new nsLookAndFeel();
220   }
221   return sInstance;
222 }
223 
224 // static
Shutdown()225 void nsXPLookAndFeel::Shutdown() {
226   if (sShutdown) {
227     return;
228   }
229   sShutdown = true;
230   delete sInstance;
231   sInstance = nullptr;
232 }
233 
nsXPLookAndFeel()234 nsXPLookAndFeel::nsXPLookAndFeel() : LookAndFeel() {}
235 
236 // static
IntPrefChanged(nsLookAndFeelIntPref * data)237 void nsXPLookAndFeel::IntPrefChanged(nsLookAndFeelIntPref* data) {
238   if (!data) {
239     return;
240   }
241 
242   int32_t intpref;
243   nsresult rv = Preferences::GetInt(data->name, &intpref);
244   if (NS_FAILED(rv)) {
245     return;
246   }
247   data->intVar = intpref;
248   data->isSet = true;
249 #ifdef DEBUG_akkana
250   printf("====== Changed int pref %s to %d\n", data->name, data->intVar);
251 #endif
252 }
253 
254 // static
FloatPrefChanged(nsLookAndFeelFloatPref * data)255 void nsXPLookAndFeel::FloatPrefChanged(nsLookAndFeelFloatPref* data) {
256   if (!data) {
257     return;
258   }
259 
260   int32_t intpref;
261   nsresult rv = Preferences::GetInt(data->name, &intpref);
262   if (NS_FAILED(rv)) {
263     return;
264   }
265   data->floatVar = (float)intpref / 100.0f;
266   data->isSet = true;
267 #ifdef DEBUG_akkana
268   printf("====== Changed float pref %s to %f\n", data->name, data->floatVar);
269 #endif
270 }
271 
272 // static
ColorPrefChanged(unsigned int index,const char * prefName)273 void nsXPLookAndFeel::ColorPrefChanged(unsigned int index,
274                                        const char* prefName) {
275   nsAutoString colorStr;
276   nsresult rv = Preferences::GetString(prefName, colorStr);
277   if (NS_FAILED(rv)) {
278     return;
279   }
280   if (!colorStr.IsEmpty()) {
281     nscolor thecolor;
282     if (colorStr[0] == char16_t('#')) {
283       if (NS_HexToRGBA(nsDependentString(colorStr, 1), nsHexColorType::NoAlpha,
284                        &thecolor)) {
285         int32_t id = NS_PTR_TO_INT32(index);
286         CACHE_COLOR(id, thecolor);
287       }
288     } else if (NS_ColorNameToRGB(colorStr, &thecolor)) {
289       int32_t id = NS_PTR_TO_INT32(index);
290       CACHE_COLOR(id, thecolor);
291 #ifdef DEBUG_akkana
292       printf("====== Changed color pref %s to 0x%lx\n", prefName, thecolor);
293 #endif
294     }
295   } else {
296     // Reset to the default color, by clearing the cache
297     // to force lookup when the color is next used
298     int32_t id = NS_PTR_TO_INT32(index);
299     CLEAR_COLOR_CACHE(id);
300   }
301 }
302 
InitFromPref(nsLookAndFeelIntPref * aPref)303 void nsXPLookAndFeel::InitFromPref(nsLookAndFeelIntPref* aPref) {
304   int32_t intpref;
305   nsresult rv = Preferences::GetInt(aPref->name, &intpref);
306   if (NS_SUCCEEDED(rv)) {
307     aPref->isSet = true;
308     aPref->intVar = intpref;
309   }
310 }
311 
InitFromPref(nsLookAndFeelFloatPref * aPref)312 void nsXPLookAndFeel::InitFromPref(nsLookAndFeelFloatPref* aPref) {
313   int32_t intpref;
314   nsresult rv = Preferences::GetInt(aPref->name, &intpref);
315   if (NS_SUCCEEDED(rv)) {
316     aPref->isSet = true;
317     aPref->floatVar = (float)intpref / 100.0f;
318   }
319 }
320 
InitColorFromPref(int32_t i)321 void nsXPLookAndFeel::InitColorFromPref(int32_t i) {
322   nsAutoString colorStr;
323   nsresult rv = Preferences::GetString(sColorPrefs[i], colorStr);
324   if (NS_FAILED(rv) || colorStr.IsEmpty()) {
325     return;
326   }
327   nscolor thecolor;
328   if (colorStr[0] == char16_t('#')) {
329     nsAutoString hexString;
330     colorStr.Right(hexString, colorStr.Length() - 1);
331     if (NS_HexToRGBA(hexString, nsHexColorType::NoAlpha, &thecolor)) {
332       CACHE_COLOR(i, thecolor);
333     }
334   } else if (NS_ColorNameToRGB(colorStr, &thecolor)) {
335     CACHE_COLOR(i, thecolor);
336   }
337 }
338 
339 // static
OnPrefChanged(const char * aPref,void * aClosure)340 void nsXPLookAndFeel::OnPrefChanged(const char* aPref, void* aClosure) {
341   // looping in the same order as in ::Init
342 
343   nsDependentCString prefName(aPref);
344   unsigned int i;
345   for (i = 0; i < ArrayLength(sIntPrefs); ++i) {
346     if (prefName.Equals(sIntPrefs[i].name)) {
347       IntPrefChanged(&sIntPrefs[i]);
348       return;
349     }
350   }
351 
352   for (i = 0; i < ArrayLength(sFloatPrefs); ++i) {
353     if (prefName.Equals(sFloatPrefs[i].name)) {
354       FloatPrefChanged(&sFloatPrefs[i]);
355       return;
356     }
357   }
358 
359   for (i = 0; i < ArrayLength(sColorPrefs); ++i) {
360     if (prefName.Equals(sColorPrefs[i])) {
361       ColorPrefChanged(i, sColorPrefs[i]);
362       return;
363     }
364   }
365 }
366 
367 //
368 // Read values from the user's preferences.
369 // This is done once at startup, but since the user's preferences
370 // haven't actually been read yet at that time, we also have to
371 // set a callback to inform us of changes to each pref.
372 //
Init()373 void nsXPLookAndFeel::Init() {
374   MOZ_RELEASE_ASSERT(NS_IsMainThread());
375 
376   // Say we're already initialized, and take the chance that it might fail;
377   // protects against some other process writing to our static variables.
378   sInitialized = true;
379 
380   // XXX If we could reorganize the pref names, we should separate the branch
381   //     for each types.  Then, we could reduce the unnecessary loop from
382   //     nsXPLookAndFeel::OnPrefChanged().
383   Preferences::RegisterPrefixCallback(OnPrefChanged, "ui.");
384   // We really do just want the accessibility.tabfocus pref, not other prefs
385   // that start with that string.
386   Preferences::RegisterCallback(OnPrefChanged, "accessibility.tabfocus");
387 
388   unsigned int i;
389   for (i = 0; i < ArrayLength(sIntPrefs); ++i) {
390     InitFromPref(&sIntPrefs[i]);
391   }
392 
393   for (i = 0; i < ArrayLength(sFloatPrefs); ++i) {
394     InitFromPref(&sFloatPrefs[i]);
395   }
396 
397   for (i = 0; i < ArrayLength(sColorPrefs); ++i) {
398     InitColorFromPref(i);
399   }
400 
401   Preferences::AddBoolVarCache(&sUseNativeColors, "ui.use_native_colors",
402                                sUseNativeColors);
403   Preferences::AddBoolVarCache(&sUseStandinsForNativeColors,
404                                "ui.use_standins_for_native_colors",
405                                sUseStandinsForNativeColors);
406   Preferences::AddBoolVarCache(&sFindbarModalHighlight,
407                                "findbar.modalHighlight",
408                                sFindbarModalHighlight);
409 
410   if (XRE_IsContentProcess()) {
411     mozilla::dom::ContentChild* cc = mozilla::dom::ContentChild::GetSingleton();
412 
413     LookAndFeel::SetIntCache(cc->LookAndFeelCache());
414     // This is only ever used once during initialization, and can be cleared
415     // now.
416     cc->LookAndFeelCache().Clear();
417   }
418 }
419 
~nsXPLookAndFeel()420 nsXPLookAndFeel::~nsXPLookAndFeel() {
421   NS_ASSERTION(sInstance == this,
422                "This destroying instance isn't the singleton instance");
423   sInstance = nullptr;
424 }
425 
IsSpecialColor(ColorID aID,nscolor & aColor)426 bool nsXPLookAndFeel::IsSpecialColor(ColorID aID, nscolor& aColor) {
427   switch (aID) {
428     case eColorID_TextSelectForeground:
429       return (aColor == NS_DONT_CHANGE_COLOR);
430     case eColorID_IMESelectedRawTextBackground:
431     case eColorID_IMESelectedConvertedTextBackground:
432     case eColorID_IMERawInputBackground:
433     case eColorID_IMEConvertedTextBackground:
434     case eColorID_IMESelectedRawTextForeground:
435     case eColorID_IMESelectedConvertedTextForeground:
436     case eColorID_IMERawInputForeground:
437     case eColorID_IMEConvertedTextForeground:
438     case eColorID_IMERawInputUnderline:
439     case eColorID_IMEConvertedTextUnderline:
440     case eColorID_IMESelectedRawTextUnderline:
441     case eColorID_IMESelectedConvertedTextUnderline:
442     case eColorID_SpellCheckerUnderline:
443       return NS_IS_SELECTION_SPECIAL_COLOR(aColor);
444     default:
445       /*
446        * In GetColor(), every color that is not a special color is color
447        * corrected. Use false to make other colors color corrected.
448        */
449       return false;
450   }
451   return false;
452 }
453 
ColorIsNotCSSAccessible(ColorID aID)454 bool nsXPLookAndFeel::ColorIsNotCSSAccessible(ColorID aID) {
455   bool result = false;
456 
457   switch (aID) {
458     case eColorID_WindowBackground:
459     case eColorID_WindowForeground:
460     case eColorID_WidgetBackground:
461     case eColorID_WidgetForeground:
462     case eColorID_WidgetSelectBackground:
463     case eColorID_WidgetSelectForeground:
464     case eColorID_Widget3DHighlight:
465     case eColorID_Widget3DShadow:
466     case eColorID_TextBackground:
467     case eColorID_TextForeground:
468     case eColorID_TextSelectBackground:
469     case eColorID_TextSelectForeground:
470     case eColorID_TextSelectBackgroundDisabled:
471     case eColorID_TextSelectBackgroundAttention:
472     case eColorID_TextHighlightBackground:
473     case eColorID_TextHighlightForeground:
474     case eColorID_IMERawInputBackground:
475     case eColorID_IMERawInputForeground:
476     case eColorID_IMERawInputUnderline:
477     case eColorID_IMESelectedRawTextBackground:
478     case eColorID_IMESelectedRawTextForeground:
479     case eColorID_IMESelectedRawTextUnderline:
480     case eColorID_IMEConvertedTextBackground:
481     case eColorID_IMEConvertedTextForeground:
482     case eColorID_IMEConvertedTextUnderline:
483     case eColorID_IMESelectedConvertedTextBackground:
484     case eColorID_IMESelectedConvertedTextForeground:
485     case eColorID_IMESelectedConvertedTextUnderline:
486     case eColorID_SpellCheckerUnderline:
487       result = true;
488       break;
489     default:
490       break;
491   }
492 
493   return result;
494 }
495 
GetStandinForNativeColor(ColorID aID)496 nscolor nsXPLookAndFeel::GetStandinForNativeColor(ColorID aID) {
497   nscolor result = NS_RGB(0xFF, 0xFF, 0xFF);
498 
499   // The stand-in colors are taken from the Windows 7 Aero theme
500   // except Mac-specific colors which are taken from Mac OS 10.7.
501   switch (aID) {
502     // CSS 2 colors:
503     case eColorID_activeborder:
504       result = NS_RGB(0xB4, 0xB4, 0xB4);
505       break;
506     case eColorID_activecaption:
507       result = NS_RGB(0x99, 0xB4, 0xD1);
508       break;
509     case eColorID_appworkspace:
510       result = NS_RGB(0xAB, 0xAB, 0xAB);
511       break;
512     case eColorID_background:
513       result = NS_RGB(0x00, 0x00, 0x00);
514       break;
515     case eColorID_buttonface:
516       result = NS_RGB(0xF0, 0xF0, 0xF0);
517       break;
518     case eColorID_buttonhighlight:
519       result = NS_RGB(0xFF, 0xFF, 0xFF);
520       break;
521     case eColorID_buttonshadow:
522       result = NS_RGB(0xA0, 0xA0, 0xA0);
523       break;
524     case eColorID_buttontext:
525       result = NS_RGB(0x00, 0x00, 0x00);
526       break;
527     case eColorID_captiontext:
528       result = NS_RGB(0x00, 0x00, 0x00);
529       break;
530     case eColorID_graytext:
531       result = NS_RGB(0x6D, 0x6D, 0x6D);
532       break;
533     case eColorID_highlight:
534       result = NS_RGB(0x33, 0x99, 0xFF);
535       break;
536     case eColorID_highlighttext:
537       result = NS_RGB(0xFF, 0xFF, 0xFF);
538       break;
539     case eColorID_inactiveborder:
540       result = NS_RGB(0xF4, 0xF7, 0xFC);
541       break;
542     case eColorID_inactivecaption:
543       result = NS_RGB(0xBF, 0xCD, 0xDB);
544       break;
545     case eColorID_inactivecaptiontext:
546       result = NS_RGB(0x43, 0x4E, 0x54);
547       break;
548     case eColorID_infobackground:
549       result = NS_RGB(0xFF, 0xFF, 0xE1);
550       break;
551     case eColorID_infotext:
552       result = NS_RGB(0x00, 0x00, 0x00);
553       break;
554     case eColorID_menu:
555       result = NS_RGB(0xF0, 0xF0, 0xF0);
556       break;
557     case eColorID_menutext:
558       result = NS_RGB(0x00, 0x00, 0x00);
559       break;
560     case eColorID_scrollbar:
561       result = NS_RGB(0xC8, 0xC8, 0xC8);
562       break;
563     case eColorID_threeddarkshadow:
564       result = NS_RGB(0x69, 0x69, 0x69);
565       break;
566     case eColorID_threedface:
567       result = NS_RGB(0xF0, 0xF0, 0xF0);
568       break;
569     case eColorID_threedhighlight:
570       result = NS_RGB(0xFF, 0xFF, 0xFF);
571       break;
572     case eColorID_threedlightshadow:
573       result = NS_RGB(0xE3, 0xE3, 0xE3);
574       break;
575     case eColorID_threedshadow:
576       result = NS_RGB(0xA0, 0xA0, 0xA0);
577       break;
578     case eColorID_window:
579       result = NS_RGB(0xFF, 0xFF, 0xFF);
580       break;
581     case eColorID_windowframe:
582       result = NS_RGB(0x64, 0x64, 0x64);
583       break;
584     case eColorID_windowtext:
585       result = NS_RGB(0x00, 0x00, 0x00);
586       break;
587     case eColorID__moz_buttondefault:
588       result = NS_RGB(0x69, 0x69, 0x69);
589       break;
590     case eColorID__moz_field:
591       result = NS_RGB(0xFF, 0xFF, 0xFF);
592       break;
593     case eColorID__moz_fieldtext:
594       result = NS_RGB(0x00, 0x00, 0x00);
595       break;
596     case eColorID__moz_dialog:
597       result = NS_RGB(0xF0, 0xF0, 0xF0);
598       break;
599     case eColorID__moz_dialogtext:
600       result = NS_RGB(0x00, 0x00, 0x00);
601       break;
602     case eColorID__moz_dragtargetzone:
603       result = NS_RGB(0xFF, 0xFF, 0xFF);
604       break;
605     case eColorID__moz_cellhighlight:
606       result = NS_RGB(0xF0, 0xF0, 0xF0);
607       break;
608     case eColorID__moz_cellhighlighttext:
609       result = NS_RGB(0x00, 0x00, 0x00);
610       break;
611     case eColorID__moz_html_cellhighlight:
612       result = NS_RGB(0x33, 0x99, 0xFF);
613       break;
614     case eColorID__moz_html_cellhighlighttext:
615       result = NS_RGB(0xFF, 0xFF, 0xFF);
616       break;
617     case eColorID__moz_buttonhoverface:
618       result = NS_RGB(0xF0, 0xF0, 0xF0);
619       break;
620     case eColorID__moz_buttonhovertext:
621       result = NS_RGB(0x00, 0x00, 0x00);
622       break;
623     case eColorID__moz_menuhover:
624       result = NS_RGB(0x33, 0x99, 0xFF);
625       break;
626     case eColorID__moz_menuhovertext:
627       result = NS_RGB(0x00, 0x00, 0x00);
628       break;
629     case eColorID__moz_menubartext:
630       result = NS_RGB(0x00, 0x00, 0x00);
631       break;
632     case eColorID__moz_menubarhovertext:
633       result = NS_RGB(0x00, 0x00, 0x00);
634       break;
635     case eColorID__moz_oddtreerow:
636       result = NS_RGB(0xFF, 0xFF, 0xFF);
637       break;
638     case eColorID__moz_mac_chrome_active:
639       result = NS_RGB(0xB2, 0xB2, 0xB2);
640       break;
641     case eColorID__moz_mac_chrome_inactive:
642       result = NS_RGB(0xE1, 0xE1, 0xE1);
643       break;
644     case eColorID__moz_mac_focusring:
645       result = NS_RGB(0x60, 0x9D, 0xD7);
646       break;
647     case eColorID__moz_mac_menuselect:
648       result = NS_RGB(0x38, 0x75, 0xD7);
649       break;
650     case eColorID__moz_mac_menushadow:
651       result = NS_RGB(0xA3, 0xA3, 0xA3);
652       break;
653     case eColorID__moz_mac_menutextdisable:
654       result = NS_RGB(0x88, 0x88, 0x88);
655       break;
656     case eColorID__moz_mac_menutextselect:
657       result = NS_RGB(0xFF, 0xFF, 0xFF);
658       break;
659     case eColorID__moz_mac_disabledtoolbartext:
660       result = NS_RGB(0x3F, 0x3F, 0x3F);
661       break;
662     case eColorID__moz_mac_secondaryhighlight:
663       result = NS_RGB(0xD4, 0xD4, 0xD4);
664       break;
665     case eColorID__moz_mac_vibrancy_light:
666     case eColorID__moz_mac_vibrant_titlebar_light:
667       result = NS_RGB(0xf7, 0xf7, 0xf7);
668       break;
669     case eColorID__moz_mac_vibrancy_dark:
670     case eColorID__moz_mac_vibrant_titlebar_dark:
671       result = NS_RGB(0x28, 0x28, 0x28);
672       break;
673     case eColorID__moz_mac_menupopup:
674       result = NS_RGB(0xe6, 0xe6, 0xe6);
675       break;
676     case eColorID__moz_mac_menuitem:
677       result = NS_RGB(0xe6, 0xe6, 0xe6);
678       break;
679     case eColorID__moz_mac_active_menuitem:
680       result = NS_RGB(0x0a, 0x64, 0xdc);
681       break;
682     case eColorID__moz_mac_source_list:
683       result = NS_RGB(0xf7, 0xf7, 0xf7);
684       break;
685     case eColorID__moz_mac_source_list_selection:
686       result = NS_RGB(0xc8, 0xc8, 0xc8);
687       break;
688     case eColorID__moz_mac_active_source_list_selection:
689       result = NS_RGB(0x0a, 0x64, 0xdc);
690       break;
691     case eColorID__moz_mac_tooltip:
692       result = NS_RGB(0xf7, 0xf7, 0xf7);
693       break;
694     case eColorID__moz_win_accentcolor:
695       // Seems to be the default color (hardcoded because of bug 1065998)
696       result = NS_RGB(0x9E, 0x9E, 0x9E);
697       break;
698     case eColorID__moz_win_accentcolortext:
699       result = NS_RGB(0x00, 0x00, 0x00);
700       break;
701     case eColorID__moz_win_mediatext:
702       result = NS_RGB(0xFF, 0xFF, 0xFF);
703       break;
704     case eColorID__moz_win_communicationstext:
705       result = NS_RGB(0xFF, 0xFF, 0xFF);
706       break;
707     case eColorID__moz_nativehyperlinktext:
708       result = NS_RGB(0x00, 0x66, 0xCC);
709       break;
710     case eColorID__moz_comboboxtext:
711       result = NS_RGB(0x00, 0x00, 0x00);
712       break;
713     case eColorID__moz_combobox:
714       result = NS_RGB(0xFF, 0xFF, 0xFF);
715       break;
716     default:
717       break;
718   }
719 
720   return result;
721 }
722 
723 //
724 // All these routines will return NS_OK if they have a value,
725 // in which case the nsLookAndFeel should use that value;
726 // otherwise we'll return NS_ERROR_NOT_AVAILABLE, in which case, the
727 // platform-specific nsLookAndFeel should use its own values instead.
728 //
GetColorImpl(ColorID aID,bool aUseStandinsForNativeColors,nscolor & aResult)729 nsresult nsXPLookAndFeel::GetColorImpl(ColorID aID,
730                                        bool aUseStandinsForNativeColors,
731                                        nscolor& aResult) {
732   if (!sInitialized) Init();
733 
734     // define DEBUG_SYSTEM_COLOR_USE if you want to debug system color
735     // use in a skin that uses them.  When set, it will make all system
736     // color pairs that are appropriate for foreground/background
737     // pairing the same.  This means if the skin is using system colors
738     // correctly you will not be able to see *any* text.
739 #undef DEBUG_SYSTEM_COLOR_USE
740 
741 #ifdef DEBUG_SYSTEM_COLOR_USE
742   {
743     nsresult rv = NS_OK;
744     switch (aID) {
745         // css2  http://www.w3.org/TR/REC-CSS2/ui.html#system-colors
746       case eColorID_activecaption:
747         // active window caption background
748       case eColorID_captiontext:
749         // text in active window caption
750         aResult = NS_RGB(0xff, 0x00, 0x00);
751         break;
752 
753       case eColorID_highlight:
754         // background of selected item
755       case eColorID_highlighttext:
756         // text of selected item
757         aResult = NS_RGB(0xff, 0xff, 0x00);
758         break;
759 
760       case eColorID_inactivecaption:
761         // inactive window caption
762       case eColorID_inactivecaptiontext:
763         // text in inactive window caption
764         aResult = NS_RGB(0x66, 0x66, 0x00);
765         break;
766 
767       case eColorID_infobackground:
768         // tooltip background color
769       case eColorID_infotext:
770         // tooltip text color
771         aResult = NS_RGB(0x00, 0xff, 0x00);
772         break;
773 
774       case eColorID_menu:
775         // menu background
776       case eColorID_menutext:
777         // menu text
778         aResult = NS_RGB(0x00, 0xff, 0xff);
779         break;
780 
781       case eColorID_threedface:
782       case eColorID_buttonface:
783         // 3-D face color
784       case eColorID_buttontext:
785         // text on push buttons
786         aResult = NS_RGB(0x00, 0x66, 0x66);
787         break;
788 
789       case eColorID_window:
790       case eColorID_windowtext:
791         aResult = NS_RGB(0x00, 0x00, 0xff);
792         break;
793 
794         // from the CSS3 working draft (not yet finalized)
795         // http://www.w3.org/tr/2000/wd-css3-userint-20000216.html#color
796 
797       case eColorID__moz_field:
798       case eColorID__moz_fieldtext:
799         aResult = NS_RGB(0xff, 0x00, 0xff);
800         break;
801 
802       case eColorID__moz_dialog:
803       case eColorID__moz_dialogtext:
804         aResult = NS_RGB(0x66, 0x00, 0x66);
805         break;
806 
807       default:
808         rv = NS_ERROR_NOT_AVAILABLE;
809     }
810     if (NS_SUCCEEDED(rv)) return rv;
811   }
812 #endif  // DEBUG_SYSTEM_COLOR_USE
813 
814   if (aUseStandinsForNativeColors &&
815       (ColorIsNotCSSAccessible(aID) || !sUseStandinsForNativeColors)) {
816     aUseStandinsForNativeColors = false;
817   }
818 
819   if (!aUseStandinsForNativeColors && IS_COLOR_CACHED(aID)) {
820     aResult = sCachedColors[aID];
821     return NS_OK;
822   }
823 
824     // There are no system color settings for these, so set them manually
825 #ifndef XP_MACOSX
826   if (aID == eColorID_TextSelectBackgroundDisabled) {
827     // This is used to gray out the selection when it's not focused
828     // Used with nsISelectionController::SELECTION_DISABLED
829     aResult = NS_RGB(0xb0, 0xb0, 0xb0);
830     return NS_OK;
831   }
832 #endif
833 
834   if (aID == eColorID_TextSelectBackgroundAttention) {
835     if (sFindbarModalHighlight) {
836       aResult = NS_RGBA(0, 0, 0, 0);
837       return NS_OK;
838     }
839 
840     // This makes the selection stand out when typeaheadfind is on
841     // Used with nsISelectionController::SELECTION_ATTENTION
842     aResult = NS_RGB(0x38, 0xd8, 0x78);
843     return NS_OK;
844   }
845 
846   if (aID == eColorID_TextHighlightBackground) {
847     // This makes the matched text stand out when findbar highlighting is on
848     // Used with nsISelectionController::SELECTION_FIND
849     aResult = NS_RGB(0xef, 0x0f, 0xff);
850     return NS_OK;
851   }
852 
853   if (aID == eColorID_TextHighlightForeground) {
854     // The foreground color for the matched text in findbar highlighting
855     // Used with nsISelectionController::SELECTION_FIND
856     aResult = NS_RGB(0xff, 0xff, 0xff);
857     return NS_OK;
858   }
859 
860   if (sUseNativeColors && aUseStandinsForNativeColors) {
861     aResult = GetStandinForNativeColor(aID);
862     return NS_OK;
863   }
864 
865   if (sUseNativeColors && NS_SUCCEEDED(NativeGetColor(aID, aResult))) {
866     if (!mozilla::ServoStyleSet::IsInServoTraversal()) {
867       MOZ_ASSERT(NS_IsMainThread());
868       // Make sure the preferences are initialized. In the normal run,
869       // they would already be, because gfxPlatform would have been created,
870       // but with some addon, that is not the case. See Bug 1357307.
871       gfxPrefs::GetSingleton();
872       if ((gfxPlatform::GetCMSMode() == eCMSMode_All) &&
873           !IsSpecialColor(aID, aResult)) {
874         qcms_transform* transform = gfxPlatform::GetCMSInverseRGBTransform();
875         if (transform) {
876           uint8_t color[3];
877           color[0] = NS_GET_R(aResult);
878           color[1] = NS_GET_G(aResult);
879           color[2] = NS_GET_B(aResult);
880           qcms_transform_data(transform, color, color, 1);
881           aResult = NS_RGB(color[0], color[1], color[2]);
882         }
883       }
884 
885       CACHE_COLOR(aID, aResult);
886     }
887     return NS_OK;
888   }
889 
890   return NS_ERROR_NOT_AVAILABLE;
891 }
892 
GetIntImpl(IntID aID,int32_t & aResult)893 nsresult nsXPLookAndFeel::GetIntImpl(IntID aID, int32_t& aResult) {
894   if (!sInitialized) Init();
895 
896   // Set the default values for these prefs. but allow different platforms
897   // to override them in their nsLookAndFeel if desired.
898   switch (aID) {
899     case eIntID_ScrollButtonLeftMouseButtonAction:
900       aResult = 0;
901       return NS_OK;
902     case eIntID_ScrollButtonMiddleMouseButtonAction:
903       aResult = 3;
904       return NS_OK;
905     case eIntID_ScrollButtonRightMouseButtonAction:
906       aResult = 3;
907       return NS_OK;
908     default:
909       /*
910        * The metrics above are hardcoded platform defaults. All the other
911        * metrics are stored in sIntPrefs and can be changed at runtime.
912        */
913       break;
914   }
915 
916   for (unsigned int i = 0; i < ArrayLength(sIntPrefs); ++i) {
917     if (sIntPrefs[i].isSet && (sIntPrefs[i].id == aID)) {
918       aResult = sIntPrefs[i].intVar;
919       return NS_OK;
920     }
921   }
922 
923   return NS_ERROR_NOT_AVAILABLE;
924 }
925 
GetFloatImpl(FloatID aID,float & aResult)926 nsresult nsXPLookAndFeel::GetFloatImpl(FloatID aID, float& aResult) {
927   if (!sInitialized) Init();
928 
929   for (unsigned int i = 0; i < ArrayLength(sFloatPrefs); ++i) {
930     if (sFloatPrefs[i].isSet && sFloatPrefs[i].id == aID) {
931       aResult = sFloatPrefs[i].floatVar;
932       return NS_OK;
933     }
934   }
935 
936   return NS_ERROR_NOT_AVAILABLE;
937 }
938 
RefreshImpl()939 void nsXPLookAndFeel::RefreshImpl() {
940   // Wipe out our color cache.
941   uint32_t i;
942   for (i = 0; i < eColorID_LAST_COLOR; i++) sCachedColors[i] = 0;
943   for (i = 0; i < COLOR_CACHE_SIZE; i++) sCachedColorBits[i] = 0;
944 }
945 
GetIntCacheImpl()946 nsTArray<LookAndFeelInt> nsXPLookAndFeel::GetIntCacheImpl() {
947   return nsTArray<LookAndFeelInt>();
948 }
949 
950 namespace mozilla {
951 
952 // static
GetColor(ColorID aID,nscolor * aResult)953 nsresult LookAndFeel::GetColor(ColorID aID, nscolor* aResult) {
954   return nsLookAndFeel::GetInstance()->GetColorImpl(aID, false, *aResult);
955 }
956 
GetColor(ColorID aID,bool aUseStandinsForNativeColors,nscolor * aResult)957 nsresult LookAndFeel::GetColor(ColorID aID, bool aUseStandinsForNativeColors,
958                                nscolor* aResult) {
959   return nsLookAndFeel::GetInstance()->GetColorImpl(
960       aID, aUseStandinsForNativeColors, *aResult);
961 }
962 
963 // static
GetInt(IntID aID,int32_t * aResult)964 nsresult LookAndFeel::GetInt(IntID aID, int32_t* aResult) {
965   return nsLookAndFeel::GetInstance()->GetIntImpl(aID, *aResult);
966 }
967 
968 // static
GetFloat(FloatID aID,float * aResult)969 nsresult LookAndFeel::GetFloat(FloatID aID, float* aResult) {
970   return nsLookAndFeel::GetInstance()->GetFloatImpl(aID, *aResult);
971 }
972 
973 // static
GetFont(FontID aID,nsString & aName,gfxFontStyle & aStyle,float aDevPixPerCSSPixel)974 bool LookAndFeel::GetFont(FontID aID, nsString& aName, gfxFontStyle& aStyle,
975                           float aDevPixPerCSSPixel) {
976   return nsLookAndFeel::GetInstance()->GetFontImpl(aID, aName, aStyle,
977                                                    aDevPixPerCSSPixel);
978 }
979 
980 // static
GetPasswordCharacter()981 char16_t LookAndFeel::GetPasswordCharacter() {
982   return nsLookAndFeel::GetInstance()->GetPasswordCharacterImpl();
983 }
984 
985 // static
GetEchoPassword()986 bool LookAndFeel::GetEchoPassword() {
987   return nsLookAndFeel::GetInstance()->GetEchoPasswordImpl();
988 }
989 
990 // static
GetPasswordMaskDelay()991 uint32_t LookAndFeel::GetPasswordMaskDelay() {
992   return nsLookAndFeel::GetInstance()->GetPasswordMaskDelayImpl();
993 }
994 
995 // static
Refresh()996 void LookAndFeel::Refresh() { nsLookAndFeel::GetInstance()->RefreshImpl(); }
997 
998 // static
NativeInit()999 void LookAndFeel::NativeInit() { nsLookAndFeel::GetInstance()->NativeInit(); }
1000 
1001 // static
GetIntCache()1002 nsTArray<LookAndFeelInt> LookAndFeel::GetIntCache() {
1003   return nsLookAndFeel::GetInstance()->GetIntCacheImpl();
1004 }
1005 
1006 // static
SetIntCache(const nsTArray<LookAndFeelInt> & aLookAndFeelIntCache)1007 void LookAndFeel::SetIntCache(
1008     const nsTArray<LookAndFeelInt>& aLookAndFeelIntCache) {
1009   return nsLookAndFeel::GetInstance()->SetIntCacheImpl(aLookAndFeelIntCache);
1010 }
1011 
1012 }  // namespace mozilla
1013