forked from mirrors/gecko-dev
Bug 1736914 - Implement prefers-reduced-transparency media query r=geckoview-reviewers,emilio,jonalmeida,ohall
Implemented the prefers-reduced-transparency media query for all platforms. Windows and Mac have specific settings which are used, others (Android and Linux/GTK) have it enabled if prefers-reduced-motion is also enabled as there is no dedicated setting to check. Locked behind new pref `layout.css.prefers-reduced-transparency.enabled`, off by default always for now. Also added new WPT tests (none previously). Demo video: https://goose.icu/firefox_prt.mp4 Test page: https://goose.icu/prefers-reduced-transparency Differential Revision: https://phabricator.services.mozilla.com/D172424
This commit is contained in:
parent
23b25a9b51
commit
3bbca01da2
17 changed files with 155 additions and 5 deletions
|
|
@ -630,6 +630,8 @@ void Gecko_MediaFeatures_GetDeviceSize(const mozilla::dom::Document*,
|
|||
|
||||
float Gecko_MediaFeatures_GetResolution(const mozilla::dom::Document*);
|
||||
bool Gecko_MediaFeatures_PrefersReducedMotion(const mozilla::dom::Document*);
|
||||
bool Gecko_MediaFeatures_PrefersReducedTransparency(
|
||||
const mozilla::dom::Document*);
|
||||
mozilla::StylePrefersContrast Gecko_MediaFeatures_PrefersContrast(
|
||||
const mozilla::dom::Document*);
|
||||
mozilla::StylePrefersColorScheme Gecko_MediaFeatures_PrefersColorScheme(
|
||||
|
|
|
|||
|
|
@ -283,6 +283,14 @@ bool Gecko_MediaFeatures_PrefersReducedMotion(const Document* aDocument) {
|
|||
return LookAndFeel::GetInt(LookAndFeel::IntID::PrefersReducedMotion, 0) == 1;
|
||||
}
|
||||
|
||||
bool Gecko_MediaFeatures_PrefersReducedTransparency(const Document* aDocument) {
|
||||
if (aDocument->ShouldResistFingerprinting()) {
|
||||
return false;
|
||||
}
|
||||
return LookAndFeel::GetInt(LookAndFeel::IntID::PrefersReducedTransparency,
|
||||
0) == 1;
|
||||
}
|
||||
|
||||
StylePrefersColorScheme Gecko_MediaFeatures_PrefersColorScheme(
|
||||
const Document* aDocument, bool aUseContent) {
|
||||
auto scheme = aUseContent ? LookAndFeel::PreferredColorSchemeForContent()
|
||||
|
|
|
|||
|
|
@ -3481,7 +3481,7 @@
|
|||
mirror: never
|
||||
#endif
|
||||
|
||||
# Use to control to dump CheckedUnsafePtr creation stack and assignment stacks.
|
||||
# Use to control to dump CheckedUnsafePtr creation stack and assignment stacks.
|
||||
- name: dom.checkedUnsafePtr.dumpStacks.enabled
|
||||
type: RelaxedAtomicBool
|
||||
value: false
|
||||
|
|
@ -8770,6 +8770,13 @@
|
|||
mirror: always
|
||||
rust: true
|
||||
|
||||
# Dictates whether or not the prefers-reduced-transparency media query is enabled.
|
||||
- name: layout.css.prefers-reduced-transparency.enabled
|
||||
type: RelaxedAtomicBool
|
||||
value: false
|
||||
mirror: always
|
||||
rust: true
|
||||
|
||||
# Is support for forced-color-adjust properties enabled?
|
||||
- name: layout.css.forced-color-adjust.enabled
|
||||
type: RelaxedAtomicBool
|
||||
|
|
|
|||
|
|
@ -188,6 +188,13 @@ enum PrefersReducedMotion {
|
|||
Reduce,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, FromPrimitive, Parse, ToCss)]
|
||||
#[repr(u8)]
|
||||
enum PrefersReducedTransparency {
|
||||
NoPreference,
|
||||
Reduce,
|
||||
}
|
||||
|
||||
/// Values for the prefers-color-scheme media feature.
|
||||
#[derive(Clone, Copy, Debug, FromPrimitive, Parse, PartialEq, ToCss)]
|
||||
#[repr(u8)]
|
||||
|
|
@ -227,6 +234,24 @@ fn eval_prefers_reduced_motion(
|
|||
}
|
||||
}
|
||||
|
||||
/// https://drafts.csswg.org/mediaqueries-5/#prefers-reduced-transparency
|
||||
fn eval_prefers_reduced_transparency(
|
||||
context: &Context,
|
||||
query_value: Option<PrefersReducedTransparency>,
|
||||
) -> bool {
|
||||
let prefers_reduced =
|
||||
unsafe { bindings::Gecko_MediaFeatures_PrefersReducedTransparency(context.device().document()) };
|
||||
let query_value = match query_value {
|
||||
Some(v) => v,
|
||||
None => return prefers_reduced,
|
||||
};
|
||||
|
||||
match query_value {
|
||||
PrefersReducedTransparency::NoPreference => !prefers_reduced,
|
||||
PrefersReducedTransparency::Reduce => prefers_reduced,
|
||||
}
|
||||
}
|
||||
|
||||
/// Possible values for prefers-contrast media query.
|
||||
/// https://drafts.csswg.org/mediaqueries-5/#prefers-contrast
|
||||
#[derive(Clone, Copy, Debug, FromPrimitive, Parse, PartialEq, ToCss)]
|
||||
|
|
@ -618,7 +643,7 @@ macro_rules! bool_pref_feature {
|
|||
/// to support new types in these entries and (2) ensuring that either
|
||||
/// nsPresContext::MediaFeatureValuesChanged is called when the value that
|
||||
/// would be returned by the evaluator function could change.
|
||||
pub static MEDIA_FEATURES: [QueryFeatureDescription; 63] = [
|
||||
pub static MEDIA_FEATURES: [QueryFeatureDescription; 64] = [
|
||||
feature!(
|
||||
atom!("width"),
|
||||
AllowsRanges::Yes,
|
||||
|
|
@ -742,6 +767,12 @@ pub static MEDIA_FEATURES: [QueryFeatureDescription; 63] = [
|
|||
keyword_evaluator!(eval_prefers_reduced_motion, PrefersReducedMotion),
|
||||
FeatureFlags::empty(),
|
||||
),
|
||||
feature!(
|
||||
atom!("prefers-reduced-transparency"),
|
||||
AllowsRanges::No,
|
||||
keyword_evaluator!(eval_prefers_reduced_transparency, PrefersReducedTransparency),
|
||||
FeatureFlags::empty(),
|
||||
),
|
||||
feature!(
|
||||
atom!("prefers-contrast"),
|
||||
AllowsRanges::No,
|
||||
|
|
|
|||
|
|
@ -322,6 +322,13 @@ fn disabled_by_pref(feature: &Atom, context: &ParserContext) -> bool {
|
|||
return !context.in_ua_or_chrome_sheet() &&
|
||||
!static_prefs::pref!("layout.css.prefers-contrast.enabled");
|
||||
}
|
||||
|
||||
// prefers-reduced-transparency is always enabled in the ua and chrome. On
|
||||
// the web it is hidden behind a preference (see Bug 1822176).
|
||||
if *feature == atom!("prefers-reduced-transparency") {
|
||||
return !context.in_ua_or_chrome_sheet() &&
|
||||
!static_prefs::pref!("layout.css.prefers-reduced-transparency.enabled");
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,2 @@
|
|||
[prefers-reduced-transparency.html]
|
||||
prefs: [layout.css.prefers-reduced-transparency.enabled:true]
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
<!DOCTYPE html>
|
||||
<link rel="help" href="https://drafts.csswg.org/mediaqueries-5/#prefers-reduced-transparency" />
|
||||
<script type="text/javascript" src="/resources/testharness.js"></script>
|
||||
<script type="text/javascript" src="/resources/testharnessreport.js"></script>
|
||||
|
||||
<script type="text/javascript" src="resources/matchmedia-utils.js"></script>
|
||||
<script>
|
||||
query_should_be_known("(prefers-reduced-transparency)");
|
||||
query_should_be_known("(prefers-reduced-transparency: no-preference)");
|
||||
query_should_be_known("(prefers-reduced-transparency: reduce)");
|
||||
|
||||
query_should_be_unknown("(prefers-reduced-transparency: 0)");
|
||||
query_should_be_unknown("(prefers-reduced-transparency: none)");
|
||||
query_should_be_unknown("(prefers-reduced-transparency: 10px)");
|
||||
query_should_be_unknown("(prefers-reduced-transparency: no-preference reduce)");
|
||||
query_should_be_unknown("(prefers-reduced-transparency: reduced)");
|
||||
query_should_be_unknown("(prefers-reduced-transparency: no-preference/reduce)");
|
||||
|
||||
test(() => {
|
||||
// https://drafts.csswg.org/mediaqueries-5/#boolean-context
|
||||
let booleanContext = window.matchMedia("(prefers-reduced-transparency)");
|
||||
let noPreference = window.matchMedia("(prefers-reduced-transparency: no-preference)");
|
||||
assert_equals(booleanContext.matches, !noPreference.matches);
|
||||
}, "Check that no-preference evaluates to false in the boolean context");
|
||||
|
||||
test(() => {
|
||||
let invalid = window.matchMedia("(prefers-reduced-transparency: 10px)");
|
||||
assert_equals(invalid.matches, false);
|
||||
}, "Check that invalid evaluates to false");
|
||||
</script>
|
||||
|
|
@ -292,8 +292,16 @@ class LookAndFeel {
|
|||
* 0: no-preference
|
||||
* 1: reduce
|
||||
*/
|
||||
|
||||
PrefersReducedMotion,
|
||||
|
||||
/**
|
||||
* Corresponding to prefers-reduced-transparency.
|
||||
* https://drafts.csswg.org/mediaqueries-5/#prefers-reduced-transparency
|
||||
* 0: no-preference
|
||||
* 1: reduce
|
||||
*/
|
||||
PrefersReducedTransparency,
|
||||
|
||||
/**
|
||||
* Corresponding to PointerCapabilities in ServoTypes.h
|
||||
* 0: None
|
||||
|
|
|
|||
|
|
@ -346,6 +346,10 @@ nsresult nsLookAndFeel::NativeGetInt(IntID aID, int32_t& aResult) {
|
|||
aResult = java::GeckoSystemStateListener::PrefersReducedMotion();
|
||||
break;
|
||||
|
||||
case IntID::PrefersReducedTransparency:
|
||||
aResult = 0;
|
||||
break;
|
||||
|
||||
case IntID::PrimaryPointerCapabilities:
|
||||
aResult = java::GeckoAppShell::GetAllPointerCapabilities();
|
||||
|
||||
|
|
|
|||
|
|
@ -485,6 +485,9 @@ nsresult nsLookAndFeel::NativeGetInt(IntID aID, int32_t& aResult) {
|
|||
case IntID::PrefersReducedMotion:
|
||||
aResult = NSWorkspace.sharedWorkspace.accessibilityDisplayShouldReduceMotion;
|
||||
break;
|
||||
case IntID::PrefersReducedTransparency:
|
||||
aResult = NSWorkspace.sharedWorkspace.accessibilityDisplayShouldReduceTransparency;
|
||||
break;
|
||||
case IntID::UseAccessibilityTheme:
|
||||
aResult = NSWorkspace.sharedWorkspace.accessibilityDisplayShouldIncreaseContrast;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -945,11 +945,13 @@ nsresult nsLookAndFeel::NativeGetInt(IntID aID, int32_t& aResult) {
|
|||
case IntID::GTKCSDCloseButtonPosition:
|
||||
aResult = mCSDCloseButtonPosition;
|
||||
break;
|
||||
case IntID::UseAccessibilityTheme: {
|
||||
case IntID::UseAccessibilityTheme:
|
||||
// If high contrast is enabled, enable prefers-reduced-transparency media
|
||||
// query as well as there is no dedicated option.
|
||||
case IntID::PrefersReducedTransparency:
|
||||
EnsureInit();
|
||||
aResult = mSystemTheme.mHighContrast;
|
||||
break;
|
||||
}
|
||||
case IntID::TitlebarRadius: {
|
||||
EnsureInit();
|
||||
aResult = EffectiveTheme().mTitlebarRadius;
|
||||
|
|
|
|||
|
|
@ -165,6 +165,7 @@ nsresult HeadlessLookAndFeel::NativeGetInt(IntID aID, int32_t& aResult) {
|
|||
aResult = 0;
|
||||
break;
|
||||
case IntID::PrefersReducedMotion:
|
||||
case IntID::PrefersReducedTransparency:
|
||||
aResult = 0;
|
||||
break;
|
||||
case IntID::PrimaryPointerCapabilities:
|
||||
|
|
|
|||
|
|
@ -181,6 +181,7 @@ static const char sIntPrefs[][45] = {
|
|||
"ui.GtkCSDReversedPlacement",
|
||||
"ui.systemUsesDarkTheme",
|
||||
"ui.prefersReducedMotion",
|
||||
"ui.prefersReducedTransparency",
|
||||
"ui.primaryPointerCapabilities",
|
||||
"ui.allPointerCapabilities",
|
||||
"ui.systemScrollbarSize",
|
||||
|
|
|
|||
|
|
@ -400,6 +400,20 @@ static IInspectable* GetUISettings() {
|
|||
uiSettings3->add_ColorValuesChanged(callback.Get(), &unusedToken)));
|
||||
}
|
||||
|
||||
ComPtr<IUISettings4> uiSettings4;
|
||||
if (SUCCEEDED(uiSettingsAsInspectable.As(&uiSettings4))) {
|
||||
EventRegistrationToken unusedToken;
|
||||
auto callback =
|
||||
Callback<ITypedEventHandler<UISettings*, IInspectable*>>([](auto...) {
|
||||
// Transparent effects changes change media queries only.
|
||||
LookAndFeel::NotifyChangedAllWindows(
|
||||
widget::ThemeChangeKind::MediaQueriesOnly);
|
||||
return S_OK;
|
||||
});
|
||||
(void)NS_WARN_IF(FAILED(uiSettings4->add_AdvancedEffectsEnabledChanged(
|
||||
callback.Get(), &unusedToken)));
|
||||
}
|
||||
|
||||
sUiSettingsAsInspectable = dont_AddRef(uiSettingsAsInspectable.Detach());
|
||||
ClearOnShutdown(&sUiSettingsAsInspectable);
|
||||
}
|
||||
|
|
@ -551,6 +565,28 @@ double WindowsUIUtils::ComputeTextScaleFactor() {
|
|||
#endif
|
||||
}
|
||||
|
||||
bool WindowsUIUtils::ComputeTransparencyEffects() {
|
||||
constexpr bool kDefault = true;
|
||||
#ifndef __MINGW32__
|
||||
ComPtr<IInspectable> settings = GetUISettings();
|
||||
if (NS_WARN_IF(!settings)) {
|
||||
return kDefault;
|
||||
}
|
||||
ComPtr<IUISettings4> uiSettings4;
|
||||
if (NS_WARN_IF(FAILED(settings.As(&uiSettings4)))) {
|
||||
return kDefault;
|
||||
}
|
||||
boolean transparencyEffects = kDefault;
|
||||
if (NS_WARN_IF(FAILED(
|
||||
uiSettings4->get_AdvancedEffectsEnabled(&transparencyEffects)))) {
|
||||
return kDefault;
|
||||
}
|
||||
return transparencyEffects;
|
||||
#else
|
||||
return kDefault;
|
||||
#endif
|
||||
}
|
||||
|
||||
void WindowsUIUtils::UpdateInTabletMode() {
|
||||
#ifndef __MINGW32__
|
||||
if (!IsWin10OrLater()) {
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ class WindowsUIUtils final : public nsIWindowsUIUtils {
|
|||
// Use LookAndFeel for a cached getter.
|
||||
static bool ComputeOverlayScrollbars();
|
||||
static double ComputeTextScaleFactor();
|
||||
static bool ComputeTransparencyEffects();
|
||||
|
||||
protected:
|
||||
~WindowsUIUtils();
|
||||
|
|
|
|||
|
|
@ -608,6 +608,12 @@ nsresult nsLookAndFeel::NativeGetInt(IntID aID, int32_t& aResult) {
|
|||
aResult = !enable;
|
||||
break;
|
||||
}
|
||||
case IntID::PrefersReducedTransparency: {
|
||||
// Prefers reduced transparency if the option for "Transparency Effects"
|
||||
// is disabled
|
||||
aResult = !WindowsUIUtils::ComputeTransparencyEffects();
|
||||
break;
|
||||
}
|
||||
case IntID::PrimaryPointerCapabilities: {
|
||||
aResult = static_cast<int32_t>(
|
||||
widget::WinUtils::GetPrimaryPointerCapabilities());
|
||||
|
|
|
|||
|
|
@ -1018,6 +1018,7 @@ STATIC_ATOMS = [
|
|||
Atom("preceding", "preceding"),
|
||||
Atom("precedingSibling", "preceding-sibling"),
|
||||
Atom("prefersReducedMotion", "prefers-reduced-motion"),
|
||||
Atom("prefersReducedTransparency", "prefers-reduced-transparency"),
|
||||
Atom("prefersColorScheme", "prefers-color-scheme"),
|
||||
Atom("prefersContrast", "prefers-contrast"),
|
||||
Atom("prefix", "prefix"),
|
||||
|
|
|
|||
Loading…
Reference in a new issue