michael@0: /* -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "mozilla/ArrayUtils.h" michael@0: michael@0: #include "nscore.h" michael@0: michael@0: #include "nsXPLookAndFeel.h" michael@0: #include "nsLookAndFeel.h" michael@0: #include "nsCRT.h" michael@0: #include "nsFont.h" michael@0: #include "nsThemeConstants.h" michael@0: #include "mozilla/Preferences.h" michael@0: #include "mozilla/gfx/2D.h" michael@0: michael@0: #include "gfxPlatform.h" michael@0: #include "qcms.h" michael@0: michael@0: #ifdef DEBUG michael@0: #include "nsSize.h" michael@0: #endif michael@0: michael@0: using namespace mozilla; michael@0: michael@0: nsLookAndFeelIntPref nsXPLookAndFeel::sIntPrefs[] = michael@0: { michael@0: { "ui.caretBlinkTime", michael@0: eIntID_CaretBlinkTime, michael@0: false, 0 }, michael@0: { "ui.caretWidth", michael@0: eIntID_CaretWidth, michael@0: false, 0 }, michael@0: { "ui.caretVisibleWithSelection", michael@0: eIntID_ShowCaretDuringSelection, michael@0: false, 0 }, michael@0: { "ui.submenuDelay", michael@0: eIntID_SubmenuDelay, michael@0: false, 0 }, michael@0: { "ui.dragThresholdX", michael@0: eIntID_DragThresholdX, michael@0: false, 0 }, michael@0: { "ui.dragThresholdY", michael@0: eIntID_DragThresholdY, michael@0: false, 0 }, michael@0: { "ui.useAccessibilityTheme", michael@0: eIntID_UseAccessibilityTheme, michael@0: false, 0 }, michael@0: { "ui.menusCanOverlapOSBar", michael@0: eIntID_MenusCanOverlapOSBar, michael@0: false, 0 }, michael@0: { "ui.useOverlayScrollbars", michael@0: eIntID_UseOverlayScrollbars, michael@0: false, 0 }, michael@0: { "ui.scrollbarDisplayOnMouseMove", michael@0: eIntID_ScrollbarDisplayOnMouseMove, michael@0: false, 0 }, michael@0: { "ui.scrollbarFadeBeginDelay", michael@0: eIntID_ScrollbarFadeBeginDelay, michael@0: false, 0 }, michael@0: { "ui.scrollbarFadeDuration", michael@0: eIntID_ScrollbarFadeDuration, michael@0: false, 0 }, michael@0: { "ui.showHideScrollbars", michael@0: eIntID_ShowHideScrollbars, michael@0: false, 0 }, michael@0: { "ui.skipNavigatingDisabledMenuItem", michael@0: eIntID_SkipNavigatingDisabledMenuItem, michael@0: false, 0 }, michael@0: { "ui.treeOpenDelay", michael@0: eIntID_TreeOpenDelay, michael@0: false, 0 }, michael@0: { "ui.treeCloseDelay", michael@0: eIntID_TreeCloseDelay, michael@0: false, 0 }, michael@0: { "ui.treeLazyScrollDelay", michael@0: eIntID_TreeLazyScrollDelay, michael@0: false, 0 }, michael@0: { "ui.treeScrollDelay", michael@0: eIntID_TreeScrollDelay, michael@0: false, 0 }, michael@0: { "ui.treeScrollLinesMax", michael@0: eIntID_TreeScrollLinesMax, michael@0: false, 0 }, michael@0: { "accessibility.tabfocus", michael@0: eIntID_TabFocusModel, michael@0: false, 0 }, michael@0: { "ui.alertNotificationOrigin", michael@0: eIntID_AlertNotificationOrigin, michael@0: false, 0 }, michael@0: { "ui.scrollToClick", michael@0: eIntID_ScrollToClick, michael@0: false, 0 }, michael@0: { "ui.IMERawInputUnderlineStyle", michael@0: eIntID_IMERawInputUnderlineStyle, michael@0: false, 0 }, michael@0: { "ui.IMESelectedRawTextUnderlineStyle", michael@0: eIntID_IMESelectedRawTextUnderlineStyle, michael@0: false, 0 }, michael@0: { "ui.IMEConvertedTextUnderlineStyle", michael@0: eIntID_IMEConvertedTextUnderlineStyle, michael@0: false, 0 }, michael@0: { "ui.IMESelectedConvertedTextUnderlineStyle", michael@0: eIntID_IMESelectedConvertedTextUnderline, michael@0: false, 0 }, michael@0: { "ui.SpellCheckerUnderlineStyle", michael@0: eIntID_SpellCheckerUnderlineStyle, michael@0: false, 0 }, michael@0: { "ui.scrollbarButtonAutoRepeatBehavior", michael@0: eIntID_ScrollbarButtonAutoRepeatBehavior, michael@0: false, 0 }, michael@0: { "ui.tooltipDelay", michael@0: eIntID_TooltipDelay, michael@0: false, 0 }, michael@0: { "ui.physicalHomeButton", michael@0: eIntID_PhysicalHomeButton, michael@0: false, 0 }, michael@0: }; michael@0: michael@0: nsLookAndFeelFloatPref nsXPLookAndFeel::sFloatPrefs[] = michael@0: { michael@0: { "ui.IMEUnderlineRelativeSize", michael@0: eFloatID_IMEUnderlineRelativeSize, michael@0: false, 0 }, michael@0: { "ui.SpellCheckerUnderlineRelativeSize", michael@0: eFloatID_SpellCheckerUnderlineRelativeSize, michael@0: false, 0 }, michael@0: { "ui.caretAspectRatio", michael@0: eFloatID_CaretAspectRatio, michael@0: false, 0 }, michael@0: }; michael@0: michael@0: michael@0: // This array MUST be kept in the same order as the color list in LookAndFeel.h. michael@0: /* XXX If you add any strings longer than michael@0: * "ui.IMESelectedConvertedTextBackground" michael@0: * to the following array then you MUST update the michael@0: * sizes of the sColorPrefs array in nsXPLookAndFeel.h michael@0: */ michael@0: const char nsXPLookAndFeel::sColorPrefs[][38] = michael@0: { michael@0: "ui.windowBackground", michael@0: "ui.windowForeground", michael@0: "ui.widgetBackground", michael@0: "ui.widgetForeground", michael@0: "ui.widgetSelectBackground", michael@0: "ui.widgetSelectForeground", michael@0: "ui.widget3DHighlight", michael@0: "ui.widget3DShadow", michael@0: "ui.textBackground", michael@0: "ui.textForeground", michael@0: "ui.textSelectBackground", michael@0: "ui.textSelectForeground", michael@0: "ui.textSelectBackgroundDisabled", michael@0: "ui.textSelectBackgroundAttention", michael@0: "ui.textHighlightBackground", michael@0: "ui.textHighlightForeground", michael@0: "ui.IMERawInputBackground", michael@0: "ui.IMERawInputForeground", michael@0: "ui.IMERawInputUnderline", michael@0: "ui.IMESelectedRawTextBackground", michael@0: "ui.IMESelectedRawTextForeground", michael@0: "ui.IMESelectedRawTextUnderline", michael@0: "ui.IMEConvertedTextBackground", michael@0: "ui.IMEConvertedTextForeground", michael@0: "ui.IMEConvertedTextUnderline", michael@0: "ui.IMESelectedConvertedTextBackground", michael@0: "ui.IMESelectedConvertedTextForeground", michael@0: "ui.IMESelectedConvertedTextUnderline", michael@0: "ui.SpellCheckerUnderline", michael@0: "ui.activeborder", michael@0: "ui.activecaption", michael@0: "ui.appworkspace", michael@0: "ui.background", michael@0: "ui.buttonface", michael@0: "ui.buttonhighlight", michael@0: "ui.buttonshadow", michael@0: "ui.buttontext", michael@0: "ui.captiontext", michael@0: "ui.graytext", michael@0: "ui.highlight", michael@0: "ui.highlighttext", michael@0: "ui.inactiveborder", michael@0: "ui.inactivecaption", michael@0: "ui.inactivecaptiontext", michael@0: "ui.infobackground", michael@0: "ui.infotext", michael@0: "ui.menu", michael@0: "ui.menutext", michael@0: "ui.scrollbar", michael@0: "ui.threeddarkshadow", michael@0: "ui.threedface", michael@0: "ui.threedhighlight", michael@0: "ui.threedlightshadow", michael@0: "ui.threedshadow", michael@0: "ui.window", michael@0: "ui.windowframe", michael@0: "ui.windowtext", michael@0: "ui.-moz-buttondefault", michael@0: "ui.-moz-field", michael@0: "ui.-moz-fieldtext", michael@0: "ui.-moz-dialog", michael@0: "ui.-moz-dialogtext", michael@0: "ui.-moz-dragtargetzone", michael@0: "ui.-moz-cellhighlight", michael@0: "ui.-moz_cellhighlighttext", michael@0: "ui.-moz-html-cellhighlight", michael@0: "ui.-moz-html-cellhighlighttext", michael@0: "ui.-moz-buttonhoverface", michael@0: "ui.-moz_buttonhovertext", michael@0: "ui.-moz_menuhover", michael@0: "ui.-moz_menuhovertext", michael@0: "ui.-moz_menubartext", michael@0: "ui.-moz_menubarhovertext", michael@0: "ui.-moz_eventreerow", michael@0: "ui.-moz_oddtreerow", michael@0: "ui.-moz_mac_chrome_active", michael@0: "ui.-moz_mac_chrome_inactive", michael@0: "ui.-moz-mac-focusring", michael@0: "ui.-moz-mac-menuselect", michael@0: "ui.-moz-mac-menushadow", michael@0: "ui.-moz-mac-menutextdisable", michael@0: "ui.-moz-mac-menutextselect", michael@0: "ui.-moz_mac_disabledtoolbartext", michael@0: "ui.-moz-mac-secondaryhighlight", michael@0: "ui.-moz-win-mediatext", michael@0: "ui.-moz-win-communicationstext", michael@0: "ui.-moz-nativehyperlinktext", michael@0: "ui.-moz-comboboxtext", michael@0: "ui.-moz-combobox" michael@0: }; michael@0: michael@0: int32_t nsXPLookAndFeel::sCachedColors[LookAndFeel::eColorID_LAST_COLOR] = {0}; michael@0: int32_t nsXPLookAndFeel::sCachedColorBits[COLOR_CACHE_SIZE] = {0}; michael@0: michael@0: bool nsXPLookAndFeel::sInitialized = false; michael@0: bool nsXPLookAndFeel::sUseNativeColors = true; michael@0: michael@0: nsLookAndFeel* nsXPLookAndFeel::sInstance = nullptr; michael@0: bool nsXPLookAndFeel::sShutdown = false; michael@0: michael@0: // static michael@0: nsLookAndFeel* michael@0: nsXPLookAndFeel::GetInstance() michael@0: { michael@0: if (sInstance) { michael@0: return sInstance; michael@0: } michael@0: michael@0: NS_ENSURE_TRUE(!sShutdown, nullptr); michael@0: michael@0: sInstance = new nsLookAndFeel(); michael@0: return sInstance; michael@0: } michael@0: michael@0: // static michael@0: void michael@0: nsXPLookAndFeel::Shutdown() michael@0: { michael@0: if (sShutdown) { michael@0: return; michael@0: } michael@0: sShutdown = true; michael@0: delete sInstance; michael@0: sInstance = nullptr; michael@0: } michael@0: michael@0: nsXPLookAndFeel::nsXPLookAndFeel() : LookAndFeel() michael@0: { michael@0: } michael@0: michael@0: // static michael@0: void michael@0: nsXPLookAndFeel::IntPrefChanged(nsLookAndFeelIntPref *data) michael@0: { michael@0: if (!data) { michael@0: return; michael@0: } michael@0: michael@0: int32_t intpref; michael@0: nsresult rv = Preferences::GetInt(data->name, &intpref); michael@0: if (NS_FAILED(rv)) { michael@0: return; michael@0: } michael@0: data->intVar = intpref; michael@0: data->isSet = true; michael@0: #ifdef DEBUG_akkana michael@0: printf("====== Changed int pref %s to %d\n", data->name, data->intVar); michael@0: #endif michael@0: } michael@0: michael@0: // static michael@0: void michael@0: nsXPLookAndFeel::FloatPrefChanged(nsLookAndFeelFloatPref *data) michael@0: { michael@0: if (!data) { michael@0: return; michael@0: } michael@0: michael@0: int32_t intpref; michael@0: nsresult rv = Preferences::GetInt(data->name, &intpref); michael@0: if (NS_FAILED(rv)) { michael@0: return; michael@0: } michael@0: data->floatVar = (float)intpref / 100.0f; michael@0: data->isSet = true; michael@0: #ifdef DEBUG_akkana michael@0: printf("====== Changed float pref %s to %f\n", data->name, data->floatVar); michael@0: #endif michael@0: } michael@0: michael@0: // static michael@0: void michael@0: nsXPLookAndFeel::ColorPrefChanged (unsigned int index, const char *prefName) michael@0: { michael@0: nsAutoString colorStr; michael@0: nsresult rv = Preferences::GetString(prefName, &colorStr); michael@0: if (NS_FAILED(rv)) { michael@0: return; michael@0: } michael@0: if (!colorStr.IsEmpty()) { michael@0: nscolor thecolor; michael@0: if (colorStr[0] == char16_t('#')) { michael@0: if (NS_HexToRGB(nsDependentString(colorStr, 1), &thecolor)) { michael@0: int32_t id = NS_PTR_TO_INT32(index); michael@0: CACHE_COLOR(id, thecolor); michael@0: } michael@0: } else if (NS_ColorNameToRGB(colorStr, &thecolor)) { michael@0: int32_t id = NS_PTR_TO_INT32(index); michael@0: CACHE_COLOR(id, thecolor); michael@0: #ifdef DEBUG_akkana michael@0: printf("====== Changed color pref %s to 0x%lx\n", michael@0: prefName, thecolor); michael@0: #endif michael@0: } michael@0: } else { michael@0: // Reset to the default color, by clearing the cache michael@0: // to force lookup when the color is next used michael@0: int32_t id = NS_PTR_TO_INT32(index); michael@0: CLEAR_COLOR_CACHE(id); michael@0: } michael@0: } michael@0: michael@0: void michael@0: nsXPLookAndFeel::InitFromPref(nsLookAndFeelIntPref* aPref) michael@0: { michael@0: int32_t intpref; michael@0: nsresult rv = Preferences::GetInt(aPref->name, &intpref); michael@0: if (NS_SUCCEEDED(rv)) { michael@0: aPref->isSet = true; michael@0: aPref->intVar = intpref; michael@0: } michael@0: } michael@0: michael@0: void michael@0: nsXPLookAndFeel::InitFromPref(nsLookAndFeelFloatPref* aPref) michael@0: { michael@0: int32_t intpref; michael@0: nsresult rv = Preferences::GetInt(aPref->name, &intpref); michael@0: if (NS_SUCCEEDED(rv)) { michael@0: aPref->isSet = true; michael@0: aPref->floatVar = (float)intpref / 100.0f; michael@0: } michael@0: } michael@0: michael@0: void michael@0: nsXPLookAndFeel::InitColorFromPref(int32_t i) michael@0: { michael@0: nsAutoString colorStr; michael@0: nsresult rv = Preferences::GetString(sColorPrefs[i], &colorStr); michael@0: if (NS_FAILED(rv) || colorStr.IsEmpty()) { michael@0: return; michael@0: } michael@0: nscolor thecolor; michael@0: if (colorStr[0] == char16_t('#')) { michael@0: nsAutoString hexString; michael@0: colorStr.Right(hexString, colorStr.Length() - 1); michael@0: if (NS_HexToRGB(hexString, &thecolor)) { michael@0: CACHE_COLOR(i, thecolor); michael@0: } michael@0: } else if (NS_ColorNameToRGB(colorStr, &thecolor)) { michael@0: CACHE_COLOR(i, thecolor); michael@0: } michael@0: } michael@0: michael@0: // static michael@0: void michael@0: nsXPLookAndFeel::OnPrefChanged(const char* aPref, void* aClosure) michael@0: { michael@0: michael@0: // looping in the same order as in ::Init michael@0: michael@0: nsDependentCString prefName(aPref); michael@0: unsigned int i; michael@0: for (i = 0; i < ArrayLength(sIntPrefs); ++i) { michael@0: if (prefName.Equals(sIntPrefs[i].name)) { michael@0: IntPrefChanged(&sIntPrefs[i]); michael@0: return; michael@0: } michael@0: } michael@0: michael@0: for (i = 0; i < ArrayLength(sFloatPrefs); ++i) { michael@0: if (prefName.Equals(sFloatPrefs[i].name)) { michael@0: FloatPrefChanged(&sFloatPrefs[i]); michael@0: return; michael@0: } michael@0: } michael@0: michael@0: for (i = 0; i < ArrayLength(sColorPrefs); ++i) { michael@0: if (prefName.Equals(sColorPrefs[i])) { michael@0: ColorPrefChanged(i, sColorPrefs[i]); michael@0: return; michael@0: } michael@0: } michael@0: } michael@0: michael@0: // michael@0: // Read values from the user's preferences. michael@0: // This is done once at startup, but since the user's preferences michael@0: // haven't actually been read yet at that time, we also have to michael@0: // set a callback to inform us of changes to each pref. michael@0: // michael@0: void michael@0: nsXPLookAndFeel::Init() michael@0: { michael@0: // Say we're already initialized, and take the chance that it might fail; michael@0: // protects against some other process writing to our static variables. michael@0: sInitialized = true; michael@0: michael@0: // XXX If we could reorganize the pref names, we should separate the branch michael@0: // for each types. Then, we could reduce the unnecessary loop from michael@0: // nsXPLookAndFeel::OnPrefChanged(). michael@0: Preferences::RegisterCallback(OnPrefChanged, "ui."); michael@0: Preferences::RegisterCallback(OnPrefChanged, "accessibility.tabfocus"); michael@0: michael@0: unsigned int i; michael@0: for (i = 0; i < ArrayLength(sIntPrefs); ++i) { michael@0: InitFromPref(&sIntPrefs[i]); michael@0: } michael@0: michael@0: for (i = 0; i < ArrayLength(sFloatPrefs); ++i) { michael@0: InitFromPref(&sFloatPrefs[i]); michael@0: } michael@0: michael@0: for (i = 0; i < ArrayLength(sColorPrefs); ++i) { michael@0: InitColorFromPref(i); michael@0: } michael@0: michael@0: bool val; michael@0: if (NS_SUCCEEDED(Preferences::GetBool("ui.use_native_colors", &val))) { michael@0: sUseNativeColors = val; michael@0: } michael@0: } michael@0: michael@0: nsXPLookAndFeel::~nsXPLookAndFeel() michael@0: { michael@0: NS_ASSERTION(sInstance == this, michael@0: "This destroying instance isn't the singleton instance"); michael@0: sInstance = nullptr; michael@0: } michael@0: michael@0: bool michael@0: nsXPLookAndFeel::IsSpecialColor(ColorID aID, nscolor &aColor) michael@0: { michael@0: switch (aID) { michael@0: case eColorID_TextSelectForeground: michael@0: return (aColor == NS_DONT_CHANGE_COLOR); michael@0: case eColorID_IMESelectedRawTextBackground: michael@0: case eColorID_IMESelectedConvertedTextBackground: michael@0: case eColorID_IMERawInputBackground: michael@0: case eColorID_IMEConvertedTextBackground: michael@0: case eColorID_IMESelectedRawTextForeground: michael@0: case eColorID_IMESelectedConvertedTextForeground: michael@0: case eColorID_IMERawInputForeground: michael@0: case eColorID_IMEConvertedTextForeground: michael@0: case eColorID_IMERawInputUnderline: michael@0: case eColorID_IMEConvertedTextUnderline: michael@0: case eColorID_IMESelectedRawTextUnderline: michael@0: case eColorID_IMESelectedConvertedTextUnderline: michael@0: case eColorID_SpellCheckerUnderline: michael@0: return NS_IS_SELECTION_SPECIAL_COLOR(aColor); michael@0: default: michael@0: /* michael@0: * In GetColor(), every color that is not a special color is color michael@0: * corrected. Use false to make other colors color corrected. michael@0: */ michael@0: return false; michael@0: } michael@0: return false; michael@0: } michael@0: michael@0: bool michael@0: nsXPLookAndFeel::ColorIsNotCSSAccessible(ColorID aID) michael@0: { michael@0: bool result = false; michael@0: michael@0: switch (aID) { michael@0: case eColorID_WindowBackground: michael@0: case eColorID_WindowForeground: michael@0: case eColorID_WidgetBackground: michael@0: case eColorID_WidgetForeground: michael@0: case eColorID_WidgetSelectBackground: michael@0: case eColorID_WidgetSelectForeground: michael@0: case eColorID_Widget3DHighlight: michael@0: case eColorID_Widget3DShadow: michael@0: case eColorID_TextBackground: michael@0: case eColorID_TextForeground: michael@0: case eColorID_TextSelectBackground: michael@0: case eColorID_TextSelectForeground: michael@0: case eColorID_TextSelectBackgroundDisabled: michael@0: case eColorID_TextSelectBackgroundAttention: michael@0: case eColorID_TextHighlightBackground: michael@0: case eColorID_TextHighlightForeground: michael@0: case eColorID_IMERawInputBackground: michael@0: case eColorID_IMERawInputForeground: michael@0: case eColorID_IMERawInputUnderline: michael@0: case eColorID_IMESelectedRawTextBackground: michael@0: case eColorID_IMESelectedRawTextForeground: michael@0: case eColorID_IMESelectedRawTextUnderline: michael@0: case eColorID_IMEConvertedTextBackground: michael@0: case eColorID_IMEConvertedTextForeground: michael@0: case eColorID_IMEConvertedTextUnderline: michael@0: case eColorID_IMESelectedConvertedTextBackground: michael@0: case eColorID_IMESelectedConvertedTextForeground: michael@0: case eColorID_IMESelectedConvertedTextUnderline: michael@0: case eColorID_SpellCheckerUnderline: michael@0: result = true; michael@0: break; michael@0: default: michael@0: break; michael@0: } michael@0: michael@0: return result; michael@0: } michael@0: michael@0: nscolor michael@0: nsXPLookAndFeel::GetStandinForNativeColor(ColorID aID) michael@0: { michael@0: nscolor result = NS_RGB(0xFF, 0xFF, 0xFF); michael@0: michael@0: // The stand-in colors are taken from the Windows 7 Aero theme michael@0: // except Mac-specific colors which are taken from Mac OS 10.7. michael@0: switch (aID) { michael@0: // CSS 2 colors: michael@0: case eColorID_activeborder: result = NS_RGB(0xB4, 0xB4, 0xB4); break; michael@0: case eColorID_activecaption: result = NS_RGB(0x99, 0xB4, 0xD1); break; michael@0: case eColorID_appworkspace: result = NS_RGB(0xAB, 0xAB, 0xAB); break; michael@0: case eColorID_background: result = NS_RGB(0x00, 0x00, 0x00); break; michael@0: case eColorID_buttonface: result = NS_RGB(0xF0, 0xF0, 0xF0); break; michael@0: case eColorID_buttonhighlight: result = NS_RGB(0xFF, 0xFF, 0xFF); break; michael@0: case eColorID_buttonshadow: result = NS_RGB(0xA0, 0xA0, 0xA0); break; michael@0: case eColorID_buttontext: result = NS_RGB(0x00, 0x00, 0x00); break; michael@0: case eColorID_captiontext: result = NS_RGB(0x00, 0x00, 0x00); break; michael@0: case eColorID_graytext: result = NS_RGB(0x6D, 0x6D, 0x6D); break; michael@0: case eColorID_highlight: result = NS_RGB(0x33, 0x99, 0xFF); break; michael@0: case eColorID_highlighttext: result = NS_RGB(0xFF, 0xFF, 0xFF); break; michael@0: case eColorID_inactiveborder: result = NS_RGB(0xF4, 0xF7, 0xFC); break; michael@0: case eColorID_inactivecaption: result = NS_RGB(0xBF, 0xCD, 0xDB); break; michael@0: case eColorID_inactivecaptiontext: michael@0: result = NS_RGB(0x43, 0x4E, 0x54); break; michael@0: case eColorID_infobackground: result = NS_RGB(0xFF, 0xFF, 0xE1); break; michael@0: case eColorID_infotext: result = NS_RGB(0x00, 0x00, 0x00); break; michael@0: case eColorID_menu: result = NS_RGB(0xF0, 0xF0, 0xF0); break; michael@0: case eColorID_menutext: result = NS_RGB(0x00, 0x00, 0x00); break; michael@0: case eColorID_scrollbar: result = NS_RGB(0xC8, 0xC8, 0xC8); break; michael@0: case eColorID_threeddarkshadow: result = NS_RGB(0x69, 0x69, 0x69); break; michael@0: case eColorID_threedface: result = NS_RGB(0xF0, 0xF0, 0xF0); break; michael@0: case eColorID_threedhighlight: result = NS_RGB(0xFF, 0xFF, 0xFF); break; michael@0: case eColorID_threedlightshadow: result = NS_RGB(0xE3, 0xE3, 0xE3); break; michael@0: case eColorID_threedshadow: result = NS_RGB(0xA0, 0xA0, 0xA0); break; michael@0: case eColorID_window: result = NS_RGB(0xFF, 0xFF, 0xFF); break; michael@0: case eColorID_windowframe: result = NS_RGB(0x64, 0x64, 0x64); break; michael@0: case eColorID_windowtext: result = NS_RGB(0x00, 0x00, 0x00); break; michael@0: case eColorID__moz_buttondefault: michael@0: result = NS_RGB(0x69, 0x69, 0x69); break; michael@0: case eColorID__moz_field: result = NS_RGB(0xFF, 0xFF, 0xFF); break; michael@0: case eColorID__moz_fieldtext: result = NS_RGB(0x00, 0x00, 0x00); break; michael@0: case eColorID__moz_dialog: result = NS_RGB(0xF0, 0xF0, 0xF0); break; michael@0: case eColorID__moz_dialogtext: result = NS_RGB(0x00, 0x00, 0x00); break; michael@0: case eColorID__moz_dragtargetzone: michael@0: result = NS_RGB(0xFF, 0xFF, 0xFF); break; michael@0: case eColorID__moz_cellhighlight: michael@0: result = NS_RGB(0xF0, 0xF0, 0xF0); break; michael@0: case eColorID__moz_cellhighlighttext: michael@0: result = NS_RGB(0x00, 0x00, 0x00); break; michael@0: case eColorID__moz_html_cellhighlight: michael@0: result = NS_RGB(0x33, 0x99, 0xFF); break; michael@0: case eColorID__moz_html_cellhighlighttext: michael@0: result = NS_RGB(0xFF, 0xFF, 0xFF); break; michael@0: case eColorID__moz_buttonhoverface: michael@0: result = NS_RGB(0xF0, 0xF0, 0xF0); break; michael@0: case eColorID__moz_buttonhovertext: michael@0: result = NS_RGB(0x00, 0x00, 0x00); break; michael@0: case eColorID__moz_menuhover: michael@0: result = NS_RGB(0x33, 0x99, 0xFF); break; michael@0: case eColorID__moz_menuhovertext: michael@0: result = NS_RGB(0x00, 0x00, 0x00); break; michael@0: case eColorID__moz_menubartext: michael@0: result = NS_RGB(0x00, 0x00, 0x00); break; michael@0: case eColorID__moz_menubarhovertext: michael@0: result = NS_RGB(0x00, 0x00, 0x00); break; michael@0: case eColorID__moz_oddtreerow: michael@0: result = NS_RGB(0xFF, 0xFF, 0xFF); break; michael@0: case eColorID__moz_mac_chrome_active: michael@0: result = NS_RGB(0xB2, 0xB2, 0xB2); break; michael@0: case eColorID__moz_mac_chrome_inactive: michael@0: result = NS_RGB(0xE1, 0xE1, 0xE1); break; michael@0: case eColorID__moz_mac_focusring: michael@0: result = NS_RGB(0x60, 0x9D, 0xD7); break; michael@0: case eColorID__moz_mac_menuselect: michael@0: result = NS_RGB(0x38, 0x75, 0xD7); break; michael@0: case eColorID__moz_mac_menushadow: michael@0: result = NS_RGB(0xA3, 0xA3, 0xA3); break; michael@0: case eColorID__moz_mac_menutextdisable: michael@0: result = NS_RGB(0x88, 0x88, 0x88); break; michael@0: case eColorID__moz_mac_menutextselect: michael@0: result = NS_RGB(0xFF, 0xFF, 0xFF); break; michael@0: case eColorID__moz_mac_disabledtoolbartext: michael@0: result = NS_RGB(0x3F, 0x3F, 0x3F); break; michael@0: case eColorID__moz_mac_secondaryhighlight: michael@0: result = NS_RGB(0xD4, 0xD4, 0xD4); break; michael@0: case eColorID__moz_win_mediatext: michael@0: result = NS_RGB(0xFF, 0xFF, 0xFF); break; michael@0: case eColorID__moz_win_communicationstext: michael@0: result = NS_RGB(0xFF, 0xFF, 0xFF); break; michael@0: case eColorID__moz_nativehyperlinktext: michael@0: result = NS_RGB(0x00, 0x66, 0xCC); break; michael@0: case eColorID__moz_comboboxtext: michael@0: result = NS_RGB(0x00, 0x00, 0x00); break; michael@0: case eColorID__moz_combobox: michael@0: result = NS_RGB(0xFF, 0xFF, 0xFF); break; michael@0: default: michael@0: break; michael@0: } michael@0: michael@0: return result; michael@0: } michael@0: michael@0: // michael@0: // All these routines will return NS_OK if they have a value, michael@0: // in which case the nsLookAndFeel should use that value; michael@0: // otherwise we'll return NS_ERROR_NOT_AVAILABLE, in which case, the michael@0: // platform-specific nsLookAndFeel should use its own values instead. michael@0: // michael@0: nsresult michael@0: nsXPLookAndFeel::GetColorImpl(ColorID aID, bool aUseStandinsForNativeColors, michael@0: nscolor &aResult) michael@0: { michael@0: if (!sInitialized) michael@0: Init(); michael@0: michael@0: // define DEBUG_SYSTEM_COLOR_USE if you want to debug system color michael@0: // use in a skin that uses them. When set, it will make all system michael@0: // color pairs that are appropriate for foreground/background michael@0: // pairing the same. This means if the skin is using system colors michael@0: // correctly you will not be able to see *any* text. michael@0: #undef DEBUG_SYSTEM_COLOR_USE michael@0: michael@0: #ifdef DEBUG_SYSTEM_COLOR_USE michael@0: { michael@0: nsresult rv = NS_OK; michael@0: switch (aID) { michael@0: // css2 http://www.w3.org/TR/REC-CSS2/ui.html#system-colors michael@0: case eColorID_activecaption: michael@0: // active window caption background michael@0: case eColorID_captiontext: michael@0: // text in active window caption michael@0: aResult = NS_RGB(0xff, 0x00, 0x00); michael@0: break; michael@0: michael@0: case eColorID_highlight: michael@0: // background of selected item michael@0: case eColorID_highlighttext: michael@0: // text of selected item michael@0: aResult = NS_RGB(0xff, 0xff, 0x00); michael@0: break; michael@0: michael@0: case eColorID_inactivecaption: michael@0: // inactive window caption michael@0: case eColorID_inactivecaptiontext: michael@0: // text in inactive window caption michael@0: aResult = NS_RGB(0x66, 0x66, 0x00); michael@0: break; michael@0: michael@0: case eColorID_infobackground: michael@0: // tooltip background color michael@0: case eColorID_infotext: michael@0: // tooltip text color michael@0: aResult = NS_RGB(0x00, 0xff, 0x00); michael@0: break; michael@0: michael@0: case eColorID_menu: michael@0: // menu background michael@0: case eColorID_menutext: michael@0: // menu text michael@0: aResult = NS_RGB(0x00, 0xff, 0xff); michael@0: break; michael@0: michael@0: case eColorID_threedface: michael@0: case eColorID_buttonface: michael@0: // 3-D face color michael@0: case eColorID_buttontext: michael@0: // text on push buttons michael@0: aResult = NS_RGB(0x00, 0x66, 0x66); michael@0: break; michael@0: michael@0: case eColorID_window: michael@0: case eColorID_windowtext: michael@0: aResult = NS_RGB(0x00, 0x00, 0xff); michael@0: break; michael@0: michael@0: // from the CSS3 working draft (not yet finalized) michael@0: // http://www.w3.org/tr/2000/wd-css3-userint-20000216.html#color michael@0: michael@0: case eColorID__moz_field: michael@0: case eColorID__moz_fieldtext: michael@0: aResult = NS_RGB(0xff, 0x00, 0xff); michael@0: break; michael@0: michael@0: case eColorID__moz_dialog: michael@0: case eColorID__moz_dialogtext: michael@0: aResult = NS_RGB(0x66, 0x00, 0x66); michael@0: break; michael@0: michael@0: default: michael@0: rv = NS_ERROR_NOT_AVAILABLE; michael@0: } michael@0: if (NS_SUCCEEDED(rv)) michael@0: return rv; michael@0: } michael@0: #endif // DEBUG_SYSTEM_COLOR_USE michael@0: michael@0: if (aUseStandinsForNativeColors && ColorIsNotCSSAccessible(aID)) michael@0: aUseStandinsForNativeColors = false; michael@0: michael@0: if (!aUseStandinsForNativeColors && IS_COLOR_CACHED(aID)) { michael@0: aResult = sCachedColors[aID]; michael@0: return NS_OK; michael@0: } michael@0: michael@0: // There are no system color settings for these, so set them manually michael@0: if (aID == eColorID_TextSelectBackgroundDisabled) { michael@0: // This is used to gray out the selection when it's not focused michael@0: // Used with nsISelectionController::SELECTION_DISABLED michael@0: aResult = NS_RGB(0xb0, 0xb0, 0xb0); michael@0: return NS_OK; michael@0: } michael@0: michael@0: if (aID == eColorID_TextSelectBackgroundAttention) { michael@0: // This makes the selection stand out when typeaheadfind is on michael@0: // Used with nsISelectionController::SELECTION_ATTENTION michael@0: aResult = NS_RGB(0x38, 0xd8, 0x78); michael@0: return NS_OK; michael@0: } michael@0: michael@0: if (aID == eColorID_TextHighlightBackground) { michael@0: // This makes the matched text stand out when findbar highlighting is on michael@0: // Used with nsISelectionController::SELECTION_FIND michael@0: aResult = NS_RGB(0xef, 0x0f, 0xff); michael@0: return NS_OK; michael@0: } michael@0: michael@0: if (aID == eColorID_TextHighlightForeground) { michael@0: // The foreground color for the matched text in findbar highlighting michael@0: // Used with nsISelectionController::SELECTION_FIND michael@0: aResult = NS_RGB(0xff, 0xff, 0xff); michael@0: return NS_OK; michael@0: } michael@0: michael@0: if (sUseNativeColors && aUseStandinsForNativeColors) michael@0: { michael@0: aResult = GetStandinForNativeColor(aID); michael@0: return NS_OK; michael@0: } michael@0: michael@0: if (sUseNativeColors && NS_SUCCEEDED(NativeGetColor(aID, aResult))) { michael@0: if ((gfxPlatform::GetCMSMode() == eCMSMode_All) && michael@0: !IsSpecialColor(aID, aResult)) { michael@0: qcms_transform *transform = gfxPlatform::GetCMSInverseRGBTransform(); michael@0: if (transform) { michael@0: uint8_t color[3]; michael@0: color[0] = NS_GET_R(aResult); michael@0: color[1] = NS_GET_G(aResult); michael@0: color[2] = NS_GET_B(aResult); michael@0: qcms_transform_data(transform, color, color, 1); michael@0: aResult = NS_RGB(color[0], color[1], color[2]); michael@0: } michael@0: } michael@0: michael@0: CACHE_COLOR(aID, aResult); michael@0: return NS_OK; michael@0: } michael@0: michael@0: return NS_ERROR_NOT_AVAILABLE; michael@0: } michael@0: michael@0: nsresult michael@0: nsXPLookAndFeel::GetIntImpl(IntID aID, int32_t &aResult) michael@0: { michael@0: if (!sInitialized) michael@0: Init(); michael@0: michael@0: // Set the default values for these prefs. but allow different platforms michael@0: // to override them in their nsLookAndFeel if desired. michael@0: switch (aID) { michael@0: case eIntID_ScrollButtonLeftMouseButtonAction: michael@0: aResult = 0; michael@0: return NS_OK; michael@0: case eIntID_ScrollButtonMiddleMouseButtonAction: michael@0: aResult = 3; michael@0: return NS_OK; michael@0: case eIntID_ScrollButtonRightMouseButtonAction: michael@0: aResult = 3; michael@0: return NS_OK; michael@0: default: michael@0: /* michael@0: * The metrics above are hardcoded platform defaults. All the other michael@0: * metrics are stored in sIntPrefs and can be changed at runtime. michael@0: */ michael@0: break; michael@0: } michael@0: michael@0: for (unsigned int i = 0; i < ArrayLength(sIntPrefs); ++i) { michael@0: if (sIntPrefs[i].isSet && (sIntPrefs[i].id == aID)) { michael@0: aResult = sIntPrefs[i].intVar; michael@0: return NS_OK; michael@0: } michael@0: } michael@0: michael@0: return NS_ERROR_NOT_AVAILABLE; michael@0: } michael@0: michael@0: nsresult michael@0: nsXPLookAndFeel::GetFloatImpl(FloatID aID, float &aResult) michael@0: { michael@0: if (!sInitialized) michael@0: Init(); michael@0: michael@0: for (unsigned int i = 0; i < ArrayLength(sFloatPrefs); ++i) { michael@0: if (sFloatPrefs[i].isSet && sFloatPrefs[i].id == aID) { michael@0: aResult = sFloatPrefs[i].floatVar; michael@0: return NS_OK; michael@0: } michael@0: } michael@0: michael@0: return NS_ERROR_NOT_AVAILABLE; michael@0: } michael@0: michael@0: void michael@0: nsXPLookAndFeel::RefreshImpl() michael@0: { michael@0: // Wipe out our color cache. michael@0: uint32_t i; michael@0: for (i = 0; i < eColorID_LAST_COLOR; i++) michael@0: sCachedColors[i] = 0; michael@0: for (i = 0; i < COLOR_CACHE_SIZE; i++) michael@0: sCachedColorBits[i] = 0; michael@0: } michael@0: michael@0: namespace mozilla { michael@0: michael@0: // static michael@0: nsresult michael@0: LookAndFeel::GetColor(ColorID aID, nscolor* aResult) michael@0: { michael@0: return nsLookAndFeel::GetInstance()->GetColorImpl(aID, false, *aResult); michael@0: } michael@0: michael@0: nsresult michael@0: LookAndFeel::GetColor(ColorID aID, bool aUseStandinsForNativeColors, michael@0: nscolor* aResult) michael@0: { michael@0: return nsLookAndFeel::GetInstance()->GetColorImpl(aID, michael@0: aUseStandinsForNativeColors, *aResult); michael@0: } michael@0: michael@0: // static michael@0: nsresult michael@0: LookAndFeel::GetColorForNativeAppearance(uint8_t aWidgetType, bool aIsDisabled, michael@0: nscolor* aResult) michael@0: { michael@0: NS_ENSURE_ARG_POINTER(aResult); michael@0: michael@0: ColorID colorID = eColorID_LAST_COLOR; michael@0: switch (aWidgetType) { michael@0: case NS_THEME_TEXTFIELD: michael@0: case NS_THEME_TEXTFIELD_MULTILINE: michael@0: case NS_THEME_LISTBOX: michael@0: case NS_THEME_DROPDOWN: michael@0: case NS_THEME_DROPDOWN_TEXTFIELD: michael@0: case NS_THEME_TREEVIEW: michael@0: colorID = (aIsDisabled) ? eColorID_graytext : eColorID__moz_fieldtext; michael@0: break; michael@0: michael@0: case NS_THEME_TOOLTIP: michael@0: colorID = eColorID_infotext; michael@0: break; michael@0: michael@0: case NS_THEME_BUTTON: michael@0: case NS_THEME_GROUPBOX: michael@0: case NS_THEME_PROGRESSBAR: michael@0: case NS_THEME_PROGRESSBAR_VERTICAL: michael@0: case NS_THEME_TAB_PANEL: michael@0: case NS_THEME_STATUSBAR: michael@0: case NS_THEME_STATUSBAR_RESIZER_PANEL: michael@0: colorID = (aIsDisabled) ? eColorID_graytext : eColorID_buttontext; michael@0: break; michael@0: } michael@0: michael@0: if (LookAndFeel::eColorID_LAST_COLOR == colorID) michael@0: return NS_ERROR_FAILURE; michael@0: michael@0: *aResult = NS_RGB(0, 0, 0); michael@0: return nsLookAndFeel::GetInstance()->NativeGetColor(colorID, *aResult); michael@0: } michael@0: michael@0: // static michael@0: nsresult michael@0: LookAndFeel::GetInt(IntID aID, int32_t* aResult) michael@0: { michael@0: return nsLookAndFeel::GetInstance()->GetIntImpl(aID, *aResult); michael@0: } michael@0: michael@0: // static michael@0: nsresult michael@0: LookAndFeel::GetFloat(FloatID aID, float* aResult) michael@0: { michael@0: return nsLookAndFeel::GetInstance()->GetFloatImpl(aID, *aResult); michael@0: } michael@0: michael@0: // static michael@0: bool michael@0: LookAndFeel::GetFont(FontID aID, nsString& aName, gfxFontStyle& aStyle, michael@0: float aDevPixPerCSSPixel) michael@0: { michael@0: return nsLookAndFeel::GetInstance()->GetFontImpl(aID, aName, aStyle, michael@0: aDevPixPerCSSPixel); michael@0: } michael@0: michael@0: // static michael@0: char16_t michael@0: LookAndFeel::GetPasswordCharacter() michael@0: { michael@0: return nsLookAndFeel::GetInstance()->GetPasswordCharacterImpl(); michael@0: } michael@0: michael@0: // static michael@0: bool michael@0: LookAndFeel::GetEchoPassword() michael@0: { michael@0: return nsLookAndFeel::GetInstance()->GetEchoPasswordImpl(); michael@0: } michael@0: michael@0: // static michael@0: uint32_t michael@0: LookAndFeel::GetPasswordMaskDelay() michael@0: { michael@0: return nsLookAndFeel::GetInstance()->GetPasswordMaskDelayImpl(); michael@0: } michael@0: michael@0: // static michael@0: void michael@0: LookAndFeel::Refresh() michael@0: { michael@0: nsLookAndFeel::GetInstance()->RefreshImpl(); michael@0: } michael@0: michael@0: } // namespace mozilla