Bug 1515774 - Use Screen pixels for gesture detection. r=botond

We currently use ParentLayer pixels in GestureEventListener, it should
be Screen pixels because we care about physical distances and
thresholds, not layer-relative ones.

Differential Revision: https://phabricator.services.mozilla.com/D17042

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Eitan Isaacson 2019-01-31 16:45:53 +00:00
parent 6c95500b14
commit 186e2cc4ca
7 changed files with 51 additions and 79 deletions

View File

@ -1891,10 +1891,8 @@ void APZCTreeManager::SynthesizePinchGestureFromMouseWheel(
ScreenPoint focusPoint = aWheelInput.mOrigin;
// Compute span values based on the wheel delta.
// See the PinchGestureInput constructor called below for why
// it's OK to use ParentLayer coordinates for the span values.
ParentLayerCoord oldSpan = 100;
ParentLayerCoord newSpan = oldSpan + aWheelInput.mDeltaY;
ScreenCoord oldSpan = 100;
ScreenCoord newSpan = oldSpan + aWheelInput.mDeltaY;
// There's no ambiguity as to the target for pinch gesture events.
TargetConfirmationFlags confFlags{true};

View File

@ -1078,18 +1078,20 @@ nsEventStatus AsyncPanZoomController::HandleInputEvent(
switch (aEvent.mInputType) {
case MULTITOUCH_INPUT: {
MultiTouchInput multiTouchInput = aEvent.AsMultiTouchInput();
if (!multiTouchInput.TransformToLocal(aTransformToApzc)) {
return rv;
}
RefPtr<GestureEventListener> listener = GetGestureEventListener();
if (listener) {
// We only care about screen coordinates in the gesture listener,
// so we don't bother transforming the event to parent layer coordinates
rv = listener->HandleInputEvent(multiTouchInput);
if (rv == nsEventStatus_eConsumeNoDefault) {
return rv;
}
}
if (!multiTouchInput.TransformToLocal(aTransformToApzc)) {
return rv;
}
switch (multiTouchInput.mType) {
case MultiTouchInput::MULTITOUCH_START:
rv = OnTouchStart(multiTouchInput);
@ -1192,7 +1194,8 @@ nsEventStatus AsyncPanZoomController::HandleGestureEvent(
switch (aEvent.mInputType) {
case PINCHGESTURE_INPUT: {
const PinchGestureInput& pinchGestureInput = aEvent.AsPinchGestureInput();
PinchGestureInput pinchGestureInput = aEvent.AsPinchGestureInput();
pinchGestureInput.TransformToLocal(GetTransformToThis());
switch (pinchGestureInput.mType) {
case PinchGestureInput::PINCHGESTURE_START:
rv = OnScaleBegin(pinchGestureInput);
@ -1207,7 +1210,8 @@ nsEventStatus AsyncPanZoomController::HandleGestureEvent(
break;
}
case TAPGESTURE_INPUT: {
const TapGestureInput& tapGestureInput = aEvent.AsTapGestureInput();
TapGestureInput tapGestureInput = aEvent.AsTapGestureInput();
tapGestureInput.TransformToLocal(GetTransformToThis());
switch (tapGestureInput.mType) {
case TapGestureInput::TAPGESTURE_LONG:
rv = OnLongPress(tapGestureInput);

View File

@ -38,24 +38,24 @@ static const float ONE_TOUCH_PINCH_SPEED = 0.005f;
static bool sLongTapEnabled = true;
ParentLayerPoint GetCurrentFocus(const MultiTouchInput& aEvent) {
const ParentLayerPoint& firstTouch = aEvent.mTouches[0].mLocalScreenPoint;
const ParentLayerPoint& secondTouch = aEvent.mTouches[1].mLocalScreenPoint;
ScreenPoint GetCurrentFocus(const MultiTouchInput& aEvent) {
const ScreenPoint& firstTouch = aEvent.mTouches[0].mScreenPoint;
const ScreenPoint& secondTouch = aEvent.mTouches[1].mScreenPoint;
return (firstTouch + secondTouch) / 2;
}
ParentLayerCoord GetCurrentSpan(const MultiTouchInput& aEvent) {
const ParentLayerPoint& firstTouch = aEvent.mTouches[0].mLocalScreenPoint;
const ParentLayerPoint& secondTouch = aEvent.mTouches[1].mLocalScreenPoint;
ParentLayerPoint delta = secondTouch - firstTouch;
ScreenCoord GetCurrentSpan(const MultiTouchInput& aEvent) {
const ScreenPoint& firstTouch = aEvent.mTouches[0].mScreenPoint;
const ScreenPoint& secondTouch = aEvent.mTouches[1].mScreenPoint;
ScreenPoint delta = secondTouch - firstTouch;
return delta.Length();
}
ParentLayerCoord GestureEventListener::GetYSpanFromGestureStartPoint() {
ScreenCoord GestureEventListener::GetYSpanFromGestureStartPoint() {
// use the position that began the one-touch-pinch gesture rather
// mTouchStartPosition
const ParentLayerPoint start = mOneTouchPinchStartPosition;
const ParentLayerPoint& current = mTouches[0].mLocalScreenPoint;
const ScreenPoint start = mOneTouchPinchStartPosition;
const ScreenPoint& current = mTouches[0].mScreenPoint;
return current.y - start.y;
}
@ -157,7 +157,7 @@ nsEventStatus GestureEventListener::HandleInputTouchSingleStart() {
switch (mState) {
case GESTURE_NONE:
SetState(GESTURE_FIRST_SINGLE_TOUCH_DOWN);
mTouchStartPosition = mLastTouchInput.mTouches[0].mLocalScreenPoint;
mTouchStartPosition = mLastTouchInput.mTouches[0].mScreenPoint;
if (sLongTapEnabled) {
CreateLongTapTimeoutTask();
@ -176,7 +176,7 @@ nsEventStatus GestureEventListener::HandleInputTouchSingleStart() {
// Otherwise, reset the touch start position so that, if this turns into
// a one-touch-pinch gesture, it uses the second tap's down position as
// the focus, rather than the first tap's.
mTouchStartPosition = mLastTouchInput.mTouches[0].mLocalScreenPoint;
mTouchStartPosition = mLastTouchInput.mTouches[0].mScreenPoint;
SetState(GESTURE_SECOND_SINGLE_TOUCH_DOWN);
}
break;
@ -240,10 +240,9 @@ nsEventStatus GestureEventListener::HandleInputTouchMultiStart() {
}
bool GestureEventListener::MoveDistanceExceeds(ScreenCoord aThreshold) const {
const ParentLayerPoint start = mLastTouchInput.mTouches[0].mLocalScreenPoint;
ParentLayerPoint delta = start - mTouchStartPosition;
ScreenPoint screenDelta =
mAsyncPanZoomController->ToScreenCoordinates(delta, start);
ScreenPoint(mLastTouchInput.mTouches[0].mScreenPoint) -
mTouchStartPosition;
return (screenDelta.Length() > aThreshold);
}
@ -304,12 +303,11 @@ nsEventStatus GestureEventListener::HandleInputTouchMove() {
SetState(GESTURE_ONE_TOUCH_PINCH);
ParentLayerCoord currentSpan = 1.0f;
ParentLayerPoint currentFocus = mTouchStartPosition;
ScreenCoord currentSpan = 1.0f;
ScreenPoint currentFocus = mTouchStartPosition;
// save the position that the one-touch-pinch gesture actually begins
mOneTouchPinchStartPosition =
mLastTouchInput.mTouches[0].mLocalScreenPoint;
mOneTouchPinchStartPosition = mLastTouchInput.mTouches[0].mScreenPoint;
PinchGestureInput pinchEvent(
PinchGestureInput::PINCHGESTURE_START, mLastTouchInput.mTime,
@ -332,8 +330,8 @@ nsEventStatus GestureEventListener::HandleInputTouchMove() {
break;
}
ParentLayerCoord currentSpan = GetCurrentSpan(mLastTouchInput);
ParentLayerPoint currentFocus = GetCurrentFocus(mLastTouchInput);
ScreenCoord currentSpan = GetCurrentSpan(mLastTouchInput);
ScreenPoint currentFocus = GetCurrentFocus(mLastTouchInput);
mSpanChange += fabsf(currentSpan - mPreviousSpan);
mFocusChange += (currentFocus - mPreviousFocus).Length();
@ -366,7 +364,7 @@ nsEventStatus GestureEventListener::HandleInputTouchMove() {
break;
}
ParentLayerCoord currentSpan = GetCurrentSpan(mLastTouchInput);
ScreenCoord currentSpan = GetCurrentSpan(mLastTouchInput);
PinchGestureInput pinchEvent(
PinchGestureInput::PINCHGESTURE_SCALE, mLastTouchInput.mTime,
@ -380,10 +378,10 @@ nsEventStatus GestureEventListener::HandleInputTouchMove() {
}
case GESTURE_ONE_TOUCH_PINCH: {
ParentLayerCoord currentSpan = GetYSpanFromGestureStartPoint();
ScreenCoord currentSpan = GetYSpanFromGestureStartPoint();
float effectiveSpan =
1.0f + (fabsf(currentSpan.value) * ONE_TOUCH_PINCH_SPEED);
ParentLayerPoint currentFocus = mTouchStartPosition;
ScreenPoint currentFocus = mTouchStartPosition;
// Invert zoom.
if (currentSpan.value < 0) {
@ -468,11 +466,11 @@ nsEventStatus GestureEventListener::HandleInputTouchEnd() {
case GESTURE_PINCH:
if (mTouches.Length() < 2) {
SetState(GESTURE_NONE);
ParentLayerPoint point = PinchGestureInput::BothFingersLifted();
ScreenPoint point = PinchGestureInput::BothFingersLifted<ScreenPixel>();
if (mTouches.Length() == 1) {
// As user still keeps one finger down the event's focus point should
// contain meaningful data.
point = mTouches[0].mLocalScreenPoint;
point = mTouches[0].mScreenPoint;
}
PinchGestureInput pinchEvent(PinchGestureInput::PINCHGESTURE_END,
mLastTouchInput.mTime,
@ -487,7 +485,7 @@ nsEventStatus GestureEventListener::HandleInputTouchEnd() {
case GESTURE_ONE_TOUCH_PINCH: {
SetState(GESTURE_NONE);
ParentLayerPoint point(-1, -1);
ScreenPoint point = PinchGestureInput::BothFingersLifted<ScreenPixel>();
PinchGestureInput pinchEvent(PinchGestureInput::PINCHGESTURE_END,
mLastTouchInput.mTime,
mLastTouchInput.mTimeStamp, point, 1.0f,

View File

@ -156,7 +156,7 @@ class GestureEventListener final {
* Returns current vertical span, counting from the where the gesture first
* began (after a brief delay detecting the gesture from first touch).
*/
ParentLayerCoord GetYSpanFromGestureStartPoint();
ScreenCoord GetYSpanFromGestureStartPoint();
/**
* Do actual state transition and reset substates.
@ -185,17 +185,17 @@ class GestureEventListener final {
* out we are compared to our original pinch span. Note that this does _not_
* continue to be updated once we jump into the |GESTURE_PINCH| state.
*/
ParentLayerCoord mSpanChange;
ScreenCoord mSpanChange;
/**
* Previous span calculated for the purposes of setting inside a
* PinchGestureInput.
*/
ParentLayerCoord mPreviousSpan;
ScreenCoord mPreviousSpan;
/* Properties similar to mSpanChange and mPreviousSpan, but for the focus */
ParentLayerCoord mFocusChange;
ParentLayerPoint mPreviousFocus;
ScreenCoord mFocusChange;
ScreenPoint mPreviousFocus;
/**
* Cached copy of the last touch input.
@ -219,7 +219,7 @@ class GestureEventListener final {
* is calculated from, instead of starting at 1.0 when the threshold gets
* passed.
*/
ParentLayerPoint mOneTouchPinchStartPosition;
ScreenPoint mOneTouchPinchStartPosition;
/**
* Position of the last touch starting. This is only valid during an attempt
@ -230,7 +230,7 @@ class GestureEventListener final {
* or GESTURE_SECOND_SINGLE_TOUCH_DOWN then we're certain the gesture is
* not tap.
*/
ParentLayerPoint mTouchStartPosition;
ScreenPoint mTouchStartPosition;
/**
* Task used to timeout a long tap. This gets posted to the UI thread such

View File

@ -31,10 +31,8 @@
PinchGestureInput CreatePinchGestureInput(
PinchGestureInput::PinchGestureType aType, const ScreenPoint& aFocus,
float aCurrentSpan, float aPreviousSpan) {
ParentLayerPoint localFocus(aFocus.x, aFocus.y);
PinchGestureInput result(aType, 0, TimeStamp(), localFocus, aCurrentSpan,
PinchGestureInput result(aType, 0, TimeStamp(), aFocus, aCurrentSpan,
aPreviousSpan, 0);
result.mFocusPoint = aFocus;
return result;
}

View File

@ -549,8 +549,8 @@ PinchGestureInput::PinchGestureInput()
PinchGestureInput::PinchGestureInput(PinchGestureType aType, uint32_t aTime,
TimeStamp aTimeStamp,
const ScreenPoint& aFocusPoint,
ParentLayerCoord aCurrentSpan,
ParentLayerCoord aPreviousSpan,
ScreenCoord aCurrentSpan,
ScreenCoord aPreviousSpan,
Modifiers aModifiers)
: InputData(PINCHGESTURE_INPUT, aTime, aTimeStamp, aModifiers),
mType(aType),
@ -558,18 +558,6 @@ PinchGestureInput::PinchGestureInput(PinchGestureType aType, uint32_t aTime,
mCurrentSpan(aCurrentSpan),
mPreviousSpan(aPreviousSpan) {}
PinchGestureInput::PinchGestureInput(PinchGestureType aType, uint32_t aTime,
TimeStamp aTimeStamp,
const ParentLayerPoint& aLocalFocusPoint,
ParentLayerCoord aCurrentSpan,
ParentLayerCoord aPreviousSpan,
Modifiers aModifiers)
: InputData(PINCHGESTURE_INPUT, aTime, aTimeStamp, aModifiers),
mType(aType),
mLocalFocusPoint(aLocalFocusPoint),
mCurrentSpan(aCurrentSpan),
mPreviousSpan(aPreviousSpan) {}
bool PinchGestureInput::TransformToLocal(
const ScreenToParentLayerMatrix4x4& aTransform) {
if (mFocusPoint == BothFingersLifted<ScreenPixel>()) {

View File

@ -414,24 +414,10 @@ class PinchGestureInput : public InputData {
// clang-format on
// Construct a pinch gesture from a Screen point.
// (Technically, we should take the span values in Screen pixels as well,
// but that would require also storing them in Screen pixels and then
// converting them in TransformToLocal() like the focus point. Since pinch
// gesture events are processed by the root content APZC, the only transform
// between Screen and ParentLayer pixels should be a translation, which is
// irrelevant to span values, so we don't bother.)
PinchGestureInput(PinchGestureType aType, uint32_t aTime,
TimeStamp aTimeStamp, const ScreenPoint& aFocusPoint,
ParentLayerCoord aCurrentSpan,
ParentLayerCoord aPreviousSpan, Modifiers aModifiers);
// Construct a pinch gesture from a ParentLayer point.
// mFocusPoint remains (0,0) unless it's set later.
PinchGestureInput(PinchGestureType aType, uint32_t aTime,
TimeStamp aTimeStamp,
const ParentLayerPoint& aLocalFocusPoint,
ParentLayerCoord aCurrentSpan,
ParentLayerCoord aPreviousSpan, Modifiers aModifiers);
ScreenCoord aCurrentSpan, ScreenCoord aPreviousSpan,
Modifiers aModifiers);
bool TransformToLocal(const ScreenToParentLayerMatrix4x4& aTransform);
@ -454,12 +440,12 @@ class PinchGestureInput : public InputData {
ParentLayerPoint mLocalFocusPoint;
// The distance between the touches responsible for the pinch gesture.
ParentLayerCoord mCurrentSpan;
ScreenCoord mCurrentSpan;
// The previous |mCurrentSpan| in the PinchGestureInput preceding this one.
// This is only really relevant during a PINCHGESTURE_SCALE because when it is
// of this type then there must have been a history of spans.
ParentLayerCoord mPreviousSpan;
ScreenCoord mPreviousSpan;
// A special value for mFocusPoint used in PINCHGESTURE_END events to
// indicate that both fingers have been lifted. If only one finger has