protected void checkSubclass() {
   String name = getClass().getName();
   String validName = DragSource.class.getName();
   if (!validName.equals(name)) {
     DND.error(SWT.ERROR_INVALID_SUBCLASS);
   }
 }
 /**
  * Adds the listener to the collection of listeners who will be notified when a drag and drop
  * operation is in progress, by sending it one of the messages defined in the <code>
  * DragSourceListener</code> interface.
  *
  * <p>
  *
  * <ul>
  *   <li><code>dragStart</code> is called when the user has begun the actions required to drag the
  *       widget. This event gives the application the chance to decide if a drag should be
  *       started.
  *   <li><code>dragSetData</code> is called when the data is required from the drag source.
  *   <li><code>dragFinished</code> is called when the drop has successfully completed (mouse up
  *       over a valid target) or has been terminated (such as hitting the ESC key). Perform
  *       cleanup such as removing data from the source side on a successful move operation.
  * </ul>
  *
  * @param listener the listener which should be notified
  * @exception IllegalArgumentException
  *     <ul>
  *       <li>ERROR_NULL_ARGUMENT - if the listener is null
  *     </ul>
  *
  * @exception SWTException
  *     <ul>
  *       <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  *       <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
  *     </ul>
  *
  * @see DragSourceListener
  * @see #getDragListeners
  * @see #removeDragListener
  * @see DragSourceEvent
  */
 public void addDragListener(DragSourceListener listener) {
   if (listener == null) DND.error(SWT.ERROR_NULL_ARGUMENT);
   DNDListener typedListener = new DNDListener(listener);
   typedListener.dndWidget = this;
   addListener(DND.DragStart, typedListener);
   addListener(DND.DragSetData, typedListener);
   addListener(DND.DragEnd, typedListener);
 }
  /**
   * Creates a new <code>DragSource</code> to handle dragging from the specified <code>Control
   * </code>. Creating an instance of a DragSource may cause system resources to be allocated
   * depending on the platform. It is therefore mandatory that the DragSource instance be disposed
   * when no longer required.
   *
   * @param control the <code>Control</code> that the user clicks on to initiate the drag
   * @param style the bitwise OR'ing of allowed operations; this may be a combination of any of
   *     DND.DROP_NONE, DND.DROP_COPY, DND.DROP_MOVE, DND.DROP_LINK
   * @exception SWTException
   *     <ul>
   *       <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
   *       <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
   *     </ul>
   *
   * @exception SWTError
   *     <ul>
   *       <li>ERROR_CANNOT_INIT_DRAG - unable to initiate drag source; this will occur if more than
   *           one drag source is created for a control or if the operating system will not allow
   *           the creation of the drag source
   *     </ul>
   *     <p>NOTE: ERROR_CANNOT_INIT_DRAG should be an SWTException, since it is a recoverable error,
   *     but can not be changed due to backward compatibility.
   * @see Widget#dispose
   * @see DragSource#checkSubclass
   * @see DND#DROP_NONE
   * @see DND#DROP_COPY
   * @see DND#DROP_MOVE
   * @see DND#DROP_LINK
   */
  public DragSource(Control control, int style) {
    super(control, checkStyle(style));
    this.control = control;
    if (control.getData(DND.DRAG_SOURCE_KEY) != null) {
      DND.error(DND.ERROR_CANNOT_INIT_DRAG);
    }
    control.setData(DND.DRAG_SOURCE_KEY, this);
    createCOMInterfaces();
    this.AddRef();

    controlListener =
        new Listener() {
          public void handleEvent(Event event) {
            if (event.type == SWT.Dispose) {
              if (!DragSource.this.isDisposed()) {
                DragSource.this.dispose();
              }
            }
            if (event.type == SWT.DragDetect) {
              if (!DragSource.this.isDisposed()) {
                DragSource.this.drag(event);
              }
            }
          }
        };
    control.addListener(SWT.Dispose, controlListener);
    control.addListener(SWT.DragDetect, controlListener);

    this.addListener(
        SWT.Dispose,
        new Listener() {
          public void handleEvent(Event e) {
            DragSource.this.onDispose();
          }
        });

    Object effect = control.getData(DEFAULT_DRAG_SOURCE_EFFECT);
    if (effect instanceof DragSourceEffect) {
      dragEffect = (DragSourceEffect) effect;
    } else if (control instanceof Tree) {
      dragEffect = new TreeDragSourceEffect((Tree) control);
    } else if (control instanceof Table) {
      dragEffect = new TableDragSourceEffect((Table) control);
    }
  }
  /**
   * This implementation of <code>javaToNative</code> converts an ImageData object represented by
   * java <code>ImageData</code> to a platform specific representation.
   *
   * @param object a java <code>ImageData</code> containing the ImageData to be converted
   * @param transferData an empty <code>TransferData</code> object that will be filled in on return
   *     with the platform specific format of the data
   * @see Transfer#nativeToJava
   */
  public void javaToNative(Object object, TransferData transferData) {
    if (!checkImage(object) || !isSupportedType(transferData)) {
      DND.error(DND.ERROR_INVALID_DATA);
    }
    if (OS.GTK_VERSION < OS.VERSION(2, 4, 0)) return;

    ImageData imgData = (ImageData) object;
    if (imgData == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
    Image image = new Image(Display.getCurrent(), imgData);
    long /*int*/ pixbuf = ImageList.createPixbuf(image);
    if (pixbuf != 0) {
      String typeStr = "";
      if (transferData.type == JPEG_ID) typeStr = "jpeg";
      else if (transferData.type == PNG_ID) typeStr = "png";
      else if (transferData.type == BMP_ID) typeStr = "bmp";
      else if (transferData.type == EPS_ID) typeStr = "eps";
      else if (transferData.type == PCX_ID) typeStr = "pcx";
      else if (transferData.type == PPM_ID) typeStr = "ppm";
      else if (transferData.type == RGB_ID) typeStr = "rgb";
      else if (transferData.type == TGA_ID) typeStr = "tga";
      else if (transferData.type == XBM_ID) typeStr = "xbm";
      else if (transferData.type == XPM_ID) typeStr = "xpm";
      else if (transferData.type == XV_ID) typeStr = "xv";
      byte[] type = Converter.wcsToMbcs(null, typeStr, true);
      long /*int*/[] buffer = new long /*int*/[1];
      long /*int*/[] len = new long /*int*/[1];
      if (type == null) return;
      OS.gdk_pixbuf_save_to_bufferv(pixbuf, buffer, len, type, null, null, null);
      OS.g_object_unref(pixbuf);
      transferData.pValue = buffer[0];
      transferData.length = (int) (len[0] + 3) / 4 * 4;
      transferData.result = 1;
      transferData.format = 32;
    }
    image.dispose();
  }
 /**
  * Removes the listener from the collection of listeners who will be notified when a drag and drop
  * operation is in progress.
  *
  * @param listener the listener which should no longer be notified
  * @exception IllegalArgumentException
  *     <ul>
  *       <li>ERROR_NULL_ARGUMENT - if the listener is null
  *     </ul>
  *
  * @exception SWTException
  *     <ul>
  *       <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  *       <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
  *     </ul>
  *
  * @see DragSourceListener
  * @see #addDragListener
  * @see #getDragListeners
  */
 public void removeDragListener(DragSourceListener listener) {
   if (listener == null) DND.error(SWT.ERROR_NULL_ARGUMENT);
   removeListener(DND.DragStart, listener);
   removeListener(DND.DragSetData, listener);
   removeListener(DND.DragEnd, listener);
 }