JDK-7199783 : Setting cursor on DragSourceContext does not work on OSX
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 7
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • OS: os_x
  • CPU: x86
  • Submitted: 2012-09-20
  • Updated: 2014-10-15
  • Resolved: 2013-04-05
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.
JDK 7 JDK 8
7u40Fixed 8 b86Fixed
Description
FULL PRODUCT VERSION :
java version "1.7.0_07"
Java(TM) SE Runtime Environment (build 1.7.0_07-b10)
Java HotSpot(TM) 64-Bit Server VM (build 23.2-b09, mixed mode)

ADDITIONAL OS VERSION INFORMATION :
Mac OS X 10.7.4
Darwin Kernel Version 11.4.0: RELEASE_X86_64 x86_64

A DESCRIPTION OF THE PROBLEM :
When setting the cursor on a DragSourceContext object during a drag operation, the cursor does not change it appearance. According to the documentation of DragSourceContext this should work. Under Windows it does show the appropriate behavior, but under Mac OS X the cursor does not change it appearance.

Tested with different JREs: Java 6 and 7 and OpenJDK 8 all show incorrect behavior on OS X.


STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Implement a DragSourceListener and DragGestureListener and attach it to a Component. Set the cursor using the setCursor method in DragSourceContext. The DragSourceContext can be obtained using the DragSourceDragEvent parameters in the dragEnter and dragOver methods.

Alternatively, a DragSourceMotionListener can be added to the DragSource on a Component. The cursor can then be set, using the same setCursor method in DragSourceContext, in the dragMouseMoved method.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The cursor should change it appearance to the custom component when dragging an object.
ACTUAL -
The cursor does not change it appearance at all.

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.datatransfer.StringSelection;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DragGestureEvent;
import java.awt.dnd.DragGestureListener;
import java.awt.dnd.DragSource;
import java.awt.dnd.DragSourceDragEvent;
import java.awt.dnd.DragSourceDropEvent;
import java.awt.dnd.DragSourceEvent;
import java.awt.dnd.DragSourceListener;
import java.awt.dnd.DragSourceMotionListener;

import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.ListSelectionModel;

public class CustomCursorDSCTest extends JFrame implements DragSourceListener, DragGestureListener
{
  private JList<String> list;
  
  public CustomCursorDSCTest()
  {
    super("DragSourceContext setCursor Test");
    setSize(300, 350);
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    this.getContentPane().add(new ComponentPanel());
    DragSource ds = new DragSource();
    ds.createDefaultDragGestureRecognizer(list, DnDConstants.ACTION_COPY, this);
    ds.addDragSourceMotionListener(new MotionListener());
    setVisible(true);
  }

  public void dragGestureRecognized(DragGestureEvent dge)
  {
    StringSelection transferable = new StringSelection(list.getSelectedValue().toString());
    dge.getDragSource().startDrag(dge, DragSource.DefaultCopyDrop, transferable, this);
  }

  public void dragEnter(DragSourceDragEvent dsde)
  {
    System.out.println("Drag enter, setting cursor");
    dsde.getDragSourceContext().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
  }

  public void dragOver(DragSourceDragEvent dsde)
  {
    System.out.println("Drag over, setting cursor");
    dsde.getDragSourceContext().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
  }

  public void dropActionChanged(DragSourceDragEvent dsde)
  {
  }

  public void dragExit(DragSourceEvent dse)
  {
    System.out.println("Drag exit");
  }

  public void dragDropEnd(DragSourceDropEvent dsde)
  {
    System.out.println("Drag end");
  }
  
  private class ComponentPanel extends JPanel
  {
    public ComponentPanel()
    {
      String[] items = {"Java", "C", "C++", "Lisp", "Perl", "Python"};
      list = new JList<String>(items);
      list.setPreferredSize(new Dimension(75, 150));
      list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
      JTextArea textArea = new JTextArea(6, 20);
      this.add(list);
      this.add(textArea);
    }
  }
  
  private class MotionListener implements DragSourceMotionListener
  {
    public void dragMouseMoved(DragSourceDragEvent dsde)
    {
      dsde.getDragSourceContext().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
    }
  }
  
  public static void main(String args[])
  {
    new CustomCursorDSCTest();
  }
}
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Setting the cursor on a component does seem to work. A workaround would be to install a glasspane when dragging and setting the cursor on this glasspane.

Comments
It is impossible to query if the native cursor was actually set or not, so it's hard to create a regression test.
22-08-2013

Based on a comment from Lana - I have marked this bug as 7u40-critical-approved. I am about to finish my 7u40-dev push to the Master. One thing to note: The following changeset mentions two bugids: one has the approval, the other - 7199783 does not. I am going to assume that the whole changeset was approved via the first bug, however it would be clearer if both bugs had the approval keyword. http://hg.openjdk.java.net/jdk7u/jdk7u40-dev/jdk/rev/b2c2cbad0d1d 8006941: [macosx] Deadlock in drag and drop 7199783: Setting cursor on DragSourceContext does not work on OSX Reviewed-by: anthony, serb
17-07-2013

Mac OSX specific issue.
27-09-2012