JDK-8187495 : Drag and Drop not working in mix mode (JavaFX / Swing)
  • Type: Bug
  • Component: javafx
  • Sub-Component: swing
  • Affected Version: 8,9
  • Priority: P3
  • Status: Closed
  • Resolution: Not an Issue
  • OS: other
  • CPU: x86
  • Submitted: 2017-09-12
  • Updated: 2018-10-29
  • Resolved: 2017-09-21
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 10
10Resolved
Related Reports
Duplicate :  
Duplicate :  
Relates :  
Relates :  
Description
FULL PRODUCT VERSION :
java version "9"
Java(TM) SE Runtime Environment (build 9+181)
Java HotSpot(TM) 64-Bit Server VM (build 9+181, mixed mode)

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows [Version 10.0.15063]

A DESCRIPTION OF THE PROBLEM :
DnD does not work in mixed mode.

In the example here, nothing happens when running as a JavaFX application.  When running as a Swing application, the drag is initiated as expected.

Using the source code in https://bugs.openjdk.java.net/browse/JDK-8094457, yields a different result, the drag gesture is recognized but doesn't do anything.  However, trying a second time causes an exception:
Exception in thread "JavaFX Application Thread" java.awt.dnd.InvalidDnDOperationException: Drag and drop in progress
	at java.desktop/sun.awt.dnd.SunDragSourceContextPeer.setDragDropInProgress(SunDragSourceContextPeer.java:357)
	at java.desktop/java.awt.dnd.DragSource.startDrag(DragSource.java:303)
	at java.desktop/java.awt.dnd.DragSource.startDrag(DragSource.java:422)
	at java.desktop/java.awt.dnd.DragGestureEvent.startDrag(DragGestureEvent.java:238)
	at dsi.SwingDnD$2$1.dragGestureRecognized(SwingDnD.java:78)
[snip]



STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
In the program, set the testFX variable in the main() method to false.  This will run it in Swing.  The drag starts correctly.
Change the testFX variable to true and try again; this time the drag will not be initiated.

Also try the code in https://bugs.openjdk.java.net/browse/JDK-8094457.  Here, the bug will manifest itself as a java.awt.dnd.InvalidDnDOperationException



EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Drag and Drop to work as it did
ACTUAL -
Nothing happens

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------

import java.awt.GridLayout;
import javafx.application.Application;
import javafx.embed.swing.SwingNode;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

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

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

public class SwingFx extends Application {

	@Override
	public void start(Stage stage) {
		final SwingNode swingNode = new SwingNode();

		createSwingContent(swingNode);

		StackPane pane = new StackPane();
		pane.getChildren().add(swingNode);

		stage.setTitle("JavaFX Sample App");
		stage.setScene(new Scene(pane, 800, 600));
		stage.show();
	}
	private static JPanel createPanel() {
		JButton button = new JButton("Click Here!");
		JTextField field = new JTextField("Text");
		field.setDragEnabled(true);
		button.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				System.out.println("Button Clicked!!!");
			}
		});
		JPanel p = new JPanel(new GridLayout(1, 2));
		p.add(button);
		p.add(field);
		return p;
	}

	private void createSwingContent(final SwingNode swingNode) {
		SwingUtilities.invokeLater(new Runnable() {
			@Override
			public void run() {
				swingNode.setContent(createPanel());
			}
		});
	}
	public static void main(String[] args) {
		boolean testFX = true;
		
		if (testFX)
			Application.launch(SwingFx.class, args);
		else {
			SwingUtilities.invokeLater(() -> {
				JFrame frame = new JFrame();
				frame.setSize(200, 200);
				frame.setContentPane(createPanel());
				frame.setVisible(true);
			});
		}
	}
}

---------- END SOURCE ----------


Comments
The second issue(InvalidDnDOperationException with -Djavafx.embed.singleThread=true) mentioned in this bug don't have any direct relation with the base bug, so that issue is tracking as separate bug : JDK-8187781
21-09-2017

FX design/implementation is such that the drag/drop is performed/handled once FXDragGestureRecogniser is instantiated "after" the component which is to initiate the drag (be in JTextField etc) is added to SwingNode via SwingNode.setContent() call. Way to instantiate FXDragGestureRecogniser object is to call dragSource.createDefaultDragGestureRecognizer() after SwingNode.setContent(). Swing implementation is little different in the sense as it creates SwingDragGestureRecognizer when mouse is dragged but it is not so for fx. In swing, When mouse is dragged, DragRecognitionSupport#mouseDraggedImpl() calls TransferHandler#exportDrag() which calls SwingDragGestureRecognizer(). It then calls fireDragGestureRecognized() which calls TransferHandler#startDrag() which calls DragSource.startDrag() which calls WDragSourceContextPeer.startDrag() which does the dragdrop operations by calling native doDragDrop(). FX Implementation is such that DragSource.startDrag() calls FXDnD.startDrag() which creates a Secondary loop and waits. The actual drag operations are done in FXDragGestureRecognizer.onDragStartHandler (which is registered in FXDragGestureRecognizer.registerListeners) and secondary loop is also exited in onDragStartHandler, so unless secondary loop exits, the drag operations is not finished. That is why, we do not see drag finishing if we do not call createDefaultDragGestureRecogniser to instantiate FXDragGestureRecognizer. Attached file shows how to get FXDnD to work.
20-09-2017

After checking with reporter, came to know that test code from JDK-8094457 gives "java.awt.dnd.InvalidDnDOperationException" when the threads are synchronized, i.e. using jvm option -"Djavafx.embed.singleThread=true". Its reproducible. in 8u144, 9-ea+181, 10ea+23.
19-09-2017

When verified in windows 10 : -> swing mode: Pass - works as expected -> mixed mode/embedding swing into javafx: Fails Reported issue is reproducible in JDK 8 and 9 (9-ea+181). As mentioned by reporter, i also verified test code from JDK-8094457 but it is working fine as drag gesture is recognized always. This bug looks related to JDK-8146900
13-09-2017