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(); }
WebInputEventResult TouchEventManager::dispatchTouchEvents( const PlatformTouchEvent& event, const HeapVector<TouchInfo>& touchInfos, bool allTouchesReleased) { bool touchStartOrFirstTouchMove = false; if (event.type() == PlatformEvent::TouchStart) { m_waitingForFirstTouchMove = true; touchStartOrFirstTouchMove = true; } else if (event.type() == PlatformEvent::TouchMove) { touchStartOrFirstTouchMove = m_waitingForFirstTouchMove; m_waitingForFirstTouchMove = false; } // Build up the lists to use for the |touches|, |targetTouches| and // |changedTouches| attributes in the JS event. See // http://www.w3.org/TR/touch-events/#touchevent-interface for how these // lists fit together. // Holds the complete set of touches on the screen. TouchList* touches = TouchList::create(); // A different view on the 'touches' list above, filtered and grouped by // event target. Used for the |targetTouches| list in the JS event. using TargetTouchesHeapMap = HeapHashMap<EventTarget*, Member<TouchList>>; TargetTouchesHeapMap touchesByTarget; // Array of touches per state, used to assemble the |changedTouches| list. ChangedTouches changedTouches[PlatformTouchPoint::TouchStateEnd]; for (unsigned i = 0; i < touchInfos.size(); ++i) { const TouchInfo& touchInfo = touchInfos[i]; const PlatformTouchPoint& point = touchInfo.point; PlatformTouchPoint::TouchState pointState = point.state(); if (touchInfo.consumed) continue; Touch* touch = Touch::create( touchInfo.targetFrame.get(), touchInfo.touchNode.get(), point.id(), point.screenPos(), touchInfo.contentPoint, touchInfo.adjustedRadius, point.rotationAngle(), point.force(), touchInfo.region); // Ensure this target's touch list exists, even if it ends up empty, so // it can always be passed to TouchEvent::Create below. TargetTouchesHeapMap::iterator targetTouchesIterator = touchesByTarget.find(touchInfo.touchNode.get()); if (targetTouchesIterator == touchesByTarget.end()) { touchesByTarget.set(touchInfo.touchNode.get(), TouchList::create()); targetTouchesIterator = touchesByTarget.find(touchInfo.touchNode.get()); } // |touches| and |targetTouches| should only contain information about // touches still on the screen, so if this point is released or // cancelled it will only appear in the |changedTouches| list. if (pointState != PlatformTouchPoint::TouchReleased && pointState != PlatformTouchPoint::TouchCancelled) { touches->append(touch); targetTouchesIterator->value->append(touch); } // Now build up the correct list for |changedTouches|. // Note that any touches that are in the TouchStationary state (e.g. if // the user had several points touched but did not move them all) should // never be in the |changedTouches| list so we do not handle them // explicitly here. See https://bugs.webkit.org/show_bug.cgi?id=37609 // for further discussion about the TouchStationary state. if (pointState != PlatformTouchPoint::TouchStationary && touchInfo.knownTarget) { ASSERT(pointState < PlatformTouchPoint::TouchStateEnd); if (!changedTouches[pointState].m_touches) changedTouches[pointState].m_touches = TouchList::create(); changedTouches[pointState].m_touches->append(touch); changedTouches[pointState].m_targets.add(touchInfo.touchNode); } } if (allTouchesReleased) { m_touchSequenceDocument.clear(); m_touchSequenceUserGestureToken.clear(); } WebInputEventResult eventResult = WebInputEventResult::NotHandled; // Now iterate through the |changedTouches| list and |m_targets| within it, // sending TouchEvents to the targets as required. for (unsigned state = 0; state != PlatformTouchPoint::TouchStateEnd; ++state) { if (!changedTouches[state].m_touches) continue; const AtomicString& eventName(touchEventNameForTouchPointState(static_cast<PlatformTouchPoint::TouchState>(state))); for (const auto& eventTarget : changedTouches[state].m_targets) { EventTarget* touchEventTarget = eventTarget; TouchEvent* touchEvent = TouchEvent::create( touches, touchesByTarget.get(touchEventTarget), changedTouches[state].m_touches.get(), eventName, touchEventTarget->toNode()->document().domWindow(), event.getModifiers(), event.cancelable(), event.causesScrollingIfUncanceled(), event.timestamp()); DispatchEventResult domDispatchResult = touchEventTarget->dispatchEvent(touchEvent); // Only report for top level documents with a single touch on // touch-start or the first touch-move. if (touchStartOrFirstTouchMove && touchInfos.size() == 1 && event.cancelable() && m_frame->isMainFrame()) { DEFINE_STATIC_LOCAL(EnumerationHistogram, rootDocumentListenerHistogram, ("Event.Touch.TargetAndDispatchResult", TouchTargetAndDispatchResultTypeMax)); rootDocumentListenerHistogram.count(toTouchTargetHistogramValue(eventTarget, domDispatchResult)); // Count the handled touch starts and first touch moves before and after the page is fully loaded respectively. if (m_frame->document()->isLoadCompleted()) { DEFINE_STATIC_LOCAL(EnumerationHistogram, touchDispositionsAfterPageLoadHistogram, ("Event.Touch.TouchDispositionsAfterPageLoad", TouchEventDispatchResultTypeMax)); touchDispositionsAfterPageLoadHistogram.count((domDispatchResult != DispatchEventResult::NotCanceled) ? HandledTouches : UnhandledTouches); } else { DEFINE_STATIC_LOCAL(EnumerationHistogram, touchDispositionsBeforePageLoadHistogram, ("Event.Touch.TouchDispositionsBeforePageLoad", TouchEventDispatchResultTypeMax)); touchDispositionsBeforePageLoadHistogram.count((domDispatchResult != DispatchEventResult::NotCanceled) ? HandledTouches : UnhandledTouches); } } eventResult = EventHandler::mergeEventResult(eventResult, EventHandler::toWebInputEventResult(domDispatchResult)); } } return eventResult; }