DropTargetListener in FXCanvas$HostContainer class uses an "ignoreleave" flag to prevent drag leave after drop resulting in a javafx drag exited event. but this flag is never reset.
i cannot attach a file so i'm pasting the test case code and fix.
==== TestCase.java ====
import javafx.embed.swt.FXCanvas;
import javafx.event.EventHandler;
import javafx.event.EventType;
import javafx.scene.Scene;
import javafx.scene.control.TextArea;
import javafx.scene.input.DragEvent;
import javafx.scene.input.Dragboard;
import javafx.scene.input.TransferMode;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DragSource;
import org.eclipse.swt.dnd.DragSourceAdapter;
import org.eclipse.swt.dnd.DragSourceEvent;
import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
/**
* Demonstrates that {@link javafx.embed.swt.FXCanvas} does not deliver any
* {@link javafx.scene.input.DragEvent#DRAG_EXITED} and
* {@link javafx.scene.input.DragEvent#DRAG_EXITED_TARGET} after a successful
* drop.
* <p>
* Steps to reproduce:
* </p>
* <ol>
* <li>Start dragging from the left SWT label.</li>
* <li>Drop into the JavaFX text area.</li>
* <li>Start dragging from the left SWT label once more.</li>
* <li>Drag over the JavaFX text area.</li>
* <li>Drop into the right SWT label.</li>
* </ol>
*/
public class TestCase {
public static void main( String[] args ) {
final Display display = new Display();
final Shell shell = new Shell(display);
shell.setText("JavaFX/SWT DnD Interoperability");
shell.setLayout(new GridLayout(3, false));
final Label label1 = new Label(shell, SWT.CENTER | SWT.BORDER);
label1.setText("Step 1: Drag from here.\nStep 3: Drag from here.");
label1.setLayoutData(new GridData(GridData.FILL_BOTH));
final Transfer[] transfers = new Transfer[]{TextTransfer.getInstance()};
final DragSource dragSource = new DragSource(label1, DND.DROP_COPY);
dragSource.setTransfer(transfers);
dragSource.addDragListener(new DragSourceAdapter() {
@Override
public void dragSetData( final DragSourceEvent event ) {
event.data = "Step 4: Drag text over text area.";
}
});
final FXCanvas fxCanvas = new FXCanvas(shell, SWT.NONE);
final TextArea textArea = new TextArea();
textArea.setText("Step 2: Drop text here.");
textArea.addEventFilter(DragEvent.ANY, new EventHandler<DragEvent>() {
@Override
public void handle( final DragEvent event ) {
event.acceptTransferModes(TransferMode.COPY);
final EventType<DragEvent> type = event.getEventType();
if (type != DragEvent.DRAG_OVER) {
System.out.println(type);
}
if (type == DragEvent.DRAG_DROPPED) {
final Dragboard db = event.getDragboard();
if (db != null) {
if (db.hasString()) {
textArea.setText(db.getString());
}
}
event.setDropCompleted(true);
}
event.consume();
}
});
final Scene scene = new Scene(textArea);
fxCanvas.setScene(scene);
fxCanvas.setLayoutData(new GridData(GridData.FILL_BOTH));
final Label label2 = new Label(shell, SWT.CENTER | SWT.BORDER);
label2.setText(
"Step 5: Drop text here.\n" +
"(Will have not visible effect.)");
label2.setLayoutData(new GridData(GridData.FILL_BOTH));
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
display.dispose();
}
}
=== FIX FXCanvas.java ====
== method in anonymous listener in createDropTarget of HostContainer ==
public void dragEnter(DropTargetEvent event) {
ignoreLeave = false; // this is the fix
dropTarget.setTransfer(getAllTransfers());
detail = event.detail;
operations = event.operations;
dragOver (event, true, detail);
}
i cannot attach a file so i'm pasting the test case code and fix.
==== TestCase.java ====
import javafx.embed.swt.FXCanvas;
import javafx.event.EventHandler;
import javafx.event.EventType;
import javafx.scene.Scene;
import javafx.scene.control.TextArea;
import javafx.scene.input.DragEvent;
import javafx.scene.input.Dragboard;
import javafx.scene.input.TransferMode;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DragSource;
import org.eclipse.swt.dnd.DragSourceAdapter;
import org.eclipse.swt.dnd.DragSourceEvent;
import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
/**
* Demonstrates that {@link javafx.embed.swt.FXCanvas} does not deliver any
* {@link javafx.scene.input.DragEvent#DRAG_EXITED} and
* {@link javafx.scene.input.DragEvent#DRAG_EXITED_TARGET} after a successful
* drop.
* <p>
* Steps to reproduce:
* </p>
* <ol>
* <li>Start dragging from the left SWT label.</li>
* <li>Drop into the JavaFX text area.</li>
* <li>Start dragging from the left SWT label once more.</li>
* <li>Drag over the JavaFX text area.</li>
* <li>Drop into the right SWT label.</li>
* </ol>
*/
public class TestCase {
public static void main( String[] args ) {
final Display display = new Display();
final Shell shell = new Shell(display);
shell.setText("JavaFX/SWT DnD Interoperability");
shell.setLayout(new GridLayout(3, false));
final Label label1 = new Label(shell, SWT.CENTER | SWT.BORDER);
label1.setText("Step 1: Drag from here.\nStep 3: Drag from here.");
label1.setLayoutData(new GridData(GridData.FILL_BOTH));
final Transfer[] transfers = new Transfer[]{TextTransfer.getInstance()};
final DragSource dragSource = new DragSource(label1, DND.DROP_COPY);
dragSource.setTransfer(transfers);
dragSource.addDragListener(new DragSourceAdapter() {
@Override
public void dragSetData( final DragSourceEvent event ) {
event.data = "Step 4: Drag text over text area.";
}
});
final FXCanvas fxCanvas = new FXCanvas(shell, SWT.NONE);
final TextArea textArea = new TextArea();
textArea.setText("Step 2: Drop text here.");
textArea.addEventFilter(DragEvent.ANY, new EventHandler<DragEvent>() {
@Override
public void handle( final DragEvent event ) {
event.acceptTransferModes(TransferMode.COPY);
final EventType<DragEvent> type = event.getEventType();
if (type != DragEvent.DRAG_OVER) {
System.out.println(type);
}
if (type == DragEvent.DRAG_DROPPED) {
final Dragboard db = event.getDragboard();
if (db != null) {
if (db.hasString()) {
textArea.setText(db.getString());
}
}
event.setDropCompleted(true);
}
event.consume();
}
});
final Scene scene = new Scene(textArea);
fxCanvas.setScene(scene);
fxCanvas.setLayoutData(new GridData(GridData.FILL_BOTH));
final Label label2 = new Label(shell, SWT.CENTER | SWT.BORDER);
label2.setText(
"Step 5: Drop text here.\n" +
"(Will have not visible effect.)");
label2.setLayoutData(new GridData(GridData.FILL_BOTH));
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
display.dispose();
}
}
=== FIX FXCanvas.java ====
== method in anonymous listener in createDropTarget of HostContainer ==
public void dragEnter(DropTargetEvent event) {
ignoreLeave = false; // this is the fix
dropTarget.setTransfer(getAllTransfers());
detail = event.detail;
operations = event.operations;
dragOver (event, true, detail);
}