static float ComputeDistanceFromRect(const nsPoint& aPoint, const nsRect& aRect) { nscoord dx = std::max(0, std::max(aRect.x - aPoint.x, aPoint.x - aRect.XMost())); nscoord dy = std::max(0, std::max(aRect.y - aPoint.y, aPoint.y - aRect.YMost())); return float(NS_hypot(dx, dy)); }
float GetCurrentSpan(const MultiTouchInput& aEvent) { const ScreenIntPoint& firstTouch = aEvent.mTouches[0].mScreenPoint, secondTouch = aEvent.mTouches[1].mScreenPoint; ScreenIntPoint delta = secondTouch - firstTouch; return float(NS_hypot(delta.x, delta.y)); }
bool AccessibleCaretEventHub::MoveDistanceIsLarge(const nsPoint& aPoint) const { nsPoint delta = aPoint - mPressPoint; return NS_hypot(delta.x, delta.y) > nsPresContext::AppUnitsPerCSSPixel() * kMoveStartToleranceInPixel; }
nsEventStatus GestureEventListener::HandlePinchGestureEvent(const MultiTouchInput& aEvent, bool aClearTouches) { nsEventStatus rv = nsEventStatus_eIgnore; if (mTouches.Length() > 1 && !aClearTouches) { const nsIntPoint& firstTouch = mTouches[0].mScreenPoint, secondTouch = mTouches[mTouches.Length() - 1].mScreenPoint; nsIntPoint focusPoint = nsIntPoint((firstTouch.x + secondTouch.x)/2, (firstTouch.y + secondTouch.y)/2); float currentSpan = float(NS_hypot(firstTouch.x - secondTouch.x, firstTouch.y - secondTouch.y)); if (mState == NoGesture) { PinchGestureInput pinchEvent(PinchGestureInput::PINCHGESTURE_START, aEvent.mTime, focusPoint, currentSpan, currentSpan); mAsyncPanZoomController->HandleInputEvent(pinchEvent); mState = InPinchGesture; } else { PinchGestureInput pinchEvent(PinchGestureInput::PINCHGESTURE_SCALE, aEvent.mTime, focusPoint, currentSpan, mPreviousSpan); mAsyncPanZoomController->HandleInputEvent(pinchEvent); } mPreviousSpan = currentSpan; rv = nsEventStatus_eConsumeNoDefault; } else if (mState == InPinchGesture) { PinchGestureInput pinchEvent(PinchGestureInput::PINCHGESTURE_END, aEvent.mTime, mTouches[0].mScreenPoint, 1.0f, 1.0f); mAsyncPanZoomController->HandleInputEvent(pinchEvent); mState = NoGesture; rv = nsEventStatus_eConsumeNoDefault; } if (aClearTouches) { mTouches.Clear(); } return rv; }
nsresult SVGNumberPairSMILType::ComputeDistance(const SMILValue& aFrom, const SMILValue& aTo, double& aDistance) const { MOZ_ASSERT(aFrom.mType == aTo.mType, "Trying to compare different types"); MOZ_ASSERT(aFrom.mType == this, "Unexpected source type"); double delta[2]; delta[0] = aTo.mU.mNumberPair[0] - aFrom.mU.mNumberPair[0]; delta[1] = aTo.mU.mNumberPair[1] - aFrom.mU.mNumberPair[1]; aDistance = NS_hypot(delta[0], delta[1]); return NS_OK; }
// For 'by'. bool SVGMotionSMILPathUtils::PathGenerator:: LineToRelative(const nsAString& aCoordPairStr, double& aSegmentDistance) { mHaveReceivedCommands = true; float xVal, yVal; if (!ParseCoordinatePair(aCoordPairStr, xVal, yVal)) { return false; } mPathBuilder->LineTo(mPathBuilder->CurrentPoint() + Point(xVal, yVal)); aSegmentDistance = NS_hypot(xVal, yVal); return true; }
nsresult SVGIntegerPairSMILType::ComputeDistance(const nsSMILValue& aFrom, const nsSMILValue& aTo, double& aDistance) const { NS_PRECONDITION(aFrom.mType == aTo.mType,"Trying to compare different types"); NS_PRECONDITION(aFrom.mType == this, "Unexpected source type"); double delta[2]; delta[0] = aTo.mU.mIntPair[0] - aFrom.mU.mIntPair[0]; delta[1] = aTo.mU.mIntPair[1] - aFrom.mU.mIntPair[1]; aDistance = NS_hypot(delta[0], delta[1]); return NS_OK; }
// For 'to' and every entry in 'values' except the first. bool SVGMotionSMILPathUtils::PathGenerator:: LineToAbsolute(const nsAString& aCoordPairStr, double& aSegmentDistance) { mHaveReceivedCommands = true; float xVal, yVal; if (!ParseCoordinatePair(aCoordPairStr, xVal, yVal)) { return false; } gfxPoint initialPoint = mGfxContext.CurrentPoint(); mGfxContext.LineTo(gfxPoint(xVal, yVal)); aSegmentDistance = NS_hypot(initialPoint.x - xVal, initialPoint.y -yVal); return true; }
nsresult SVGMotionSMILType::ComputeDistance(const nsSMILValue& aFrom, const nsSMILValue& aTo, double& aDistance) const { NS_ABORT_IF_FALSE(aFrom.mType == aTo.mType, "Incompatible SMIL types"); NS_ABORT_IF_FALSE(aFrom.mType == this, "Unexpected SMIL type"); const MotionSegmentArray& fromArr = ExtractMotionSegmentArray(aFrom); const MotionSegmentArray& toArr = ExtractMotionSegmentArray(aTo); // ComputeDistance is only used for calculating distances between single // values in a values array. So we should only have one entry in each array. NS_ABORT_IF_FALSE(fromArr.Length() == 1, "Wrong number of elements in from value"); NS_ABORT_IF_FALSE(toArr.Length() == 1, "Wrong number of elements in to value"); const MotionSegment& from = fromArr[0]; const MotionSegment& to = toArr[0]; NS_ABORT_IF_FALSE(from.mSegmentType == to.mSegmentType, "Mismatched MotionSegment types"); if (from.mSegmentType == eSegmentType_PathPoint) { const PathPointParams& fromParams = from.mU.mPathPointParams; const PathPointParams& toParams = to.mU.mPathPointParams; NS_ABORT_IF_FALSE(fromParams.mPath == toParams.mPath, "Interpolation endpoints should be from same path"); NS_ABORT_IF_FALSE(fromParams.mDistToPoint <= toParams.mDistToPoint, "To value shouldn't be before from value on path"); aDistance = fabs(toParams.mDistToPoint - fromParams.mDistToPoint); } else { const TranslationParams& fromParams = from.mU.mTranslationParams; const TranslationParams& toParams = to.mU.mTranslationParams; float dX = toParams.mX - fromParams.mX; float dY = toParams.mY - fromParams.mY; aDistance = NS_hypot(dX, dY); } return NS_OK; }
bool AnalyserNode::FFTAnalysis() { float* inputBuffer; bool allocated = false; if (mWriteIndex == 0) { inputBuffer = mBuffer.Elements(); } else { inputBuffer = static_cast<float*>(moz_malloc(FftSize() * sizeof(float))); if (!inputBuffer) { return false; } memcpy(inputBuffer, mBuffer.Elements() + mWriteIndex, sizeof(float) * (FftSize() - mWriteIndex)); memcpy(inputBuffer + FftSize() - mWriteIndex, mBuffer.Elements(), sizeof(float) * mWriteIndex); allocated = true; } ApplyBlackmanWindow(inputBuffer, FftSize()); mAnalysisBlock.PerformFFT(inputBuffer); // Normalize so than an input sine wave at 0dBfs registers as 0dBfs (undo FFT scaling factor). const double magnitudeScale = 1.0 / FftSize(); for (uint32_t i = 0; i < mOutputBuffer.Length(); ++i) { double scalarMagnitude = NS_hypot(mAnalysisBlock.RealData(i), mAnalysisBlock.ImagData(i)) * magnitudeScale; mOutputBuffer[i] = mSmoothingTimeConstant * mOutputBuffer[i] + (1.0 - mSmoothingTimeConstant) * scalarMagnitude; } if (allocated) { moz_free(inputBuffer); } return true; }
nsEventStatus GestureEventListener::HandleInputTouchMove() { nsEventStatus rv = nsEventStatus_eIgnore; switch (mState) { case GESTURE_NONE: case GESTURE_LONG_TOUCH_DOWN: // Ignore this input signal as the corresponding events get handled by APZC break; case GESTURE_FIRST_SINGLE_TOUCH_DOWN: case GESTURE_FIRST_SINGLE_TOUCH_MAX_TAP_DOWN: case GESTURE_SECOND_SINGLE_TOUCH_DOWN: { // If we move too much, bail out of the tap. ScreenIntPoint delta = mLastTouchInput.mTouches[0].mScreenPoint - mTouchStartPosition; if (NS_hypot(delta.x, delta.y) > AsyncPanZoomController::GetTouchStartTolerance()) { CancelLongTapTimeoutTask(); CancelMaxTapTimeoutTask(); SetState(GESTURE_NONE); } break; } case GESTURE_MULTI_TOUCH_DOWN: { if (mLastTouchInput.mTouches.Length() < 2) { NS_WARNING("Wrong input: less than 2 moving points in GESTURE_MULTI_TOUCH_DOWN state"); break; } float currentSpan = GetCurrentSpan(mLastTouchInput); mSpanChange += fabsf(currentSpan - mPreviousSpan); if (mSpanChange > PINCH_START_THRESHOLD) { SetState(GESTURE_PINCH); PinchGestureInput pinchEvent(PinchGestureInput::PINCHGESTURE_START, mLastTouchInput.mTime, GetCurrentFocus(mLastTouchInput), currentSpan, currentSpan, mLastTouchInput.modifiers); mAsyncPanZoomController->HandleGestureEvent(pinchEvent); } rv = nsEventStatus_eConsumeNoDefault; mPreviousSpan = currentSpan; break; } case GESTURE_PINCH: { if (mLastTouchInput.mTouches.Length() < 2) { NS_WARNING("Wrong input: less than 2 moving points in GESTURE_PINCH state"); // Prevent APZC::OnTouchMove() from handling this wrong input rv = nsEventStatus_eConsumeNoDefault; break; } float currentSpan = GetCurrentSpan(mLastTouchInput); PinchGestureInput pinchEvent(PinchGestureInput::PINCHGESTURE_SCALE, mLastTouchInput.mTime, GetCurrentFocus(mLastTouchInput), currentSpan, mPreviousSpan, mLastTouchInput.modifiers); mAsyncPanZoomController->HandleGestureEvent(pinchEvent); rv = nsEventStatus_eConsumeNoDefault; mPreviousSpan = currentSpan; break; } default: NS_WARNING("Unhandled state upon touch move"); SetState(GESTURE_NONE); break; } return rv; }
nsEventStatus GestureEventListener::HandleInputEvent(const InputData& aEvent) { if (aEvent.mInputType != MULTITOUCH_INPUT) { return nsEventStatus_eIgnore; } const MultiTouchInput& event = static_cast<const MultiTouchInput&>(aEvent); // Cache the current event since it may become the single or long tap that we // send. mLastTouchInput = event; switch (event.mType) { case MultiTouchInput::MULTITOUCH_START: case MultiTouchInput::MULTITOUCH_ENTER: { for (size_t i = 0; i < event.mTouches.Length(); i++) { bool foundAlreadyExistingTouch = false; for (size_t j = 0; j < mTouches.Length(); j++) { if (mTouches[j].mIdentifier == event.mTouches[i].mIdentifier) { foundAlreadyExistingTouch = true; } } NS_WARN_IF_FALSE(!foundAlreadyExistingTouch, "Tried to add a touch that already exists"); // If we didn't find a touch in our list that matches this, then add it. // If it already existed, we don't want to add it twice because that // messes with our touch move/end code. if (!foundAlreadyExistingTouch) { mTouches.AppendElement(event.mTouches[i]); } } size_t length = mTouches.Length(); if (length == 1) { mTapStartTime = event.mTime; mTouchStartPosition = event.mTouches[0].mScreenPoint; if (mState == GESTURE_NONE) { mState = GESTURE_WAITING_SINGLE_TAP; mLongTapTimeoutTask = NewRunnableMethod(this, &GestureEventListener::TimeoutLongTap); MessageLoop::current()->PostDelayedTask( FROM_HERE, mLongTapTimeoutTask, Preferences::GetInt("ui.click_hold_context_menus.delay", 500)); } } else if (length == 2) { // Another finger has been added; it can't be a tap anymore. HandleTapCancel(event); } break; } case MultiTouchInput::MULTITOUCH_MOVE: { // If we move too much, bail out of the tap. nsIntPoint touch = (nsIntPoint&)event.mTouches[0].mScreenPoint; if (mTouches.Length() == 1 && NS_hypot(mTouchStartPosition.x - touch.x, mTouchStartPosition.y - touch.y) > mAsyncPanZoomController->GetDPI() * AsyncPanZoomController::TOUCH_START_TOLERANCE) { HandleTapCancel(event); } bool foundAlreadyExistingTouch = false; for (size_t i = 0; i < mTouches.Length(); i++) { for (size_t j = 0; j < event.mTouches.Length(); j++) { if (mTouches[i].mIdentifier == event.mTouches[j].mIdentifier) { foundAlreadyExistingTouch = true; mTouches[i] = event.mTouches[j]; } } } NS_WARN_IF_FALSE(foundAlreadyExistingTouch, "Touch moved, but not in list"); break; } case MultiTouchInput::MULTITOUCH_END: case MultiTouchInput::MULTITOUCH_LEAVE: { bool foundAlreadyExistingTouch = false; for (size_t i = 0; i < event.mTouches.Length() && !foundAlreadyExistingTouch; i++) { for (size_t j = 0; j < mTouches.Length() && !foundAlreadyExistingTouch; j++) { if (event.mTouches[i].mIdentifier == mTouches[j].mIdentifier) { foundAlreadyExistingTouch = true; mTouches.RemoveElementAt(j); } } } NS_WARN_IF_FALSE(foundAlreadyExistingTouch, "Touch ended, but not in list"); if (event.mTime - mTapStartTime <= MAX_TAP_TIME) { if (mState == GESTURE_WAITING_DOUBLE_TAP && event.mTime - mLastTapEndTime > MAX_TAP_TIME) { // mDoubleTapTimeoutTask wasn't scheduled in time. We need to run the // task synchronously to confirm the last tap. mDoubleTapTimeoutTask->Cancel(); TimeoutDoubleTap(); // Change the state so we can proceed to process the current tap. mState = GESTURE_WAITING_SINGLE_TAP; } if (mState == GESTURE_WAITING_DOUBLE_TAP) { mDoubleTapTimeoutTask->Cancel(); // We were waiting for a double tap and it has arrived. HandleDoubleTap(event); mState = GESTURE_NONE; } else if (mState == GESTURE_WAITING_SINGLE_TAP) { mLongTapTimeoutTask->Cancel(); HandleSingleTapUpEvent(event); // We were not waiting for anything but a single tap has happened that // may turn into a double tap. Wait a while and if it doesn't turn into // a double tap, send a single tap instead. mState = GESTURE_WAITING_DOUBLE_TAP; mDoubleTapTimeoutTask = NewRunnableMethod(this, &GestureEventListener::TimeoutDoubleTap); MessageLoop::current()->PostDelayedTask( FROM_HERE, mDoubleTapTimeoutTask, MAX_TAP_TIME); } mLastTapEndTime = event.mTime; } if (mState == GESTURE_WAITING_SINGLE_TAP) { mState = GESTURE_NONE; } if (!mTouches.Length()) { mSpanChange = 0.0f; } break; } case MultiTouchInput::MULTITOUCH_CANCEL: // This gets called if there's a touch that has to bail for weird reasons // like pinching and then moving away from the window that the pinch was // started in without letting go of the screen. HandlePinchGestureEvent(event, true); break; } return HandlePinchGestureEvent(event, false); }
float AsyncPanZoomController::PanDistance() { return NS_hypot(mX.PanDistance(), mY.PanDistance()) * mFrameMetrics.mResolution.width; }
nsEventStatus GestureEventListener::HandlePinchGestureEvent(const MultiTouchInput& aEvent) { nsEventStatus rv = nsEventStatus_eIgnore; if (aEvent.mType == MultiTouchInput::MULTITOUCH_CANCEL) { mTouches.Clear(); mState = GESTURE_NONE; return rv; } if (mTouches.Length() > 1) { const ScreenIntPoint& firstTouch = mTouches[0].mScreenPoint, secondTouch = mTouches[1].mScreenPoint; ScreenPoint focusPoint = ScreenPoint(firstTouch + secondTouch) / 2; ScreenIntPoint delta = secondTouch - firstTouch; float currentSpan = float(NS_hypot(delta.x, delta.y)); switch (mState) { case GESTURE_NONE: mPreviousSpan = currentSpan; mState = GESTURE_WAITING_PINCH; // Deliberately fall through. If the user pinched and took their fingers // off the screen such that they still had 1 left on it, we want there to // be no resistance. We should only reset |mSpanChange| once all fingers // are off the screen. case GESTURE_WAITING_PINCH: { mSpanChange += fabsf(currentSpan - mPreviousSpan); if (mSpanChange > PINCH_START_THRESHOLD) { PinchGestureInput pinchEvent(PinchGestureInput::PINCHGESTURE_START, aEvent.mTime, focusPoint, currentSpan, currentSpan, aEvent.modifiers); mAsyncPanZoomController->HandleInputEvent(pinchEvent); mState = GESTURE_PINCH; } break; } case GESTURE_PINCH: { PinchGestureInput pinchEvent(PinchGestureInput::PINCHGESTURE_SCALE, aEvent.mTime, focusPoint, currentSpan, mPreviousSpan, aEvent.modifiers); mAsyncPanZoomController->HandleInputEvent(pinchEvent); break; } default: // What? break; } mPreviousSpan = currentSpan; rv = nsEventStatus_eConsumeNoDefault; } else if (mState == GESTURE_PINCH) { PinchGestureInput pinchEvent(PinchGestureInput::PINCHGESTURE_END, aEvent.mTime, ScreenPoint(), 1.0f, 1.0f, aEvent.modifiers); mAsyncPanZoomController->HandleInputEvent(pinchEvent); mState = GESTURE_NONE; // If the user left a finger on the screen, spoof a touch start event and // send it to APZC so that they can continue panning from that point. if (mTouches.Length() == 1) { MultiTouchInput touchEvent(MultiTouchInput::MULTITOUCH_START, aEvent.mTime, aEvent.modifiers); touchEvent.mTouches.AppendElement(mTouches[0]); mAsyncPanZoomController->HandleInputEvent(touchEvent); // The spoofed touch start will get back to GEL and make us enter the // GESTURE_WAITING_SINGLE_TAP state, but this isn't a new touch, so there // is no condition under which this touch should turn into any tap. mState = GESTURE_NONE; } rv = nsEventStatus_eConsumeNoDefault; } else if (mState == GESTURE_WAITING_PINCH) { mState = GESTURE_NONE; } return rv; }
nsEventStatus GestureEventListener::HandlePinchGestureEvent(const MultiTouchInput& aEvent, bool aClearTouches) { nsEventStatus rv = nsEventStatus_eIgnore; if (mTouches.Length() > 1 && !aClearTouches) { const nsIntPoint& firstTouch = mTouches[0].mScreenPoint, secondTouch = mTouches[mTouches.Length() - 1].mScreenPoint; nsIntPoint focusPoint = nsIntPoint((firstTouch.x + secondTouch.x)/2, (firstTouch.y + secondTouch.y)/2); float currentSpan = float(NS_hypot(firstTouch.x - secondTouch.x, firstTouch.y - secondTouch.y)); switch (mState) { case GESTURE_NONE: mPreviousSpan = currentSpan; mState = GESTURE_WAITING_PINCH; // Deliberately fall through. If the user pinched and took their fingers // off the screen such that they still had 1 left on it, we want there to // be no resistance. We should only reset |mSpanChange| once all fingers // are off the screen. case GESTURE_WAITING_PINCH: { mSpanChange += fabsf(currentSpan - mPreviousSpan); if (mSpanChange > PINCH_START_THRESHOLD) { PinchGestureInput pinchEvent(PinchGestureInput::PINCHGESTURE_START, aEvent.mTime, focusPoint, currentSpan, currentSpan); mAsyncPanZoomController->ReceiveInputEvent(pinchEvent); mState = GESTURE_PINCH; } break; } case GESTURE_PINCH: { PinchGestureInput pinchEvent(PinchGestureInput::PINCHGESTURE_SCALE, aEvent.mTime, focusPoint, currentSpan, mPreviousSpan); mAsyncPanZoomController->ReceiveInputEvent(pinchEvent); break; } default: // What? break; } mPreviousSpan = currentSpan; rv = nsEventStatus_eConsumeNoDefault; } else if (mState == GESTURE_PINCH) { PinchGestureInput pinchEvent(PinchGestureInput::PINCHGESTURE_END, aEvent.mTime, mTouches[0].mScreenPoint, 1.0f, 1.0f); mAsyncPanZoomController->ReceiveInputEvent(pinchEvent); mState = GESTURE_NONE; rv = nsEventStatus_eConsumeNoDefault; } if (aClearTouches) { mTouches.Clear(); } return rv; }
nsEventStatus GestureEventListener::HandleInputEvent(const MultiTouchInput& aEvent) { // Cache the current event since it may become the single or long tap that we // send. mLastTouchInput = aEvent; switch (aEvent.mType) { case MultiTouchInput::MULTITOUCH_START: case MultiTouchInput::MULTITOUCH_ENTER: { for (size_t i = 0; i < aEvent.mTouches.Length(); i++) { bool foundAlreadyExistingTouch = false; for (size_t j = 0; j < mTouches.Length(); j++) { if (mTouches[j].mIdentifier == aEvent.mTouches[i].mIdentifier) { foundAlreadyExistingTouch = true; break; } } // If we didn't find a touch in our list that matches this, then add it. if (!foundAlreadyExistingTouch) { mTouches.AppendElement(aEvent.mTouches[i]); } } size_t length = mTouches.Length(); if (length == 1) { mTapStartTime = aEvent.mTime; mTouchStartPosition = aEvent.mTouches[0].mScreenPoint; if (mState == GESTURE_NONE) { mState = GESTURE_WAITING_SINGLE_TAP; mLongTapTimeoutTask = NewRunnableMethod(this, &GestureEventListener::TimeoutLongTap); mAsyncPanZoomController->PostDelayedTask( mLongTapTimeoutTask, Preferences::GetInt("ui.click_hold_context_menus.delay", 500)); } } else if (length == 2) { // Another finger has been added; it can't be a tap anymore. HandleTapCancel(aEvent); } break; } case MultiTouchInput::MULTITOUCH_MOVE: { // If we move too much, bail out of the tap. ScreenIntPoint delta = aEvent.mTouches[0].mScreenPoint - mTouchStartPosition; if (mTouches.Length() == 1 && NS_hypot(delta.x, delta.y) > AsyncPanZoomController::GetTouchStartTolerance()) { HandleTapCancel(aEvent); } size_t eventTouchesMatched = 0; for (size_t i = 0; i < mTouches.Length(); i++) { bool isTouchRemoved = true; for (size_t j = 0; j < aEvent.mTouches.Length(); j++) { if (mTouches[i].mIdentifier == aEvent.mTouches[j].mIdentifier) { eventTouchesMatched++; isTouchRemoved = false; mTouches[i] = aEvent.mTouches[j]; } } if (isTouchRemoved) { // this touch point was lifted, so remove it from our list mTouches.RemoveElementAt(i); i--; } } NS_WARN_IF_FALSE(eventTouchesMatched == aEvent.mTouches.Length(), "Touch moved, but not in list"); break; } case MultiTouchInput::MULTITOUCH_END: case MultiTouchInput::MULTITOUCH_LEAVE: { for (size_t i = 0; i < aEvent.mTouches.Length(); i++) { bool foundAlreadyExistingTouch = false; for (size_t j = 0; j < mTouches.Length() && !foundAlreadyExistingTouch; j++) { if (aEvent.mTouches[i].mIdentifier == mTouches[j].mIdentifier) { foundAlreadyExistingTouch = true; mTouches.RemoveElementAt(j); } } NS_WARN_IF_FALSE(foundAlreadyExistingTouch, "Touch ended, but not in list"); } if (mState == GESTURE_WAITING_DOUBLE_TAP) { CancelDoubleTapTimeoutTask(); if (mTapStartTime - mLastTapEndTime > MAX_TAP_TIME || aEvent.mTime - mTapStartTime > MAX_TAP_TIME) { // Either the time between taps or the last tap took too long // confirm previous tap and handle current tap seperately TimeoutDoubleTap(); mState = GESTURE_WAITING_SINGLE_TAP; } else { // We were waiting for a double tap and it has arrived. HandleDoubleTap(aEvent); mState = GESTURE_NONE; } } if (mState == GESTURE_LONG_TAP_UP) { HandleLongTapUpEvent(aEvent); mState = GESTURE_NONE; } else if (mState == GESTURE_WAITING_SINGLE_TAP && aEvent.mTime - mTapStartTime > MAX_TAP_TIME) { // Extended taps are immediately dispatched as single taps CancelLongTapTimeoutTask(); HandleSingleTapConfirmedEvent(aEvent); mState = GESTURE_NONE; } else if (mState == GESTURE_WAITING_SINGLE_TAP) { CancelLongTapTimeoutTask(); nsEventStatus tapupEvent = HandleSingleTapUpEvent(aEvent); if (tapupEvent == nsEventStatus_eIgnore) { // We were not waiting for anything but a single tap has happened that // may turn into a double tap. Wait a while and if it doesn't turn into // a double tap, send a single tap instead. mState = GESTURE_WAITING_DOUBLE_TAP; mDoubleTapTimeoutTask = NewRunnableMethod(this, &GestureEventListener::TimeoutDoubleTap); mAsyncPanZoomController->PostDelayedTask( mDoubleTapTimeoutTask, MAX_TAP_TIME); } else if (tapupEvent == nsEventStatus_eConsumeNoDefault) { // We sent the tapup into content without waiting for a double tap mState = GESTURE_NONE; } } mLastTapEndTime = aEvent.mTime; if (!mTouches.Length()) { mSpanChange = 0.0f; } break; } case MultiTouchInput::MULTITOUCH_CANCEL: // FIXME: we should probably clear a bunch of gesture state here break; } return HandlePinchGestureEvent(aEvent); }
bool GestureEventListener::MoveDistanceIsLarge() { ScreenIntPoint delta = mLastTouchInput.mTouches[0].mScreenPoint - mTouchStartPosition; return (NS_hypot(delta.x, delta.y) > AsyncPanZoomController::GetTouchStartTolerance()); }