JDK-4819437 : DragSourceListener.dragExit() is called unexpectedly
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 5.0
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2003-02-17
  • Updated: 2017-05-16
  • Resolved: 2003-06-06
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
5.0 tigerFixed
Related Reports
Relates :  
Relates :  
Relates :  
Description

Name: dsR10078			Date: 02/17/2003



The problem is reproducible with JDK 1.5.0-b01 on all platforms 
with the following test case:
----------------------------------------------------------------------
import java.awt.*;
import java.awt.datatransfer.*;
import java.awt.dnd.*;

public class Test {
    final Frame frame = new Frame();
    final TextField source = new TextField("Drag me!");
    final TextField target = new TextField("Drop here");

    final DragSource ds = DragSource.getDefaultDragSource();
    final DragSourceListener dsl = new DragSourceListener() {
            public void dragEnter(DragSourceDragEvent dsde) {
                System.out.println("[Source] dragEnter");
            }
            public void dragOver(DragSourceDragEvent dsde) {
                System.out.println("[Source] dragOver");
            }
            public void dragMouseMoved(DragSourceDragEvent dsde) {
                System.out.println("[Source] dragMouseMoved");
            }
            public void dropActionChanged(DragSourceDragEvent dsde) {
                System.out.println("[Source] dropActionChanged");
            }
            public void dragExit(DragSourceEvent dse) {
                System.out.println("[Source] dragExit");
            }
            public void dragDropEnd(DragSourceDropEvent dsde) {
                System.out.println("[Source] dragDropEnd");
            }
        };
    final DragGestureListener dgl = new DragGestureListener() {
            public void dragGestureRecognized(DragGestureEvent dge) {
                Transferable t = new StringSelection("TEXT");
                dge.startDrag(null, t, dsl);
            }
        };
    final DragGestureRecognizer dgr =
        ds.createDefaultDragGestureRecognizer(source, 
                                              DnDConstants.ACTION_COPY,
                                              dgl);

    final DropTargetListener dtl = new DropTargetListener() {
            public void dragEnter(DropTargetDragEvent dtde) {
                System.out.println("[Target] dragEnter");
                dtde.rejectDrag();
            }
            public void dragOver(DropTargetDragEvent dtde) {
                System.out.println("[Target] dragOver");
            }
            public void dropActionChanged(DropTargetDragEvent dtde) {
                System.out.println("[Target] dropActionChanged");
            }
            public void dragExit(DropTargetEvent dte) {
                System.out.println("[Target] dragExit");
            }
            public void drop(DropTargetDropEvent dtde) {
                System.out.println("[Target] drop");
                dtde.rejectDrop();
            }
        };
    final DropTarget dt = new DropTarget(target, dtl);

    public static void main(String[] args) {
        Test test = new Test();
        test.run();
    }

    public void run() {
        frame.setLayout(new FlowLayout());
        frame.add(source);
        frame.add(target);
        frame.pack();
        frame.setVisible(true);
    }
}
----------------------------------------------------------------------

Run the test case - a frame will appear.
Drag from "Drag me!" text field to "Drop here" text field and watch 
the output dumped to the console. 
On Solaris/Linux the typical output is as follows:
----------------------------------------------------------------------
[Source] dragExit
[Source] dragExit
[Source] dragExit
[Source] dragExit
[Source] dragExit
[Target] dragEnter
[Target] dragOver
[Source] dragExit
[Target] dragOver
[Source] dragExit
[Target] dragOver
[Source] dragExit
[Target] dragOver
[Source] dragExit
[Source] dragExit
[Target] dragExit
[Source] dragDropEnd
----------------------------------------------------------------------

On Windows the typical output is as follows:
----------------------------------------------------------------------
[Source] dragExit
[Source] dragExit
[Target] dragEnter
[Source] dragExit
[Target] dragOver
[Source] dragExit
[Target] dragOver
[Source] dragExit
[Target] dragOver
[Source] dragExit
[Target] dragOver
[Source] dragExit
[Target] dragExit
[Source] dragExit
[Source] dragDropEnd
----------------------------------------------------------------------

There are two problems with the observed behavior:
1.DragSourceListener.dragExit() is called even before the drag enters the drop 
  target. This behavior doesn't match the javadoc comments for the method.
2.DragSourceListener.dragExit() is called after the drag enters the drop target 
  and the drop target rejects the drag. This behavior matches the javadoc 
  comments for the method, but it contradicts with the Drag and Drop 
  Specification (see
http://java.sun.com/j2se/1.4.1/docs/guide/dragndrop/spec/dnd1.doc5.html#920315).
 
  The difference between the javadoc and the Drag and Drop Specification is in 
  the condition for the DragSourceListener.dragExit() to be called if the drop 
  target rejected the drag. dragExit() is invoked when:

javadoc:
   "...the current drop site has rejected the drag."
DnD spec:
   "...the current DropTarget's DropTargetListener has invoked rejectDrag() 
    since the last dragEnter() or dragOver() invocation."

We believe that the behavior prescribed by javadoc is counter-intuitive: 
dragExit() can be called without preceeding dragEnter() or dragOver().
The behavior documented in the DnD spec is more reasonable:
dragExit() is called only after respective dragEnter() or dragOver().

###@###.### 2003-02-17
======================================================================

Comments
CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: tiger FIXED IN: tiger INTEGRATED IN: tiger tiger-b09
14-06-2004

WORK AROUND Name: dsR10078 Date: 02/17/2003 ======================================================================
11-06-2004

EVALUATION ###@###.### 2003-05-15
15-05-2003