зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1402498 - Add ScrollAnimationMSDPhysics, can be enabled using general.smoothScroll.msdPhysics.enabled. r=rhunt
MozReview-Commit-ID: fr8Q9iod5k --HG-- extra : rebase_source : b9113d40081371872deff6aade13fd226b3e72a9
This commit is contained in:
Родитель
c2ed209689
Коммит
4b4d6f1561
|
@ -11,6 +11,7 @@
|
|||
#include "nsPoint.h"
|
||||
#include "ScrollAnimationPhysics.h"
|
||||
#include "ScrollAnimationBezierPhysics.h"
|
||||
#include "ScrollAnimationMSDPhysics.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
@ -19,10 +20,14 @@ GenericScrollAnimation::GenericScrollAnimation(AsyncPanZoomController& aApzc,
|
|||
const nsPoint& aInitialPosition,
|
||||
const ScrollAnimationBezierPhysicsSettings& aSettings)
|
||||
: mApzc(aApzc)
|
||||
, mAnimationPhysics(MakeUnique<ScrollAnimationBezierPhysics>(aInitialPosition, aSettings))
|
||||
, mFinalDestination(aInitialPosition)
|
||||
, mForceVerticalOverscroll(false)
|
||||
{
|
||||
if (gfxPrefs::SmoothScrollMSDPhysicsEnabled()) {
|
||||
mAnimationPhysics = MakeUnique<ScrollAnimationMSDPhysics>(aInitialPosition);
|
||||
} else {
|
||||
mAnimationPhysics = MakeUnique<ScrollAnimationBezierPhysics>(aInitialPosition, aSettings);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -404,6 +404,21 @@ private:
|
|||
DECL_GFX_PREF(Live, "general.smoothScroll.stopDecelerationWeighting",
|
||||
SmoothScrollStopDecelerationWeighting, float, 0.4f);
|
||||
|
||||
DECL_GFX_PREF(Live, "general.smoothScroll.msdPhysics.enabled",
|
||||
SmoothScrollMSDPhysicsEnabled, bool, false);
|
||||
DECL_GFX_PREF(Live, "general.smoothScroll.msdPhysics.continuousMotionMaxDeltaMS",
|
||||
SmoothScrollMSDPhysicsContinuousMotionMaxDeltaMS, int32_t, 120);
|
||||
DECL_GFX_PREF(Live, "general.smoothScroll.msdPhysics.motionBeginSpringConstant",
|
||||
SmoothScrollMSDPhysicsMotionBeginSpringConstant, int32_t, 1250);
|
||||
DECL_GFX_PREF(Live, "general.smoothScroll.msdPhysics.slowdownMinDeltaMS",
|
||||
SmoothScrollMSDPhysicsSlowdownMinDeltaMS, int32_t, 12);
|
||||
DECL_GFX_PREF(Live, "general.smoothScroll.msdPhysics.slowdownMinDeltaRatio",
|
||||
SmoothScrollMSDPhysicsSlowdownMinDeltaRatio, float, 1.3f);
|
||||
DECL_GFX_PREF(Live, "general.smoothScroll.msdPhysics.slowdownSpringConstant",
|
||||
SmoothScrollMSDPhysicsSlowdownSpringConstant, int32_t, 2000);
|
||||
DECL_GFX_PREF(Live, "general.smoothScroll.msdPhysics.regularSpringConstant",
|
||||
SmoothScrollMSDPhysicsRegularSpringConstant, int32_t, 1000);
|
||||
|
||||
DECL_GFX_PREF(Once, "gfx.android.rgb16.force", AndroidRGB16Force, bool, false);
|
||||
#if defined(ANDROID)
|
||||
DECL_GFX_PREF(Once, "gfx.apitrace.enabled", UseApitrace, bool, false);
|
||||
|
|
|
@ -0,0 +1,109 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "ScrollAnimationMSDPhysics.h"
|
||||
#include "gfxPrefs.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
ScrollAnimationMSDPhysics::ScrollAnimationMSDPhysics(const nsPoint& aStartPos)
|
||||
: mStartPos(aStartPos)
|
||||
, mModelX(0, 0, 0, gfxPrefs::SmoothScrollMSDPhysicsRegularSpringConstant(), 1)
|
||||
, mModelY(0, 0, 0, gfxPrefs::SmoothScrollMSDPhysicsRegularSpringConstant(), 1)
|
||||
, mIsFirstIteration(true)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
ScrollAnimationMSDPhysics::Update(const TimeStamp& aTime,
|
||||
const nsPoint& aDestination,
|
||||
const nsSize& aCurrentVelocity)
|
||||
{
|
||||
double springConstant = ComputeSpringConstant(aTime);
|
||||
|
||||
// mLastSimulatedTime is the most recent time that this animation has been
|
||||
// "observed" at. We don't want to update back to a state in the past, so we
|
||||
// set mStartTime to the more recent of mLastSimulatedTime and aTime.
|
||||
// aTime can be in the past if we're processing an input event whose internal
|
||||
// timestamp is in the past.
|
||||
if (mLastSimulatedTime && aTime < mLastSimulatedTime) {
|
||||
mStartTime = mLastSimulatedTime;
|
||||
} else {
|
||||
mStartTime = aTime;
|
||||
}
|
||||
|
||||
if (!mIsFirstIteration) {
|
||||
mStartPos = PositionAt(mStartTime);
|
||||
}
|
||||
|
||||
mLastSimulatedTime = mStartTime;
|
||||
mDestination = aDestination;
|
||||
mModelX = AxisPhysicsMSDModel(mStartPos.x, aDestination.x,
|
||||
aCurrentVelocity.width, springConstant, 1);
|
||||
mModelY = AxisPhysicsMSDModel(mStartPos.y, aDestination.y,
|
||||
aCurrentVelocity.height, springConstant, 1);
|
||||
mIsFirstIteration = false;
|
||||
}
|
||||
|
||||
double
|
||||
ScrollAnimationMSDPhysics::ComputeSpringConstant(const TimeStamp& aTime)
|
||||
{
|
||||
if (!mPreviousEventTime) {
|
||||
mPreviousEventTime = aTime;
|
||||
mPreviousDelta = TimeDuration();
|
||||
return gfxPrefs::SmoothScrollMSDPhysicsMotionBeginSpringConstant();
|
||||
}
|
||||
|
||||
TimeDuration delta = aTime - mPreviousEventTime;
|
||||
TimeDuration previousDelta = mPreviousDelta;
|
||||
|
||||
mPreviousEventTime = aTime;
|
||||
mPreviousDelta = delta;
|
||||
|
||||
double deltaMS = delta.ToMilliseconds();
|
||||
if (deltaMS >= gfxPrefs::SmoothScrollMSDPhysicsContinuousMotionMaxDeltaMS()) {
|
||||
return gfxPrefs::SmoothScrollMSDPhysicsMotionBeginSpringConstant();
|
||||
}
|
||||
|
||||
if (previousDelta &&
|
||||
deltaMS >= gfxPrefs::SmoothScrollMSDPhysicsSlowdownMinDeltaMS() &&
|
||||
deltaMS >= previousDelta.ToMilliseconds() * gfxPrefs::SmoothScrollMSDPhysicsSlowdownMinDeltaRatio()) {
|
||||
// The rate of events has slowed (the time delta between events has
|
||||
// increased) enough that we think that the current scroll motion is coming
|
||||
// to a stop. Use a stiffer spring in order to reach the destination more
|
||||
// quickly.
|
||||
return gfxPrefs::SmoothScrollMSDPhysicsSlowdownSpringConstant();
|
||||
}
|
||||
|
||||
return gfxPrefs::SmoothScrollMSDPhysicsRegularSpringConstant();
|
||||
}
|
||||
|
||||
void
|
||||
ScrollAnimationMSDPhysics::SimulateUntil(const TimeStamp& aTime)
|
||||
{
|
||||
if (!mLastSimulatedTime || aTime < mLastSimulatedTime) {
|
||||
return;
|
||||
}
|
||||
TimeDuration delta = aTime - mLastSimulatedTime;
|
||||
mModelX.Simulate(delta);
|
||||
mModelY.Simulate(delta);
|
||||
mLastSimulatedTime = aTime;
|
||||
}
|
||||
|
||||
nsPoint
|
||||
ScrollAnimationMSDPhysics::PositionAt(const TimeStamp& aTime)
|
||||
{
|
||||
SimulateUntil(aTime);
|
||||
return nsPoint(NSToCoordRound(mModelX.GetPosition()),
|
||||
NSToCoordRound(mModelY.GetPosition()));
|
||||
}
|
||||
|
||||
nsSize
|
||||
ScrollAnimationMSDPhysics::VelocityAt(const TimeStamp& aTime)
|
||||
{
|
||||
SimulateUntil(aTime);
|
||||
return nsSize(NSToCoordRound(mModelX.GetVelocity()),
|
||||
NSToCoordRound(mModelY.GetVelocity()));
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_layout_ScrollAnimationMSDPhysics_h_
|
||||
#define mozilla_layout_ScrollAnimationMSDPhysics_h_
|
||||
|
||||
#include "ScrollAnimationPhysics.h"
|
||||
#include "mozilla/layers/AxisPhysicsMSDModel.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
// This class implements a cubic MSD timing function and automatically
|
||||
// adapts the animation duration based on the scrolling rate.
|
||||
class ScrollAnimationMSDPhysics : public ScrollAnimationPhysics
|
||||
{
|
||||
public:
|
||||
typedef mozilla::layers::AxisPhysicsMSDModel AxisPhysicsMSDModel;
|
||||
|
||||
explicit ScrollAnimationMSDPhysics(const nsPoint& aStartPos);
|
||||
|
||||
void Update(const TimeStamp& aTime,
|
||||
const nsPoint& aDestination,
|
||||
const nsSize& aCurrentVelocity) override;
|
||||
|
||||
// Get the velocity at a point in time in nscoords/sec.
|
||||
nsSize VelocityAt(const TimeStamp& aTime) override;
|
||||
|
||||
// Returns the expected scroll position at a given point in time, in app
|
||||
// units, relative to the scroll frame.
|
||||
nsPoint PositionAt(const TimeStamp& aTime) override;
|
||||
|
||||
bool IsFinished(const TimeStamp& aTime) override {
|
||||
SimulateUntil(aTime);
|
||||
return mModelX.IsFinished(1) && mModelY.IsFinished(1);
|
||||
}
|
||||
|
||||
protected:
|
||||
double ComputeSpringConstant(const TimeStamp& aTime);
|
||||
void SimulateUntil(const TimeStamp& aTime);
|
||||
|
||||
TimeStamp mPreviousEventTime;
|
||||
TimeDuration mPreviousDelta;
|
||||
|
||||
TimeStamp mStartTime;
|
||||
|
||||
nsPoint mStartPos;
|
||||
nsPoint mDestination;
|
||||
TimeStamp mLastSimulatedTime;
|
||||
AxisPhysicsMSDModel mModelX;
|
||||
AxisPhysicsMSDModel mModelY;
|
||||
bool mIsFirstIteration;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_layout_ScrollAnimationMSDPhysics_h_
|
|
@ -101,6 +101,7 @@ EXPORTS += [
|
|||
'nsTextRunTransformations.h',
|
||||
'RubyUtils.h',
|
||||
'ScrollAnimationBezierPhysics.h',
|
||||
'ScrollAnimationMSDPhysics.h',
|
||||
'ScrollAnimationPhysics.h',
|
||||
'ScrollbarActivity.h',
|
||||
'ScrollSnap.h',
|
||||
|
@ -178,6 +179,7 @@ UNIFIED_SOURCES += [
|
|||
'ReflowOutput.cpp',
|
||||
'RubyUtils.cpp',
|
||||
'ScrollAnimationBezierPhysics.cpp',
|
||||
'ScrollAnimationMSDPhysics.cpp',
|
||||
'ScrollbarActivity.cpp',
|
||||
'ScrollSnap.cpp',
|
||||
'ScrollVelocityQueue.cpp',
|
||||
|
|
|
@ -59,6 +59,7 @@
|
|||
#include "gfxPrefs.h"
|
||||
#include "ScrollAnimationPhysics.h"
|
||||
#include "ScrollAnimationBezierPhysics.h"
|
||||
#include "ScrollAnimationMSDPhysics.h"
|
||||
#include "ScrollSnap.h"
|
||||
#include "UnitTransforms.h"
|
||||
#include "nsPluginFrame.h"
|
||||
|
@ -1912,7 +1913,7 @@ private:
|
|||
* (also maintain previous timestamps - which are only used here).
|
||||
*/
|
||||
static ScrollAnimationBezierPhysicsSettings
|
||||
ComputeAnimationSettingsForOrigin(nsIAtom *aOrigin)
|
||||
ComputeBezierAnimationSettingsForOrigin(nsIAtom *aOrigin)
|
||||
{
|
||||
int32_t minMS = 0;
|
||||
int32_t maxMS = 0;
|
||||
|
@ -1972,9 +1973,14 @@ ScrollFrameHelper::AsyncScroll::InitSmoothScroll(TimeStamp aTime,
|
|||
// Read preferences only on first iteration or for a different event origin.
|
||||
if (!mAnimationPhysics || aOrigin != mOrigin) {
|
||||
mOrigin = aOrigin;
|
||||
ScrollAnimationBezierPhysicsSettings settings = ComputeAnimationSettingsForOrigin(mOrigin);
|
||||
mAnimationPhysics =
|
||||
MakeUnique<ScrollAnimationBezierPhysics>(aInitialPosition, settings);
|
||||
if (gfxPrefs::SmoothScrollMSDPhysicsEnabled()) {
|
||||
mAnimationPhysics = MakeUnique<ScrollAnimationMSDPhysics>(aInitialPosition);
|
||||
} else {
|
||||
ScrollAnimationBezierPhysicsSettings settings =
|
||||
ComputeBezierAnimationSettingsForOrigin(mOrigin);
|
||||
mAnimationPhysics =
|
||||
MakeUnique<ScrollAnimationBezierPhysics>(aInitialPosition, settings);
|
||||
}
|
||||
}
|
||||
|
||||
mRange = aRange;
|
||||
|
|
|
@ -2806,6 +2806,14 @@ pref("general.smoothScroll.durationToIntervalRatio", 200);
|
|||
// These two prefs determine the timing function.
|
||||
pref("general.smoothScroll.currentVelocityWeighting", "0.25");
|
||||
pref("general.smoothScroll.stopDecelerationWeighting", "0.4");
|
||||
// Alternative smooth scroll physics ("MSD" = Mass-Spring-Damper)
|
||||
pref("general.smoothScroll.msdPhysics.enabled", false);
|
||||
pref("general.smoothScroll.msdPhysics.continuousMotionMaxDeltaMS", 120);
|
||||
pref("general.smoothScroll.msdPhysics.motionBeginSpringConstant", 1250);
|
||||
pref("general.smoothScroll.msdPhysics.slowdownMinDeltaMS", 12);
|
||||
pref("general.smoothScroll.msdPhysics.slowdownMinDeltaRatio", "1.3");
|
||||
pref("general.smoothScroll.msdPhysics.slowdownSpringConstant", 2000);
|
||||
pref("general.smoothScroll.msdPhysics.regularSpringConstant", 1000);
|
||||
|
||||
pref("profile.confirm_automigration",true);
|
||||
// profile.migration_behavior determines how the profiles root is set
|
||||
|
|
Загрузка…
Ссылка в новой задаче