Touch* nsDOMTouchList::IdentifiedTouch(int32_t aIdentifier) const { for (uint32_t i = 0; i < mPoints.Length(); ++i) { Touch* point = mPoints[i]; if (point && point->Identifier() == aIdentifier) { return point; } } return nullptr; }
/* static */ void PointerEventHandler::ProcessPointerCaptureForTouch( WidgetTouchEvent* aEvent) { if (!ShouldGeneratePointerEventFromTouch(aEvent)) { return; } for (uint32_t i = 0; i < aEvent->mTouches.Length(); ++i) { Touch* touch = aEvent->mTouches[i]; if (!TouchManager::ShouldConvertTouchToPointer(touch, aEvent)) { continue; } PointerCaptureInfo* info = GetPointerCaptureInfo(touch->Identifier()); if (!info || info->mPendingContent == info->mOverrideContent) { continue; } WidgetPointerEvent event(aEvent->IsTrusted(), eVoidEvent, aEvent->mWidget); InitPointerEventFromTouch(&event, aEvent, touch, i == 0); CheckPointerCaptureState(&event); } }
bool TouchManager::PreHandleEvent(WidgetEvent* aEvent, nsEventStatus* aStatus, bool& aTouchIsNew, bool& aIsHandlingUserInput, nsCOMPtr<nsIContent>& aCurrentEventContent) { switch (aEvent->mMessage) { case eTouchStart: { aIsHandlingUserInput = true; WidgetTouchEvent* touchEvent = aEvent->AsTouchEvent(); // if there is only one touch in this touchstart event, assume that it is // the start of a new touch session and evict any old touches in the // queue if (touchEvent->mTouches.Length() == 1) { WidgetTouchEvent::AutoTouchArray touches; AppendToTouchList(&touches); for (uint32_t i = 0; i < touches.Length(); ++i) { EvictTouchPoint(touches[i]); } } // Add any new touches to the queue for (uint32_t i = 0; i < touchEvent->mTouches.Length(); ++i) { Touch* touch = touchEvent->mTouches[i]; int32_t id = touch->Identifier(); if (!sCaptureTouchList->Get(id, nullptr)) { // If it is not already in the queue, it is a new touch touch->mChanged = true; } touch->mMessage = aEvent->mMessage; TouchInfo info = { touch, GetNonAnonymousAncestor(touch->mTarget) }; sCaptureTouchList->Put(id, info); } break; } case eTouchMove: { // Check for touches that changed. Mark them add to queue WidgetTouchEvent* touchEvent = aEvent->AsTouchEvent(); WidgetTouchEvent::TouchArray& touches = touchEvent->mTouches; bool haveChanged = false; for (int32_t i = touches.Length(); i; ) { --i; Touch* touch = touches[i]; if (!touch) { continue; } int32_t id = touch->Identifier(); touch->mMessage = aEvent->mMessage; TouchInfo info; if (!sCaptureTouchList->Get(id, &info)) { touches.RemoveElementAt(i); continue; } RefPtr<Touch> oldTouch = info.mTouch; if (!touch->Equals(oldTouch)) { touch->mChanged = true; haveChanged = true; } nsCOMPtr<EventTarget> targetPtr = oldTouch->mTarget; if (!targetPtr) { touches.RemoveElementAt(i); continue; } nsCOMPtr<nsINode> targetNode(do_QueryInterface(targetPtr)); if (!targetNode->IsInComposedDoc()) { targetPtr = do_QueryInterface(info.mNonAnonymousTarget); } touch->SetTarget(targetPtr); info.mTouch = touch; // info.mNonAnonymousTarget is still valid from above sCaptureTouchList->Put(id, info); // if we're moving from touchstart to touchmove for this touch // we allow preventDefault to prevent mouse events if (oldTouch->mMessage != touch->mMessage) { aTouchIsNew = true; } } // is nothing has changed, we should just return if (!haveChanged) { if (aTouchIsNew) { // however, if this is the first touchmove after a touchstart, // it is special in that preventDefault is allowed on it, so // we must dispatch it to content even if nothing changed. we // arbitrarily pick the first touch point to be the "changed" // touch because firing an event with no changed events doesn't // work. for (uint32_t i = 0; i < touchEvent->mTouches.Length(); ++i) { if (touchEvent->mTouches[i]) { touchEvent->mTouches[i]->mChanged = true; break; } } } else { return false; } } break; } case eTouchEnd: aIsHandlingUserInput = true; // Fall through to touchcancel code MOZ_FALLTHROUGH; case eTouchCancel: { // Remove the changed touches // need to make sure we only remove touches that are ending here WidgetTouchEvent* touchEvent = aEvent->AsTouchEvent(); WidgetTouchEvent::TouchArray& touches = touchEvent->mTouches; for (uint32_t i = 0; i < touches.Length(); ++i) { Touch* touch = touches[i]; if (!touch) { continue; } touch->mMessage = aEvent->mMessage; touch->mChanged = true; int32_t id = touch->Identifier(); TouchInfo info; if (!sCaptureTouchList->Get(id, &info)) { continue; } nsCOMPtr<EventTarget> targetPtr = info.mTouch->mTarget; nsCOMPtr<nsINode> targetNode(do_QueryInterface(targetPtr)); if (targetNode && !targetNode->IsInComposedDoc()) { targetPtr = do_QueryInterface(info.mNonAnonymousTarget); } aCurrentEventContent = do_QueryInterface(targetPtr); touch->SetTarget(targetPtr); sCaptureTouchList->Remove(id); } // add any touches left in the touch list, but ensure changed=false AppendToTouchList(&touches); break; } default: break; } return true; }