/*
   * Zooming
   */
  @Override
  public boolean onScaleBegin(SimpleScaleGestureDetector detector) {
    if (mState == PanZoomState.ANIMATED_ZOOM) return false;

    if (!mTarget.getZoomConstraints().getAllowZoom()) return false;

    setState(PanZoomState.PINCHING);
    mLastZoomFocus = new PointF(detector.getFocusX(), detector.getFocusY());
    cancelTouch();

    GeckoAppShell.sendEventToGecko(
        GeckoEvent.createNativeGestureEvent(
            GeckoEvent.ACTION_MAGNIFY_START, mLastZoomFocus, getMetrics().zoomFactor));

    return true;
  }
  private boolean onTouchCancel(MotionEvent event) {
    cancelTouch();

    if (mState == PanZoomState.WAITING_LISTENERS) {
      // we might get a cancel event from the TouchEventHandler while in the
      // WAITING_LISTENERS state if the touch listeners prevent-default the
      // block of events. at this point being in WAITING_LISTENERS is equivalent
      // to being in NOTHING with the exception of possibly being in overscroll.
      // so here we don't want to do anything right now; the overscroll will be
      // corrected in preventedTouchFinished().
      return false;
    }

    // ensure we snap back if we're overscrolled
    bounce();
    return false;
  }
  private boolean onTouchMove(MotionEvent event) {

    switch (mState) {
      case FLING:
      case BOUNCE:
      case WAITING_LISTENERS:
        // should never happen
        Log.e(LOGTAG, "Received impossible touch move while in " + mState);
        // fall through
      case ANIMATED_ZOOM:
      case NOTHING:
        // may happen if user double-taps and drags without lifting after the
        // second tap. ignore the move if this happens.
        return false;

      case TOUCHING:
        if (panDistance(event) < PAN_THRESHOLD) {
          return false;
        }
        cancelTouch();
        startPanning(event.getX(0), event.getY(0), event.getEventTime());
        track(event);
        return true;

      case PANNING_HOLD_LOCKED:
        setState(PanZoomState.PANNING_LOCKED);
        // fall through
      case PANNING_LOCKED:
        track(event);
        return true;

      case PANNING_HOLD:
        setState(PanZoomState.PANNING);
        // fall through
      case PANNING:
        track(event);
        return true;

      case PINCHING:
        // scale gesture listener will handle this
        return false;
    }
    Log.e(LOGTAG, "Unhandled case " + mState + " in onTouchMove");
    return false;
  }