128 lines
4.6 KiB
C++
128 lines
4.6 KiB
C++
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
/* 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 "FlingAccelerator.h"
|
|
|
|
#include "mozilla/StaticPrefs_apz.h"
|
|
|
|
#include "GenericFlingAnimation.h" // for FLING_LOG and FlingHandoffState
|
|
|
|
namespace mozilla {
|
|
namespace layers {
|
|
|
|
void FlingAccelerator::Reset() {
|
|
mPreviousFlingStartingVelocity = ParentLayerPoint{};
|
|
mPreviousFlingCancelVelocity = ParentLayerPoint{};
|
|
mIsTracking = false;
|
|
}
|
|
|
|
static bool SameDirection(float aVelocity1, float aVelocity2) {
|
|
return (aVelocity1 == 0.0f) || (aVelocity2 == 0.0f) ||
|
|
(IsNegative(aVelocity1) == IsNegative(aVelocity2));
|
|
}
|
|
|
|
static float Accelerate(float aBase, float aSupplemental) {
|
|
return (aBase * StaticPrefs::apz_fling_accel_base_mult()) +
|
|
(aSupplemental * StaticPrefs::apz_fling_accel_supplemental_mult());
|
|
}
|
|
|
|
ParentLayerPoint FlingAccelerator::GetFlingStartingVelocity(
|
|
const SampleTime& aNow, const ParentLayerPoint& aVelocity,
|
|
const FlingHandoffState& aHandoffState) {
|
|
// If the fling should be accelerated and is in the same direction as the
|
|
// previous fling, boost the velocity to be the sum of the two. Check separate
|
|
// axes separately because we could have two vertical flings with small
|
|
// horizontal components on the opposite side of zero, and we still want the
|
|
// y-fling to get accelerated.
|
|
ParentLayerPoint velocity = aVelocity;
|
|
if (ShouldAccelerate(aNow, aVelocity, aHandoffState)) {
|
|
if (velocity.x != 0 &&
|
|
SameDirection(velocity.x, mPreviousFlingStartingVelocity.x)) {
|
|
velocity.x = Accelerate(velocity.x, mPreviousFlingStartingVelocity.x);
|
|
FLING_LOG("%p Applying fling x-acceleration from %f to %f (delta %f)\n",
|
|
this, aVelocity.x.value, velocity.x.value,
|
|
mPreviousFlingStartingVelocity.x.value);
|
|
}
|
|
if (velocity.y != 0 &&
|
|
SameDirection(velocity.y, mPreviousFlingStartingVelocity.y)) {
|
|
velocity.y = Accelerate(velocity.y, mPreviousFlingStartingVelocity.y);
|
|
FLING_LOG("%p Applying fling y-acceleration from %f to %f (delta %f)\n",
|
|
this, aVelocity.y.value, velocity.y.value,
|
|
mPreviousFlingStartingVelocity.y.value);
|
|
}
|
|
}
|
|
|
|
Reset();
|
|
|
|
mPreviousFlingStartingVelocity = velocity;
|
|
mIsTracking = true;
|
|
|
|
return velocity;
|
|
}
|
|
|
|
bool FlingAccelerator::ShouldAccelerate(
|
|
const SampleTime& aNow, const ParentLayerPoint& aVelocity,
|
|
const FlingHandoffState& aHandoffState) const {
|
|
if (!IsTracking()) {
|
|
FLING_LOG("%p Fling accelerator was reset, not accelerating.\n", this);
|
|
return false;
|
|
}
|
|
|
|
if (!aHandoffState.mTouchStartRestingTime) {
|
|
FLING_LOG("%p Don't have a touch start resting time, not accelerating.\n",
|
|
this);
|
|
return false;
|
|
}
|
|
|
|
double msBetweenTouchStartAndPanStart =
|
|
aHandoffState.mTouchStartRestingTime->ToMilliseconds();
|
|
FLING_LOG(
|
|
"%p ShouldAccelerate with pan velocity %f pixels/ms, min pan velocity %f "
|
|
"pixels/ms, previous fling cancel velocity %f pixels/ms, time elapsed "
|
|
"since starting previous time between touch start and pan "
|
|
"start %fms.\n",
|
|
this, float(aVelocity.Length()), float(aHandoffState.mMinPanVelocity),
|
|
float(mPreviousFlingCancelVelocity.Length()),
|
|
float(msBetweenTouchStartAndPanStart));
|
|
|
|
if (aVelocity.Length() < StaticPrefs::apz_fling_accel_min_fling_velocity()) {
|
|
FLING_LOG("%p Fling velocity too low (%f), not accelerating.\n", this,
|
|
float(aVelocity.Length()));
|
|
return false;
|
|
}
|
|
|
|
if (aHandoffState.mMinPanVelocity <
|
|
StaticPrefs::apz_fling_accel_min_pan_velocity()) {
|
|
FLING_LOG(
|
|
"%p Panning velocity was too slow at some point during the pan (%f), "
|
|
"not accelerating.\n",
|
|
this, float(aHandoffState.mMinPanVelocity));
|
|
return false;
|
|
}
|
|
|
|
if (mPreviousFlingCancelVelocity.Length() <
|
|
StaticPrefs::apz_fling_accel_min_fling_velocity()) {
|
|
FLING_LOG(
|
|
"%p The previous fling animation had slowed down too much when it was "
|
|
"interrupted (%f), not accelerating.\n",
|
|
this, float(mPreviousFlingCancelVelocity.Length()));
|
|
return false;
|
|
}
|
|
|
|
if (msBetweenTouchStartAndPanStart >=
|
|
StaticPrefs::apz_fling_accel_max_pause_interval_ms()) {
|
|
FLING_LOG(
|
|
"%p Too much time (%fms) elapsed between touch start and pan start, "
|
|
"not accelerating.\n",
|
|
this, msBetweenTouchStartAndPanStart);
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
} // namespace layers
|
|
} // namespace mozilla
|