Skip to content
Snippets Groups Projects
Commit 907fde94 authored by Dennis Ek's avatar Dennis Ek
Browse files

Bug 1111333 - Enable double-tap-drag to zoom. r=kats

MozReview-Commit-ID: KpwVNZZdLPd
parent 123ab8fe
No related branches found
No related tags found
No related merge requests found
......@@ -290,6 +290,7 @@ Dean Tessman <dean_tessman@hotmail.com>
<deneen@alum.bucknell.edu>
Denis Antrushin <adu@sparc.spb.su>
Denis Issoupov <denis@macadamian.com>
Dennis Ek <contact@dennisek.se>
Dennis Handly
Derrick Rice <derrick.rice@gmail.com>
<desale@netscape.com>
......
......@@ -37,6 +37,12 @@ static const uint32_t MAX_TAP_TIME = 300;
*/
static const float PINCH_START_THRESHOLD = 35.0f;
/**
* Determines how fast a one touch pinch zooms in and out. The greater the
* value, the faster it zooms.
*/
static const float ONE_TOUCH_PINCH_SPEED = 0.005f;
static bool sLongTapEnabled = true;
ParentLayerPoint GetCurrentFocus(const MultiTouchInput& aEvent)
......@@ -54,6 +60,13 @@ ParentLayerCoord GetCurrentSpan(const MultiTouchInput& aEvent)
return delta.Length();
}
ParentLayerCoord GestureEventListener::GetYSpanFromStartPoint()
{
const ParentLayerPoint start = mTouchStartPosition;
const ParentLayerPoint& current = mTouches[0].mLocalScreenPoint;
return current.y - start.y;
}
TapGestureInput CreateTapEvent(const MultiTouchInput& aTouch, TapGestureInput::TapGestureType aType)
{
return TapGestureInput(aType,
......@@ -93,6 +106,7 @@ nsEventStatus GestureEventListener::HandleInputEvent(const MultiTouchInput& aEve
switch (aEvent.mType) {
case MultiTouchInput::MULTITOUCH_START:
mTouches.Clear();
// Cache every touch.
for (size_t i = 0; i < aEvent.mTouches.Length(); i++) {
mTouches.AppendElement(aEvent.mTouches[i]);
}
......@@ -104,6 +118,7 @@ nsEventStatus GestureEventListener::HandleInputEvent(const MultiTouchInput& aEve
}
break;
case MultiTouchInput::MULTITOUCH_MOVE:
// Update the screen points of the cached touches.
for (size_t i = 0; i < aEvent.mTouches.Length(); i++) {
for (size_t j = 0; j < mTouches.Length(); j++) {
if (aEvent.mTouches[i].mIdentifier == mTouches[j].mIdentifier) {
......@@ -115,6 +130,7 @@ nsEventStatus GestureEventListener::HandleInputEvent(const MultiTouchInput& aEve
rv = HandleInputTouchMove();
break;
case MultiTouchInput::MULTITOUCH_END:
// Remove the cache of the touch that ended.
for (size_t i = 0; i < aEvent.mTouches.Length(); i++) {
for (size_t j = 0; j < mTouches.Length(); j++) {
if (aEvent.mTouches[i].mIdentifier == mTouches[j].mIdentifier) {
......@@ -254,8 +270,7 @@ nsEventStatus GestureEventListener::HandleInputTouchMove()
break;
case GESTURE_FIRST_SINGLE_TOUCH_DOWN:
case GESTURE_FIRST_SINGLE_TOUCH_MAX_TAP_DOWN:
case GESTURE_SECOND_SINGLE_TOUCH_DOWN: {
case GESTURE_FIRST_SINGLE_TOUCH_MAX_TAP_DOWN: {
// If we move too much, bail out of the tap.
if (MoveDistanceIsLarge()) {
CancelLongTapTimeoutTask();
......@@ -266,6 +281,34 @@ nsEventStatus GestureEventListener::HandleInputTouchMove()
break;
}
// The user has performed a double tap, but not lifted her finger.
case GESTURE_SECOND_SINGLE_TOUCH_DOWN: {
// If touch has moved noticeably (within MAX_TAP_TIME), change state.
if (MoveDistanceIsLarge()) {
CancelLongTapTimeoutTask();
CancelMaxTapTimeoutTask();
mSingleTapSent = Nothing();
SetState(GESTURE_ONE_TOUCH_PINCH);
ParentLayerCoord currentSpan = 1.0f;
ParentLayerPoint currentFocus = mTouchStartPosition;
PinchGestureInput pinchEvent(PinchGestureInput::PINCHGESTURE_START,
mLastTouchInput.mTime,
mLastTouchInput.mTimeStamp,
currentFocus,
currentSpan,
currentSpan,
mLastTouchInput.modifiers);
rv = mAsyncPanZoomController->HandleGestureEvent(pinchEvent);
mPreviousSpan = currentSpan;
mPreviousFocus = currentFocus;
}
break;
}
case GESTURE_MULTI_TOUCH_DOWN: {
if (mLastTouchInput.mTouches.Length() < 2) {
NS_WARNING("Wrong input: less than 2 moving points in GESTURE_MULTI_TOUCH_DOWN state");
......@@ -324,6 +367,30 @@ nsEventStatus GestureEventListener::HandleInputTouchMove()
break;
}
case GESTURE_ONE_TOUCH_PINCH: {
ParentLayerCoord currentSpan = GetYSpanFromStartPoint();
float effectiveSpan = 1.0f + (fabsf(currentSpan.value) * ONE_TOUCH_PINCH_SPEED);
ParentLayerPoint currentFocus = mTouchStartPosition;
// Invert zoom.
if (currentSpan.value < 0) {
effectiveSpan = 1.0f / effectiveSpan;
}
PinchGestureInput pinchEvent(PinchGestureInput::PINCHGESTURE_SCALE,
mLastTouchInput.mTime,
mLastTouchInput.mTimeStamp,
currentFocus,
effectiveSpan,
mPreviousSpan,
mLastTouchInput.modifiers);
rv = mAsyncPanZoomController->HandleGestureEvent(pinchEvent);
mPreviousSpan = effectiveSpan;
break;
}
default:
NS_WARNING("Unhandled state upon touch move");
SetState(GESTURE_NONE);
......@@ -411,6 +478,23 @@ nsEventStatus GestureEventListener::HandleInputTouchEnd()
break;
case GESTURE_ONE_TOUCH_PINCH: {
SetState(GESTURE_NONE);
ParentLayerPoint point(-1, -1);
PinchGestureInput pinchEvent(PinchGestureInput::PINCHGESTURE_END,
mLastTouchInput.mTime,
mLastTouchInput.mTimeStamp,
point,
1.0f,
1.0f,
mLastTouchInput.modifiers);
mAsyncPanZoomController->HandleGestureEvent(pinchEvent);
rv = nsEventStatus_eConsumeNoDefault;
break;
}
default:
NS_WARNING("Unhandled state upon touch end");
SetState(GESTURE_NONE);
......
......@@ -105,7 +105,8 @@ private:
// A user put down her finger again right after a single tap thus the
// gesture can't be a single tap, but rather a double tap. But we're
// still not sure about that until the user lifts her finger again.
// Allowed next states: GESTURE_MULTI_TOUCH_DOWN, GESTURE_NONE.
// Allowed next states: GESTURE_MULTI_TOUCH_DOWN, GESTURE_ONE_TOUCH_PINCH,
// GESTURE_NONE.
GESTURE_SECOND_SINGLE_TOUCH_DOWN,
// A long touch has happened, but the user still keeps her finger down.
......@@ -122,7 +123,12 @@ private:
// There are two or more fingers on the screen, and the user has already
// pinched enough for us to start zooming the screen.
// Allowed next states: GESTURE_NONE
GESTURE_PINCH
GESTURE_PINCH,
// The user has double tapped, but not lifted her finger, and moved her
// finger more than PINCH_START_THRESHOLD.
// Allowed next states: GESTURE_NONE.
GESTURE_ONE_TOUCH_PINCH
};
/**
......@@ -141,6 +147,12 @@ private:
bool MoveDistanceIsLarge();
/**
* Returns current vertical span, counting from the where the user first put
* her finger down.
*/
ParentLayerCoord GetYSpanFromStartPoint();
/**
* Do actual state transition and reset substates.
*/
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment