зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1062483 - Make the overscroll effect harder to trigger accidentally. r=kats
--HG-- rename : gfx/layers/apz/src/OverscrollHandoffChain.cpp => gfx/layers/apz/src/OverscrollHandoffState.cpp rename : gfx/layers/apz/src/OverscrollHandoffChain.h => gfx/layers/apz/src/OverscrollHandoffState.h extra : rebase_source : 155c68fcd76c5f1e7a4e57818d238908bc8eb3c2
This commit is contained in:
Родитель
a6b78c05d6
Коммит
ce4474100b
|
@ -23,7 +23,7 @@
|
|||
#include "mozilla/gfx/Logging.h" // for gfx::TreeLog
|
||||
#include "UnitTransforms.h" // for ViewAs
|
||||
#include "gfxPrefs.h" // for gfxPrefs
|
||||
#include "OverscrollHandoffChain.h" // for OverscrollHandoffChain
|
||||
#include "OverscrollHandoffState.h" // for OverscrollHandoffState
|
||||
#include "LayersLogging.h" // for Stringify
|
||||
|
||||
#define APZCTM_LOG(...)
|
||||
|
@ -896,18 +896,19 @@ bool
|
|||
APZCTreeManager::DispatchScroll(AsyncPanZoomController* aPrev,
|
||||
ScreenPoint aStartPoint,
|
||||
ScreenPoint aEndPoint,
|
||||
const OverscrollHandoffChain& aOverscrollHandoffChain,
|
||||
uint32_t aOverscrollHandoffChainIndex)
|
||||
OverscrollHandoffState& aOverscrollHandoffState)
|
||||
{
|
||||
const OverscrollHandoffChain& overscrollHandoffChain = aOverscrollHandoffState.mChain;
|
||||
uint32_t overscrollHandoffChainIndex = aOverscrollHandoffState.mChainIndex;
|
||||
nsRefPtr<AsyncPanZoomController> next;
|
||||
// If we have reached the end of the overscroll handoff chain, there is
|
||||
// nothing more to scroll, so we ignore the rest of the pan gesture.
|
||||
if (aOverscrollHandoffChainIndex >= aOverscrollHandoffChain.Length()) {
|
||||
if (overscrollHandoffChainIndex >= overscrollHandoffChain.Length()) {
|
||||
// Nothing more to scroll - ignore the rest of the pan gesture.
|
||||
return false;
|
||||
}
|
||||
|
||||
next = aOverscrollHandoffChain.GetApzcAtIndex(aOverscrollHandoffChainIndex);
|
||||
next = overscrollHandoffChain.GetApzcAtIndex(overscrollHandoffChainIndex);
|
||||
|
||||
if (next == nullptr || next->IsDestroyed()) {
|
||||
return false;
|
||||
|
@ -924,8 +925,7 @@ APZCTreeManager::DispatchScroll(AsyncPanZoomController* aPrev,
|
|||
|
||||
// Scroll |next|. If this causes overscroll, it will call DispatchScroll()
|
||||
// again with an incremented index.
|
||||
return next->AttemptScroll(aStartPoint, aEndPoint, aOverscrollHandoffChain,
|
||||
aOverscrollHandoffChainIndex);
|
||||
return next->AttemptScroll(aStartPoint, aEndPoint, aOverscrollHandoffState);
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -44,6 +44,7 @@ class AsyncPanZoomController;
|
|||
class CompositorParent;
|
||||
class APZPaintLogHelper;
|
||||
class OverscrollHandoffChain;
|
||||
class OverscrollHandoffState;
|
||||
class LayerMetricsWrapper;
|
||||
|
||||
/**
|
||||
|
@ -312,8 +313,7 @@ public:
|
|||
bool DispatchScroll(AsyncPanZoomController* aApzc,
|
||||
ScreenPoint aStartPoint,
|
||||
ScreenPoint aEndPoint,
|
||||
const OverscrollHandoffChain& aOverscrollHandoffChain,
|
||||
uint32_t aOverscrollHandoffChainIndex);
|
||||
OverscrollHandoffState& aOverscrollHandoffState);
|
||||
|
||||
/**
|
||||
* This is a callback for AsyncPanZoomController to call when it wants to
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
#include "GestureEventListener.h" // for GestureEventListener
|
||||
#include "InputData.h" // for MultiTouchInput, etc
|
||||
#include "InputBlockState.h" // for InputBlockState, TouchBlockState
|
||||
#include "OverscrollHandoffChain.h" // for OverscrollHandoffChain
|
||||
#include "OverscrollHandoffState.h" // for OverscrollHandoffState
|
||||
#include "Units.h" // for CSSRect, CSSPoint, etc
|
||||
#include "UnitTransforms.h" // for TransformTo
|
||||
#include "base/message_loop.h" // for MessageLoop
|
||||
|
@ -269,6 +269,11 @@ typedef mozilla::gfx::Matrix4x4 Matrix4x4;
|
|||
* number, we stop the fling.
|
||||
* Units: screen pixels per millisecond
|
||||
*
|
||||
* "apz.overscroll.min_pan_distance_ratio"
|
||||
* The minimum ratio of the pan distance along one axis to the pan distance
|
||||
* along the other axis needed to initiate overscroll along the first axis
|
||||
* during panning.
|
||||
*
|
||||
* "apz.overscroll.stretch_factor"
|
||||
* How much overscrolling can stretch content along an axis.
|
||||
* The maximum stretch along an axis is a factor of (1 + kStretchFactor).
|
||||
|
@ -1573,8 +1578,10 @@ nsEventStatus AsyncPanZoomController::OnPan(const PanGestureInput& aEvent, bool
|
|||
|
||||
// TODO: Handle pan events sent without pan begin / pan end events properly.
|
||||
if (mPanGestureState) {
|
||||
OverscrollHandoffState handoffState(
|
||||
*mPanGestureState->GetOverscrollHandoffChain(), panDisplacement);
|
||||
CallDispatchScroll(aEvent.mPanStartPoint, aEvent.mPanStartPoint + aEvent.mPanDisplacement,
|
||||
*mPanGestureState->GetOverscrollHandoffChain(), 0);
|
||||
handoffState);
|
||||
}
|
||||
|
||||
return nsEventStatus_eConsumeNoDefault;
|
||||
|
@ -1837,16 +1844,16 @@ void AsyncPanZoomController::HandlePanning(double aAngle) {
|
|||
}
|
||||
}
|
||||
|
||||
void AsyncPanZoomController::HandlePanningUpdate(const ScreenPoint& aDelta) {
|
||||
void AsyncPanZoomController::HandlePanningUpdate(const ScreenPoint& aPanDistance) {
|
||||
// If we're axis-locked, check if the user is trying to break the lock
|
||||
if (GetAxisLockMode() == STICKY && !mPanDirRestricted) {
|
||||
|
||||
double angle = atan2(aDelta.y, aDelta.x); // range [-pi, pi]
|
||||
double angle = atan2(aPanDistance.y, aPanDistance.x); // range [-pi, pi]
|
||||
angle = fabs(angle); // range [0, pi]
|
||||
|
||||
float breakThreshold = gfxPrefs::APZAxisBreakoutThreshold() * APZCTreeManager::GetDPI();
|
||||
|
||||
if (fabs(aDelta.x) > breakThreshold || fabs(aDelta.y) > breakThreshold) {
|
||||
if (fabs(aPanDistance.x) > breakThreshold || fabs(aPanDistance.y) > breakThreshold) {
|
||||
if (mState == PANNING_LOCKED_X || mState == CROSS_SLIDING_X) {
|
||||
if (!IsCloseToHorizontal(angle, gfxPrefs::APZAxisBreakoutAngle())) {
|
||||
mY.SetAxisLocked(false);
|
||||
|
@ -1905,8 +1912,7 @@ void AsyncPanZoomController::UpdateWithTouchAtDevicePoint(const MultiTouchInput&
|
|||
|
||||
bool AsyncPanZoomController::AttemptScroll(const ScreenPoint& aStartPoint,
|
||||
const ScreenPoint& aEndPoint,
|
||||
const OverscrollHandoffChain& aOverscrollHandoffChain,
|
||||
uint32_t aOverscrollHandoffChainIndex) {
|
||||
OverscrollHandoffState& aOverscrollHandoffState) {
|
||||
|
||||
// "start - end" rather than "end - start" because e.g. moving your finger
|
||||
// down (*positive* direction along y axis) causes the vertical scroll offset
|
||||
|
@ -1941,8 +1947,9 @@ bool AsyncPanZoomController::AttemptScroll(const ScreenPoint& aStartPoint,
|
|||
// overscroll).
|
||||
// Note: "+ overscroll" rather than "- overscroll" because "overscroll"
|
||||
// is what's left of "displacement", and "displacement" is "start - end".
|
||||
++aOverscrollHandoffState.mChainIndex;
|
||||
if (CallDispatchScroll(aEndPoint + overscroll, aEndPoint,
|
||||
aOverscrollHandoffChain, aOverscrollHandoffChainIndex + 1)) {
|
||||
aOverscrollHandoffState)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1950,7 +1957,24 @@ bool AsyncPanZoomController::AttemptScroll(const ScreenPoint& aStartPoint,
|
|||
// overscroll, try to accept it ourselves. We only accept it if we
|
||||
// are pannable.
|
||||
APZC_LOG("%p taking overscroll during panning\n", this);
|
||||
return OverscrollBy(overscroll);
|
||||
return OverscrollForPanning(overscroll, aOverscrollHandoffState.mPanDistance);
|
||||
}
|
||||
|
||||
bool AsyncPanZoomController::OverscrollForPanning(ScreenPoint aOverscroll,
|
||||
const ScreenPoint& aPanDistance) {
|
||||
// Only allow entering overscroll along an axis if the pan distance along
|
||||
// that axis is greater than the pan distance along the other axis by a
|
||||
// configurable factor. If we are already overscrolled, don't check this.
|
||||
if (!IsOverscrolled()) {
|
||||
if (aPanDistance.x < gfxPrefs::APZMinPanDistanceRatio() * aPanDistance.y) {
|
||||
aOverscroll.x = 0;
|
||||
}
|
||||
if (aPanDistance.y < gfxPrefs::APZMinPanDistanceRatio() * aPanDistance.x) {
|
||||
aOverscroll.y = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return OverscrollBy(aOverscroll);
|
||||
}
|
||||
|
||||
bool AsyncPanZoomController::OverscrollBy(const ScreenPoint& aOverscroll) {
|
||||
|
@ -2066,33 +2090,32 @@ void AsyncPanZoomController::StartSnapBack() {
|
|||
|
||||
bool AsyncPanZoomController::CallDispatchScroll(const ScreenPoint& aStartPoint,
|
||||
const ScreenPoint& aEndPoint,
|
||||
const OverscrollHandoffChain& aOverscrollHandoffChain,
|
||||
uint32_t aOverscrollHandoffChainIndex) {
|
||||
OverscrollHandoffState& aOverscrollHandoffState) {
|
||||
// Make a local copy of the tree manager pointer and check if it's not
|
||||
// null before calling DispatchScroll(). This is necessary because
|
||||
// Destroy(), which nulls out mTreeManager, could be called concurrently.
|
||||
APZCTreeManager* treeManagerLocal = GetApzcTreeManager();
|
||||
return treeManagerLocal
|
||||
&& treeManagerLocal->DispatchScroll(this, aStartPoint, aEndPoint,
|
||||
aOverscrollHandoffChain,
|
||||
aOverscrollHandoffChainIndex);
|
||||
aOverscrollHandoffState);
|
||||
}
|
||||
|
||||
void AsyncPanZoomController::TrackTouch(const MultiTouchInput& aEvent) {
|
||||
ScreenPoint prevTouchPoint(mX.GetPos(), mY.GetPos());
|
||||
ScreenPoint touchPoint = GetFirstTouchScreenPoint(aEvent);
|
||||
|
||||
ScreenPoint delta(mX.PanDistance(touchPoint.x),
|
||||
ScreenPoint panDistance(mX.PanDistance(touchPoint.x),
|
||||
mY.PanDistance(touchPoint.y));
|
||||
const ScreenPoint panStart = PanStart();
|
||||
ToGlobalScreenCoordinates(&delta, panStart);
|
||||
HandlePanningUpdate(delta);
|
||||
ToGlobalScreenCoordinates(&panDistance, panStart);
|
||||
HandlePanningUpdate(panDistance);
|
||||
|
||||
UpdateWithTouchAtDevicePoint(aEvent);
|
||||
|
||||
if (prevTouchPoint != touchPoint) {
|
||||
CallDispatchScroll(prevTouchPoint, touchPoint,
|
||||
*CurrentTouchBlock()->GetOverscrollHandoffChain(), 0);
|
||||
OverscrollHandoffState handoffState(
|
||||
*CurrentTouchBlock()->GetOverscrollHandoffChain(), panDistance);
|
||||
CallDispatchScroll(prevTouchPoint, touchPoint, handoffState);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1010,8 +1010,7 @@ public:
|
|||
* an overscrolled state itself if it can.
|
||||
*/
|
||||
bool AttemptScroll(const ScreenPoint& aStartPoint, const ScreenPoint& aEndPoint,
|
||||
const OverscrollHandoffChain& aOverscrollHandoffChain,
|
||||
uint32_t aOverscrollHandoffChainIndex = 0);
|
||||
OverscrollHandoffState& aOverscrollHandoffState);
|
||||
|
||||
void FlushRepaintForOverscrollHandoff();
|
||||
|
||||
|
@ -1029,8 +1028,15 @@ private:
|
|||
*/
|
||||
bool CallDispatchScroll(const ScreenPoint& aStartPoint,
|
||||
const ScreenPoint& aEndPoint,
|
||||
const OverscrollHandoffChain& aOverscrollHandoffChain,
|
||||
uint32_t aOverscrollHandoffChainIndex);
|
||||
OverscrollHandoffState& aOverscrollHandoffState);
|
||||
|
||||
/**
|
||||
* A helper function for overscrolling during panning. This is a wrapper
|
||||
* around OverscrollBy() that also implements restrictions on entering
|
||||
* overscroll based on the pan angle.
|
||||
*/
|
||||
bool OverscrollForPanning(ScreenPoint aOverscroll,
|
||||
const ScreenPoint& aPanDistance);
|
||||
|
||||
/**
|
||||
* Try to overscroll by 'aOverscroll'.
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#include "InputBlockState.h"
|
||||
#include "mozilla/layers/APZCTreeManager.h" // for AllowedTouchBehavior
|
||||
#include "gfxPrefs.h" // for gfxPrefs
|
||||
#include "OverscrollHandoffChain.h"
|
||||
#include "OverscrollHandoffState.h"
|
||||
|
||||
#define TBS_LOG(...)
|
||||
// #define TBS_LOG(...) printf_stderr("TBS: " __VA_ARGS__)
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* 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 "OverscrollHandoffChain.h"
|
||||
#include "OverscrollHandoffState.h"
|
||||
|
||||
#include <algorithm> // for std::stable_sort
|
||||
#include "mozilla/Assertions.h"
|
||||
|
@ -90,13 +90,25 @@ OverscrollHandoffChain::ClearOverscroll() const
|
|||
void
|
||||
OverscrollHandoffChain::SnapBackOverscrolledApzc() const
|
||||
{
|
||||
for (uint32_t i = 0; i < Length(); ++i) {
|
||||
uint32_t i = 0;
|
||||
for (i = 0; i < Length(); ++i) {
|
||||
AsyncPanZoomController* apzc = mChain[i];
|
||||
if (!apzc->IsDestroyed() && apzc->SnapBackIfOverscrolled()) {
|
||||
// At most one APZC along the hand-off chain can be overscrolled.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// In debug builds, verify our assumption that only one APZC is overscrolled.
|
||||
#ifdef DEBUG
|
||||
++i;
|
||||
for (; i < Length(); ++i) {
|
||||
AsyncPanZoomController* apzc = mChain[i];
|
||||
if (!apzc->IsDestroyed()) {
|
||||
MOZ_ASSERT(!apzc->IsOverscrolled());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool
|
|
@ -110,6 +110,28 @@ private:
|
|||
void ForEachApzc(APZCMethod aMethod) const;
|
||||
};
|
||||
|
||||
/**
|
||||
* This class groups the state maintained during overscroll handoff.
|
||||
*/
|
||||
struct OverscrollHandoffState {
|
||||
OverscrollHandoffState(const OverscrollHandoffChain& aChain,
|
||||
const ScreenPoint& aPanDistance)
|
||||
: mChain(aChain), mChainIndex(0), mPanDistance(aPanDistance) {}
|
||||
|
||||
// The chain of APZCs along which we hand off scroll.
|
||||
// This is const to indicate that the chain does not change over the
|
||||
// course of handoff.
|
||||
const OverscrollHandoffChain& mChain;
|
||||
|
||||
// The index of the APZC in the chain that we are currently giving scroll to.
|
||||
// This is non-const to indicate that this changes over the course of handoff.
|
||||
uint32_t mChainIndex;
|
||||
|
||||
// The total distance since touch-start of the pan that triggered the
|
||||
// handoff. This is const to indicate that it does not change over the
|
||||
// course of handoff.
|
||||
const ScreenPoint mPanDistance;
|
||||
};
|
||||
// Don't pollute other files with this macro for now.
|
||||
#undef NS_INLINE_DECL_THREADSAFE_MUTABLE_REFCOUNTING
|
||||
|
|
@ -244,7 +244,7 @@ UNIFIED_SOURCES += [
|
|||
'apz/src/Axis.cpp',
|
||||
'apz/src/GestureEventListener.cpp',
|
||||
'apz/src/InputBlockState.cpp',
|
||||
'apz/src/OverscrollHandoffChain.cpp',
|
||||
'apz/src/OverscrollHandoffState.cpp',
|
||||
'apz/src/TaskThrottler.cpp',
|
||||
'apz/testutil/APZTestData.cpp',
|
||||
'apz/util/ActiveElementManager.cpp',
|
||||
|
|
|
@ -157,6 +157,7 @@ private:
|
|||
DECL_GFX_PREF(Live, "apz.overscroll.enabled", APZOverscrollEnabled, bool, false);
|
||||
DECL_GFX_PREF(Live, "apz.overscroll.fling_friction", APZOverscrollFlingFriction, float, 0.02f);
|
||||
DECL_GFX_PREF(Live, "apz.overscroll.fling_stopped_threshold", APZOverscrollFlingStoppedThreshold, float, 0.4f);
|
||||
DECL_GFX_PREF(Live, "apz.overscroll.min_pan_distance_ratio", APZMinPanDistanceRatio, float, 1.0f);
|
||||
DECL_GFX_PREF(Live, "apz.overscroll.stretch_factor", APZOverscrollStretchFactor, float, 0.5f);
|
||||
DECL_GFX_PREF(Live, "apz.overscroll.snap_back.spring_stiffness", APZOverscrollSnapBackSpringStiffness, float, 0.6f);
|
||||
DECL_GFX_PREF(Live, "apz.overscroll.snap_back.spring_friction", APZOverscrollSnapBackSpringFriction, float, 0.1f);
|
||||
|
|
|
@ -464,6 +464,7 @@ pref("apz.num_paint_duration_samples", 3);
|
|||
pref("apz.overscroll.enabled", false);
|
||||
pref("apz.overscroll.fling_friction", "0.02");
|
||||
pref("apz.overscroll.fling_stopped_threshold", "0.4");
|
||||
pref("apz.overscroll.min_pan_distance_ratio", "1.0");
|
||||
pref("apz.overscroll.stretch_factor", "0.5");
|
||||
pref("apz.overscroll.snap_back.spring_stiffness", "0.6");
|
||||
pref("apz.overscroll.snap_back.spring_friction", "0.1");
|
||||
|
|
Загрузка…
Ссылка в новой задаче