/*
   * DO NOT USE is_hint field of xmotion since it could not be set when we
   * convert XKeyEvent or XButtonRelease to XMotionEvent.
   */
  private void processMouseMove(XMotionEvent xmotion) {
    if (!dragInProgress) {
      return;
    }
    if (xRoot != xmotion.get_x_root() || yRoot != xmotion.get_y_root()) {
      xRoot = xmotion.get_x_root();
      yRoot = xmotion.get_y_root();

      postDragSourceDragEvent(
          targetAction,
          XWindow.getModifiers(xmotion.get_state(), 0, 0),
          xRoot,
          yRoot,
          DISPATCH_MOUSE_MOVED);
    }

    if (eventState != xmotion.get_state()) {
      if (updateSourceAction(xmotion.get_state()) && dragProtocol != null) {
        postDragSourceDragEvent(
            targetAction,
            XWindow.getModifiers(xmotion.get_state(), 0, 0),
            xRoot,
            yRoot,
            DISPATCH_CHANGED);
      }
      eventState = xmotion.get_state();
    }

    updateTargetWindow(xmotion);

    if (dragProtocol != null) {
      dragProtocol.sendMoveMessage(
          xmotion.get_x_root(),
          xmotion.get_y_root(),
          sourceAction,
          sourceActions,
          xmotion.get_time());
    }
  }
  private void updateTargetWindow(XMotionEvent xmotion) {
    assert XToolkit.isAWTLockHeldByCurrentThread();

    int x = xmotion.get_x_root();
    int y = xmotion.get_y_root();
    long time = xmotion.get_time();
    long subwindow = xmotion.get_subwindow();

    /*
     * If this event had occurred before the pointer was grabbed,
     * query the server for the current root subwindow.
     */
    if (xmotion.get_window() != xmotion.get_root()) {
      XlibWrapper.XQueryPointer(
          XToolkit.getDisplay(),
          xmotion.get_root(),
          XlibWrapper.larg1, // root
          XlibWrapper.larg2, // subwindow
          XlibWrapper.larg3, // x_root
          XlibWrapper.larg4, // y_root
          XlibWrapper.larg5, // x
          XlibWrapper.larg6, // y
          XlibWrapper.larg7); // modifiers
      subwindow = Native.getLong(XlibWrapper.larg2);
    }

    if (targetRootSubwindow != subwindow) {
      if (dragProtocol != null) {
        dragProtocol.sendLeaveMessage(time);

        /*
         * Neither Motif DnD nor XDnD provide a mean for the target
         * to notify the source that the pointer exits the drop site
         * that occupies the whole top level.
         * We detect this situation and post dragExit.
         */
        if (targetAction != DnDConstants.ACTION_NONE) {
          dragExit(x, y);
        }
      }

      /* Update the global state. */
      doUpdateTargetWindow(subwindow, time);

      if (dragProtocol != null) {
        dragProtocol.sendEnterMessage(sourceFormats, sourceAction, sourceActions, time);
      }
    }
  }