Bug 1269032 - Add support for user multipliers to pan gesture inputs. r?mstange
MozReview-Commit-ID: 91ooLOswm7q
--- a/gfx/layers/apz/src/APZCTreeManager.cpp
+++ b/gfx/layers/apz/src/APZCTreeManager.cpp
@@ -776,16 +776,26 @@ APZCTreeManager::ReceiveInputEvent(Input
FlushRepaintsToClearScreenToGeckoTransform();
PanGestureInput& panInput = aEvent.AsPanGestureInput();
panInput.mHandledByAPZ = WillHandleInput(panInput);
if (!panInput.mHandledByAPZ) {
return result;
}
+ // If/when we enable support for pan inputs off-main-thread, we'll need
+ // to duplicate this EventStateManager code or something. See the other
+ // call to GetUserPrefsForWheelEvent in this file for why these fields
+ // are stored separately.
+ MOZ_ASSERT(NS_IsMainThread());
+ WidgetWheelEvent wheelEvent = panInput.ToWidgetWheelEvent(nullptr);
+ EventStateManager::GetUserPrefsForWheelEvent(&wheelEvent,
+ &panInput.mUserDeltaMultiplierX,
+ &panInput.mUserDeltaMultiplierY);
+
RefPtr<AsyncPanZoomController> apzc = GetTargetAPZC(panInput.mPanStartPoint,
&hitResult);
if (apzc) {
MOZ_ASSERT(hitResult == HitLayer || hitResult == HitDispatchToContentRegion);
// For pan gesture events, the call to ReceiveInputEvent below may result in
// scrolling, which changes the async transform. However, the event we
// want to pass to gecko should be the pre-scroll event coordinates,
--- a/gfx/layers/apz/src/AsyncPanZoomController.cpp
+++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp
@@ -1745,17 +1745,17 @@ AsyncPanZoomController::GetScrollWheelDe
bool
AsyncPanZoomController::CanScroll(const InputData& aEvent) const
{
ParentLayerPoint delta;
if (aEvent.mInputType == SCROLLWHEEL_INPUT) {
delta = GetScrollWheelDelta(aEvent.AsScrollWheelInput());
} else if (aEvent.mInputType == PANGESTURE_INPUT) {
const PanGestureInput& panInput = aEvent.AsPanGestureInput();
- delta = ToParentLayerCoordinates(panInput.mPanDisplacement, panInput.mPanStartPoint);
+ delta = ToParentLayerCoordinates(panInput.UserMultipliedPanDisplacement(), panInput.mPanStartPoint);
}
if (!delta.x && !delta.y) {
return false;
}
return CanScrollWithWheel(delta);
}
@@ -2014,43 +2014,51 @@ nsEventStatus AsyncPanZoomController::On
if (!aFingersOnTouchpad) {
return nsEventStatus_eConsumeNoDefault;
}
// Resume / restart the pan.
// PanBegin will call back into this function with mState == PANNING.
return OnPanBegin(aEvent);
}
+ // Note that there is a multiplier that applies onto the "physical" pan
+ // displacement (how much the user's fingers moved) that produces the "logical"
+ // pan displacement (how much the page should move). For some of the code
+ // below it makes more sense to use the physical displacement rather than
+ // the logical displacement, and vice-versa.
+ ScreenPoint physicalPanDisplacement = aEvent.mPanDisplacement;
+ ParentLayerPoint logicalPanDisplacement = aEvent.UserMultipliedLocalPanDisplacement();
+
// We need to update the axis velocity in order to get a useful display port
// size and position. We need to do so even if this is a momentum pan (i.e.
// aFingersOnTouchpad == false); in that case the "with touch" part is not
// really appropriate, so we may want to rethink this at some point.
- mX.UpdateWithTouchAtDevicePoint(aEvent.mLocalPanStartPoint.x, aEvent.mLocalPanDisplacement.x, aEvent.mTime);
- mY.UpdateWithTouchAtDevicePoint(aEvent.mLocalPanStartPoint.y, aEvent.mLocalPanDisplacement.y, aEvent.mTime);
-
- HandlePanningUpdate(aEvent.mPanDisplacement);
+ mX.UpdateWithTouchAtDevicePoint(aEvent.mLocalPanStartPoint.x, logicalPanDisplacement.x, aEvent.mTime);
+ mY.UpdateWithTouchAtDevicePoint(aEvent.mLocalPanStartPoint.y, logicalPanDisplacement.y, aEvent.mTime);
+
+ HandlePanningUpdate(physicalPanDisplacement);
mozilla::Telemetry::Accumulate(mozilla::Telemetry::SCROLL_INPUT_METHODS,
(uint32_t) ScrollInputMethod::ApzPanGesture);
- ScreenPoint panDistance(fabs(aEvent.mPanDisplacement.x), fabs(aEvent.mPanDisplacement.y));
+ ScreenPoint panDistance(fabs(physicalPanDisplacement.x), fabs(physicalPanDisplacement.y));
OverscrollHandoffState handoffState(
*CurrentPanGestureBlock()->GetOverscrollHandoffChain(),
panDistance,
ScrollSource::Wheel);
// Create fake "touch" positions that will result in the desired scroll motion.
// Note that the pan displacement describes the change in scroll position:
// positive displacement values mean that the scroll position increases.
// However, an increase in scroll position means that the scrolled contents
// are moved to the left / upwards. Since our simulated "touches" determine
// the motion of the scrolled contents, not of the scroll position, they need
// to move in the opposite direction of the pan displacement.
ParentLayerPoint startPoint = aEvent.mLocalPanStartPoint;
- ParentLayerPoint endPoint = aEvent.mLocalPanStartPoint - aEvent.mLocalPanDisplacement;
+ ParentLayerPoint endPoint = aEvent.mLocalPanStartPoint - logicalPanDisplacement;
CallDispatchScroll(startPoint, endPoint, handoffState);
return nsEventStatus_eConsumeNoDefault;
}
nsEventStatus AsyncPanZoomController::OnPanEnd(const PanGestureInput& aEvent) {
APZC_LOG("%p got a pan-end in state %d\n", this, mState);
--- a/widget/InputData.cpp
+++ b/widget/InputData.cpp
@@ -414,16 +414,30 @@ PanGestureInput::TransformToLocal(const
Maybe<ParentLayerPoint> panDisplacement = UntransformVector(aTransform, mPanDisplacement, mPanStartPoint);
if (!panDisplacement) {
return false;
}
mLocalPanDisplacement = *panDisplacement;
return true;
}
+ScreenPoint
+PanGestureInput::UserMultipliedPanDisplacement() const
+{
+ return ScreenPoint(mPanDisplacement.x * mUserDeltaMultiplierX,
+ mPanDisplacement.y * mUserDeltaMultiplierY);
+}
+
+ParentLayerPoint
+PanGestureInput::UserMultipliedLocalPanDisplacement() const
+{
+ return ParentLayerPoint(mLocalPanDisplacement.x * mUserDeltaMultiplierX,
+ mLocalPanDisplacement.y * mUserDeltaMultiplierY);
+}
+
bool
PinchGestureInput::TransformToLocal(const ScreenToParentLayerMatrix4x4& aTransform)
{
Maybe<ParentLayerPoint> point = UntransformBy(aTransform, mFocusPoint);
if (!point) {
return false;
}
mLocalFocusPoint = *point;
--- a/widget/InputData.h
+++ b/widget/InputData.h
@@ -366,43 +366,52 @@ public:
const ScreenPoint& aPanDisplacement,
Modifiers aModifiers)
: InputData(PANGESTURE_INPUT, aTime, aTimeStamp, aModifiers),
mType(aType),
mPanStartPoint(aPanStartPoint),
mPanDisplacement(aPanDisplacement),
mLineOrPageDeltaX(0),
mLineOrPageDeltaY(0),
+ mUserDeltaMultiplierX(1.0),
+ mUserDeltaMultiplierY(1.0),
mHandledByAPZ(false),
mFollowedByMomentum(false),
mRequiresContentResponseIfCannotScrollHorizontallyInStartDirection(false)
{
}
bool IsMomentum() const;
WidgetWheelEvent ToWidgetWheelEvent(nsIWidget* aWidget) const;
bool TransformToLocal(const ScreenToParentLayerMatrix4x4& aTransform);
+ ScreenPoint UserMultipliedPanDisplacement() const;
+ ParentLayerPoint UserMultipliedLocalPanDisplacement() const;
+
PanGestureType mType;
ScreenPoint mPanStartPoint;
// The delta. This can be non-zero on any type of event.
ScreenPoint mPanDisplacement;
// Versions of |mPanStartPoint| and |mPanDisplacement| in the local
// coordinates of the APZC receiving the pan. These are set and used by APZ.
ParentLayerPoint mLocalPanStartPoint;
ParentLayerPoint mLocalPanDisplacement;
// See lineOrPageDeltaX/Y on WidgetWheelEvent.
int32_t mLineOrPageDeltaX;
int32_t mLineOrPageDeltaY;
+ // User-set delta multipliers.
+ double mUserDeltaMultiplierX;
+ double mUserDeltaMultiplierY;
+
bool mHandledByAPZ;
// true if this is a PANGESTURE_END event that will be followed by a
// PANGESTURE_MOMENTUMSTART event.
bool mFollowedByMomentum;
// 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