JDK-4451328 : 1.3.1 Regression: DnD Custom Cursors are Getting overridden by defaults
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 1.2.0,1.2.2,1.2.2_005,1.3.1
  • Priority: P2
  • Status: Resolved
  • Resolution: Fixed
  • OS:
    solaris_8,windows_98,windows_nt,windows_2000 solaris_8,windows_98,windows_nt,windows_2000
  • CPU: x86,sparc
  • Submitted: 2001-04-26
  • Updated: 2001-05-03
  • Resolved: 2001-05-01
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 Other
1.3.1 ladybirdFixed 1.4.0Fixed
Related Reports
Duplicate :  
Relates :  
Description

Name: krC82822			Date: 04/26/2001


26 Apr 2001, eval1127@eng -- reproducible with 1.3.1 RC1,
1.3.1 RC2 (build 23), and merlin (1.4) beta build 61.

Both 1.3.0 and 1.3.0_02 work fine (i.e., the custom cursor
stays visible till you reach the drop target, at which point
the image disappears).
-------------------
C:\javawrk>java -version
java version "1.3.1-rc1"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.1-rc1-b21)
Java HotSpot(TM) Client VM (build 1.3.1-rc1-b21, mixed mode)

java version "1.3.1-rc2"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.1-rc2-b23)
Java HotSpot(TM) Client VM (build 1.3.1-rc2-b23, mixed mode)

java version "1.4.0-beta"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0-beta-b61)
Java HotSpot(TM) Client VM (build 1.4.0-beta-b61, mixed mode)

Using JDK 1.3.0_02 the following code creates a custom
drag cursor. Using 1.3.1RC-1 the custom cursor gets instantiated,
for a brief, flash then it gets overridden with the default
Copy_Drop cursor.

  To Test/Verify compile the test example. You'll need an image.
I'm using middle.gif available from
http://www.java.sun.com/docs/books/tutorial/uiswing/components/example-
swing/images/middle.gif

Just compile and run Test2.java
Then drag the text that says "Drag from here" and the cursors change.
-------

revised test case:

import java.awt.*;
import java.awt.event.*;
import javax.swing.event.*;
import javax.swing.*;
import javax.swing.text.*;
import java.awt.datatransfer.*;
import java.io.*;
import java.awt.dnd.*;

public class Test12334_Revised extends JPanel {

  public Test12334_Revised()  {
    this.setLayout( new GridLayout(1,2, 5, 5));

    DragLabel2 dragLabel = new DragLabel2("Drag from here",DnDConstants.ACTION_COPY_OR_MOVE);
    dragLabel.setBackground(Color.white);
    dragLabel.setOpaque(true);
    add(dragLabel);

    DropLabel2 dropLabel = new DropLabel2("Drop here",DnDConstants.ACTION_COPY_OR_MOVE);
    dropLabel.setBackground(Color.yellow);
    dropLabel.setOpaque(true);
    add(dropLabel);
  }

  public static void main(String[] args) {
    JFrame frame = new JFrame();
    frame.setTitle("Drag and Drop test");
    Container cont = frame.getContentPane();
    cont.add( new Test12334_Revised() );
    frame.addWindowListener( new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
 System.exit(0);
      }
    });
    frame.setSize(300,300);
    frame.setVisible(true);
  }

}

class DragLabel2 extends JLabel {

  public DragLabel2(String s, int a) {
    this.dragAction = a;
    this.setText(s);
    this.setOpaque(true);
    this.dragSource = DragSource.getDefaultDragSource();
    this.dgListener = new DGListener();
    this.dsListener = new DSListener();

    // component, action, listener
    this.dragSource.createDefaultDragGestureRecognizer(
      this,
      this.dragAction,
      this.dgListener);
  }


  /**
   * DGListener
   * a listener that will start the drag.
   */
  class DGListener implements DragGestureListener {
   private Cursor movingCursor = null;

    public void dragGestureRecognized(DragGestureEvent e) {

      // get the label's text and put it inside a Transferable
      Transferable transferable = new StringSelection( DragLabel2.this.getText());

      // now kick off the drag
      try {
  Point hotspot = new Point(0,0);;
  Toolkit toolkit = Toolkit.getDefaultToolkit();
  ImageIcon picture = new ImageIcon("middle.gif");
  if (picture == null) {
   movingCursor = DragSource.DefaultCopyDrop;
   System.out.println("default Cursor");
   }
  else
  {
   Dimension d = toolkit.getBestCursorSize(picture.getIconWidth(),
    picture.getIconHeight());
   hotspot = new Point(d.width / 2, d.height / 2);
   movingCursor = toolkit.createCustomCursor(
    picture.getImage(), hotspot, "movingCursor");
  }
   // cursor, image, point, transferrable, dsource listener
   file://e.startDrag(movingCursor, transferable, dsListener);
   e.startDrag(movingCursor, picture.getImage(), hotspot, transferable,
dsListener);

      }catch( InvalidDnDOperationException idoe ) {
  idoe.printStackTrace();
      }
    }
  }

  /**
   * DSListener
   * a listener that will track the state of the DnD operation
   */
  class DSListener implements DragSourceListener {
    public void dragDropEnd(DragSourceDropEvent e) {
    }

    public void dragEnter(DragSourceDragEvent e) {
    }

    public void dragOver(DragSourceDragEvent e) {
    }

    public void dragExit(DragSourceEvent e) {
    }

    public void dropActionChanged (DragSourceDragEvent e) {
    }
  }


  private DragSource dragSource;
  private DragGestureListener dgListener;
  private DragSourceListener dsListener;
  private int dragAction = DnDConstants.ACTION_COPY;
}

class DropLabel2 extends JLabel {

  public DropLabel2(String s, int a) {
    this.acceptableActions = a;
    this.setText(s);
    this.borderColor=Color.green;
    this.dtListener = new DTListener();

    // component, ops, listener, accepting
    this.dropTarget = new DropTarget(this,
      this.acceptableActions,
      this.dtListener,
      true);

  }

  private void showBorder(boolean b) {
    if(b) {
      this.setBorder( BorderFactory.createLineBorder(this.borderColor, 10));
    } else {
      this.setBorder( BorderFactory.createEmptyBorder() );
    }
    this.getParent().validate();
    this.repaint();
  }

  /**
   * DTListener
   * a listener that tracks the state of the operation
   */
  class DTListener implements DropTargetListener {


    public void dragEnter(DropTargetDragEvent e) {
      DropLabel2.this.borderColor=Color.green;
      showBorder(true);
      e.acceptDrag(e.getDropAction());
    }

    public void dragOver(DropTargetDragEvent e) {
      e.acceptDrag(e.getDropAction());
    }

    public void dropActionChanged(DropTargetDragEvent e) {
      e.acceptDrag(e.getDropAction());
    }

    public void dragExit(DropTargetEvent e) {
      DropLabel2.this.borderColor=Color.green;
      showBorder(false);
    }

    public void drop(DropTargetDropEvent e) {
      // the actual operation
      int da = e.getDropAction();
      // the actions that the source has specified with DragGestureRecognizer
      int sa = e.getSourceActions();

  e.acceptDrop(DropLabel2.this.acceptableActions);
  e.dropComplete(false);
  showBorder(false);
 }
  }

  private DropTarget dropTarget;
  private DropTargetListener dtListener;

  private int acceptableActions = DnDConstants.ACTION_COPY;

  private Color borderColor;
}


(Review ID: 123334) 
======================================================================
pratul.wadher@Eng 2001-05-08
Verified with Ladybird build 24 on Solaris 2.8 and WinNT. The test passed.

=========================================================================

Comments
CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: ladybird merlin-beta2 FIXED IN: ladybird merlin-beta2 INTEGRATED IN: ladybird merlin-beta2
14-06-2004

EVALUATION On Windows, the behavior has regressed in ladybird, but not in merlin. On Solaris, the behavior has regressed in both ladybird and merlin. Should be investigated further and fixed in ladybird if the fix is low risk. Committing to ladybird and merlin-beta2. david.mendenhall@east 2001-04-27 Name: dsR10078 Date: 04/28/2001 Currently custom drag cursors are implemented so that the cursor stays corrent until the first drag notification is sent to the drag source. This is wrong, since by design we shouldn't set default drag cursors after the drag cursor is explicitly set from client code. This bug exists since 1.2. In 1.3 the drag cursor doesn't change to the default one until the drag enters the drop target, since the drag source doesn't receive drag notifications until the drag enters the drop target. The cause of the regression is that the drag source receives the first drag notification as soon as the drag starts. On Solaris this change was introduced with the fix for 4341996, which posts dragExit notification to the drag source whenever the mouse moves when the drag is not over a valid drop target. This change exists both in Merlin and Ladybird. On Win32 this change was introduced with Solaris/Win32 dnd code unification (under bug id 4289735). Because of code merge error the drop target responce to drag notification is incorrectly reported to the native DnD system. As a result the native DnD system considers the whole frame as a valid drop target, so it starts posting drag notifications to the drag source as soon as the drag starts. In Merlin this problem was fixed with DnD lightweight event dispatch redesign, this is why the bug is not reproducible in Merlin on Win32. ###@###.### 2001-04-28 ====================================================================== Name: dsR10078 Date: 05/04/2001 After all the described problems are fixed we discovered another problem related to custom drag cursors on Win32. If a system cursor (e.g., Cursor.HAND_CURSOR) is specified as a drag cursor the actual drag cursor will change back and forth between the specified system cursor and the default drag cursor - you will see continuous flickering of a drag cursor. This happens since win32 native dnd code incorrectly assumes that a custom drag cursor is a real custom cursor. This problem is not a regression - the app will crash on 1.3 if a system cursor is used as a custom drag cursor - see bug id 4343300. ###@###.### 2001-05-04 ======================================================================
04-05-2001

SUGGESTED FIX Name: dsR10078 Date: 04/28/2001 Properly determine whether a custom drag cursor is set and avoid setting the default drag cursor in this case. Additionally fix the code merge error in ladybird: properly report the drop target response to the native DnD system. ###@###.### 2001-04-28 ====================================================================== Name: dsR10078 Date: 05/04/2001 To fix the drag cursor flickering problem on Win32 i suggest to handle "system custom drag cursors" properly, i.e. we should distinguish three cases: - default drag cursor; - custom drag cursor which is a system cursor; - custom drag cursor which is a custom cursor. ###@###.### 2001-05-04 ======================================================================
04-05-2001