Implement prefers-reduced-motion media query
authordino@apple.com <dino@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 11 Oct 2016 22:45:22 +0000 (22:45 +0000)
committerdino@apple.com <dino@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 11 Oct 2016 22:45:22 +0000 (22:45 +0000)
https://bugs.webkit.org/show_bug.cgi?id=163250
<rdar://problem/28704129>

Reviewed by Simon Fraser.

Source/WebCore:

Implement the prefers-reduced-motion media query, as
described in https://github.com/w3c/csswg-drafts/issues/442.

Tests: fast/media/mq-prefers-reduced-motion-forced-value.html
       fast/media/mq-prefers-reduced-motion.html

* Configurations/WebCoreTestSupport.xcconfig: Link against AppKit and UIKit.

* css/CSSValueKeywords.in: New keyword for "reduce".

* css/MediaFeatureNames.h: Add prefers-reduced-motion.
* css/MediaQueryEvaluator.cpp:
(WebCore::prefersReducedMotionEvaluate):
* css/MediaQueryExp.cpp:
(WebCore::featureWithValidIdent):
(WebCore::isFeatureValidWithoutValue):

* platform/Theme.h: New API to detect the system accessibility settings.
(WebCore::Theme::userPrefersReducedMotion):
* platform/ios/ThemeIOS.h:
* platform/ios/ThemeIOS.mm:
(WebCore::ThemeIOS::userPrefersReducedMotion):
* platform/mac/ThemeMac.h:
* platform/mac/ThemeMac.mm:
(WebCore::ThemeMac::userPrefersReducedMotion):

* testing/Internals.cpp: Expose the same API to internals, so that
a test can examine the value too.
(WebCore::Internals::userPrefersReducedMotion):
* testing/Internals.h:
* testing/Internals.idl:
* testing/Internals.mm:
(WebCore::Internals::userPrefersReducedMotion):

* page/Settings.h: New setting to override the system value...
* page/Settings.in:

* testing/InternalSettings.cpp: ... plumbed through internals.
(WebCore::InternalSettings::Backup::Backup):
(WebCore::InternalSettings::Backup::restoreTo):
(WebCore::InternalSettings::forcedPrefersReducedMotionValue):
(WebCore::InternalSettings::setForcedPrefersReducedMotionValue):
* testing/InternalSettings.h:
* testing/InternalSettings.idl:
* testing/Internals.cpp:
(WebCore::Internals::userPrefersReducedMotion):
* testing/Internals.h:
* testing/Internals.idl:
* testing/Internals.mm:
(WebCore::Internals::userPrefersReducedMotion):

LayoutTests:

One test checks the system value. The other test overrides
the system values to make sure as much as possible is working.

* fast/media/mq-prefers-reduced-motion-expected.html: Added.
* fast/media/mq-prefers-reduced-motion-forced-value-expected.html: Added.
* fast/media/mq-prefers-reduced-motion-forced-value.html: Added.
* fast/media/mq-prefers-reduced-motion.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@207173 268f45cc-cd09-0410-ab3c-d52691b4dbfc

25 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/media/mq-prefers-reduced-motion-expected.html [new file with mode: 0644]
LayoutTests/fast/media/mq-prefers-reduced-motion-forced-value-expected.html [new file with mode: 0644]
LayoutTests/fast/media/mq-prefers-reduced-motion-forced-value.html [new file with mode: 0644]
LayoutTests/fast/media/mq-prefers-reduced-motion.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/Configurations/WebCoreTestSupport.xcconfig
Source/WebCore/css/CSSValueKeywords.in
Source/WebCore/css/MediaFeatureNames.h
Source/WebCore/css/MediaQueryEvaluator.cpp
Source/WebCore/css/MediaQueryExp.cpp
Source/WebCore/page/Settings.h
Source/WebCore/page/Settings.in
Source/WebCore/platform/Theme.h
Source/WebCore/platform/ios/ThemeIOS.h
Source/WebCore/platform/ios/ThemeIOS.mm
Source/WebCore/platform/mac/ThemeMac.h
Source/WebCore/platform/mac/ThemeMac.mm
Source/WebCore/testing/InternalSettings.cpp
Source/WebCore/testing/InternalSettings.h
Source/WebCore/testing/InternalSettings.idl
Source/WebCore/testing/Internals.cpp
Source/WebCore/testing/Internals.h
Source/WebCore/testing/Internals.idl
Source/WebCore/testing/Internals.mm

index 3499917..fe3ac46 100644 (file)
@@ -1,3 +1,19 @@
+2016-10-11  Dean Jackson  <dino@apple.com>
+
+        Implement prefers-reduced-motion media query
+        https://bugs.webkit.org/show_bug.cgi?id=163250
+        <rdar://problem/28704129>
+
+        Reviewed by Simon Fraser.
+
+        One test checks the system value. The other test overrides
+        the system values to make sure as much as possible is working.
+
+        * fast/media/mq-prefers-reduced-motion-expected.html: Added.
+        * fast/media/mq-prefers-reduced-motion-forced-value-expected.html: Added.
+        * fast/media/mq-prefers-reduced-motion-forced-value.html: Added.
+        * fast/media/mq-prefers-reduced-motion.html: Added.
+
 2016-10-11  Ryan Haddad  <ryanhaddad@apple.com>
 
         Skip tests added with r207155 that rely on touch events.
diff --git a/LayoutTests/fast/media/mq-prefers-reduced-motion-expected.html b/LayoutTests/fast/media/mq-prefers-reduced-motion-expected.html
new file mode 100644 (file)
index 0000000..6065811
--- /dev/null
@@ -0,0 +1,32 @@
+<html>
+<head>
+<title>CSS4 media query test: prefers-reduced-motion.</title>
+<style type="text/css">
+#a { color: black; }
+#b { color: black; }
+#c { color: black; }
+#d { color: black; }
+</style>
+<script>
+window.addEventListener("load", function () {
+
+    if (!window.internals) {
+        ["a", "b", "c", "d"].forEach(id => { document.getElementById(id).textContent = "This expected result requires DRT/WKTR."; });
+        return;
+    }
+
+    if (window.internals.userPrefersReducedMotion())
+        ["a", "b", "c"].forEach(id => { document.getElementById(id).style.color = "green"; });
+    else
+        document.getElementById("d").style.color = "green";
+
+}, false);
+</script>
+</head>
+<body>
+  <p id="a">This text should be green if the user requested reduced motion. Black otherwise.</p>
+  <p id="b">This text should be green if the user requested reduced motion. Black otherwise.</p>
+  <p id="c">This text should be green if the user requested reduced motion. Black otherwise.</p>
+  <p id="d">This text should be green if the user has not requested reduced motion. Black otherwise.</p>
+</body>
+</html>
diff --git a/LayoutTests/fast/media/mq-prefers-reduced-motion-forced-value-expected.html b/LayoutTests/fast/media/mq-prefers-reduced-motion-forced-value-expected.html
new file mode 100644 (file)
index 0000000..551c474
--- /dev/null
@@ -0,0 +1,14 @@
+<html>
+<head>
+<title>CSS4 media query test: prefers-reduced-motion.</title>
+<style type="text/css">
+p { color: green; }
+</style>
+</head>
+<body>
+  <p id="a">This text should be green.</p>
+  <p id="b">This text should be green.</p>
+  <p id="c">This text should be green.</p>
+  <p id="d">This text should be green.</p>
+</body>
+</html>
diff --git a/LayoutTests/fast/media/mq-prefers-reduced-motion-forced-value.html b/LayoutTests/fast/media/mq-prefers-reduced-motion-forced-value.html
new file mode 100644 (file)
index 0000000..ec095a4
--- /dev/null
@@ -0,0 +1,32 @@
+<html>
+<head>
+<title>CSS4 media query test: prefers-reduced-motion.</title>
+<style type="text/css">
+p { color: black; }
+</style>
+<script>
+window.addEventListener("load", function () {
+    if (!window.internals)
+        return;
+
+    window.internals.settings.forcedPrefersReducedMotionValue = "on";
+    if (window.matchMedia("(prefers-reduced-motion)").matches)
+        document.getElementById("a").style.color = "green";
+    if (window.matchMedia("(prefers-reduced-motion: reduce)").matches)
+        document.getElementById("b").style.color = "green";
+
+    window.internals.settings.forcedPrefersReducedMotionValue = "off";
+    if (!window.matchMedia("(prefers-reduced-motion)").matches)
+        document.getElementById("c").style.color = "green";
+    if (window.matchMedia("(prefers-reduced-motion: default)").matches)
+        document.getElementById("d").style.color = "green";
+}, false);
+</script>
+</head>
+<body>
+  <p id="a">This text should be green.</p>
+  <p id="b">This text should be green.</p>
+  <p id="c">This text should be green.</p>
+  <p id="d">This text should be green.</p>
+</body>
+</html>
diff --git a/LayoutTests/fast/media/mq-prefers-reduced-motion.html b/LayoutTests/fast/media/mq-prefers-reduced-motion.html
new file mode 100644 (file)
index 0000000..3f995ae
--- /dev/null
@@ -0,0 +1,35 @@
+<html>
+<head>
+<title>CSS4 media query test: prefers-reduced-motion.</title>
+<style type="text/css">
+#a { color: black; }
+#b { color: black; }
+#c { color: black; }
+#d { color: black; }
+
+@media (prefers-reduced-motion) {
+#a { color: green; }
+}
+
+@media (prefers-reduced-motion: reduce) {
+#b { color: green; }
+}
+
+@media (prefers-reduced-motion: default) {
+#d { color: green; }
+}
+</style>
+<script>
+window.addEventListener("load", function () {
+    if (window.matchMedia("(prefers-reduced-motion)").matches)
+        document.getElementById("c").style.color = "green";
+}, false);
+</script>
+</head>
+<body>
+  <p id="a">This text should be green if the user requested reduced motion. Black otherwise.</p>
+  <p id="b">This text should be green if the user requested reduced motion. Black otherwise.</p>
+  <p id="c">This text should be green if the user requested reduced motion. Black otherwise.</p>
+  <p id="d">This text should be green if the user has not requested reduced motion. Black otherwise.</p>
+</body>
+</html>
index 3e8919c..c143370 100644 (file)
@@ -1,3 +1,63 @@
+2016-10-11  Dean Jackson  <dino@apple.com>
+
+        Implement prefers-reduced-motion media query
+        https://bugs.webkit.org/show_bug.cgi?id=163250
+        <rdar://problem/28704129>
+
+        Reviewed by Simon Fraser.
+
+        Implement the prefers-reduced-motion media query, as
+        described in https://github.com/w3c/csswg-drafts/issues/442.
+
+        Tests: fast/media/mq-prefers-reduced-motion-forced-value.html
+               fast/media/mq-prefers-reduced-motion.html
+
+        * Configurations/WebCoreTestSupport.xcconfig: Link against AppKit and UIKit.
+
+        * css/CSSValueKeywords.in: New keyword for "reduce".
+
+        * css/MediaFeatureNames.h: Add prefers-reduced-motion.
+        * css/MediaQueryEvaluator.cpp:
+        (WebCore::prefersReducedMotionEvaluate):
+        * css/MediaQueryExp.cpp:
+        (WebCore::featureWithValidIdent):
+        (WebCore::isFeatureValidWithoutValue):
+
+        * platform/Theme.h: New API to detect the system accessibility settings.
+        (WebCore::Theme::userPrefersReducedMotion):
+        * platform/ios/ThemeIOS.h:
+        * platform/ios/ThemeIOS.mm:
+        (WebCore::ThemeIOS::userPrefersReducedMotion):
+        * platform/mac/ThemeMac.h:
+        * platform/mac/ThemeMac.mm:
+        (WebCore::ThemeMac::userPrefersReducedMotion):
+
+        * testing/Internals.cpp: Expose the same API to internals, so that
+        a test can examine the value too.
+        (WebCore::Internals::userPrefersReducedMotion):
+        * testing/Internals.h:
+        * testing/Internals.idl:
+        * testing/Internals.mm:
+        (WebCore::Internals::userPrefersReducedMotion):
+
+        * page/Settings.h: New setting to override the system value...
+        * page/Settings.in:
+
+        * testing/InternalSettings.cpp: ... plumbed through internals.
+        (WebCore::InternalSettings::Backup::Backup):
+        (WebCore::InternalSettings::Backup::restoreTo):
+        (WebCore::InternalSettings::forcedPrefersReducedMotionValue):
+        (WebCore::InternalSettings::setForcedPrefersReducedMotionValue):
+        * testing/InternalSettings.h:
+        * testing/InternalSettings.idl:
+        * testing/Internals.cpp:
+        (WebCore::Internals::userPrefersReducedMotion):
+        * testing/Internals.h:
+        * testing/Internals.idl:
+        * testing/Internals.mm:
+        (WebCore::Internals::userPrefersReducedMotion):
+
+
 2016-10-10  Ryosuke Niwa  <rniwa@webkit.org>
 
         Annotate DOM API with CEReactions
index c9da659..99036fd 100644 (file)
@@ -49,6 +49,7 @@ EXECUTABLE_PREFIX = lib;
 EXPORTED_SYMBOLS_FILE = ;
 GCC_SYMBOLS_PRIVATE_EXTERN = YES;
 OTHER_LDFLAGS = $(ASAN_OTHER_LDFLAGS);
-OTHER_LDFLAGS[sdk=iphoneos*] = $(ASAN_OTHER_LDFLAGS) -lAccessibility -F$(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/PhonyWebKitLegacy;
-OTHER_LDFLAGS[sdk=iphonesimulator*] = $(ASAN_OTHER_LDFLAGS) -lAccessibility -F$(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/PhonyWebKitLegacy;
+OTHER_LDFLAGS[sdk=macos*] = $(ASAN_OTHER_LDFLAGS) -framework AppKit;
+OTHER_LDFLAGS[sdk=iphoneos*] = $(ASAN_OTHER_LDFLAGS) -framework UIKit -lAccessibility -F$(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/PhonyWebKitLegacy;
+OTHER_LDFLAGS[sdk=iphonesimulator*] = $(ASAN_OTHER_LDFLAGS) -framework UIKit -lAccessibility -F$(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/PhonyWebKitLegacy;
 SECT_ORDER_FLAGS = ;
index 451fa90..e61fd97 100644 (file)
@@ -1304,6 +1304,9 @@ last
 p3
 rec2020
 
+// prefers-reduced-motion
+reduce
+
 #if defined(ENABLE_CSS_GRID_LAYOUT) && ENABLE_CSS_GRID_LAYOUT
 // auto-repeat
 auto-fill
index 62971c0..664d34f 100644 (file)
@@ -69,6 +69,7 @@
     macro(monochrome, "monochrome") \
     macro(orientation, "orientation") \
     macro(pointer, "pointer") \
+    macro(prefersReducedMotion, "prefers-reduced-motion") \
     macro(resolution, "resolution") \
     macro(transform2d, "-webkit-transform-2d") \
     macro(transform3d, "-webkit-transform-3d") \
index 584c8ec..c6392be 100644 (file)
@@ -49,6 +49,7 @@
 #include "Screen.h"
 #include "Settings.h"
 #include "StyleResolver.h"
+#include "Theme.h"
 #include <wtf/HashMap.h>
 
 #if ENABLE(3D_TRANSFORMS)
@@ -655,6 +656,25 @@ static bool anyPointerEvaluate(CSSValue* value, const CSSToLengthConversionData&
     return pointerEvaluate(value, cssToLengthConversionData, frame, prefix);
 }
 
+static bool prefersReducedMotionEvaluate(CSSValue* value, const CSSToLengthConversionData&, Frame& frame, MediaFeaturePrefix)
+{
+#if USE(NEW_THEME)
+    bool userPrefersReducedMotion = platformTheme()->userPrefersReducedMotion();
+#else
+    bool userPrefersReducedMotion = false;
+#endif
+
+    if (frame.settings().forcedPrefersReducedMotionValue() == Settings::ForcedPrefersReducedMotionValue::On)
+        userPrefersReducedMotion = true;
+    else if (frame.settings().forcedPrefersReducedMotionValue() == Settings::ForcedPrefersReducedMotionValue::Off)
+        userPrefersReducedMotion = false;
+
+    if (!value)
+        return userPrefersReducedMotion;
+
+    return downcast<CSSPrimitiveValue>(*value).getValueID() == (userPrefersReducedMotion ? CSSValueReduce : CSSValueDefault);
+}
+
 // Use this function instead of calling add directly to avoid inlining.
 static void add(MediaQueryFunctionMap& map, AtomicStringImpl* key, MediaQueryFunction value)
 {
index 2fd18be..80f2f77 100644 (file)
@@ -50,9 +50,10 @@ static inline bool featureWithValidIdent(const AtomicString& mediaFeature)
     || mediaFeature == MediaFeatureNames::anyPointer
     || mediaFeature == MediaFeatureNames::hover
     || mediaFeature == MediaFeatureNames::invertedColors
-    || mediaFeature == MediaFeatureNames::pointer;
+    || mediaFeature == MediaFeatureNames::pointer
+    || mediaFeature == MediaFeatureNames::prefersReducedMotion;
 }
-    
+
 static inline bool featureWithValidDensity(const String& mediaFeature, const CSSParserToken& token)
 {
     if ((token.unitType() != CSSPrimitiveValue::UnitTypes::CSS_DPPX && token.unitType() != CSSPrimitiveValue::UnitTypes::CSS_DPI && token.unitType() != CSSPrimitiveValue::UnitTypes::CSS_DPCM) || token.numericValue() <= 0)
@@ -228,6 +229,7 @@ static inline bool isFeatureValidWithoutValue(const AtomicString& mediaFeature)
         || mediaFeature == MediaFeatureNames::viewMode
 #endif
         || mediaFeature == MediaFeatureNames::pointer
+        || mediaFeature == MediaFeatureNames::prefersReducedMotion
         || mediaFeature == MediaFeatureNames::devicePixelRatio
         || mediaFeature == MediaFeatureNames::resolution
         || mediaFeature == MediaFeatureNames::videoPlayableInline;
index c4503d8..713b2fe 100644 (file)
@@ -98,6 +98,9 @@ public:
 
     void pageDestroyed() { m_page = nullptr; }
 
+    enum class ForcedPrefersReducedMotionValue { System, On, Off };
+    static const Settings::ForcedPrefersReducedMotionValue defaultForcedPrefersReducedMotionValue = ForcedPrefersReducedMotionValue::System;
+
     WEBCORE_EXPORT void setStandardFontFamily(const AtomicString&, UScriptCode = USCRIPT_COMMON);
     WEBCORE_EXPORT const AtomicString& standardFontFamily(UScriptCode = USCRIPT_COMMON) const;
 
index 9716396..8dc4f7c 100644 (file)
@@ -283,3 +283,5 @@ inputEventsEnabled initial=false
 
 quickTimePluginReplacementEnabled initial=defaultQuickTimePluginReplacementEnabled
 youTubeFlashPluginReplacementEnabled initial=defaultYouTubeFlashPluginReplacementEnabled
+
+forcedPrefersReducedMotionValue type=ForcedPrefersReducedMotionValue, initial=defaultForcedPrefersReducedMotionValue
index 9663773..35863bc 100644 (file)
@@ -110,6 +110,8 @@ public:
 
     virtual void drawNamedImage(const String&, GraphicsContext&, const FloatRect&) const;
 
+    virtual bool userPrefersReducedMotion() const { return false; }
+
     // This method is called once, from RenderTheme::adjustDefaultStyleSheet(), to let each platform adjust
     // the default CSS rules in html.css.
     static String defaultStyleSheet();
index 8d809f2..377b822 100644 (file)
@@ -34,6 +34,8 @@ class ThemeIOS : public ThemeCocoa {
 public:
     ThemeIOS() { }
     virtual ~ThemeIOS() { }
+
+    bool userPrefersReducedMotion() const override;
 };
 
 } // namespace WebCore
index b46fc3a..b1b0bc5 100644 (file)
 
 #import "GraphicsContext.h"
 #import "ScrollView.h"
+#import "SoftLinking.h"
 #include <wtf/NeverDestroyed.h>
 #include <wtf/StdLibExtras.h>
 
+SOFT_LINK_FRAMEWORK(UIKit)
+SOFT_LINK(UIKit, UIAccessibilityIsReduceMotionEnabled, BOOL, (void), ())
+
 using namespace std;
 
 namespace WebCore {
@@ -43,4 +47,9 @@ Theme* platformTheme()
     return &themeIOS.get();
 }
 
+bool ThemeIOS::userPrefersReducedMotion() const
+{
+    return UIAccessibilityIsReduceMotionEnabled();
+}
+
 }
index 3d0e183..e4c7271 100644 (file)
@@ -55,6 +55,8 @@ public:
     void paint(ControlPart, ControlStates&, GraphicsContext&, const FloatRect&, float zoomFactor, ScrollView*, float deviceScaleFactor, float pageScaleFactor) override;
     void inflateControlPaintRect(ControlPart, const ControlStates&, FloatRect&, float zoomFactor) const override;
 
+    bool userPrefersReducedMotion() const override;
+
     // FIXME: Once RenderThemeMac is converted over to use Theme then this can be internal to ThemeMac.
     static NSView* ensuredView(ScrollView*, const ControlStates&, bool useUnparentedView = false);
     static void setFocusRingClipRect(const FloatRect&);
index 1588ead..c16b9e6 100644 (file)
@@ -870,4 +870,13 @@ void ThemeMac::paint(ControlPart part, ControlStates& states, GraphicsContext& c
     }
 }
 
+bool ThemeMac::userPrefersReducedMotion() const
+{
+#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200
+    return [[NSWorkspace sharedWorkspace] accessibilityDisplayShouldReduceMotion];
+#else
+    return false;
+#endif
+}
+
 }
index d28b568..bd4ad4d 100644 (file)
@@ -115,6 +115,7 @@ InternalSettings::Backup::Backup(Settings& settings)
     , m_userInterfaceDirectionPolicy(settings.userInterfaceDirectionPolicy())
     , m_systemLayoutDirection(settings.systemLayoutDirection())
     , m_pdfImageCachingPolicy(settings.pdfImageCachingPolicy())
+    , m_forcedPrefersReducedMotionValue(settings.forcedPrefersReducedMotionValue())
 {
 }
 
@@ -194,6 +195,7 @@ void InternalSettings::Backup::restoreTo(Settings& settings)
     settings.setUserInterfaceDirectionPolicy(m_userInterfaceDirectionPolicy);
     settings.setSystemLayoutDirection(m_systemLayoutDirection);
     settings.setPdfImageCachingPolicy(m_pdfImageCachingPolicy);
+    settings.setForcedPrefersReducedMotionValue(m_forcedPrefersReducedMotionValue);
     Settings::setAllowsAnySSLCertificate(false);
 }
 
@@ -679,6 +681,33 @@ void InternalSettings::setVariationFontsEnabled(bool enabled, ExceptionCode& ec)
 #endif
 }
 
+InternalSettings::ForcedPrefersReducedMotionValue InternalSettings::forcedPrefersReducedMotionValue() const
+{
+    switch (settings()->forcedPrefersReducedMotionValue()) {
+    case Settings::ForcedPrefersReducedMotionValue::System:
+        return InternalSettings::ForcedPrefersReducedMotionValue::System;
+    case Settings::ForcedPrefersReducedMotionValue::On:
+        return InternalSettings::ForcedPrefersReducedMotionValue::On;
+    case Settings::ForcedPrefersReducedMotionValue::Off:
+        return InternalSettings::ForcedPrefersReducedMotionValue::Off;
+    }
+}
+
+void InternalSettings::setForcedPrefersReducedMotionValue(InternalSettings::ForcedPrefersReducedMotionValue value)
+{
+    switch (value) {
+    case InternalSettings::ForcedPrefersReducedMotionValue::System:
+        settings()->setForcedPrefersReducedMotionValue(Settings::ForcedPrefersReducedMotionValue::System);
+        break;
+    case InternalSettings::ForcedPrefersReducedMotionValue::On:
+        settings()->setForcedPrefersReducedMotionValue(Settings::ForcedPrefersReducedMotionValue::On);
+        break;
+    case InternalSettings::ForcedPrefersReducedMotionValue::Off:
+        settings()->setForcedPrefersReducedMotionValue(Settings::ForcedPrefersReducedMotionValue::Off);
+        break;
+    }
+}
+
 // If you add to this list, make sure that you update the Backup class for test reproducability!
 
 }
index 1cfa506..9b3230b 100644 (file)
@@ -115,6 +115,7 @@ public:
         UserInterfaceDirectionPolicy m_userInterfaceDirectionPolicy;
         TextDirection m_systemLayoutDirection;
         PDFImageCachingPolicy m_pdfImageCachingPolicy;
+        Settings::ForcedPrefersReducedMotionValue m_forcedPrefersReducedMotionValue;
     };
 
     static Ref<InternalSettings> create(Page* page)
@@ -174,6 +175,10 @@ public:
     bool variationFontsEnabled(ExceptionCode&);
     void setVariationFontsEnabled(bool, ExceptionCode&);
 
+    enum class ForcedPrefersReducedMotionValue { System, On, Off };
+    ForcedPrefersReducedMotionValue forcedPrefersReducedMotionValue() const;
+    void setForcedPrefersReducedMotionValue(ForcedPrefersReducedMotionValue);
+
     static void setAllowsAnySSLCertificate(bool);
 
 private:
index a10dd0b..4404fcb 100644 (file)
@@ -24,6 +24,8 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+enum ForcedPrefersReducedMotionValue { "system", "on", "off" };
+
 [
     NoInterfaceObject,
     JSGenerateToJSObject,
@@ -89,6 +91,8 @@
     [MayThrowLegacyException] boolean variationFontsEnabled();
     [MayThrowLegacyException] void setVariationFontsEnabled(boolean enabled);
 
+    attribute ForcedPrefersReducedMotionValue forcedPrefersReducedMotionValue;
+
     void setInputEventsEnabled(boolean enabled);
 };
 
index 7bb5127..ff0ab22 100644 (file)
@@ -3378,4 +3378,11 @@ void Internals::setUserInterfaceLayoutDirection(UserInterfaceLayoutDirection use
     page->setUserInterfaceLayoutDirection(userInterfaceLayoutDirection == UserInterfaceLayoutDirection::LTR ? WebCore::UserInterfaceLayoutDirection::LTR : WebCore::UserInterfaceLayoutDirection::RTL);
 }
 
+#if !PLATFORM(COCOA)
+bool Internals::userPrefersReducedMotion() const
+{
+    return false;
+}
+#endif
+
 } // namespace WebCore
index 85bf318..35a8ab7 100644 (file)
@@ -495,6 +495,8 @@ public:
     enum class UserInterfaceLayoutDirection { LTR, RTL };
     void setUserInterfaceLayoutDirection(UserInterfaceLayoutDirection);
 
+    bool userPrefersReducedMotion() const;
+
 private:
     explicit Internals(Document&);
     Document* contextDocument() const;
index 2179f69..371b5e0 100644 (file)
@@ -466,4 +466,6 @@ enum UserInterfaceLayoutDirection {
     GCObservation observeGC(any observed);
 
     void setUserInterfaceLayoutDirection(UserInterfaceLayoutDirection userInterfaceLayoutDirection);
+
+    boolean userPrefersReducedMotion();
 };
index 1b9921c..418bcf7 100644 (file)
 #include "EditorClient.h"
 #include "Frame.h"
 
+#if PLATFORM(IOS)
+#import <UIKit/UIKit.h>
+#endif
+
 namespace WebCore {
 
 String Internals::userVisibleString(const DOMURL& url)
@@ -39,4 +43,17 @@ String Internals::userVisibleString(const DOMURL& url)
     return contextDocument()->frame()->editor().client()->userVisibleString(url.href());
 }
 
+#if PLATFORM(COCOA)
+bool Internals::userPrefersReducedMotion() const
+{
+#if PLATFORM(IOS)
+    return UIAccessibilityIsReduceMotionEnabled();
+#elif PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200
+    return [[NSWorkspace sharedWorkspace] accessibilityDisplayShouldReduceMotion];
+#else
+    return false;
+#endif
+}
+#endif
+
 }