Clamp APZ wheel animations to their scrollable range. (bug 1152011 part 2, r=botond)

This commit is contained in:
David Anderson 2015-04-12 17:47:11 -07:00
parent 94f9cac02e
commit eb5695f5af
5 changed files with 66 additions and 14 deletions

View File

@ -8,6 +8,8 @@
#define mozilla_layers_APZUtils_h
#include <stdint.h> // for uint32_t
#include "mozilla/gfx/Point.h"
#include "mozilla/FloatingPoint.h"
namespace mozilla {
namespace layers {
@ -36,6 +38,13 @@ enum class ScrollSource {
typedef uint32_t TouchBehaviorFlags;
template <typename Units>
static bool IsZero(const gfx::PointTyped<Units>& aPoint)
{
return FuzzyEqualsAdditive(aPoint.x, 0.0f)
&& FuzzyEqualsAdditive(aPoint.y, 0.0f);
}
}
}

View File

@ -370,13 +370,6 @@ static bool IsCloseToVertical(float aAngle, float aThreshold)
return (fabs(aAngle - (M_PI / 2)) < aThreshold);
}
template <typename Units>
static bool IsZero(const gfx::PointTyped<Units>& aPoint)
{
return FuzzyEqualsAdditive(aPoint.x, 0.0f)
&& FuzzyEqualsAdditive(aPoint.y, 0.0f);
}
static inline void LogRendertraceRect(const ScrollableLayerGuid& aGuid, const char* aDesc, const char* aColor, const CSSRect& aRect)
{
#ifdef APZC_ENABLE_RENDERTRACE

View File

@ -410,6 +410,23 @@ bool Axis::CanScroll(double aDelta) const
return DisplacementWillOverscrollAmount(delta) != delta;
}
CSSCoord Axis::ClampOriginToScrollableRect(CSSCoord aOrigin) const
{
CSSToParentLayerScale zoom = GetScaleForAxis(GetFrameMetrics().GetZoom());
ParentLayerCoord origin = aOrigin * zoom;
ParentLayerCoord result;
if (origin < GetPageStart()) {
result = GetPageStart();
} else if (origin + GetCompositionLength() > GetPageEnd()) {
result = GetPageEnd() - GetCompositionLength();
} else {
result = origin;
}
return result / zoom;
}
bool Axis::CanScrollNow() const {
return !mAxisLocked && CanScroll();
}
@ -549,6 +566,11 @@ ParentLayerCoord AxisX::GetRectOffset(const ParentLayerRect& aRect) const
return aRect.x;
}
CSSToParentLayerScale AxisX::GetScaleForAxis(const CSSToParentLayerScale2D& aScale) const
{
return CSSToParentLayerScale(aScale.xScale);
}
ScreenPoint AxisX::MakePoint(ScreenCoord aCoord) const
{
return ScreenPoint(aCoord, 0);
@ -580,6 +602,11 @@ ParentLayerCoord AxisY::GetRectOffset(const ParentLayerRect& aRect) const
return aRect.y;
}
CSSToParentLayerScale AxisY::GetScaleForAxis(const CSSToParentLayerScale2D& aScale) const
{
return CSSToParentLayerScale(aScale.yScale);
}
ScreenPoint AxisY::MakePoint(ScreenCoord aCoord) const
{
return ScreenPoint(0, aCoord);

View File

@ -168,6 +168,12 @@ public:
*/
bool CanScrollNow() const;
/**
* Clamp a point to the page's scrollable bounds. That is, a scroll
* destination to the returned point will not contain any overscroll.
*/
CSSCoord ClampOriginToScrollableRect(CSSCoord aOrigin) const;
void SetAxisLocked(bool aAxisLocked) { mAxisLocked = aAxisLocked; }
/**
@ -226,6 +232,7 @@ public:
virtual ParentLayerCoord GetPointOffset(const ParentLayerPoint& aPoint) const = 0;
virtual ParentLayerCoord GetRectLength(const ParentLayerRect& aRect) const = 0;
virtual ParentLayerCoord GetRectOffset(const ParentLayerRect& aRect) const = 0;
virtual CSSToParentLayerScale GetScaleForAxis(const CSSToParentLayerScale2D& aScale) const = 0;
virtual ScreenPoint MakePoint(ScreenCoord aCoord) const = 0;
@ -285,6 +292,7 @@ public:
virtual ParentLayerCoord GetPointOffset(const ParentLayerPoint& aPoint) const override;
virtual ParentLayerCoord GetRectLength(const ParentLayerRect& aRect) const override;
virtual ParentLayerCoord GetRectOffset(const ParentLayerRect& aRect) const override;
virtual CSSToParentLayerScale GetScaleForAxis(const CSSToParentLayerScale2D& aScale) const override;
virtual ScreenPoint MakePoint(ScreenCoord aCoord) const override;
virtual const char* Name() const override;
};
@ -295,6 +303,7 @@ public:
virtual ParentLayerCoord GetPointOffset(const ParentLayerPoint& aPoint) const override;
virtual ParentLayerCoord GetRectLength(const ParentLayerRect& aRect) const override;
virtual ParentLayerCoord GetRectOffset(const ParentLayerRect& aRect) const override;
virtual CSSToParentLayerScale GetScaleForAxis(const CSSToParentLayerScale2D& aScale) const override;
virtual ScreenPoint MakePoint(ScreenCoord aCoord) const override;
virtual const char* Name() const override;
};

View File

@ -21,7 +21,15 @@ void
WheelScrollAnimation::Update(TimeStamp aTime, nsPoint aDelta, const nsSize& aCurrentVelocity)
{
InitPreferences(aTime);
mFinalDestination += aDelta;
// Clamp the final destination to the scrollable area.
CSSPoint clamped = CSSPoint::FromAppUnits(mFinalDestination);
clamped.x = mApzc.mX.ClampOriginToScrollableRect(clamped.x);
clamped.y = mApzc.mY.ClampOriginToScrollableRect(clamped.y);
mFinalDestination = CSSPoint::ToAppUnits(clamped);
AsyncScrollBase::Update(aTime, mFinalDestination, aCurrentVelocity);
}
@ -29,24 +37,30 @@ bool
WheelScrollAnimation::DoSample(FrameMetrics& aFrameMetrics, const TimeDuration& aDelta)
{
TimeStamp now = AsyncPanZoomController::GetFrameTime();
if (IsFinished(now)) {
return false;
}
CSSToParentLayerScale2D zoom = aFrameMetrics.GetZoom();
nsPoint position = PositionAt(now);
// If the animation is finished, make sure the final position is correct by
// using one last displacement. Otherwise, compute the delta via the timing
// function as normal.
bool finished = IsFinished(now);
nsPoint sampledDest = finished
? mDestination
: PositionAt(now);
ParentLayerPoint displacement =
(CSSPoint::FromAppUnits(position) - aFrameMetrics.GetScrollOffset()) * zoom;
(CSSPoint::FromAppUnits(sampledDest) - aFrameMetrics.GetScrollOffset()) * zoom;
// Note: we ignore overscroll for wheel animations.
ParentLayerPoint adjustedOffset, overscroll;
mApzc.mX.AdjustDisplacement(displacement.x, adjustedOffset.x, overscroll.x);
mApzc.mY.AdjustDisplacement(displacement.y, adjustedOffset.y, overscroll.y,
!aFrameMetrics.AllowVerticalScrollWithWheel());
if (IsZero(adjustedOffset)) {
// Nothing more to do - end the animation.
return false;
}
aFrameMetrics.ScrollBy(adjustedOffset / zoom);
return true;
return !finished;
}
void