diff --git a/layout/base/nsPresContext.cpp b/layout/base/nsPresContext.cpp index 98e9dbb81d22..4e7123d4c463 100644 --- a/layout/base/nsPresContext.cpp +++ b/layout/base/nsPresContext.cpp @@ -297,7 +297,8 @@ nsPresContext::nsPresContext(dom::Document* aDocument, nsPresContextType aType) #ifdef DEBUG mInitialized(false), #endif - mOverriddenOrEmbedderColorScheme(dom::PrefersColorSchemeOverride::None) { + mOverriddenOrEmbedderColorScheme(dom::PrefersColorSchemeOverride::None), + mForcedColors(StyleForcedColors::None) { #ifdef DEBUG PodZero(&mLayoutPhaseCount); #endif @@ -328,6 +329,7 @@ nsPresContext::nsPresContext(dom::Document* aDocument, nsPresContextType aType) } UpdateFontVisibility(); + UpdateForcedColors(/* aNotify = */ false); } static const char* gExactCallbackPrefs[] = { @@ -617,6 +619,7 @@ void nsPresContext::PreferenceChanged(const char* aPrefName) { if (PreferenceSheet::AffectedByPref(prefName)) { restyleHint |= RestyleHint::RestyleSubtree(); PreferenceSheet::Refresh(); + UpdateForcedColors(); } // Same, this just frees a bunch of memory. @@ -736,6 +739,46 @@ nsresult nsPresContext::Init(nsDeviceContext* aDeviceContext) { return NS_OK; } +void nsPresContext::UpdateForcedColors(bool aNotify) { + auto old = mForcedColors; + mForcedColors = [&] { + if (Document()->IsBeingUsedAsImage()) { + return StyleForcedColors::None; + } + + // TODO: Handle BrowsingContext override. + + const auto& prefs = PrefSheetPrefs(); + if (!prefs.mUseDocumentColors) { + return StyleForcedColors::Active; + } + // On Windows, having a high contrast theme also means that the OS is + // requesting the colors to be forced. This is mostly convenience for the + // front-end, which wants to reuse the forced-colors styles for chrome in + // this case as well, and it's a lot more convenient to use + // `(forced-colors)` than `(forced-colors) or ((-moz-platform: windows) and + // (prefers-contrast))`. + // + // TODO(emilio): We might want to factor in here the lwtheme attribute in + // the root element and so on. +#ifdef XP_WINDOWS + if (prefs.mUseAccessibilityTheme && prefs.mIsChrome) { + return StyleForcedColors::Requested; + } +#endif + return StyleForcedColors::None; + }(); + if (aNotify && mForcedColors != old) { + MediaFeatureValuesChanged( + MediaFeatureChange::ForPreferredColorSchemeOrForcedColorsChange(), + MediaFeatureChangePropagation::JustThisDocument); + } +} + +bool nsPresContext::ForcingColors() const { + return mForcedColors == StyleForcedColors::Active; +} + bool nsPresContext::UpdateFontVisibility() { FontVisibility oldValue = mFontVisibility; @@ -924,7 +967,7 @@ void nsPresContext::SetColorSchemeOverride( if (mDocument->PreferredColorScheme() != oldScheme) { MediaFeatureValuesChanged( - MediaFeatureChange::ForPreferredColorSchemeChange(), + MediaFeatureChange::ForPreferredColorSchemeOrForcedColorsChange(), MediaFeatureChangePropagation::JustThisDocument); } } @@ -963,6 +1006,8 @@ void nsPresContext::RecomputeBrowsingContextDependentData() { return browsingContext->GetEmbedderColorSchemes().mPreferred; }()); + UpdateForcedColors(); + SetInRDMPane(top->GetInRDMPane()); if (doc == mDocument) { @@ -1845,6 +1890,7 @@ void nsPresContext::ThemeChangedInternal() { LookAndFeel::HandleGlobalThemeChange(); // Full zoom might have changed as a result of the text scale factor. + // Forced colors might also have changed. RecomputeBrowsingContextDependentData(); // Changes to system metrics and other look and feel values can change media @@ -1949,7 +1995,7 @@ void nsPresContext::EmulateMedium(nsAtom* aMediaType) { MediaFeatureChange change(MediaFeatureChangeReason::MediumChange); if (oldScheme != mDocument->PreferredColorScheme()) { - change |= MediaFeatureChange::ForPreferredColorSchemeChange(); + change |= MediaFeatureChange::ForPreferredColorSchemeOrForcedColorsChange(); } MediaFeatureValuesChanged(change, MediaFeatureChangePropagation::JustThisDocument); diff --git a/layout/base/nsPresContext.h b/layout/base/nsPresContext.h index 0d1da270f836..f82f9aad8789 100644 --- a/layout/base/nsPresContext.h +++ b/layout/base/nsPresContext.h @@ -85,6 +85,7 @@ class TimelineManager; struct MediaFeatureChange; enum class MediaFeatureChangePropagation : uint8_t; enum class ColorScheme : uint8_t; +enum class StyleForcedColors : uint8_t; namespace layers { class ContainerLayer; class LayerManager; @@ -377,10 +378,7 @@ class nsPresContext : public nsISupports, public mozilla::SupportsWeakPtr { return mozilla::PreferenceSheet::PrefsFor(*mDocument); } - bool ForcingColors() const { - return mozilla::PreferenceSheet::MayForceColors() && - !PrefSheetPrefs().mUseDocumentColors; - } + bool ForcingColors() const; mozilla::ColorScheme DefaultBackgroundColorScheme() const; nscolor DefaultBackgroundColor() const; @@ -560,6 +558,7 @@ class nsPresContext : public nsISupports, public mozilla::SupportsWeakPtr { void SetOverrideDPPX(float); void SetInRDMPane(bool aInRDMPane); void UpdateTopInnerSizeForRFP(); + void UpdateForcedColors(bool aNotify = true); public: float GetFullZoom() { return mFullZoom; } @@ -1402,6 +1401,7 @@ class nsPresContext : public nsISupports, public mozilla::SupportsWeakPtr { // that breaks bindgen in win32. FontVisibility mFontVisibility = FontVisibility::Unknown; mozilla::dom::PrefersColorSchemeOverride mOverriddenOrEmbedderColorScheme; + mozilla::StyleForcedColors mForcedColors; protected: virtual ~nsPresContext(); diff --git a/layout/style/MediaFeatureChange.h b/layout/style/MediaFeatureChange.h index a766406219cb..40118ca99232 100644 --- a/layout/style/MediaFeatureChange.h +++ b/layout/style/MediaFeatureChange.h @@ -77,7 +77,7 @@ struct MediaFeatureChange { return *this; } - static MediaFeatureChange ForPreferredColorSchemeChange() { + static MediaFeatureChange ForPreferredColorSchemeOrForcedColorsChange() { // We need to restyle because not only media queries have changed, system // colors may as well via the prefers-color-scheme meta tag / effective // color-scheme property value. diff --git a/layout/style/ServoBindings.toml b/layout/style/ServoBindings.toml index 0cd4846aad46..0d42a79f79c2 100644 --- a/layout/style/ServoBindings.toml +++ b/layout/style/ServoBindings.toml @@ -595,6 +595,7 @@ cbindgen-types = [ { gecko = "StyleImageRendering", servo = "crate::values::computed::ImageRendering" }, { gecko = "StylePrintColorAdjust", servo = "crate::values::computed::PrintColorAdjust" }, { gecko = "StyleForcedColorAdjust", servo = "crate::values::computed::ForcedColorAdjust" }, + { gecko = "StyleForcedColors", servo = "crate::gecko::media_features::ForcedColors" }, { gecko = "StyleScrollbarGutter", servo = "crate::values::computed::ScrollbarGutter" }, { gecko = "StyleHyphenateCharacter", servo = "crate::values::computed::HyphenateCharacter" }, { gecko = "StyleColumnCount", servo = "crate::values::computed::ColumnCount" }, diff --git a/servo/components/style/gecko/media_queries.rs b/servo/components/style/gecko/media_queries.rs index fb092ff89878..6867786cb27b 100644 --- a/servo/components/style/gecko/media_queries.rs +++ b/servo/components/style/gecko/media_queries.rs @@ -500,26 +500,7 @@ impl Device { /// Returns whether document colors are enabled. #[inline] pub fn forced_colors(&self) -> ForcedColors { - if self.document().mIsBeingUsedAsImage() { - // SVG images never force colors. - return ForcedColors::None; - } - let prefs = self.pref_sheet_prefs(); - if !prefs.mUseDocumentColors { - return ForcedColors::Active; - } - // On Windows, having a high contrast theme also means that the OS is requesting the - // colors to be forced. This is mostly convenience for the front-end, which wants to - // reuse the forced-colors styles for chrome in this case as well, and it's a lot - // more convenient to use `(forced-colors)` than - // `(forced-colors) or ((-moz-platform: windows) and (prefers-contrast))`. - // - // TODO(emilio): We might want to factor in here the lwtheme attribute in the root element - // and so on. - if cfg!(target_os = "windows") && prefs.mUseAccessibilityTheme && prefs.mIsChrome { - return ForcedColors::Requested; - } - ForcedColors::None + self.pres_context().map_or(ForcedColors::None, |pc| pc.mForcedColors) } /// Computes a system color and returns it as an nscolor. diff --git a/servo/ports/geckolib/cbindgen.toml b/servo/ports/geckolib/cbindgen.toml index c95d090795dd..3cf38a5e4477 100644 --- a/servo/ports/geckolib/cbindgen.toml +++ b/servo/ports/geckolib/cbindgen.toml @@ -305,6 +305,7 @@ include = [ "ImageRendering", "PrintColorAdjust", "ForcedColorAdjust", + "ForcedColors", "ScrollbarGutter", "ScrollDirection", "HyphenateCharacter",