Bug 1697712 - Allow going into overscroll using the test async scroll offset r=tnikkel

Also add a reftest which uses this to test overscroll rendering.

Differential Revision: https://phabricator.services.mozilla.com/D102115
This commit is contained in:
Sawyer Bergeron 2021-03-20 02:20:42 +00:00
Родитель 1c61cfc77a
Коммит cca020a971
7 изменённых файлов: 119 добавлений и 4 удалений

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

@ -575,6 +575,7 @@ class MOZ_RAII AutoApplyAsyncTestAttributes final {
private:
AsyncPanZoomController* mApzc;
FrameMetrics mPrevFrameMetrics;
ParentLayerPoint mPrevOverscroll;
const RecursiveMutexAutoLock& mProofOfLock;
};
@ -587,12 +588,14 @@ AutoApplyAsyncTestAttributes::AutoApplyAsyncTestAttributes(
// query the async transforms non-const.
: mApzc(const_cast<AsyncPanZoomController*>(aApzc)),
mPrevFrameMetrics(aApzc->Metrics()),
mPrevOverscroll(aApzc->GetOverscrollAmount()),
mProofOfLock(aProofOfLock) {
mApzc->ApplyAsyncTestAttributes(aProofOfLock);
}
AutoApplyAsyncTestAttributes::~AutoApplyAsyncTestAttributes() {
mApzc->UnapplyAsyncTestAttributes(mProofOfLock, mPrevFrameMetrics);
mApzc->UnapplyAsyncTestAttributes(mProofOfLock, mPrevFrameMetrics,
mPrevOverscroll);
}
class ZoomAnimation : public AsyncPanZoomAnimation {
@ -3710,6 +3713,16 @@ ExternalPoint AsyncPanZoomController::GetFirstExternalTouchPoint(
((SingleTouchData&)aEvent.mTouches[0]).mScreenPoint);
}
ParentLayerPoint AsyncPanZoomController::GetOverscrollAmount() const {
return {mX.GetOverscroll(), mY.GetOverscroll()};
}
void AsyncPanZoomController::RestoreOverscrollAmount(
const ParentLayerPoint& aOverscroll) {
mX.RestoreOverscroll(aOverscroll.x);
mY.RestoreOverscroll(aOverscroll.y);
}
void AsyncPanZoomController::StartAnimation(AsyncPanZoomAnimation* aAnimation) {
RecursiveMutexAutoLock lock(mRecursiveMutex);
mAnimation = aAnimation;
@ -4254,6 +4267,7 @@ bool AsyncPanZoomController::UpdateAnimation(
AsyncTransformComponentMatrix AsyncPanZoomController::GetOverscrollTransform(
AsyncTransformConsumer aMode) const {
RecursiveMutexAutoLock lock(mRecursiveMutex);
AutoApplyAsyncTestAttributes testAttributeApplier(this, lock);
if (aMode == eForCompositing && mScrollMetadata.IsApzForceDisabled()) {
return AsyncTransformComponentMatrix();
@ -4289,13 +4303,14 @@ bool AsyncPanZoomController::AdvanceAnimations(const SampleTime& aSampleTime) {
{
RecursiveMutexAutoLock lock(mRecursiveMutex);
{ // scope lock
CSSRect visibleRect = GetVisibleRect(lock);
MutexAutoLock lock2(mCheckerboardEventLock);
// Update RendertraceProperty before UpdateAnimation() call, since
// the UpdateAnimation() updates effective ScrollOffset for next frame
// if APZFrameDelay is enabled.
if (mCheckerboardEvent) {
mCheckerboardEvent->UpdateRendertraceProperty(
CheckerboardEvent::UserVisible, GetVisibleRect(lock));
CheckerboardEvent::UserVisible, visibleRect);
}
}
@ -4481,7 +4496,16 @@ void AsyncPanZoomController::ApplyAsyncTestAttributes(
// mSampledState.front(). We can even save/restore that SampledAPZCState
// instance in the AutoApplyAsyncTestAttributes instead of Metrics().
Metrics().ZoomBy(mTestAsyncZoom.scale);
CSSPoint asyncScrollPosition = Metrics().GetVisualScrollOffset();
CSSPoint requestedPoint =
asyncScrollPosition + this->mTestAsyncScrollOffset;
CSSPoint clampedPoint =
Metrics().CalculateScrollRange().ClampPoint(requestedPoint);
CSSPoint difference = mTestAsyncScrollOffset - clampedPoint;
ScrollByAndClamp(mTestAsyncScrollOffset);
ParentLayerPoint overscroll = difference * Metrics().GetZoom();
OverscrollBy(overscroll);
ResampleCompositedAsyncTransform(aProofOfLock);
}
}
@ -4490,13 +4514,15 @@ void AsyncPanZoomController::ApplyAsyncTestAttributes(
void AsyncPanZoomController::UnapplyAsyncTestAttributes(
const RecursiveMutexAutoLock& aProofOfLock,
const FrameMetrics& aPrevFrameMetrics) {
const FrameMetrics& aPrevFrameMetrics,
const ParentLayerPoint& aPrevOverscroll) {
MOZ_ASSERT(mTestAttributeAppliers >= 1);
--mTestAttributeAppliers;
if (mTestAttributeAppliers == 0) {
if (mTestAsyncScrollOffset != CSSPoint() ||
mTestAsyncZoom != LayerToParentLayerScale()) {
Metrics() = aPrevFrameMetrics;
RestoreOverscrollAmount(aPrevOverscroll);
ResampleCompositedAsyncTransform(aProofOfLock);
}
}

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

@ -794,6 +794,17 @@ class AsyncPanZoomController {
*/
ExternalPoint GetFirstExternalTouchPoint(const MultiTouchInput& aEvent);
/**
* Gets the amount by which this APZC is overscrolled along both axes.
*/
ParentLayerPoint GetOverscrollAmount() const;
/**
* Restore the amount by which this APZC is overscrolled along both axes
* to the specified amount. This is for test-related use; overscrolling
* as a result of user input should happen via OverscrollBy().
*/
void RestoreOverscrollAmount(const ParentLayerPoint& aOverscroll);
/**
* Sets the panning state basing on the pan direction angle and current
* touch-action value.
@ -1245,7 +1256,8 @@ class AsyncPanZoomController {
* by |ApplyAsyncTestAttributes|.
*/
void UnapplyAsyncTestAttributes(const RecursiveMutexAutoLock& aProofOfLock,
const FrameMetrics& aPrevFrameMetrics);
const FrameMetrics& aPrevFrameMetrics,
const ParentLayerPoint& aPrevOverscroll);
/* ===================================================================
* The functions and members in this section are used to manage

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

@ -180,6 +180,10 @@ void Axis::OverscrollBy(ParentLayerCoord aOverscroll) {
ParentLayerCoord Axis::GetOverscroll() const { return mOverscroll; }
void Axis::RestoreOverscroll(ParentLayerCoord aOverscroll) {
mOverscroll = aOverscroll;
}
void Axis::StartOverscrollAnimation(float aVelocity) {
aVelocity = clamped(aVelocity / 2.0f, -20.0f, 20.0f);
SetVelocity(aVelocity);

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

@ -141,6 +141,13 @@ class Axis {
*/
ParentLayerCoord GetOverscroll() const;
/**
* Restore the amount by which this axis is overscrolled to the specified
* amount. This is for test-related use; overscrolling as a result of user
* input should happen via OverscrollBy().
*/
void RestoreOverscroll(ParentLayerCoord aOverscroll);
/**
* Start an overscroll animation with the given initial velocity.
*/

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

@ -0,0 +1,24 @@
<!DOCTYPE html>
<html>
<head>
<style>
html {
scrollbar-width: none;
}
body {
height: 3000px;
margin: 0;
}
div {
position: absolute;
top: 8px;
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>

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

@ -97,6 +97,9 @@ skip-if(!Android) pref(apz.allow_zooming,true) == position-sticky-async-zoom-2.h
fuzzy-if(!webrender,111-112,600-600) pref(apz.allow_zooming,true) == async-scroll-and-zoom.html async-scroll-and-zoom-ref.html
# on Android we have a different overscroll effect so this test is disabled
pref(apz.overscroll.enabled,true) skip-if(!asyncPan || Android) == overscroll.html overscroll-ref.html
# 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)
skip-if(!Android) pref(apz.allow_zooming,true) test-pref(apz.fixed-margin-override.enabled,true) test-pref(apz.fixed-margin-override.bottom,50) == dynamic-toolbar-fixed-bottom-1.html dynamic-toolbar-fixed-bottom-1-ref.html