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); }
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; }
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(); }