JDK-4217341 : Problems with drag and drop across Java applications
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 1.2.0
  • Priority: P2
  • Status: Closed
  • Resolution: Not an Issue
  • OS: windows_nt
  • CPU: x86
  • Submitted: 1999-03-04
  • Updated: 2000-10-05
  • Resolved: 2000-10-05
Related Reports
Relates :  
Relates :  
Description

Name: vi73552			Date: 03/04/99


Despite the closed bug report 4126713 drag and drop is still
not working between java applications. The code which follows
illustrates the point...

The code works fine when the drag and drop is within one 
application but when two instances are started and you attempt
to drag and drop between them an exception is generated which
reads as follows...

java.io.IOException: class java.awt.dnd.InvalidDnDOperationException:No drop current caught while getting Data
        at java.awt.dnd.DropTargetContext$TransferableProxy.getTransferData(DropTargetContext.java:270)
        at dnd$MyDropTargetListener.drop(dnd.java:69)
        at java.awt.dnd.DropTarget.drop(DropTarget.java:343)
        at sun.awt.windows.WDropTargetContextPeer.processDropMessage(WDropTargetContextPeer.java:941)
        at sun.awt.windows.WDropTargetContextPeer.run(Compiled Code)
        at javax.swing.SystemEventQueueUtilities.processRunnableEvent(Compiled Code)
        at javax.swing.SystemEventQueueUtilities$RunnableTarget.processEvent(Compiled Code)
        at java.awt.Component.dispatchEventImpl(Compiled Code)
        at java.awt.Component.dispatchEvent(Compiled Code)
        at java.awt.EventQueue.dispatchEvent(Compiled Code)
        at java.awt.EventDispatchThread.run(EventDispatchThread.java:68)

//
// Simple Drag & Drop Program
//
// Author:  M.Shaw (###@###.###)
// Date:    15 Dec 1998
//

import java.io.IOException;

import java.awt.GridBagLayout;
import java.awt.GridBagConstraints;
import java.awt.Container;
import java.awt.Component;
import java.awt.Label;
import java.awt.Cursor;
import java.awt.Point;

import java.awt.dnd.*; // about 20 classes/interfaces are used

import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.UnsupportedFlavorException;

import java.awt.event.WindowEvent;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JComponent;
import javax.swing.ImageIcon;
import javax.swing.SwingConstants;

public class dnd extends JFrame
{
    public static void main( String[] args )
    {
        dnd dd = new dnd();
    }

    class MyDropTargetListener implements DropTargetListener
    {
        public void dragEnter(DropTargetDragEvent dtde)
        {
//            System.out.println("MyDropTargetListener.dragEnter");
//            dropOntoMe.setIcon(new ImageIcon("images/openbox.gif"));
        }

        public void dragExit(DropTargetEvent dtde)
        {
//            System.out.println("MyDropTargetListener.dragExit");
//            dropOntoMe.setIcon(new ImageIcon("images/closedbox.gif"));
        }

        public void dragOver(DropTargetDragEvent dtde)
        {
//            System.out.println("MyDropTargetListener.dragOver");
        }

        public void drop(DropTargetDropEvent dtde)
        {
//            System.out.println("MyDropTargetListener.drop");
            if (dtde.isDataFlavorSupported(DataFlavor.stringFlavor))
            {
                try
                {
                    Object transData = dtde.getTransferable().getTransferData(DataFlavor.stringFlavor);
                    if ( transData instanceof String )
                        System.out.println("Dropped a '" + (String) transData + "'!!");
                    dtde.acceptDrop(DnDConstants.ACTION_COPY);
//                    dropOntoMe.setIcon(new ImageIcon("images/box.gif"));
                }
                catch (UnsupportedFlavorException ufe)
                {
//                    System.out.println("trans.getTransferData() threw UnsupportedFlavorException");
                    ufe.printStackTrace();
                    dtde.rejectDrop();
                    dtde.dropComplete(true);
                }
                catch (IOException ioe)
                {
//                    System.out.println("trans.getTransferData() threw IOException");
                    ioe.printStackTrace();
                    dtde.rejectDrop();
                    dtde.dropComplete(false);
                }
            }
            else
            {
                dtde.rejectDrop();
                dtde.dropComplete(false);
            }
        }

        public void dropActionChanged(DropTargetDragEvent dtde)
        {
            //System.out.println("MyDropTargetListener.dropActionChanged");
        }
    }

    class MyDragSourceListener implements DragSourceListener
    {
        public void dragDropEnd(DragSourceDropEvent e)
        {
//            System.out.println("MyDragSourceListener.dragDropEnd");
        }

        public void dragEnter(DragSourceDragEvent e)
        {
//            System.out.println("MyDragSourceListener.dragEnter");
        }

        public void dragExit(DragSourceEvent e)
        {
//            System.out.println("MyDragSourceListener.dragExit");
        }

        public void dragOver(DragSourceDragEvent e)
        {
//            System.out.println("MyDragSourceListener.dragOver");
            if ( e.getDragSourceContext().getCursor().getType() != Cursor.DEFAULT_CURSOR );
              e.getDragSourceContext().setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
        }

        public void dropActionChanged(DragSourceDragEvent e)
        {
//            System.out.println("MyDragSourceListener.dropActionChanged");
        }
    }

    class MyDragGestureListener implements DragGestureListener
    {
        public void dragGestureRecognized(DragGestureEvent dge)
        {
//            System.out.println("MyDragGestureListener.dragGestureRecognized");
            MyDragSourceListener dsl = new MyDragSourceListener();
            MyTransferable transfer = new MyTransferable();

            try
            {
                dge.startDrag(new Cursor(Cursor.DEFAULT_CURSOR), transfer, dsl);
            }
            catch (InvalidDnDOperationException e)
            {
                System.err.println("startDrag threw InvalidDndOperationException");
                e.printStackTrace();
            }
        }
    }

    class MyTransferable implements Transferable
    {
        public DataFlavor[] getTransferDataFlavors()
        {
            //System.out.println("MyTransferable.getTransferDataFlavors");
            DataFlavor[] flavors = { DataFlavor.stringFlavor };
            return flavors;
        }

        public boolean isDataFlavorSupported(DataFlavor flavor)
        {
            //System.out.println("MyTransferable.isDataFlavorSupported");
            return (flavor.equals(DataFlavor.stringFlavor));
        }

        public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException
        {
            //System.out.println("MyTransferable.getTransferData");
            return new String("dragon");
        }

    }

    class MyActionListener implements ActionListener
    {
        public void actionPerformed(ActionEvent e)
        {
            resetAction();
        }
    }

    public dnd()
    {
        JPanel panel = new JPanel();
        getContentPane().add(panel);
        panel.setLayout(new GridBagLayout());
        dragMe = new JLabel("drag me", /*new ImageIcon("images/duke.gif"),*/ SwingConstants.CENTER);
        dropOntoMe = new JLabel("drop onto me", /*new ImageIcon("images/closedbox.gif"),*/ SwingConstants.CENTER);
//        JButton reset = new JButton("reset");
//    	MyActionListener al = new MyActionListener();
//        reset.addActionListener(al);
        attachWidget(panel, dragMe, 0, 0, 1, 1, 1, 1);
        attachWidget(panel, dropOntoMe, 1, 0, 1, 1, 1, 1);
//        attachWidget(panel, reset, 0, 1, 2, 1, 1, 1);

        DragSource ds = new DragSource();

        MyDragGestureListener dgl = new MyDragGestureListener();
        DragGestureRecognizer dgr = ds.createDefaultDragGestureRecognizer(dragMe, DnDConstants.ACTION_COPY, dgl);

        MyDropTargetListener dtl = new MyDropTargetListener();
        DropTarget dt = new DropTarget(dropOntoMe, dtl);
        dt.setDefaultActions(DnDConstants.ACTION_COPY);
        dt.setActive(true);
        pack();
        show();
    }

    protected void resetAction()
    {
//        dropOntoMe.setIcon(new ImageIcon("images/closedbox.gif"));
    }

    protected void processWindowEvent (WindowEvent e)
    {
        if (e.getID() == WindowEvent.WINDOW_CLOSING)
            System.exit(0);
        super.processWindowEvent (e);
    }

    static void attachWidget(Container cont, JComponent comp, int x, int y, int w, int h,
                          double weightx, double weighty)
    {
        GridBagLayout gbl = (GridBagLayout) cont.getLayout();
        GridBagConstraints c = new GridBagConstraints();

        c.fill = GridBagConstraints.BOTH;
        c.gridx = x;
        c.gridy = y;
        c.gridwidth = w;
        c.gridheight = h;
        c.weightx = weightx;
        c.weighty = weighty;
        cont.add(comp);
        gbl.setConstraints(comp, c);
    }

    JLabel dragMe;
    JLabel dropOntoMe;
}
(Review ID: 48148) 
======================================================================

Comments
EVALUATION The situation is even worse in kestrel and merlin. Java crashes as soon as a drag is initiated. david.mendenhall@eng 2000-08-03 I am committing this bug to ladybird and merlin-beta, but only the regression portion of this bug is critical for these releases. Once we are back to the 1.2.2 behavior, this bug should be reevaluated and possibly decommitted. david.mendenhall@east 2000-08-04 Name: dsR10078 Date: 09/09/2000 ###@###.### The crash which is a regression from kestrel is a duplicate of 4343300. The rest of the bug is 'not a bug', since there are two bugs in the test case. 1.DropTargetDropEvent.getTransferable() is invoked before DropTargetDropEvent.acceptDrop() Javadoc for DropTargetListener.drop() prescribes that DropTargetDropEvent.getTransferable() may be invoked only subsequent to DropTargetDropEvent.acceptDrop(). Failing to do so causes the exception described in the bug report. 2.DropTargetListener.drop() doesn't call DropTargetDropEvent.dropComplete(). Javadoc for DropTargetListener.drop() prescribes that DropTargetDropEvent.dropComplete() must be called at the completion of a drop. Failing to do so causes the test case to hang. This hang is documented 4187912. When the test is corrected accordingly dnd operates successfully between two jvms. ======================================================================
11-06-2004

WORK AROUND Name: vi73552 Date: 03/04/99 I have tried various workarounds including including using the clipboard and sockets. So far none are satisfactory. ======================================================================
11-06-2004