void GestureRecognizer::pinchGesture(WKTouchEventRef eventRef)
{
    WKArrayRef touchPoints = WKTouchEventGetTouchPoints(eventRef);
    size_t numberOfTouchPoints = WKArrayGetSize(touchPoints);
    ASSERT(numberOfTouchPoints >= 2);

    switch (WKTouchEventGetType(eventRef)) {
    case kWKEventTypeTouchMove: {
        m_gestureHandler->handlePinch(createVectorWithWKArray(touchPoints, 2));
        break;
    }
    case kWKEventTypeTouchEnd:
        if (numberOfTouchPoints == 2) {
            m_gestureHandler->handlePinchFinished();
            m_recognizerFunction = &GestureRecognizer::panGesture;
            WKTouchPointRef pointRef;
            for (size_t i = 0; i < numberOfTouchPoints; ++i) {
                pointRef = static_cast<WKTouchPointRef>(WKArrayGetItemAtIndex(touchPoints, i));
                WKTouchPointState state = WKTouchPointGetState(pointRef);
                if (state != kWKTouchPointStateTouchReleased && state != kWKTouchPointStateTouchCancelled)
                    break;
            }
            ASSERT(pointRef);
            m_gestureHandler->handlePanStarted(toIntPoint(WKTouchPointGetPosition(pointRef)));
        }
        break;
    case kWKEventTypeTouchStart:
        break;
    default:
        ASSERT_NOT_REACHED();
        break;
    }
}
void GestureRecognizer::noGesture(WKTouchEventRef eventRef)
{
    switch (WKTouchEventGetType(eventRef)) {
    case kWKEventTypeTouchStart: {
        WKArrayRef touchPoints = WKTouchEventGetTouchPoints(eventRef);
        switch (WKArrayGetSize(touchPoints)) {
        case 1:
            m_gestureHandler->reset();
            m_recognizerFunction = &GestureRecognizer::singleTapGesture;
            m_firstPressedPoint = toIntPoint(getPointAtIndex(touchPoints, 0));
            ASSERT(!m_tapAndHoldTimer);
            m_tapAndHoldTimer = ecore_timer_add(s_tapAndHoldTimeoutInSeconds, tapAndHoldTimerCallback, this);
            m_doubleTapTimer = ecore_timer_add(s_doubleTapTimeoutInSeconds, doubleTapTimerCallback, this);
            break;
        case 2:
            m_recognizerFunction = &GestureRecognizer::pinchGesture;
            m_gestureHandler->handlePinchStarted(createVectorWithWKArray(touchPoints, 2));
            break;
        default:
            // There's no defined gesture when we touch three or more points.
            notImplemented();
            break;
        }
        break;
    }
    case kWKEventTypeTouchMove:
    case kWKEventTypeTouchEnd:
        break;
    default:
        ASSERT_NOT_REACHED();
        break;
    }
}
void GestureRecognizer::processTouchEvent(WKTouchEventRef eventRef)
{
    WKEventType type = WKTouchEventGetType(eventRef);
    if (type == kWKEventTypeTouchCancel) {
        reset();
        return;
    }

    (this->*m_recognizerFunction)(type, WKTouchEventGetTouchPoints(eventRef));
}
void GestureRecognizer::noGesture(WKTouchEventRef eventRef)
{
    switch (WKTouchEventGetType(eventRef)) {
    case kWKEventTypeTouchStart:
        m_gestureHandler->reset();

        m_recognizerFunction = &GestureRecognizer::singleTapGesture;
        m_firstPressedPoint = toIntPoint(getPointAtIndex(WKTouchEventGetTouchPoints(eventRef), 0));
        ASSERT(!m_tapAndHoldTimer);
        m_tapAndHoldTimer = ecore_timer_add(s_tapAndHoldTimeoutInSeconds, tapAndHoldTimerCallback, this);
        m_doubleTapTimer = ecore_timer_add(s_doubleTapTimeoutInSeconds, doubleTapTimerCallback, this);
        break;
    case kWKEventTypeTouchMove:
    case kWKEventTypeTouchEnd:
        break;
    default:
        ASSERT_NOT_REACHED();
        break;
    }
}
void GestureRecognizer::panGesture(WKTouchEventRef eventRef)
{
    WKArrayRef touchPoints = WKTouchEventGetTouchPoints(eventRef);

    switch (WKTouchEventGetType(eventRef)) {
    case kWKEventTypeTouchStart:
        m_recognizerFunction = &GestureRecognizer::pinchGesture;
        m_gestureHandler->handlePinchStarted(createVectorWithWKArray(touchPoints, 2));
        break;
    case kWKEventTypeTouchMove:
        m_gestureHandler->handlePan(toIntPoint(getPointAtIndex(touchPoints, 0)), WKTouchEventGetTimestamp(eventRef));
        break;
    case kWKEventTypeTouchEnd:
        m_gestureHandler->handlePanFinished();
        m_recognizerFunction = &GestureRecognizer::noGesture;
        break;
    default:
        ASSERT_NOT_REACHED();
        break;
    }
}
void GestureRecognizer::doubleTapGesture(WKTouchEventRef eventRef)
{
    WKArrayRef touchPoints = WKTouchEventGetTouchPoints(eventRef);

    switch (WKTouchEventGetType(eventRef)) {
    case kWKEventTypeTouchStart: {
        if (m_doubleTapTimer) {
            ecore_timer_del(m_doubleTapTimer);
            m_doubleTapTimer = 0;
        }

        size_t numberOfTouchPoints = WKArrayGetSize(touchPoints);
        if (numberOfTouchPoints == 1) {
            if (exceedsDoubleTapThreshold(m_firstPressedPoint, toIntPoint(getPointAtIndex(touchPoints, 0))))
                m_recognizerFunction = &GestureRecognizer::singleTapGesture;
        } else {
            m_recognizerFunction = &GestureRecognizer::pinchGesture;
            m_gestureHandler->handlePinchStarted(createVectorWithWKArray(touchPoints, 2));
        }
        break;
    }
    case kWKEventTypeTouchMove: {
        IntPoint currentPoint = toIntPoint(getPointAtIndex(touchPoints, 0));
        if (exceedsPanThreshold(m_firstPressedPoint, currentPoint)) {
            m_recognizerFunction = &GestureRecognizer::panGesture;
            m_gestureHandler->handlePanStarted(currentPoint);
        }
        break;
    }
    case kWKEventTypeTouchEnd:
        m_gestureHandler->handleDoubleTap(m_firstPressedPoint);
        m_recognizerFunction = &GestureRecognizer::noGesture;
        break;
    default:
        ASSERT_NOT_REACHED();
        break;
    }
}