Bug 951793 - Obey overscroll-behavior for swipe navigation. r=mstange
MozReview-Commit-ID: i2BuiAfG71
--- a/gfx/layers/apz/src/APZCTreeManager.cpp
+++ b/gfx/layers/apz/src/APZCTreeManager.cpp
@@ -1193,16 +1193,19 @@ APZCTreeManager::ReceiveInputEvent(Input
apzc,
/* aTargetConfirmed = */ hitResult != HitDispatchToContentRegion,
panInput, aOutInputBlockId);
// Update the out-parameters so they are what the caller expects.
apzc->GetGuid(aOutTargetGuid);
panInput.mPanStartPoint = *untransformedStartPoint;
panInput.mPanDisplacement = *untransformedDisplacement;
+
+ panInput.mOverscrollBehaviorAllowsSwipe =
+ apzc->OverscrollBehaviorAllowsSwipe();
}
break;
} case PINCHGESTURE_INPUT: { // note: no one currently sends these
PinchGestureInput& pinchInput = aEvent.AsPinchGestureInput();
RefPtr<AsyncPanZoomController> apzc = GetTargetAPZC(pinchInput.mFocusPoint,
&hitResult);
if (apzc) {
MOZ_ASSERT(hitResult != HitNothing);
--- a/gfx/layers/apz/src/AsyncPanZoomController.cpp
+++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp
@@ -2875,16 +2875,22 @@ ParentLayerPoint AsyncPanZoomController:
}
if (!mY.OverscrollBehaviorAllowsHandoff()) {
residualVelocity.y = aHandoffVelocity.y;
aHandoffVelocity.y = 0;
}
return residualVelocity;
}
+bool AsyncPanZoomController::OverscrollBehaviorAllowsSwipe() const
+{
+ RecursiveMutexAutoLock lock(mRecursiveMutex);
+ // Swipe navigation is a "non-local" overscroll behavior like handoff.
+ return mX.OverscrollBehaviorAllowsHandoff();
+}
void AsyncPanZoomController::HandleFlingOverscroll(const ParentLayerPoint& aVelocity,
const RefPtr<const OverscrollHandoffChain>& aOverscrollHandoffChain,
const RefPtr<const AsyncPanZoomController>& aScrolledApzc) {
APZCTreeManager* treeManagerLocal = GetApzcTreeManager();
if (treeManagerLocal) {
const FlingHandoffState handoffState{aVelocity,
aOverscrollHandoffChain,
--- a/gfx/layers/apz/src/AsyncPanZoomController.h
+++ b/gfx/layers/apz/src/AsyncPanZoomController.h
@@ -437,16 +437,18 @@ public:
* to CSS coordinates relative to the beginning of the scroll track.
* Only the component in the direction of scrolling is returned.
*/
CSSCoord ConvertScrollbarPoint(const ParentLayerPoint& aScrollbarPoint,
const ScrollThumbData& aThumbData) const;
void NotifyMozMouseScrollEvent(const nsString& aString) const;
+ bool OverscrollBehaviorAllowsSwipe() const;
+
protected:
// Protected destructor, to discourage deletion outside of Release():
virtual ~AsyncPanZoomController();
// Returns the cached current frame time.
TimeStamp GetFrameTime() const;
/**
--- a/widget/InputData.cpp
+++ b/widget/InputData.cpp
@@ -485,16 +485,17 @@ PanGestureInput::PanGestureInput()
: InputData(PANGESTURE_INPUT)
, mLineOrPageDeltaX(0)
, mLineOrPageDeltaY(0)
, mUserDeltaMultiplierX(1.0)
, mUserDeltaMultiplierY(1.0)
, mHandledByAPZ(false)
, mFollowedByMomentum(false)
, mRequiresContentResponseIfCannotScrollHorizontallyInStartDirection(false)
+ , mOverscrollBehaviorAllowsSwipe(false)
{
}
PanGestureInput::PanGestureInput(PanGestureType aType, uint32_t aTime,
TimeStamp aTimeStamp,
const ScreenPoint& aPanStartPoint,
const ScreenPoint& aPanDisplacement,
Modifiers aModifiers)
@@ -504,16 +505,17 @@ PanGestureInput::PanGestureInput(PanGest
, mPanDisplacement(aPanDisplacement)
, mLineOrPageDeltaX(0)
, mLineOrPageDeltaY(0)
, mUserDeltaMultiplierX(1.0)
, mUserDeltaMultiplierY(1.0)
, mHandledByAPZ(false)
, mFollowedByMomentum(false)
, mRequiresContentResponseIfCannotScrollHorizontallyInStartDirection(false)
+ , mOverscrollBehaviorAllowsSwipe(false)
{
}
bool
PanGestureInput::IsMomentum() const
{
switch (mType) {
case PanGestureInput::PANGESTURE_MOMENTUMSTART:
--- a/widget/InputData.h
+++ b/widget/InputData.h
@@ -380,16 +380,24 @@ public:
// If this is true, and this event started a new input block that couldn't
// find a scrollable target which is scrollable in the horizontal component
// of the scroll start direction, then this input block needs to be put on
// hold until a content response has arrived, even if the block has a
// confirmed target.
// This is used by events that can result in a swipe instead of a scroll.
bool mRequiresContentResponseIfCannotScrollHorizontallyInStartDirection;
+
+ // This is used by APZ to communicate to the macOS widget code whether
+ // the overscroll-behavior of the scroll frame handling this swipe allows
+ // non-local overscroll behaviors in the horizontal direction (such as
+ // swipe navigation).
+ bool mOverscrollBehaviorAllowsSwipe;
+
+ // XXX: If adding any more bools, switch to using bitfields instead.
};
/**
* Encapsulation class for pinch events. In general, these will be generated by
* a gesture listener by looking at SingleTouchData/MultiTouchInput instances and
* determining whether or not the user was trying to do a gesture.
*/
class PinchGestureInput : public InputData
--- a/widget/cocoa/nsChildView.mm
+++ b/widget/cocoa/nsChildView.mm
@@ -2918,17 +2918,17 @@ nsChildView::DispatchAPZWheelInputEvent(
result = mAPZC->ReceiveInputEvent(aEvent, &guid, &inputBlockId);
if (result == nsEventStatus_eConsumeNoDefault) {
return;
}
PanGestureInput& panInput = aEvent.AsPanGestureInput();
event = panInput.ToWidgetWheelEvent(this);
- if (aCanTriggerSwipe) {
+ if (aCanTriggerSwipe && panInput.mOverscrollBehaviorAllowsSwipe) {
SwipeInfo swipeInfo = SendMayStartSwipe(panInput);
event.mCanTriggerSwipe = swipeInfo.wantsSwipe;
if (swipeInfo.wantsSwipe) {
if (result == nsEventStatus_eIgnore) {
// APZ has determined and that scrolling horizontally in the
// requested direction is impossible, so it didn't do any
// scrolling for the event.
// We know now that MayStartSwipe wants a swipe, so we can start
--- a/widget/nsGUIEventIPC.h
+++ b/widget/nsGUIEventIPC.h
@@ -1220,33 +1220,35 @@ struct ParamTraits<mozilla::PanGestureIn
WriteParam(aMsg, aParam.mLocalPanDisplacement);
WriteParam(aMsg, aParam.mLineOrPageDeltaX);
WriteParam(aMsg, aParam.mLineOrPageDeltaY);
WriteParam(aMsg, aParam.mUserDeltaMultiplierX);
WriteParam(aMsg, aParam.mUserDeltaMultiplierY);
WriteParam(aMsg, aParam.mHandledByAPZ);
WriteParam(aMsg, aParam.mFollowedByMomentum);
WriteParam(aMsg, aParam.mRequiresContentResponseIfCannotScrollHorizontallyInStartDirection);
+ WriteParam(aMsg, aParam.mOverscrollBehaviorAllowsSwipe);
}
static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
{
return ReadParam(aMsg, aIter, static_cast<mozilla::InputData*>(aResult)) &&
ReadParam(aMsg, aIter, &aResult->mType) &&
ReadParam(aMsg, aIter, &aResult->mPanStartPoint) &&
ReadParam(aMsg, aIter, &aResult->mPanDisplacement) &&
ReadParam(aMsg, aIter, &aResult->mLocalPanStartPoint) &&
ReadParam(aMsg, aIter, &aResult->mLocalPanDisplacement) &&
ReadParam(aMsg, aIter, &aResult->mLineOrPageDeltaX) &&
ReadParam(aMsg, aIter, &aResult->mLineOrPageDeltaY) &&
ReadParam(aMsg, aIter, &aResult->mUserDeltaMultiplierX) &&
ReadParam(aMsg, aIter, &aResult->mUserDeltaMultiplierY) &&
ReadParam(aMsg, aIter, &aResult->mHandledByAPZ) &&
ReadParam(aMsg, aIter, &aResult->mFollowedByMomentum) &&
- ReadParam(aMsg, aIter, &aResult->mRequiresContentResponseIfCannotScrollHorizontallyInStartDirection);
+ ReadParam(aMsg, aIter, &aResult->mRequiresContentResponseIfCannotScrollHorizontallyInStartDirection) &&
+ ReadParam(aMsg, aIter, &aResult->mOverscrollBehaviorAllowsSwipe);
}
};
template<>
struct ParamTraits<mozilla::PinchGestureInput::PinchGestureType>
: public ContiguousEnumSerializerInclusive<
mozilla::PinchGestureInput::PinchGestureType,
mozilla::PinchGestureInput::PinchGestureType::PINCHGESTURE_START,