2012-07-19 23:48:25 -07:00
|
|
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
2013-10-02 18:03:04 -07:00
|
|
|
/* vim: set sw=2 ts=8 et tw=80 : */
|
2012-07-19 23:48:25 -07:00
|
|
|
/* 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 "Axis.h"
|
2013-08-11 16:17:23 -07:00
|
|
|
#include <math.h> // for fabsf, pow, powf
|
|
|
|
#include <algorithm> // for max
|
|
|
|
#include "AsyncPanZoomController.h" // for AsyncPanZoomController
|
2014-03-14 12:49:00 -07:00
|
|
|
#include "mozilla/layers/APZCTreeManager.h" // for APZCTreeManager
|
2013-08-11 16:17:23 -07:00
|
|
|
#include "FrameMetrics.h" // for FrameMetrics
|
|
|
|
#include "mozilla/Attributes.h" // for MOZ_FINAL
|
|
|
|
#include "mozilla/Preferences.h" // for Preferences
|
|
|
|
#include "mozilla/gfx/Rect.h" // for RoundedIn
|
|
|
|
#include "mozilla/mozalloc.h" // for operator new
|
|
|
|
#include "nsMathUtils.h" // for NS_lround
|
|
|
|
#include "nsThreadUtils.h" // for NS_DispatchToMainThread, etc
|
|
|
|
#include "nscore.h" // for NS_IMETHOD
|
2014-03-03 08:53:21 -08:00
|
|
|
#include "gfxPrefs.h" // for the preferences
|
2012-07-19 23:48:25 -07:00
|
|
|
|
|
|
|
namespace mozilla {
|
|
|
|
namespace layers {
|
|
|
|
|
|
|
|
Axis::Axis(AsyncPanZoomController* aAsyncPanZoomController)
|
2013-04-09 19:17:54 -07:00
|
|
|
: mPos(0),
|
2012-07-19 23:48:25 -07:00
|
|
|
mVelocity(0.0f),
|
2014-01-21 09:33:52 -08:00
|
|
|
mAxisLocked(false),
|
2012-10-24 01:37:53 -07:00
|
|
|
mAsyncPanZoomController(aAsyncPanZoomController)
|
2012-07-19 23:48:25 -07:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2012-08-22 08:56:38 -07:00
|
|
|
void Axis::UpdateWithTouchAtDevicePoint(int32_t aPos, const TimeDuration& aTimeDelta) {
|
2014-01-21 09:33:52 -08:00
|
|
|
float newVelocity = mAxisLocked ? 0 : (mPos - aPos) / aTimeDelta.ToMilliseconds();
|
2014-03-03 08:53:21 -08:00
|
|
|
if (gfxPrefs::APZMaxVelocity() > 0.0f) {
|
2014-03-14 12:49:00 -07:00
|
|
|
newVelocity = std::min(newVelocity, gfxPrefs::APZMaxVelocity() * APZCTreeManager::GetDPI());
|
2014-02-24 13:08:31 -08:00
|
|
|
}
|
2012-07-19 23:48:25 -07:00
|
|
|
|
|
|
|
mVelocity = newVelocity;
|
|
|
|
mPos = aPos;
|
2013-02-20 14:59:15 -08:00
|
|
|
|
2014-03-03 08:53:21 -08:00
|
|
|
// Limit queue size pased on pref
|
2013-02-20 14:59:15 -08:00
|
|
|
mVelocityQueue.AppendElement(mVelocity);
|
2014-03-03 08:53:21 -08:00
|
|
|
if (mVelocityQueue.Length() > gfxPrefs::APZMaxVelocityQueueSize()) {
|
2013-02-20 14:59:15 -08:00
|
|
|
mVelocityQueue.RemoveElementAt(0);
|
|
|
|
}
|
2012-07-19 23:48:25 -07:00
|
|
|
}
|
|
|
|
|
2012-08-22 08:56:38 -07:00
|
|
|
void Axis::StartTouch(int32_t aPos) {
|
2012-07-19 23:48:25 -07:00
|
|
|
mStartPos = aPos;
|
|
|
|
mPos = aPos;
|
2014-01-21 09:33:52 -08:00
|
|
|
mAxisLocked = false;
|
2012-07-19 23:48:25 -07:00
|
|
|
}
|
|
|
|
|
2014-03-07 05:41:23 -08:00
|
|
|
float Axis::AdjustDisplacement(float aDisplacement, float& aOverscrollAmountOut) {
|
2014-01-21 09:33:52 -08:00
|
|
|
if (mAxisLocked) {
|
2013-10-02 18:03:04 -07:00
|
|
|
aOverscrollAmountOut = 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-02-05 06:15:05 -08:00
|
|
|
float displacement = aDisplacement;
|
2012-09-28 21:02:45 -07:00
|
|
|
|
2012-07-19 23:48:25 -07:00
|
|
|
// If this displacement will cause an overscroll, throttle it. Can potentially
|
|
|
|
// bring it to 0 even if the velocity is high.
|
|
|
|
if (DisplacementWillOverscroll(displacement) != OVERSCROLL_NONE) {
|
2012-08-13 21:08:38 -07:00
|
|
|
// No need to have a velocity along this axis anymore; it won't take us
|
|
|
|
// anywhere, so we're just spinning needlessly.
|
|
|
|
mVelocity = 0.0f;
|
2013-08-20 16:00:57 -07:00
|
|
|
aOverscrollAmountOut = DisplacementWillOverscrollAmount(displacement);
|
|
|
|
displacement -= aOverscrollAmountOut;
|
2012-07-19 23:48:25 -07:00
|
|
|
}
|
|
|
|
return displacement;
|
|
|
|
}
|
|
|
|
|
|
|
|
float Axis::PanDistance() {
|
|
|
|
return fabsf(mPos - mStartPos);
|
|
|
|
}
|
|
|
|
|
2013-10-02 18:03:04 -07:00
|
|
|
float Axis::PanDistance(float aPos) {
|
|
|
|
return fabsf(aPos - mStartPos);
|
|
|
|
}
|
|
|
|
|
2012-08-13 21:08:38 -07:00
|
|
|
void Axis::EndTouch() {
|
2013-02-20 14:59:15 -08:00
|
|
|
// Calculate the mean velocity and empty the queue.
|
|
|
|
int count = mVelocityQueue.Length();
|
|
|
|
if (count) {
|
|
|
|
mVelocity = 0;
|
|
|
|
while (!mVelocityQueue.IsEmpty()) {
|
|
|
|
mVelocity += mVelocityQueue[0];
|
|
|
|
mVelocityQueue.RemoveElementAt(0);
|
|
|
|
}
|
|
|
|
mVelocity /= count;
|
|
|
|
}
|
2012-08-13 21:08:38 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void Axis::CancelTouch() {
|
2012-07-19 23:48:25 -07:00
|
|
|
mVelocity = 0.0f;
|
2013-02-20 14:59:15 -08:00
|
|
|
while (!mVelocityQueue.IsEmpty()) {
|
|
|
|
mVelocityQueue.RemoveElementAt(0);
|
|
|
|
}
|
2012-07-19 23:48:25 -07:00
|
|
|
}
|
|
|
|
|
2013-10-02 18:03:04 -07:00
|
|
|
bool Axis::Scrollable() {
|
2014-01-21 09:33:52 -08:00
|
|
|
if (mAxisLocked) {
|
2013-10-02 18:03:04 -07:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return GetCompositionLength() < GetPageLength();
|
|
|
|
}
|
|
|
|
|
2012-07-19 23:48:25 -07:00
|
|
|
bool Axis::FlingApplyFrictionOrCancel(const TimeDuration& aDelta) {
|
2014-03-03 08:53:21 -08:00
|
|
|
if (fabsf(mVelocity) <= gfxPrefs::APZFlingStoppedThreshold()) {
|
2012-07-19 23:48:25 -07:00
|
|
|
// If the velocity is very low, just set it to 0 and stop the fling,
|
|
|
|
// otherwise we'll just asymptotically approach 0 and the user won't
|
|
|
|
// actually see any changes.
|
|
|
|
mVelocity = 0.0f;
|
|
|
|
return false;
|
|
|
|
} else {
|
2014-03-03 08:53:21 -08:00
|
|
|
mVelocity *= pow(1.0f - gfxPrefs::APZFlingFriction(), float(aDelta.ToMilliseconds()));
|
2012-07-19 23:48:25 -07:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
Axis::Overscroll Axis::GetOverscroll() {
|
2012-09-28 19:16:34 -07:00
|
|
|
// If the current pan takes the window to the left of or above the current
|
2012-07-19 23:48:25 -07:00
|
|
|
// page rect.
|
|
|
|
bool minus = GetOrigin() < GetPageStart();
|
2012-09-28 19:16:34 -07:00
|
|
|
// If the current pan takes the window to the right of or below the current
|
2012-07-19 23:48:25 -07:00
|
|
|
// page rect.
|
2012-09-28 19:16:34 -07:00
|
|
|
bool plus = GetCompositionEnd() > GetPageEnd();
|
2012-07-19 23:48:25 -07:00
|
|
|
if (minus && plus) {
|
|
|
|
return OVERSCROLL_BOTH;
|
|
|
|
}
|
|
|
|
if (minus) {
|
|
|
|
return OVERSCROLL_MINUS;
|
|
|
|
}
|
|
|
|
if (plus) {
|
|
|
|
return OVERSCROLL_PLUS;
|
|
|
|
}
|
|
|
|
return OVERSCROLL_NONE;
|
|
|
|
}
|
|
|
|
|
2012-08-21 21:37:15 -07:00
|
|
|
float Axis::GetExcess() {
|
2012-07-19 23:48:25 -07:00
|
|
|
switch (GetOverscroll()) {
|
|
|
|
case OVERSCROLL_MINUS: return GetOrigin() - GetPageStart();
|
2012-09-28 19:16:34 -07:00
|
|
|
case OVERSCROLL_PLUS: return GetCompositionEnd() - GetPageEnd();
|
|
|
|
case OVERSCROLL_BOTH: return (GetCompositionEnd() - GetPageEnd()) +
|
|
|
|
(GetPageStart() - GetOrigin());
|
2012-07-19 23:48:25 -07:00
|
|
|
default: return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-02 06:24:16 -07:00
|
|
|
Axis::Overscroll Axis::DisplacementWillOverscroll(float aDisplacement) {
|
2012-09-28 19:16:34 -07:00
|
|
|
// If the current pan plus a displacement takes the window to the left of or
|
2012-07-19 23:48:25 -07:00
|
|
|
// above the current page rect.
|
|
|
|
bool minus = GetOrigin() + aDisplacement < GetPageStart();
|
2012-09-28 19:16:34 -07:00
|
|
|
// If the current pan plus a displacement takes the window to the right of or
|
2012-07-19 23:48:25 -07:00
|
|
|
// below the current page rect.
|
2012-09-28 19:16:34 -07:00
|
|
|
bool plus = GetCompositionEnd() + aDisplacement > GetPageEnd();
|
2012-07-19 23:48:25 -07:00
|
|
|
if (minus && plus) {
|
|
|
|
return OVERSCROLL_BOTH;
|
|
|
|
}
|
|
|
|
if (minus) {
|
|
|
|
return OVERSCROLL_MINUS;
|
|
|
|
}
|
|
|
|
if (plus) {
|
|
|
|
return OVERSCROLL_PLUS;
|
|
|
|
}
|
|
|
|
return OVERSCROLL_NONE;
|
|
|
|
}
|
|
|
|
|
2013-05-02 06:24:16 -07:00
|
|
|
float Axis::DisplacementWillOverscrollAmount(float aDisplacement) {
|
2012-07-19 23:48:25 -07:00
|
|
|
switch (DisplacementWillOverscroll(aDisplacement)) {
|
|
|
|
case OVERSCROLL_MINUS: return (GetOrigin() + aDisplacement) - GetPageStart();
|
2012-09-28 19:16:34 -07:00
|
|
|
case OVERSCROLL_PLUS: return (GetCompositionEnd() + aDisplacement) - GetPageEnd();
|
2012-07-19 23:48:25 -07:00
|
|
|
// Don't handle overscrolled in both directions; a displacement can't cause
|
|
|
|
// this, it must have already been zoomed out too far.
|
|
|
|
default: return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-10 14:02:25 -07:00
|
|
|
float Axis::ScaleWillOverscrollAmount(float aScale, float aFocus) {
|
2013-10-10 09:21:50 -07:00
|
|
|
float originAfterScale = (GetOrigin() + aFocus) - (aFocus / aScale);
|
2012-07-19 23:48:25 -07:00
|
|
|
|
|
|
|
bool both = ScaleWillOverscrollBothSides(aScale);
|
2013-10-10 09:21:50 -07:00
|
|
|
bool minus = originAfterScale < GetPageStart();
|
|
|
|
bool plus = (originAfterScale + (GetCompositionLength() / aScale)) > GetPageEnd();
|
2012-07-19 23:48:25 -07:00
|
|
|
|
|
|
|
if ((minus && plus) || both) {
|
2013-10-10 14:02:25 -07:00
|
|
|
// If we ever reach here it's a bug in the client code.
|
|
|
|
MOZ_ASSERT(false, "In an OVERSCROLL_BOTH condition in ScaleWillOverscrollAmount");
|
|
|
|
return 0;
|
2012-07-19 23:48:25 -07:00
|
|
|
}
|
|
|
|
if (minus) {
|
2013-10-10 14:02:25 -07:00
|
|
|
return originAfterScale - GetPageStart();
|
2012-07-19 23:48:25 -07:00
|
|
|
}
|
|
|
|
if (plus) {
|
2013-10-10 14:02:25 -07:00
|
|
|
return originAfterScale + (GetCompositionLength() / aScale) - GetPageEnd();
|
2012-07-19 23:48:25 -07:00
|
|
|
}
|
2013-10-10 14:02:25 -07:00
|
|
|
return 0;
|
2012-07-19 23:48:25 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
float Axis::GetVelocity() {
|
2014-01-21 09:33:52 -08:00
|
|
|
return mAxisLocked ? 0 : mVelocity;
|
2012-07-19 23:48:25 -07:00
|
|
|
}
|
|
|
|
|
2014-03-10 17:04:44 -07:00
|
|
|
void Axis::SetVelocity(float aVelocity) {
|
|
|
|
mVelocity = aVelocity;
|
|
|
|
}
|
|
|
|
|
2014-04-11 11:38:34 -07:00
|
|
|
float Axis::GetCompositionEnd() const {
|
2012-09-28 19:16:34 -07:00
|
|
|
return GetOrigin() + GetCompositionLength();
|
2012-07-19 23:48:25 -07:00
|
|
|
}
|
|
|
|
|
2014-04-11 11:38:34 -07:00
|
|
|
float Axis::GetPageEnd() const {
|
2012-07-19 23:48:25 -07:00
|
|
|
return GetPageStart() + GetPageLength();
|
|
|
|
}
|
|
|
|
|
2014-04-11 11:38:34 -07:00
|
|
|
float Axis::GetOrigin() const {
|
2014-03-12 23:34:34 -07:00
|
|
|
CSSPoint origin = mAsyncPanZoomController->GetFrameMetrics().GetScrollOffset();
|
2012-07-19 23:48:25 -07:00
|
|
|
return GetPointOffset(origin);
|
|
|
|
}
|
|
|
|
|
2014-04-11 11:38:34 -07:00
|
|
|
float Axis::GetCompositionLength() const {
|
2012-10-11 22:46:24 -07:00
|
|
|
const FrameMetrics& metrics = mAsyncPanZoomController->GetFrameMetrics();
|
2014-03-28 07:36:47 -07:00
|
|
|
return GetRectLength(metrics.CalculateCompositedRectInCssPixels());
|
2012-07-19 23:48:25 -07:00
|
|
|
}
|
|
|
|
|
2014-04-11 11:38:34 -07:00
|
|
|
float Axis::GetPageStart() const {
|
2013-06-03 06:52:44 -07:00
|
|
|
CSSRect pageRect = mAsyncPanZoomController->GetFrameMetrics().mScrollableRect;
|
2012-07-19 23:48:25 -07:00
|
|
|
return GetRectOffset(pageRect);
|
|
|
|
}
|
|
|
|
|
2014-04-11 11:38:34 -07:00
|
|
|
float Axis::GetPageLength() const {
|
2013-06-03 06:52:44 -07:00
|
|
|
CSSRect pageRect = mAsyncPanZoomController->GetFrameMetrics().mScrollableRect;
|
2012-07-19 23:48:25 -07:00
|
|
|
return GetRectLength(pageRect);
|
|
|
|
}
|
|
|
|
|
2013-10-10 09:21:50 -07:00
|
|
|
bool Axis::ScaleWillOverscrollBothSides(float aScale) {
|
2012-07-19 23:48:25 -07:00
|
|
|
const FrameMetrics& metrics = mAsyncPanZoomController->GetFrameMetrics();
|
|
|
|
|
2014-03-10 14:56:59 -07:00
|
|
|
CSSToParentLayerScale scale(metrics.GetZoomToParent().scale * aScale);
|
2013-10-10 14:00:30 -07:00
|
|
|
CSSRect cssCompositionBounds = metrics.mCompositionBounds / scale;
|
2012-07-19 23:48:25 -07:00
|
|
|
|
2013-10-10 14:00:30 -07:00
|
|
|
return GetRectLength(metrics.mScrollableRect) < GetRectLength(cssCompositionBounds);
|
2012-07-19 23:48:25 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
AxisX::AxisX(AsyncPanZoomController* aAsyncPanZoomController)
|
|
|
|
: Axis(aAsyncPanZoomController)
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2014-04-11 11:38:34 -07:00
|
|
|
float AxisX::GetPointOffset(const CSSPoint& aPoint) const
|
2012-07-19 23:48:25 -07:00
|
|
|
{
|
|
|
|
return aPoint.x;
|
|
|
|
}
|
|
|
|
|
2014-04-11 11:38:34 -07:00
|
|
|
float AxisX::GetRectLength(const CSSRect& aRect) const
|
2012-07-19 23:48:25 -07:00
|
|
|
{
|
2012-08-21 21:37:15 -07:00
|
|
|
return aRect.width;
|
2012-07-19 23:48:25 -07:00
|
|
|
}
|
|
|
|
|
2014-04-11 11:38:34 -07:00
|
|
|
float AxisX::GetRectOffset(const CSSRect& aRect) const
|
2012-07-19 23:48:25 -07:00
|
|
|
{
|
2012-08-21 21:37:15 -07:00
|
|
|
return aRect.x;
|
2012-07-19 23:48:25 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
AxisY::AxisY(AsyncPanZoomController* aAsyncPanZoomController)
|
|
|
|
: Axis(aAsyncPanZoomController)
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2014-04-11 11:38:34 -07:00
|
|
|
float AxisY::GetPointOffset(const CSSPoint& aPoint) const
|
2012-07-19 23:48:25 -07:00
|
|
|
{
|
|
|
|
return aPoint.y;
|
|
|
|
}
|
|
|
|
|
2014-04-11 11:38:34 -07:00
|
|
|
float AxisY::GetRectLength(const CSSRect& aRect) const
|
2012-07-19 23:48:25 -07:00
|
|
|
{
|
2012-08-21 21:37:15 -07:00
|
|
|
return aRect.height;
|
2012-07-19 23:48:25 -07:00
|
|
|
}
|
|
|
|
|
2014-04-11 11:38:34 -07:00
|
|
|
float AxisY::GetRectOffset(const CSSRect& aRect) const
|
2012-07-19 23:48:25 -07:00
|
|
|
{
|
2012-08-21 21:37:15 -07:00
|
|
|
return aRect.y;
|
2012-07-19 23:48:25 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|