зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1096513 - Disallow underscroll in APZC. r=botond
This commit is contained in:
Родитель
fa5c39586f
Коммит
c86dcd22c0
|
@ -2513,30 +2513,19 @@ Matrix4x4 AsyncPanZoomController::GetOverscrollTransform() const {
|
|||
float scaleX = 1 + kStretchFactor * fabsf(mX.GetOverscroll()) / mX.GetCompositionLength();
|
||||
float scaleY = 1 + kStretchFactor * fabsf(mY.GetOverscroll()) / mY.GetCompositionLength();
|
||||
|
||||
// If an axis is in underscroll, the interpretation of its overscroll
|
||||
// amount changes: instead of stretching along that axis, we compress.
|
||||
if (mX.IsInUnderscroll()) {
|
||||
scaleX = 1 / scaleX;
|
||||
}
|
||||
if (mY.IsInUnderscroll()) {
|
||||
scaleY = 1 / scaleY;
|
||||
}
|
||||
|
||||
// The scale is applied relative to the origin of the composition bounds, i.e.
|
||||
// it keeps the top-left corner of the content in place. This is fine if we
|
||||
// are overscrolling at the top or on the left, but if we are overscrolling
|
||||
// at the bottom or on the right, we want the bottom or right edge of the
|
||||
// content to stay in place instead, so we add a translation to compensate.
|
||||
ParentLayerPoint translation;
|
||||
bool overscrolledOnRight = (mX.GetOverscroll() > 0 && !mX.IsInUnderscroll())
|
||||
|| (mX.GetOverscroll() < 0 && mX.IsInUnderscroll());
|
||||
bool overscrolledOnRight = mX.GetOverscroll() > 0;
|
||||
if (overscrolledOnRight) {
|
||||
ParentLayerCoord overscrolledCompositionWidth = scaleX * compositionSize.width;
|
||||
ParentLayerCoord extraCompositionWidth = overscrolledCompositionWidth - compositionSize.width;
|
||||
translation.x = -extraCompositionWidth;
|
||||
}
|
||||
bool overscrolledAtBottom = (mY.GetOverscroll() > 0 && !mY.IsInUnderscroll())
|
||||
|| (mY.GetOverscroll() < 0 && mY.IsInUnderscroll());
|
||||
bool overscrolledAtBottom = mY.GetOverscroll() > 0;
|
||||
if (overscrolledAtBottom) {
|
||||
ParentLayerCoord overscrolledCompositionHeight = scaleY * compositionSize.height;
|
||||
ParentLayerCoord extraCompositionHeight = overscrolledCompositionHeight - compositionSize.height;
|
||||
|
|
|
@ -38,7 +38,9 @@ Axis::Axis(AsyncPanZoomController* aAsyncPanZoomController)
|
|||
mAxisLocked(false),
|
||||
mAsyncPanZoomController(aAsyncPanZoomController),
|
||||
mOverscroll(0),
|
||||
mInUnderscroll(false)
|
||||
mFirstOverscrollAnimationSample(0),
|
||||
mOverscrollOffset(0),
|
||||
mOverscrollScale(1.0f)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -190,11 +192,12 @@ void Axis::OverscrollBy(ParentLayerCoord aOverscroll) {
|
|||
}
|
||||
|
||||
ParentLayerCoord Axis::GetOverscroll() const {
|
||||
return mOverscroll;
|
||||
}
|
||||
ParentLayerCoord result = (mOverscroll - mOverscrollOffset) / mOverscrollScale;
|
||||
|
||||
bool Axis::IsInUnderscroll() const {
|
||||
return mInUnderscroll;
|
||||
// Assert that we return overscroll in the correct direction
|
||||
MOZ_ASSERT((result * mOverscrollOffset) >= 0.0f);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void Axis::StepOverscrollAnimation(double aStepDurationMilliseconds) {
|
||||
|
@ -218,6 +221,7 @@ void Axis::StepOverscrollAnimation(double aStepDurationMilliseconds) {
|
|||
// Apply spring force.
|
||||
float springForce = -1 * kSpringStiffness * mOverscroll;
|
||||
// Assume unit mass, so force = acceleration.
|
||||
float oldVelocity = mVelocity;
|
||||
mVelocity += springForce * aStepDurationMilliseconds;
|
||||
|
||||
// Apply dampening.
|
||||
|
@ -225,21 +229,38 @@ void Axis::StepOverscrollAnimation(double aStepDurationMilliseconds) {
|
|||
AXIS_LOG("%p|%s sampled overscroll animation, leaving velocity at %f\n",
|
||||
mAsyncPanZoomController, Name(), mVelocity);
|
||||
|
||||
// Adjust the amount of overscroll based on the velocity.
|
||||
// Note that we allow for oscillations. mInUnderscroll tracks whether
|
||||
// we are currently in a state where we have overshot and the spring is
|
||||
// displaced in the other direction.
|
||||
float oldOverscroll = mOverscroll;
|
||||
mOverscroll += (mVelocity * aStepDurationMilliseconds);
|
||||
bool signChange = (oldOverscroll * mOverscroll) < 0;
|
||||
if (signChange) {
|
||||
// If the sign of mOverscroll changed, we have either entered underscroll
|
||||
// or exited it.
|
||||
mInUnderscroll = !mInUnderscroll;
|
||||
// At the peak of each oscillation, record new offset and scaling factors for
|
||||
// overscroll, to ensure that GetOverscroll always returns a value of the
|
||||
// same sign, and that this value is correctly adjusted as the spring is
|
||||
// dampened.
|
||||
bool velocitySignChange = (oldVelocity * mVelocity) < 0;
|
||||
if (mFirstOverscrollAnimationSample == 0.0f) {
|
||||
mFirstOverscrollAnimationSample = mOverscroll;
|
||||
|
||||
// It's possible to start sampling overscroll with velocity == 0, or
|
||||
// velocity in the opposite direction of overscroll, so make sure we
|
||||
// correctly record the peak in this case.
|
||||
if ((mOverscroll >= 0 ? oldVelocity : -oldVelocity) <= 0.0f) {
|
||||
velocitySignChange = true;
|
||||
}
|
||||
}
|
||||
if (velocitySignChange) {
|
||||
bool oddOscillation = (mOverscroll.value * mFirstOverscrollAnimationSample.value) < 0.0f;
|
||||
mOverscrollOffset = oddOscillation ? mOverscroll : -mOverscroll;
|
||||
mOverscrollScale = 2.0f;
|
||||
}
|
||||
|
||||
// Adjust the amount of overscroll based on the velocity.
|
||||
// Note that we allow for oscillations.
|
||||
mOverscroll += (mVelocity * aStepDurationMilliseconds);
|
||||
}
|
||||
|
||||
bool Axis::SampleOverscrollAnimation(const TimeDuration& aDelta) {
|
||||
// Short-circuit early rather than running through all the sampling code.
|
||||
if (mVelocity == 0.0f && mOverscroll == 0.0f) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// We approximate the curve traced out by the velocity of the spring
|
||||
// over time by breaking up the curve into small segments over which we
|
||||
// consider the velocity to be constant. If the animation is sampled
|
||||
|
@ -267,9 +288,8 @@ bool Axis::SampleOverscrollAnimation(const TimeDuration& aDelta) {
|
|||
// velocity and overscroll are already low.
|
||||
AXIS_LOG("%p|%s oscillation dropped below threshold, going to rest\n",
|
||||
mAsyncPanZoomController, Name());
|
||||
mOverscroll = 0;
|
||||
ClearOverscroll();
|
||||
mVelocity = 0;
|
||||
mInUnderscroll = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -283,6 +303,9 @@ bool Axis::IsOverscrolled() const {
|
|||
|
||||
void Axis::ClearOverscroll() {
|
||||
mOverscroll = 0;
|
||||
mFirstOverscrollAnimationSample = 0;
|
||||
mOverscrollOffset = 0;
|
||||
mOverscrollScale = 1.0f;
|
||||
}
|
||||
|
||||
ParentLayerCoord Axis::PanStart() const {
|
||||
|
|
|
@ -91,34 +91,9 @@ public:
|
|||
* extreme allowed value in the relevant direction (that is, it must be at
|
||||
* its maximum value if we are overscrolled at our composition length, and
|
||||
* at its minimum value if we are overscrolled at the origin).
|
||||
* Note that if |mInUnderscroll| is true, the interpretation of this field
|
||||
* changes slightly (see below).
|
||||
*/
|
||||
ParentLayerCoord GetOverscroll() const;
|
||||
|
||||
/**
|
||||
* Return whether the axis is in underscroll.
|
||||
*
|
||||
* This flag is set when an overscroll animation is in a state where the
|
||||
* spring physics caused a snap-back movement to "overshoot" its target and
|
||||
* as a result the spring is stretched in a direction opposite to the one
|
||||
* when we were in overscroll. We call this situation "underscroll". When in
|
||||
* underscroll, GetOverscroll() can be nonzero, but rather than being
|
||||
* interpreted as overscroll (stretch) at the other end of the composition
|
||||
* bounds, it's interpeted as an "underscroll" (compression) at the same end.
|
||||
* This table summarizes what the possible combinations of GetOverscroll()
|
||||
* and IsInUnderscroll() mean:
|
||||
*
|
||||
* GetOverscroll() | IsInUnderscroll() | Description
|
||||
*-------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
* negative | false | The axis is overscrolled at its origin. A stretch is applied with the content fixed in place at the origin.
|
||||
* positive | false | The axis is overscrolled at its composition end. A stretch is applied with the content fixed in place at the composition end.
|
||||
* positive | true | The axis is underscrolled at its origin. A compression is applied with the content fixed in place at the origin.
|
||||
* negative | true | The axis is underscrolled at its composition end. A compression is applied with the content fixed in place at the composition end.
|
||||
*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
bool IsInUnderscroll() const;
|
||||
|
||||
/**
|
||||
* Sample the snap-back animation to relieve overscroll.
|
||||
* |aDelta| is the time since the last sample.
|
||||
|
@ -247,8 +222,23 @@ protected:
|
|||
float mVelocity; // Units: ParentLayerCoords per millisecond
|
||||
bool mAxisLocked; // Whether movement on this axis is locked.
|
||||
AsyncPanZoomController* mAsyncPanZoomController;
|
||||
ParentLayerCoord mOverscroll; // See GetOverscroll().
|
||||
bool mInUnderscroll; // See IsInUnderscroll().
|
||||
|
||||
// mOverscroll is the displacement of an oscillating spring from its resting
|
||||
// state. The resting state moves as the overscroll animation progresses.
|
||||
ParentLayerCoord mOverscroll;
|
||||
// Used to record the initial overscroll when we start sampling for animation.
|
||||
ParentLayerCoord mFirstOverscrollAnimationSample;
|
||||
// These two variables are used in combination to make sure that
|
||||
// GetOverscroll() never changes sign during animation. This is necessary,
|
||||
// as mOverscroll itself oscillates around zero during animation.
|
||||
// If we're not sampling overscroll animation, mOverscrollScale will be 1.0
|
||||
// and mOverscrollOffset will be zero.
|
||||
// If we are animating, after the overscroll reaches its peak,
|
||||
// mOverscrollScale will be 2.0 and mOverscrollOffset will store a value that
|
||||
// guarantees that the result of GetOverscroll() never changes sign.
|
||||
ParentLayerCoord mOverscrollOffset;
|
||||
float mOverscrollScale;
|
||||
|
||||
// A queue of (timestamp, velocity) pairs; these are the historical
|
||||
// velocities at the given timestamps. Timestamps are in milliseconds,
|
||||
// velocities are in screen pixels per ms. This member can only be
|
||||
|
|
Загрузка…
Ссылка в новой задаче