Bug 1705927 - Make GenericOverscrollEffect a no-op if prefers-reduced-motion is set. r=hiro

Differential Revision: https://phabricator.services.mozilla.com/D112660
This commit is contained in:
Botond Ballo 2021-04-21 02:25:11 +00:00
Родитель 203db5c4d1
Коммит 70d48281d5
9 изменённых файлов: 92 добавлений и 0 удалений

Просмотреть файл

@ -820,6 +820,7 @@ struct ScrollMetadata {
mResolutionUpdated(false), mResolutionUpdated(false),
mIsRDMTouchSimulationActive(false), mIsRDMTouchSimulationActive(false),
mDidContentGetPainted(true), mDidContentGetPainted(true),
mPrefersReducedMotion(false),
mOverscrollBehavior() {} mOverscrollBehavior() {}
bool operator==(const ScrollMetadata& aOther) const { bool operator==(const ScrollMetadata& aOther) const {
@ -837,6 +838,7 @@ struct ScrollMetadata {
mResolutionUpdated == aOther.mResolutionUpdated && mResolutionUpdated == aOther.mResolutionUpdated &&
mIsRDMTouchSimulationActive == aOther.mIsRDMTouchSimulationActive && mIsRDMTouchSimulationActive == aOther.mIsRDMTouchSimulationActive &&
mDidContentGetPainted == aOther.mDidContentGetPainted && mDidContentGetPainted == aOther.mDidContentGetPainted &&
mPrefersReducedMotion == aOther.mPrefersReducedMotion &&
mDisregardedDirection == aOther.mDisregardedDirection && mDisregardedDirection == aOther.mDisregardedDirection &&
mOverscrollBehavior == aOther.mOverscrollBehavior && mOverscrollBehavior == aOther.mOverscrollBehavior &&
mScrollUpdates == aOther.mScrollUpdates; mScrollUpdates == aOther.mScrollUpdates;
@ -924,6 +926,9 @@ struct ScrollMetadata {
return mIsRDMTouchSimulationActive; return mIsRDMTouchSimulationActive;
} }
void SetPrefersReducedMotion(bool aValue) { mPrefersReducedMotion = aValue; }
bool PrefersReducedMotion() const { return mPrefersReducedMotion; }
bool DidContentGetPainted() const { return mDidContentGetPainted; } bool DidContentGetPainted() const { return mDidContentGetPainted; }
private: private:
@ -1037,6 +1042,11 @@ struct ScrollMetadata {
// can use the correct transforms. // can use the correct transforms.
bool mDidContentGetPainted : 1; bool mDidContentGetPainted : 1;
// Whether the user has requested the system minimze the amount of
// non-essential motion it uses (see the prefers-reduced-motion
// media query).
bool mPrefersReducedMotion : 1;
// The disregarded direction means the direction which is disregarded anyway, // The disregarded direction means the direction which is disregarded anyway,
// even if the scroll frame overflows in that direction and the direction is // even if the scroll frame overflows in that direction and the direction is
// specified as scrollable. This could happen in some scenarios, for instance, // specified as scrollable. This could happen in some scenarios, for instance,

Просмотреть файл

@ -5069,6 +5069,8 @@ void AsyncPanZoomController::NotifyLayersUpdated(
mScrollMetadata.SetForceDisableApz(aScrollMetadata.IsApzForceDisabled()); mScrollMetadata.SetForceDisableApz(aScrollMetadata.IsApzForceDisabled());
mScrollMetadata.SetIsRDMTouchSimulationActive( mScrollMetadata.SetIsRDMTouchSimulationActive(
aScrollMetadata.GetIsRDMTouchSimulationActive()); aScrollMetadata.GetIsRDMTouchSimulationActive());
mScrollMetadata.SetPrefersReducedMotion(
aScrollMetadata.PrefersReducedMotion());
mScrollMetadata.SetDisregardedDirection( mScrollMetadata.SetDisregardedDirection(
aScrollMetadata.GetDisregardedDirection()); aScrollMetadata.GetDisregardedDirection());
mScrollMetadata.SetOverscrollBehavior( mScrollMetadata.SetOverscrollBehavior(

Просмотреть файл

@ -138,6 +138,10 @@ class GenericOverscrollEffect : public OverscrollEffectBase {
void ConsumeOverscroll(ParentLayerPoint& aOverscroll, void ConsumeOverscroll(ParentLayerPoint& aOverscroll,
ScrollDirections aOverscrolableDirections) override { ScrollDirections aOverscrolableDirections) override {
if (mApzc.mScrollMetadata.PrefersReducedMotion()) {
return;
}
if (aOverscrolableDirections.contains(ScrollDirection::eHorizontal)) { if (aOverscrolableDirections.contains(ScrollDirection::eHorizontal)) {
mApzc.mX.OverscrollBy(aOverscroll.x); mApzc.mX.OverscrollBy(aOverscroll.x);
aOverscroll.x = 0; aOverscroll.x = 0;
@ -155,6 +159,10 @@ class GenericOverscrollEffect : public OverscrollEffectBase {
void HandleFlingOverscroll(const ParentLayerPoint& aVelocity, void HandleFlingOverscroll(const ParentLayerPoint& aVelocity,
SideBits aOverscrollSideBits) override { SideBits aOverscrollSideBits) override {
if (mApzc.mScrollMetadata.PrefersReducedMotion()) {
return;
}
mApzc.StartOverscrollAnimation(aVelocity, aOverscrollSideBits); mApzc.StartOverscrollAnimation(aVelocity, aOverscrollSideBits);
} }

Просмотреть файл

@ -29,6 +29,7 @@ var prefs = [
var overscroll_prefs = [...prefs, var overscroll_prefs = [...prefs,
["apz.overscroll.enabled", true], ["apz.overscroll.enabled", true],
["apz.overscroll.test_async_scroll_offset.enabled", true], ["apz.overscroll.test_async_scroll_offset.enabled", true],
["ui.prefersReducedMotion", 0],
]; ];
var subtests = [ var subtests = [

Просмотреть файл

@ -444,6 +444,7 @@ struct ParamTraits<mozilla::layers::ScrollMetadata>
WriteParam(aMsg, aParam.mResolutionUpdated); WriteParam(aMsg, aParam.mResolutionUpdated);
WriteParam(aMsg, aParam.mIsRDMTouchSimulationActive); WriteParam(aMsg, aParam.mIsRDMTouchSimulationActive);
WriteParam(aMsg, aParam.mDidContentGetPainted); WriteParam(aMsg, aParam.mDidContentGetPainted);
WriteParam(aMsg, aParam.mPrefersReducedMotion);
WriteParam(aMsg, aParam.mDisregardedDirection); WriteParam(aMsg, aParam.mDisregardedDirection);
WriteParam(aMsg, aParam.mOverscrollBehavior); WriteParam(aMsg, aParam.mOverscrollBehavior);
WriteParam(aMsg, aParam.mScrollUpdates); WriteParam(aMsg, aParam.mScrollUpdates);
@ -483,6 +484,8 @@ struct ParamTraits<mozilla::layers::ScrollMetadata>
&paramType::SetIsRDMTouchSimulationActive)) && &paramType::SetIsRDMTouchSimulationActive)) &&
ReadBoolForBitfield(aMsg, aIter, aResult, ReadBoolForBitfield(aMsg, aIter, aResult,
&paramType::SetDidContentGetPainted) && &paramType::SetDidContentGetPainted) &&
ReadBoolForBitfield(aMsg, aIter, aResult,
&paramType::SetPrefersReducedMotion) &&
ReadParam(aMsg, aIter, &aResult->mDisregardedDirection) && ReadParam(aMsg, aIter, &aResult->mDisregardedDirection) &&
ReadParam(aMsg, aIter, &aResult->mOverscrollBehavior) && ReadParam(aMsg, aIter, &aResult->mOverscrollBehavior) &&
ReadParam(aMsg, aIter, &aResult->mScrollUpdates); ReadParam(aMsg, aIter, &aResult->mScrollUpdates);

Просмотреть файл

@ -35,6 +35,7 @@
#include "mozilla/BasicEvents.h" #include "mozilla/BasicEvents.h"
#include "mozilla/ClearOnShutdown.h" #include "mozilla/ClearOnShutdown.h"
#include "mozilla/DisplayPortUtils.h" #include "mozilla/DisplayPortUtils.h"
#include "mozilla/GeckoBindings.h"
#include "mozilla/dom/AnonymousContent.h" #include "mozilla/dom/AnonymousContent.h"
#include "mozilla/dom/BrowserChild.h" #include "mozilla/dom/BrowserChild.h"
#include "mozilla/dom/CanvasUtils.h" #include "mozilla/dom/CanvasUtils.h"
@ -8782,6 +8783,9 @@ ScrollMetadata nsLayoutUtils::ComputeScrollMetadata(
metadata.SetForceDisableApz(true); metadata.SetForceDisableApz(true);
} }
metadata.SetPrefersReducedMotion(
Gecko_MediaFeatures_PrefersReducedMotion(document));
return metadata; return metadata;
} }

Просмотреть файл

@ -0,0 +1,24 @@
<!DOCTYPE html>
<html>
<head>
<style>
html {
scrollbar-width: none;
}
body {
height: 3000px;
margin: 0;
}
div {
position: absolute;
top: 0px;
width: 200px;
height: 200px;
background: green;
}
</style>
</head>
<body>
<div></div>
</body>
</html>

Просмотреть файл

@ -0,0 +1,39 @@
<!DOCTYPE html>
<html
reftest-async-scroll
reftest-displayport-x="0" reftest-displayport-y="0"
reftest-displayport-w="800" reftest-displayport-h="2000"
reftest-async-scroll-x="0" reftest-async-scroll-y="-200">
<head>
<style>
html {
scrollbar-width: none;
}
body {
height: 3000px;
margin: 0;
}
div {
position: absolute;
top: 0px;
width: 200px;
height: 200px;
background: green;
}
</style>
</head>
<body >
<!-- Test that an overscroll past one end of a viewport is rendered
as having the content create a gutter, and that
the overscroll is reduced by some factor such that
a 100px scroll must produce a rendered translation of less than
100px.
Current overscroll physics mean that an instantaneous overscroll
by 200px produces an 8px gutter. This is governed by the logic in
Axis::ApplyResistance(); if that logic is changed, this test will
need to be modified to account for the new result.
-->
<div></div>
</body>
</html>

Просмотреть файл

@ -100,6 +100,7 @@ fuzzy-if(!webrender,111-112,600-600) pref(apz.allow_zooming,true) == async-scrol
# on Android we have a different overscroll effect so this test is disabled # on Android we have a different overscroll effect so this test is disabled
skip-if(!asyncPan||Android) pref(apz.overscroll.enabled,true) pref(apz.overscroll.test_async_scroll_offset.enabled,true) == overscroll.html overscroll-ref.html skip-if(!asyncPan||Android) pref(apz.overscroll.enabled,true) pref(apz.overscroll.test_async_scroll_offset.enabled,true) == overscroll.html overscroll-ref.html
fails-if(webrender) skip-if(!asyncPan||Android) pref(apz.overscroll.enabled,true) pref(apz.overscroll.test_async_scroll_offset.enabled,true) == overscroll-fixed.html overscroll-ref.html fails-if(webrender) skip-if(!asyncPan||Android) pref(apz.overscroll.enabled,true) pref(apz.overscroll.test_async_scroll_offset.enabled,true) == overscroll-fixed.html overscroll-ref.html
skip-if(!asyncPan||Android) pref(ui.prefersReducedMotion,1) pref(apz.overscroll.enabled,true) pref(apz.overscroll.test_async_scroll_offset.enabled,true) == overscroll-reduced-motion.html no-overscroll-ref.html
# for this test, apz.allow_zooming is needed to ensure we take the containerless scrolling codepath that creates # for this test, apz.allow_zooming is needed to ensure we take the containerless scrolling codepath that creates
# an async zoom container (since we are testing a regression in that codepath) # an async zoom container (since we are testing a regression in that codepath)