예제 #1
0
WebInputEventResult TouchEventManager::handleTouchEvent(
    const PlatformTouchEvent& event,
    const HeapVector<TouchInfo>& touchInfos)
{
    // Note that the disposition of any pointer events affects only the generation of touch
    // events. If all pointer events were handled (and hence no touch events were fired), that
    // is still equivalent to the touch events going unhandled because pointer event handler
    // don't block scroll gesture generation.

    // TODO(crbug.com/507408): If PE handlers always call preventDefault, we won't see TEs until after
    // scrolling starts because the scrolling would suppress upcoming PEs. This sudden "break" in TE
    // suppression can make the visible TEs inconsistent (e.g. touchmove without a touchstart).

    bool allTouchesReleased = true;
    for (const auto& point : event.touchPoints()) {
        if (point.state() != PlatformTouchPoint::TouchReleased
            && point.state() != PlatformTouchPoint::TouchCancelled)
            allTouchesReleased = false;
    }

    // Whether a touch should be considered a "user gesture" or not is a tricky question.
    // https://docs.google.com/document/d/1oF1T3O7_E4t1PYHV6gyCwHxOi3ystm0eSL5xZu7nvOg/edit#

    // The touchend corresponding to a tap is always a user gesture.
    bool isTap = event.touchPoints().size() == 1
        && event.touchPoints()[0].state() == PlatformTouchPoint::TouchReleased
        && !event.causesScrollingIfUncanceled();

    // For now, disallow dragging as a user gesture when the events are being sent to a
    // cross-origin iframe (crbug.com/582140).
    bool isSameOrigin = false;
    if (m_touchSequenceDocument && m_touchSequenceDocument->frame()) {
        SecurityOrigin* securityOrigin = m_touchSequenceDocument->frame()->securityContext()->getSecurityOrigin();
        Frame* top = m_frame->tree().top();
        if (top && securityOrigin->canAccess(top->securityContext()->getSecurityOrigin()))
            isSameOrigin = true;
    }

    OwnPtr<UserGestureIndicator> gestureIndicator;
    if (isTap || isSameOrigin) {
        UserGestureUtilizedCallback* callback = 0;
        if (!isTap) {
            // This is some other touch event that we currently consider a user gesture.  So
            // use a UserGestureUtilizedCallback to get metrics.
            callback = &m_touchSequenceDocument->frame()->eventHandler();
        }

        if (m_touchSequenceUserGestureToken)
            gestureIndicator = adoptPtr(new UserGestureIndicator(m_touchSequenceUserGestureToken.release(), callback));
        else
            gestureIndicator = adoptPtr(new UserGestureIndicator(DefinitelyProcessingUserGesture, callback));
        m_touchSequenceUserGestureToken = UserGestureIndicator::currentToken();
    }

    return dispatchTouchEvents(event, touchInfos, allTouchesReleased);
}
예제 #2
0
bool TouchEventManager::generateTouchInfosAfterHittest(
    const PlatformTouchEvent& event,
    HeapVector<TouchInfo>& touchInfos)
{
    bool newTouchSequence = true;
    bool allTouchesReleased = true;

    for (const auto& point : event.touchPoints()) {
        if (point.state() != PlatformTouchPoint::TouchPressed)
            newTouchSequence = false;
        if (point.state() != PlatformTouchPoint::TouchReleased && point.state() != PlatformTouchPoint::TouchCancelled)
            allTouchesReleased = false;
    }
    if (newTouchSequence) {
        // Ideally we'd ASSERT(!m_touchSequenceDocument) here since we should
        // have cleared the active document when we saw the last release. But we
        // have some tests that violate this, ClusterFuzz could trigger it, and
        // there may be cases where the browser doesn't reliably release all
        // touches. http://crbug.com/345372 tracks this.
        m_touchSequenceDocument.clear();
        m_touchSequenceUserGestureToken.clear();
    }

    ASSERT(m_frame->view());
    if (m_touchSequenceDocument && (!m_touchSequenceDocument->frame() || !m_touchSequenceDocument->frame()->view())) {
        // If the active touch document has no frame or view, it's probably being destroyed
        // so we can't dispatch events.
        return false;
    }

    for (const auto& point : event.touchPoints()) {
        TouchEventManager::TouchInfo touchInfo;
        touchInfo.point = point;
        touchInfos.append(touchInfo);
    }

    updateTargetAndRegionMapsForTouchStarts(touchInfos);

    m_touchPressed = !allTouchesReleased;

    // If there's no document receiving touch events, or no handlers on the
    // document set to receive the events, then we can skip all the rest of
    // this work.
    if (!m_touchSequenceDocument || !m_touchSequenceDocument->frameHost() || !hasTouchHandlers(m_touchSequenceDocument->frameHost()->eventHandlerRegistry()) || !m_touchSequenceDocument->frame()) {
        if (allTouchesReleased) {
            m_touchSequenceDocument.clear();
            m_touchSequenceUserGestureToken.clear();
        }
        return false;
    }

    setAllPropertiesOfTouchInfos(touchInfos);

    return true;
}
예제 #3
0
PlatformGestureRecognizer::PassGestures GestureRecognizerChromium::processTouchEventForGestures(const PlatformTouchEvent& event, bool defaultPrevented)
{
    m_ctrlKey = event.ctrlKey();
    m_altKey = event.altKey();
    m_shiftKey = event.shiftKey();
    m_metaKey = event.metaKey();

    OwnPtr<Vector<PlatformGestureEvent> > gestures = adoptPtr(new Vector<PlatformGestureEvent>());
    const Vector<PlatformTouchPoint>& points = event.touchPoints();
    for (unsigned i = 0; i < points.size(); i++) {
        const PlatformTouchPoint& p = points[i];
        updateValues(event.timestamp(), p);

        if (GestureTransitionFunction ef = m_edgeFunctions.get(signature(m_state, p.id(), p.state(), defaultPrevented)))
            ((*this).*ef)(p, gestures.get());
    }
    return gestures.release();
}