/* (non-Javadoc)
   * @see java.lang.Runnable#run()
   */
  @Override
  public void run() {
    long interval = SystemClock.uptimeMillis() - lastSent;
    lastSent += interval;
    double scale = (double) interval / 50.0;
    RemoteCanvas canvas = activity.getCanvas();
    RemotePointer p = canvas.getPointer();

    // Log.v(TAG, String.format("panning %f %d %d", scale, (int)((double)velocity.x * scale),
    // (int)((double)velocity.y * scale)));
    if (p.processPointerEvent(
        (int) (p.getX() + ((double) velocity.x * scale)),
        (int) (p.getY() + ((double) velocity.y * scale)),
        MotionEvent.ACTION_MOVE,
        0,
        false,
        false)) {
      if (updater.updateVelocity(velocity, interval)) {
        handler.postDelayed(this, 50);
      } else {
        // Log.v(TAG, "Updater requests stop");
        stop();
      }
    } else {
      // Log.v(TAG, "Panning failed");
      stop();
    }
  }
 /**
  * Warp the mouse to x, y in the RFB coordinates
  *
  * @param x
  * @param y
  */
 public void warpMouse(int x, int y) {
   vncCanvas.invalidateMousePosition();
   mouseX = x;
   mouseY = y;
   vncCanvas.invalidateMousePosition();
   // android.util.Log.i(TAG, "warp mouse to " + x + "," + y);
   rfb.writePointerEvent(x, y, 0, MOUSE_BUTTON_NONE);
 }
  public boolean processPointerEvent(
      int x,
      int y,
      int action,
      int modifiers,
      boolean mouseIsDown,
      boolean useRightButton,
      boolean useMiddleButton,
      boolean useScrollButton,
      int direction) {

    if (rfb != null && rfb.isInNormalProtocol()) {
      if (mouseIsDown && useRightButton) {
        // Log.i(TAG,"Right mouse button mask set");
        pointerMask = MOUSE_BUTTON_RIGHT;
      } else if (mouseIsDown && useMiddleButton) {
        // Log.i(TAG,"Middle mouse button mask set");
        pointerMask = MOUSE_BUTTON_MIDDLE;
      } else if (mouseIsDown && useScrollButton) {
        // Log.d(TAG, "Sending a Mouse Scroll event: " + direction);
        if (direction == 0) {
          pointerMask = MOUSE_BUTTON_SCROLL_UP;
        } else if (direction == 1) {
          pointerMask = MOUSE_BUTTON_SCROLL_DOWN;
        } else if (direction == 2) {
          pointerMask = MOUSE_BUTTON_SCROLL_LEFT;
        } else if (direction == 3) {
          pointerMask = MOUSE_BUTTON_SCROLL_RIGHT;
        }
      } else if (mouseIsDown
          && (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_MOVE)) {
        // Log.i(TAG,"Left mouse button mask set");
        pointerMask = MOUSE_BUTTON_LEFT;
      } else {
        // Log.i(TAG,"Mouse button mask cleared");
        // If none of the conditions are satisfied, clear the pointer mask.
        pointerMask = 0;
      }

      vncCanvas.invalidateMousePosition();
      mouseX = x;
      mouseY = y;
      if (mouseX < 0) mouseX = 0;
      else if (mouseX >= rfb.framebufferWidth()) mouseX = rfb.framebufferWidth() - 1;
      if (mouseY < 0) mouseY = 0;
      else if (mouseY >= rfb.framebufferHeight()) mouseY = rfb.framebufferHeight() - 1;
      vncCanvas.invalidateMousePosition();

      rfb.writePointerEvent(
          mouseX, mouseY, modifiers | vncCanvas.getKeyboard().getMetaState(), pointerMask);
      return true;
    }
    return false;
  }
 public void mouseFollowPan() {
   if (vncCanvas.getMouseFollowPan()) {
     int scrollx = vncCanvas.getAbsoluteX();
     int scrolly = vncCanvas.getAbsoluteY();
     int width = vncCanvas.getVisibleWidth();
     int height = vncCanvas.getVisibleHeight();
     // Log.i(TAG,"scrollx " + scrollx + " scrolly " + scrolly + " mouseX " + mouseX +" Y " +
     // mouseY + " w " + width + " h " + height);
     if (mouseX < scrollx
         || mouseX >= scrollx + width
         || mouseY < scrolly
         || mouseY >= scrolly + height) {
       warpMouse(scrollx + width / 2, scrolly + height / 2);
     }
   }
 }