diff --git a/layout/forms/nsListControlFrame.cpp b/layout/forms/nsListControlFrame.cpp index 75149b118bf6..7a628d12dea1 100644 --- a/layout/forms/nsListControlFrame.cpp +++ b/layout/forms/nsListControlFrame.cpp @@ -216,9 +216,10 @@ void nsListControlFrame::PaintFocus(DrawTarget* aDrawTarget, nsPoint aPt) { } // set up back stop colors and then ask L&F service for the real colors - nscolor color = LookAndFeel::GetColor( + nscolor color = LookAndFeel::Color( lastItemIsSelected ? LookAndFeel::ColorID::WidgetSelectForeground - : LookAndFeel::ColorID::WidgetSelectBackground); + : LookAndFeel::ColorID::WidgetSelectBackground, + this); nsCSSRendering::PaintFocus(presContext, aDrawTarget, fRect, color); } diff --git a/layout/generic/nsContainerFrame.cpp b/layout/generic/nsContainerFrame.cpp index ae755ec9472c..cd7f46e858a6 100644 --- a/layout/generic/nsContainerFrame.cpp +++ b/layout/generic/nsContainerFrame.cpp @@ -443,7 +443,7 @@ DeviceColor nsDisplaySelectionOverlay::ComputeColor() const { } return ApplyTransparencyIfNecessary( - LookAndFeel::GetColor(colorID, NS_RGB(255, 255, 255))); + LookAndFeel::Color(colorID, mFrame, NS_RGB(255, 255, 255))); } void nsDisplaySelectionOverlay::Paint(nsDisplayListBuilder* aBuilder, diff --git a/layout/generic/nsFrameSetFrame.cpp b/layout/generic/nsFrameSetFrame.cpp index ac5cb62b900c..9d25d6537c09 100644 --- a/layout/generic/nsFrameSetFrame.cpp +++ b/layout/generic/nsFrameSetFrame.cpp @@ -1363,17 +1363,17 @@ void nsHTMLFramesetBorderFrame::PaintBorder(DrawTarget* aDrawTarget, if (widthInPixels <= 0) return; - ColorPattern bgColor(ToDeviceColor(LookAndFeel::GetColor( - LookAndFeel::ColorID::WidgetBackground, NS_RGB(200, 200, 200)))); + ColorPattern bgColor(ToDeviceColor(LookAndFeel::Color( + LookAndFeel::ColorID::WidgetBackground, this, NS_RGB(200, 200, 200)))); - ColorPattern fgColor(ToDeviceColor(LookAndFeel::GetColor( - LookAndFeel::ColorID::WidgetForeground, NS_RGB(0, 0, 0)))); + ColorPattern fgColor(ToDeviceColor(LookAndFeel::Color( + LookAndFeel::ColorID::WidgetForeground, this, NS_RGB(0, 0, 0)))); - ColorPattern hltColor(ToDeviceColor(LookAndFeel::GetColor( - LookAndFeel::ColorID::Widget3DHighlight, NS_RGB(255, 255, 255)))); + ColorPattern hltColor(ToDeviceColor(LookAndFeel::Color( + LookAndFeel::ColorID::Widget3DHighlight, this, NS_RGB(255, 255, 255)))); - ColorPattern sdwColor(ToDeviceColor(LookAndFeel::GetColor( - LookAndFeel::ColorID::Widget3DShadow, NS_RGB(128, 128, 128)))); + ColorPattern sdwColor(ToDeviceColor(LookAndFeel::Color( + LookAndFeel::ColorID::Widget3DShadow, this, NS_RGB(128, 128, 128)))); ColorPattern color(ToDeviceColor(NS_RGB(255, 255, 255))); // default to white if (mVisibility) { diff --git a/layout/generic/nsTextFrame.cpp b/layout/generic/nsTextFrame.cpp index f83bc59be941..da3e430d6cf4 100644 --- a/layout/generic/nsTextFrame.cpp +++ b/layout/generic/nsTextFrame.cpp @@ -357,7 +357,7 @@ class nsTextPaintStyle { float* aRelativeSize, uint8_t* aStyle); // if this returns false, we don't need to draw underline. - static bool GetSelectionUnderline(nsPresContext* aPresContext, int32_t aIndex, + static bool GetSelectionUnderline(nsIFrame*, int32_t aIndex, nscolor* aLineColor, float* aRelativeSize, uint8_t* aStyle); @@ -3899,14 +3899,13 @@ void nsTextPaintStyle::GetHighlightColors(nscolor* aForeColor, } if (!customColors) { - nscolor backColor = - LookAndFeel::GetColor(LookAndFeel::ColorID::TextHighlightBackground); - nscolor foreColor = - LookAndFeel::GetColor(LookAndFeel::ColorID::TextHighlightForeground); + nscolor backColor = LookAndFeel::Color( + LookAndFeel::ColorID::TextHighlightBackground, mFrame); + nscolor foreColor = LookAndFeel::Color( + LookAndFeel::ColorID::TextHighlightForeground, mFrame); EnsureSufficientContrast(&foreColor, &backColor); *aForeColor = foreColor; *aBackColor = backColor; - return; } @@ -4034,9 +4033,9 @@ void nsTextPaintStyle::InitCommonColors() { mFrameBackgroundColor = NS_ComposeColors(defaultBgColor, bgColor); mSystemFieldForegroundColor = - LookAndFeel::GetColor(LookAndFeel::ColorID::Fieldtext); + LookAndFeel::Color(LookAndFeel::ColorID::Fieldtext, mFrame); mSystemFieldBackgroundColor = - LookAndFeel::GetColor(LookAndFeel::ColorID::Field); + LookAndFeel::Color(LookAndFeel::ColorID::Field, mFrame); if (bgFrame->IsThemed()) { // Assume a native widget has sufficient contrast always @@ -4049,11 +4048,11 @@ void nsTextPaintStyle::InitCommonColors() { "default background color is not opaque"); nscolor defaultWindowBackgroundColor = - LookAndFeel::GetColor(LookAndFeel::ColorID::WindowBackground); + LookAndFeel::Color(LookAndFeel::ColorID::WindowBackground, mFrame); nscolor selectionTextColor = - LookAndFeel::GetColor(LookAndFeel::ColorID::TextSelectForeground); + LookAndFeel::Color(LookAndFeel::ColorID::TextSelectForeground, mFrame); nscolor selectionBGColor = - LookAndFeel::GetColor(LookAndFeel::ColorID::TextSelectBackground); + LookAndFeel::Color(LookAndFeel::ColorID::TextSelectBackground, mFrame); mSufficientContrast = std::min( std::min(NS_SUFFICIENT_LUMINOSITY_DIFFERENCE, @@ -4101,12 +4100,12 @@ bool nsTextPaintStyle::InitSelectionColorsAndShadow() { } nscolor selectionBGColor = - LookAndFeel::GetColor(LookAndFeel::ColorID::TextSelectBackground); + LookAndFeel::Color(LookAndFeel::ColorID::TextSelectBackground, mFrame); switch (selectionStatus) { case nsISelectionController::SELECTION_ATTENTION: { - mSelectionBGColor = LookAndFeel::GetColor( - LookAndFeel::ColorID::TextSelectBackgroundAttention); + mSelectionBGColor = LookAndFeel::Color( + LookAndFeel::ColorID::TextSelectBackgroundAttention, mFrame); mSelectionBGColor = EnsureDifferentColors(mSelectionBGColor, selectionBGColor); break; @@ -4116,8 +4115,8 @@ bool nsTextPaintStyle::InitSelectionColorsAndShadow() { break; } default: { - mSelectionBGColor = LookAndFeel::GetColor( - LookAndFeel::ColorID::TextSelectBackgroundDisabled); + mSelectionBGColor = LookAndFeel::Color( + LookAndFeel::ColorID::TextSelectBackgroundDisabled, mFrame); mSelectionBGColor = EnsureDifferentColors(mSelectionBGColor, selectionBGColor); break; @@ -4125,7 +4124,7 @@ bool nsTextPaintStyle::InitSelectionColorsAndShadow() { } mSelectionTextColor = - LookAndFeel::GetColor(LookAndFeel::ColorID::TextSelectForeground); + LookAndFeel::Color(LookAndFeel::ColorID::TextSelectForeground, mFrame); if (mResolveColors) { // On MacOS X, only the background color gets set, @@ -4145,8 +4144,8 @@ bool nsTextPaintStyle::InitSelectionColorsAndShadow() { : mFrame->GetVisitedDependentColor( &nsStyleText::mWebkitTextFillColor); if (frameColor == mSelectionBGColor) { - mSelectionTextColor = LookAndFeel::GetColor( - LookAndFeel::ColorID::TextSelectForegroundCustom); + mSelectionTextColor = LookAndFeel::Color( + LookAndFeel::ColorID::TextSelectForegroundCustom, mFrame); } } else { EnsureSufficientContrast(&mSelectionTextColor, &mSelectionBGColor); @@ -4207,12 +4206,12 @@ void nsTextPaintStyle::InitSelectionStyle(int32_t aIndex) { if (styleIDs->mForeground == LookAndFeel::ColorID::End) { foreColor = NS_SAME_AS_FOREGROUND_COLOR; } else { - foreColor = LookAndFeel::GetColor(styleIDs->mForeground); + foreColor = LookAndFeel::Color(styleIDs->mForeground, mFrame); } if (styleIDs->mBackground == LookAndFeel::ColorID::End) { backColor = NS_TRANSPARENT; } else { - backColor = LookAndFeel::GetColor(styleIDs->mBackground); + backColor = LookAndFeel::Color(styleIDs->mBackground, mFrame); } // Convert special color to actual color @@ -4233,8 +4232,7 @@ void nsTextPaintStyle::InitSelectionStyle(int32_t aIndex) { nscolor lineColor; float relativeSize; uint8_t lineStyle; - GetSelectionUnderline(mPresContext, aIndex, &lineColor, &relativeSize, - &lineStyle); + GetSelectionUnderline(mFrame, aIndex, &lineColor, &relativeSize, &lineStyle); if (mResolveColors) lineColor = GetResolvedForeColor(lineColor, foreColor, backColor); @@ -4248,19 +4246,18 @@ void nsTextPaintStyle::InitSelectionStyle(int32_t aIndex) { } /* static */ -bool nsTextPaintStyle::GetSelectionUnderline(nsPresContext* aPresContext, - int32_t aIndex, +bool nsTextPaintStyle::GetSelectionUnderline(nsIFrame* aFrame, int32_t aIndex, nscolor* aLineColor, float* aRelativeSize, uint8_t* aStyle) { - NS_ASSERTION(aPresContext, "aPresContext is null"); + NS_ASSERTION(aFrame, "aFrame is null"); NS_ASSERTION(aRelativeSize, "aRelativeSize is null"); NS_ASSERTION(aStyle, "aStyle is null"); NS_ASSERTION(aIndex >= 0 && aIndex < 5, "Index out of range"); StyleIDs& styleID = SelectionStyleIDs[aIndex]; - nscolor color = LookAndFeel::GetColor(styleID.mLine); + nscolor color = LookAndFeel::Color(styleID.mLine, aFrame); int32_t style = LookAndFeel::GetInt(styleID.mLineStyle); if (style > NS_STYLE_TEXT_DECORATION_STYLE_MAX) { NS_ERROR("Invalid underline style value is specified"); @@ -7375,7 +7372,7 @@ bool nsTextFrame::CombineSelectionUnderlineRect(nsPresContext* aPresContext, sd->mSelectionType); if (sd->mSelectionType == SelectionType::eSpellCheck) { if (!nsTextPaintStyle::GetSelectionUnderline( - aPresContext, index, nullptr, &relativeSize, ¶ms.style)) { + this, index, nullptr, &relativeSize, ¶ms.style)) { continue; } } else { @@ -7389,8 +7386,7 @@ bool nsTextFrame::CombineSelectionUnderlineRect(nsPresContext* aPresContext, params.style = ToStyleLineStyle(rangeStyle); relativeSize = rangeStyle.mIsBoldLine ? 2.0f : 1.0f; } else if (!nsTextPaintStyle::GetSelectionUnderline( - aPresContext, index, nullptr, &relativeSize, - ¶ms.style)) { + this, index, nullptr, &relativeSize, ¶ms.style)) { continue; } } diff --git a/layout/mathml/nsMathMLChar.cpp b/layout/mathml/nsMathMLChar.cpp index fa3362a7be70..a4acb442c7f0 100644 --- a/layout/mathml/nsMathMLChar.cpp +++ b/layout/mathml/nsMathMLChar.cpp @@ -1713,8 +1713,8 @@ void nsDisplayMathMLSelectionRect::Paint(nsDisplayListBuilder* aBuilder, mFrame->PresContext()->AppUnitsPerDevPixel(), *drawTarget); // get color to use for selection from the look&feel object - nscolor bgColor = LookAndFeel::GetColor( - LookAndFeel::ColorID::TextSelectBackground, NS_RGB(0, 0, 0)); + nscolor bgColor = + LookAndFeel::Color(LookAndFeel::ColorID::TextSelectBackground, mFrame); drawTarget->FillRect(rect, ColorPattern(ToDeviceColor(bgColor))); } @@ -1869,8 +1869,8 @@ void nsMathMLChar::PaintForeground(nsIFrame* aForFrame, &nsStyleText::mWebkitTextFillColor); if (aIsSelected) { // get color to use for selection from the look&feel object - fgColor = LookAndFeel::GetColor(LookAndFeel::ColorID::TextSelectForeground, - fgColor); + fgColor = LookAndFeel::Color(LookAndFeel::ColorID::TextSelectForeground, + aForFrame, fgColor); } aRenderingContext.SetColor(sRGBColor::FromABGR(fgColor)); aRenderingContext.Save(); diff --git a/layout/style/GeckoBindings.cpp b/layout/style/GeckoBindings.cpp index 7c92f2f3f2ce..a166d245fe85 100644 --- a/layout/style/GeckoBindings.cpp +++ b/layout/style/GeckoBindings.cpp @@ -693,52 +693,10 @@ bool Gecko_IsDocumentBody(const Element* aElement) { return doc && doc->GetBodyElement() == aElement; } -static bool ShouldUseStandinsForNativeColorForNonNativeTheme( - const Document& aDoc, LookAndFeel::ColorID aColor) { - using ColorID = LookAndFeel::ColorID; - if (!aDoc.ShouldAvoidNativeTheme()) { - return false; - } - - // The native theme doesn't use system colors backgrounds etc, except when in - // high-contrast mode, so spoof some of the colors with stand-ins to prevent - // lack of contrast. - switch (aColor) { - case ColorID::Buttonface: - case ColorID::Buttontext: - case ColorID::MozButtonhoverface: - case ColorID::MozButtonhovertext: - case ColorID::MozGtkButtonactivetext: - - case ColorID::MozCombobox: - case ColorID::MozComboboxtext: - - case ColorID::Field: - case ColorID::Fieldtext: - - case ColorID::Graytext: - - return !PreferenceSheet::PrefsFor(aDoc) - .NonNativeThemeShouldUseSystemColors(); - - default: - break; - } - - return false; -} - nscolor Gecko_GetLookAndFeelSystemColor(int32_t aId, const Document* aDoc) { auto colorId = static_cast(aId); - const bool useStandinsForNativeColors = - ShouldUseStandinsForNativeColorForNonNativeTheme(*aDoc, colorId) || - (nsContentUtils::UseStandinsForNativeColors() && - !nsContentUtils::IsChromeDoc(aDoc)); - AutoWriteLock guard(*sServoFFILock); - nscolor result = 0; - LookAndFeel::GetColor(colorId, useStandinsForNativeColors, &result); - return result; + return LookAndFeel::Color(colorId, *aDoc); } bool Gecko_MatchLang(const Element* aElement, nsAtom* aOverrideLang, diff --git a/layout/style/PreferenceSheet.cpp b/layout/style/PreferenceSheet.cpp index c525f6c9208a..e70f6e0c755f 100644 --- a/layout/style/PreferenceSheet.cpp +++ b/layout/style/PreferenceSheet.cpp @@ -14,6 +14,7 @@ #include "mozilla/StaticPrefs_devtools.h" #include "mozilla/Telemetry.h" #include "mozilla/LookAndFeel.h" +#include "mozilla/ServoBindings.h" #include "mozilla/dom/Document.h" #include "nsContentUtils.h" @@ -88,30 +89,28 @@ void PreferenceSheet::Prefs::Load(bool aIsChrome) { mFocusRingStyle = StaticPrefs::browser_display_focus_ring_style(); mFocusRingOnAnything = StaticPrefs::browser_display_focus_ring_on_anything(); - const bool usePrefColors = !aIsChrome && !mUseAccessibilityTheme && + const bool useStandins = nsContentUtils::UseStandinsForNativeColors(); + const bool usePrefColors = !useStandins && !aIsChrome && !mUseAccessibilityTheme && !StaticPrefs::browser_display_use_system_colors(); - - if (nsContentUtils::UseStandinsForNativeColors()) { - mDefaultColor = LookAndFeel::GetColorUsingStandins( - LookAndFeel::ColorID::Windowtext, mDefaultColor); - mDefaultBackgroundColor = LookAndFeel::GetColorUsingStandins( - LookAndFeel::ColorID::Window, mDefaultBackgroundColor); - mLinkColor = LookAndFeel::GetColorUsingStandins( - LookAndFeel::ColorID::MozNativehyperlinktext, mLinkColor); - } else if (usePrefColors) { + if (usePrefColors) { GetColor("browser.display.background_color", mDefaultBackgroundColor); GetColor("browser.display.foreground_color", mDefaultColor); GetColor("browser.anchor_color", mLinkColor); } else { - mDefaultColor = LookAndFeel::GetColor( - LookAndFeel::ColorID::WindowForeground, mDefaultColor); - mDefaultBackgroundColor = LookAndFeel::GetColor( - LookAndFeel::ColorID::WindowBackground, mDefaultBackgroundColor); - mLinkColor = LookAndFeel::GetColor( - LookAndFeel::ColorID::MozNativehyperlinktext, mLinkColor); + using ColorID = LookAndFeel::ColorID; + const auto standins = LookAndFeel::UseStandins(useStandins); + // TODO(emilio): In the future we probably want to keep both sets of colors + // around or something. + const auto scheme = LookAndFeel::ColorScheme::Light; + mDefaultColor = LookAndFeel::Color( + ColorID::WindowForeground, scheme, standins, mDefaultColor); + mDefaultBackgroundColor = LookAndFeel::Color( + ColorID::WindowBackground, scheme, standins, mDefaultBackgroundColor); + mLinkColor = LookAndFeel::Color( + ColorID::MozNativehyperlinktext, scheme, standins, mLinkColor); } - if (mUseAccessibilityTheme && !nsContentUtils::UseStandinsForNativeColors()) { + if (mUseAccessibilityTheme && !useStandins) { mActiveLinkColor = mLinkColor; // Visited link color is produced by preserving the foreground's green // and averaging the foreground and background for the red and blue. diff --git a/layout/tables/nsTableCellFrame.cpp b/layout/tables/nsTableCellFrame.cpp index fb2709efee92..6c7423b3cc95 100644 --- a/layout/tables/nsTableCellFrame.cpp +++ b/layout/tables/nsTableCellFrame.cpp @@ -294,8 +294,8 @@ void nsTableCellFrame::DecorateForSelection(DrawTarget* aDrawTarget, if (displaySelection == nsISelectionController::SELECTION_DISABLED) { bordercolor = NS_RGB(176, 176, 176); // disabled color } else { - bordercolor = - LookAndFeel::GetColor(LookAndFeel::ColorID::TextSelectBackground); + bordercolor = LookAndFeel::Color( + LookAndFeel::ColorID::TextSelectBackground, this); } nscoord threePx = nsPresContext::CSSPixelsToAppUnits(3); if ((mRect.width > threePx) && (mRect.height > threePx)) { diff --git a/layout/xul/nsSliderFrame.cpp b/layout/xul/nsSliderFrame.cpp index 0b8404b88ec5..40e8dda58470 100644 --- a/layout/xul/nsSliderFrame.cpp +++ b/layout/xul/nsSliderFrame.cpp @@ -55,7 +55,6 @@ using namespace mozilla; using namespace mozilla::gfx; using mozilla::dom::Document; using mozilla::dom::Event; -using mozilla::layers::APZCCallbackHelper; using mozilla::layers::AsyncDragMetrics; using mozilla::layers::InputAPZContext; using mozilla::layers::ScrollbarData; @@ -293,7 +292,7 @@ void nsDisplaySliderMarks::PaintMarks(nsDisplayListBuilder* aDisplayListBuilder, // Use the text highlight color for the tick marks. nscolor highlightColor = - LookAndFeel::GetColor(LookAndFeel::ColorID::TextHighlightBackground); + LookAndFeel::Color(LookAndFeel::ColorID::TextHighlightBackground, mFrame); DeviceColor fillColor = ToDeviceColor(highlightColor); fillColor.a = 0.3; // make the mark mostly transparent diff --git a/toolkit/components/browser/nsWebBrowser.cpp b/toolkit/components/browser/nsWebBrowser.cpp index b1419661aad7..35afa919eac0 100644 --- a/toolkit/components/browser/nsWebBrowser.cpp +++ b/toolkit/components/browser/nsWebBrowser.cpp @@ -128,8 +128,11 @@ already_AddRefed nsWebBrowser::Create( MOZ_ASSERT(browser->mDocShell == docShell); // get the system default window background colour - LookAndFeel::GetColor(LookAndFeel::ColorID::WindowBackground, - &browser->mBackgroundColor); + // + // TODO(emilio): Can we get the color-scheme from somewhere here? + browser->mBackgroundColor = LookAndFeel::Color( + LookAndFeel::ColorID::WindowBackground, LookAndFeel::ColorScheme::Light, + LookAndFeel::UseStandins::No); // HACK ALERT - this registration registers the nsDocShellTreeOwner as a // nsIWebBrowserListener so it can setup its MouseListener in one of the diff --git a/widget/LookAndFeel.h b/widget/LookAndFeel.h index 8ca6c67df75d..c9231926842a 100644 --- a/widget/LookAndFeel.h +++ b/widget/LookAndFeel.h @@ -14,12 +14,19 @@ #include "nsColor.h" #include "nsString.h" #include "nsTArray.h" +#include "mozilla/Maybe.h" #include "mozilla/widget/ThemeChangeKind.h" struct gfxFontStyle; +class nsIFrame; + namespace mozilla { +namespace dom { +class Document; +} + namespace widget { class FullLookAndFeel; } // namespace widget @@ -422,31 +429,55 @@ class LookAndFeel { using FontID = mozilla::StyleSystemFont; - /** - * GetColor() return a native color value (might be overwritten by prefs) for - * aID. Some platforms don't return an error even if the index doesn't - * match any system colors. And also some platforms may initialize the - * return value even when it returns an error. Therefore, if you want to - * use a color for the default value, you should use the other GetColor() - * which returns nscolor directly. - * - * NOTE: - * ColorID::TextSelectForeground might return NS_DONT_CHANGE_COLOR. - * ColorID::IME* might return NS_TRANSPARENT, NS_SAME_AS_FOREGROUND_COLOR or - * NS_40PERCENT_FOREGROUND_COLOR. - * These values have particular meaning. Then, they are not an actual - * color value. - */ - static nsresult GetColor(ColorID aID, nscolor* aResult); + // Whether we should use a light or dark appearance. + // + // This is currently ignored (but won't be for long). + enum class ColorScheme : uint8_t { Light, Dark }; - /** - * This variant of GetColor() takes an extra Boolean parameter that allows - * the caller to ask that hard-coded color values be substituted for - * native colors (used when it is desireable to hide system colors to - * avoid system fingerprinting). - */ - static nsresult GetColor(ColorID aID, bool aUseStandinsForNativeColors, - nscolor* aResult); + // Whether standins for native colors should be used (that is, colors faked, + // taken from win7, mostly). This forces light appearance, effectively. + enum class UseStandins : bool { No, Yes }; + + // Returns a native color value (might be overwritten by prefs) for a given + // color id. + // + // NOTE: + // ColorID::TextSelectForeground might return NS_DONT_CHANGE_COLOR. + // ColorID::IME* might return NS_TRANSPARENT, NS_SAME_AS_FOREGROUND_COLOR or + // NS_40PERCENT_FOREGROUND_COLOR. + // These values have particular meaning. Then, they are not an actual + // color value. + static Maybe GetColor(ColorID, ColorScheme, UseStandins); + + // Gets the color with appropriate defaults for UseStandins, ColorScheme etc + // for a given document. + static Maybe GetColor(ColorID, const dom::Document&); + + // Gets the color with appropriate defaults for UseStandins, ColorScheme etc + // for a given frame. + // + // TODO(emilio): This right now just peeks the document out of the frame's + // pres context, but in the future we actually want to look at the style to + // get the right color scheme, to implement the color-scheme property. + static Maybe GetColor(ColorID, const nsIFrame*); + + // Versions of the above which returns the color if found, or a default (which + // defaults to opaque black) otherwise. + static nscolor Color(ColorID aId, ColorScheme aScheme, + UseStandins aUseStandins, + nscolor aDefault = NS_RGB(0, 0, 0)) { + return GetColor(aId, aScheme, aUseStandins).valueOr(aDefault); + } + + static nscolor Color(ColorID aId, const dom::Document& aDoc, + nscolor aDefault = NS_RGB(0, 0, 0)) { + return GetColor(aId, aDoc).valueOr(aDefault); + } + + static nscolor Color(ColorID aId, nsIFrame* aFrame, + nscolor aDefault = NS_RGB(0, 0, 0)) { + return GetColor(aId, aFrame).valueOr(aDefault); + } /** * GetInt() and GetFloat() return a int or float value for aID. The result @@ -456,28 +487,9 @@ class LookAndFeel { * use a value for the default value, you should use the other method which * returns int or float directly. */ - static nsresult GetInt(IntID aID, int32_t* aResult); + static nsresult GetInt(IntID, int32_t* aResult); static nsresult GetFloat(FloatID aID, float* aResult); - static nscolor GetColor(ColorID aID, nscolor aDefault = NS_RGB(0, 0, 0)) { - nscolor result = NS_RGB(0, 0, 0); - if (NS_FAILED(GetColor(aID, &result))) { - return aDefault; - } - return result; - } - - static nscolor GetColorUsingStandins(ColorID aID, - nscolor aDefault = NS_RGB(0, 0, 0)) { - nscolor result = NS_RGB(0, 0, 0); - if (NS_FAILED(GetColor(aID, - true, // aUseStandinsForNativeColors - &result))) { - return aDefault; - } - return result; - } - static int32_t GetInt(IntID aID, int32_t aDefault = 0) { int32_t result; if (NS_FAILED(GetInt(aID, &result))) { diff --git a/widget/cocoa/nsLookAndFeel.h b/widget/cocoa/nsLookAndFeel.h index cdf3bf7a2d70..a32eb9e83f1b 100644 --- a/widget/cocoa/nsLookAndFeel.h +++ b/widget/cocoa/nsLookAndFeel.h @@ -33,7 +33,6 @@ class nsLookAndFeel final : public nsXPLookAndFeel { nscolor mColorTextSelectBackground; nscolor mColorTextSelectBackgroundDisabled; nscolor mColorHighlight; - nscolor mColorTextSelectForeground; nscolor mColorAlternateSelectedControlText; nscolor mColorControlText; nscolor mColorText; diff --git a/widget/cocoa/nsLookAndFeel.mm b/widget/cocoa/nsLookAndFeel.mm index fde80b9acbb6..a6f619532476 100644 --- a/widget/cocoa/nsLookAndFeel.mm +++ b/widget/cocoa/nsLookAndFeel.mm @@ -30,7 +30,6 @@ nsLookAndFeel::nsLookAndFeel() mColorTextSelectBackground(0), mColorTextSelectBackgroundDisabled(0), mColorHighlight(0), - mColorTextSelectForeground(0), mColorAlternateSelectedControlText(0), mColorControlText(0), mColorText(0), @@ -167,7 +166,7 @@ nsresult nsLookAndFeel::NativeGetColor(ColorID aID, nscolor& aColor) { aColor = mColorHighlight; break; case ColorID::TextSelectForeground: - aColor = mColorTextSelectForeground; + aColor = NS_DONT_CHANGE_COLOR; break; case ColorID::Highlighttext: // CSS2 color case ColorID::MozAccentColorForeground: @@ -602,8 +601,6 @@ void nsLookAndFeel::EnsureInit() { NS_OBJC_BEGIN_TRY_IGNORE_BLOCK - nscolor color; - bool appearanceIsDark = false; if (@available(macOS 10.14, *)) { @@ -627,13 +624,6 @@ void nsLookAndFeel::EnsureInit() { mColorHighlight = GetColorFromNSColor([NSColor alternateSelectedControlColor]); - GetColor(ColorID::TextSelectBackground, color); - if (color == 0x000000) { - mColorTextSelectForeground = NS_RGB(0xff, 0xff, 0xff); - } else { - mColorTextSelectForeground = NS_DONT_CHANGE_COLOR; - } - mColorAlternateSelectedControlText = GetColorFromNSColor([NSColor alternateSelectedControlTextColor]); diff --git a/widget/gtk/IMContextWrapper.cpp b/widget/gtk/IMContextWrapper.cpp index 8600efb4c35b..6078b4e8816d 100644 --- a/widget/gtk/IMContextWrapper.cpp +++ b/widget/gtk/IMContextWrapper.cpp @@ -211,6 +211,11 @@ const static bool kUseSimpleContextDefault = false; * to refer selection colors of GtkTextView via our widget. ******************************************************************************/ +static Maybe GetSystemColor(LookAndFeel::ColorID aId) { + return LookAndFeel::GetColor(aId, LookAndFeel::ColorScheme::Light, + LookAndFeel::UseStandins::No); +} + class SelectionStyleProvider final { public: static SelectionStyleProvider* GetInstance() { @@ -254,31 +259,27 @@ class SelectionStyleProvider final { // colors can be controlled by a ":selected" CSS rule. nsAutoCString style(":selected{"); // FYI: LookAndFeel always returns selection colors of GtkTextView. - nscolor selectionForegroundColor; - if (NS_SUCCEEDED( - LookAndFeel::GetColor(LookAndFeel::ColorID::TextSelectForeground, - &selectionForegroundColor))) { + if (auto selectionForegroundColor = + GetSystemColor(LookAndFeel::ColorID::TextSelectForeground)) { double alpha = - static_cast(NS_GET_A(selectionForegroundColor)) / 0xFF; + static_cast(NS_GET_A(*selectionForegroundColor)) / 0xFF; style.AppendPrintf("color:rgba(%u,%u,%u,", - NS_GET_R(selectionForegroundColor), - NS_GET_G(selectionForegroundColor), - NS_GET_B(selectionForegroundColor)); + NS_GET_R(*selectionForegroundColor), + NS_GET_G(*selectionForegroundColor), + NS_GET_B(*selectionForegroundColor)); // We can't use AppendPrintf here, because it does locale-specific // formatting of floating-point values. style.AppendFloat(alpha); style.AppendPrintf(");"); } - nscolor selectionBackgroundColor; - if (NS_SUCCEEDED( - LookAndFeel::GetColor(LookAndFeel::ColorID::TextSelectBackground, - &selectionBackgroundColor))) { + if (auto selectionBackgroundColor = + GetSystemColor(LookAndFeel::ColorID::TextSelectBackground)) { double alpha = - static_cast(NS_GET_A(selectionBackgroundColor)) / 0xFF; + static_cast(NS_GET_A(*selectionBackgroundColor)) / 0xFF; style.AppendPrintf("background-color:rgba(%u,%u,%u,", - NS_GET_R(selectionBackgroundColor), - NS_GET_G(selectionBackgroundColor), - NS_GET_B(selectionBackgroundColor)); + NS_GET_R(*selectionBackgroundColor), + NS_GET_G(*selectionBackgroundColor), + NS_GET_B(*selectionBackgroundColor)); style.AppendFloat(alpha); style.AppendPrintf(");"); } diff --git a/widget/gtk/nsNativeThemeGTK.cpp b/widget/gtk/nsNativeThemeGTK.cpp index aeabc5c63b80..9761cde36326 100644 --- a/widget/gtk/nsNativeThemeGTK.cpp +++ b/widget/gtk/nsNativeThemeGTK.cpp @@ -1223,10 +1223,11 @@ bool nsNativeThemeGTK::CreateWebRenderCommandsForWidget( switch (aAppearance) { case StyleAppearance::Window: case StyleAppearance::Dialog: - aBuilder.PushRect( - bounds, bounds, true, - wr::ToColorF(ToDeviceColor(LookAndFeel::GetColor( - LookAndFeel::ColorID::WindowBackground, NS_RGBA(0, 0, 0, 0))))); + aBuilder.PushRect(bounds, bounds, true, + wr::ToColorF(ToDeviceColor(LookAndFeel::Color( + LookAndFeel::ColorID::WindowBackground, + LookAndFeel::ColorScheme::Light, + LookAndFeel::UseStandins::No, NS_TRANSPARENT)))); return true; default: diff --git a/widget/headless/HeadlessLookAndFeelGTK.cpp b/widget/headless/HeadlessLookAndFeelGTK.cpp index 1ea92b18d0d0..d191913a3ce0 100644 --- a/widget/headless/HeadlessLookAndFeelGTK.cpp +++ b/widget/headless/HeadlessLookAndFeelGTK.cpp @@ -85,11 +85,7 @@ nsresult HeadlessLookAndFeel::NativeGetColor(ColorID aID, nscolor& aColor) { aColor = NS_RGB(0xaa, 0xaa, 0xaa); break; case ColorID::TextSelectForeground: - GetColor(ColorID::TextSelectBackground, aColor); - if (aColor == 0x000000) - aColor = NS_RGB(0xff, 0xff, 0xff); - else - aColor = NS_DONT_CHANGE_COLOR; + aColor = NS_DONT_CHANGE_COLOR; break; case ColorID::Widget3DHighlight: aColor = NS_RGB(0xa0, 0xa0, 0xa0); diff --git a/widget/nsNativeBasicTheme.cpp b/widget/nsNativeBasicTheme.cpp index ea65c8a2fa38..5d7f70035cad 100644 --- a/widget/nsNativeBasicTheme.cpp +++ b/widget/nsNativeBasicTheme.cpp @@ -72,9 +72,12 @@ static LayoutDeviceIntCoord SnapBorderWidth( static nscolor ThemedAccentColor(bool aBackground) { MOZ_ASSERT(StaticPrefs::widget_non_native_theme_use_theme_accent()); - nscolor color = LookAndFeel::GetColor( + // TODO(emilio): In the future we should probably add dark-color-scheme + // support for non-native form controls. + nscolor color = LookAndFeel::Color( aBackground ? LookAndFeel::ColorID::MozAccentColor - : LookAndFeel::ColorID::MozAccentColorForeground); + : LookAndFeel::ColorID::MozAccentColorForeground, + LookAndFeel::ColorScheme::Light, LookAndFeel::UseStandins::No); if (NS_GET_A(color) != 0xff) { // Blend with white, ensuring the color is opaque to avoid surprises if we // overdraw. @@ -196,7 +199,20 @@ static bool IsScrollbarWidthThin(nsIFrame* aFrame) { } static sRGBColor SystemColor(StyleSystemColor aColor) { - return sRGBColor::FromABGR(LookAndFeel::GetColor(aColor)); + // TODO(emilio): We could not hardcode light appearance here with a bit of + // work, but doesn't matter for now. + return sRGBColor::FromABGR(LookAndFeel::Color( + aColor, LookAndFeel::ColorScheme::Light, LookAndFeel::UseStandins::No)); +} + +template +static sRGBColor SystemColorOrElse(StyleSystemColor aColor, Compute aCompute) { + if (auto color = + LookAndFeel::GetColor(aColor, LookAndFeel::ColorScheme::Light, + LookAndFeel::UseStandins::No)) { + return sRGBColor::FromABGR(*color); + } + return aCompute(); } static std::pair SystemColorPair( @@ -539,17 +555,16 @@ sRGBColor nsNativeBasicTheme::ComputeScrollbarColor( if (ShouldUseDarkScrollbar(aFrame, aStyle)) { return sRGBColor::FromU8(20, 20, 25, 77); } - nscolor color; if (ui->mScrollbarColor.IsColors()) { - color = ui->mScrollbarColor.AsColors().track.CalcColor(aStyle); - } else if (aDocumentState.HasAllStates(NS_DOCUMENT_STATE_WINDOW_INACTIVE)) { - color = LookAndFeel::GetColor(LookAndFeel::ColorID::ThemedScrollbarInactive, - sScrollbarColor.ToABGR()); - } else { - color = LookAndFeel::GetColor(LookAndFeel::ColorID::ThemedScrollbar, - sScrollbarColor.ToABGR()); + return sRGBColor::FromABGR( + ui->mScrollbarColor.AsColors().track.CalcColor(aStyle)); } - return gfx::sRGBColor::FromABGR(color); + if (aDocumentState.HasAllStates(NS_DOCUMENT_STATE_WINDOW_INACTIVE)) { + return SystemColorOrElse(StyleSystemColor::ThemedScrollbarInactive, + [] { return sScrollbarColor; }); + } + return SystemColorOrElse(StyleSystemColor::ThemedScrollbar, + [] { return sScrollbarColor; }); } nscolor nsNativeBasicTheme::AdjustUnthemedScrollbarThumbColor( @@ -668,7 +683,6 @@ sRGBColor nsNativeBasicTheme::ComputeScrollbarThumbColor( } const nsStyleUI* ui = aStyle.StyleUI(); - nscolor color; if (ui->mScrollbarColor.IsColors()) { return sRGBColor::FromABGR(AdjustUnthemedScrollbarThumbColor( ui->mScrollbarColor.AsColors().thumb.CalcColor(aStyle), aElementState)); @@ -696,11 +710,10 @@ sRGBColor nsNativeBasicTheme::ComputeScrollbarThumbColor( return StyleSystemColor::ThemedScrollbarThumb; }(); - if (NS_FAILED(LookAndFeel::GetColor(systemColor, &color))) { - color = AdjustUnthemedScrollbarThumbColor(sScrollbarThumbColor.ToABGR(), - aElementState); - } - return gfx::sRGBColor::FromABGR(color); + return SystemColorOrElse(systemColor, [&] { + return sRGBColor::FromABGR(AdjustUnthemedScrollbarThumbColor( + sScrollbarThumbColor.ToABGR(), aElementState)); + }); } std::pair diff --git a/widget/nsXPLookAndFeel.cpp b/widget/nsXPLookAndFeel.cpp index 961596c8fe89..667d2023ac9b 100644 --- a/widget/nsXPLookAndFeel.cpp +++ b/widget/nsXPLookAndFeel.cpp @@ -14,6 +14,7 @@ #include "nsContentUtils.h" #include "nsCRT.h" #include "nsFont.h" +#include "nsIFrame.h" #include "nsIXULRuntime.h" #include "nsNativeBasicTheme.h" #include "mozilla/dom/ContentChild.h" @@ -24,6 +25,8 @@ #include "mozilla/StaticPrefs_findbar.h" #include "mozilla/StaticPrefs_ui.h" #include "mozilla/StaticPrefs_widget.h" +#include "mozilla/dom/Document.h" +#include "mozilla/PreferenceSheet.h" #include "mozilla/gfx/2D.h" #include "mozilla/widget/WidgetMessageUtils.h" #include "mozilla/Telemetry.h" @@ -62,7 +65,7 @@ struct nsLookAndFeelFloatPref { template class EnumeratedCache { static constexpr uint32_t ChunkFor(Index aIndex) { - return uint32_t(aIndex) >> 5; // >> 5 is the same as / 32. + return uint32_t(aIndex) >> 5; // >> 5 is the same as / 32. } static constexpr uint32_t BitFor(Index aIndex) { return 1u << (uint32_t(aIndex) & 31); @@ -1047,15 +1050,69 @@ void LookAndFeel::NotifyChangedAllWindows(widget::ThemeChangeKind aKind) { } } -// static -nsresult LookAndFeel::GetColor(ColorID aID, nscolor* aResult) { - return nsLookAndFeel::GetInstance()->GetColorValue(aID, false, *aResult); +static bool ShouldUseStandinsForNativeColorForNonNativeTheme( + const dom::Document& aDoc, LookAndFeel::ColorID aColor) { + using ColorID = LookAndFeel::ColorID; + if (!aDoc.ShouldAvoidNativeTheme()) { + return false; + } + + // The native theme doesn't use system colors backgrounds etc, except when in + // high-contrast mode, so spoof some of the colors with stand-ins to prevent + // lack of contrast. + switch (aColor) { + case ColorID::Buttonface: + case ColorID::Buttontext: + case ColorID::MozButtonhoverface: + case ColorID::MozButtonhovertext: + case ColorID::MozGtkButtonactivetext: + + case ColorID::MozCombobox: + case ColorID::MozComboboxtext: + + case ColorID::Field: + case ColorID::Fieldtext: + + case ColorID::Graytext: + + return !PreferenceSheet::PrefsFor(aDoc) + .NonNativeThemeShouldUseSystemColors(); + + default: + break; + } + + return false; } -nsresult LookAndFeel::GetColor(ColorID aID, bool aUseStandinsForNativeColors, - nscolor* aResult) { - return nsLookAndFeel::GetInstance()->GetColorValue( - aID, aUseStandinsForNativeColors, *aResult); +static LookAndFeel::ColorScheme ColorSchemeForDocument(const dom::Document&) { + // TODO(emilio): Actually compute a useful color scheme. + return LookAndFeel::ColorScheme::Light; +} + +// static +Maybe LookAndFeel::GetColor(ColorID aId, ColorScheme, + UseStandins aUseStandins) { + // TODO(emilio): Actually use ColorScheme. + nscolor result; + nsresult rv = nsLookAndFeel::GetInstance()->GetColorValue( + aId, bool(aUseStandins), result); + if (NS_FAILED(rv)) { + return Nothing(); + } + return Some(result); +} + +Maybe LookAndFeel::GetColor(ColorID aId, const dom::Document& aDoc) { + const bool useStandins = + ShouldUseStandinsForNativeColorForNonNativeTheme(aDoc, aId) || + (nsContentUtils::UseStandinsForNativeColors() && + !nsContentUtils::IsChromeDoc(&aDoc)); + return GetColor(aId, ColorSchemeForDocument(aDoc), UseStandins(useStandins)); +} + +Maybe LookAndFeel::GetColor(ColorID aId, const nsIFrame* aFrame) { + return GetColor(aId, *aFrame->PresContext()->Document()); } // static