changeset 5710:ade9ae7c8a2a

RT-28347: Drag & Drop between 2 JFXPanel Reviewed-by: ant, anthony, pchelko
author art
date Thu, 14 Nov 2013 14:22:18 +0400
parents 0940705ce7f4
children 45d8a3cde4ec
files modules/graphics/src/main/java/com/sun/javafx/embed/EmbeddedSceneDSInterface.java modules/graphics/src/main/java/com/sun/javafx/embed/EmbeddedSceneDTInterface.java modules/graphics/src/main/java/com/sun/javafx/embed/EmbeddedSceneDragSourceInterface.java modules/graphics/src/main/java/com/sun/javafx/embed/EmbeddedSceneDragStartListenerInterface.java modules/graphics/src/main/java/com/sun/javafx/embed/EmbeddedSceneDropTargetInterface.java modules/graphics/src/main/java/com/sun/javafx/embed/EmbeddedSceneInterface.java modules/graphics/src/main/java/com/sun/javafx/embed/HostDragStartListener.java modules/graphics/src/main/java/com/sun/javafx/tk/quantum/AbstractEventLoop.java modules/graphics/src/main/java/com/sun/javafx/tk/quantum/EmbeddedScene.java modules/graphics/src/main/java/com/sun/javafx/tk/quantum/EmbeddedSceneDS.java modules/graphics/src/main/java/com/sun/javafx/tk/quantum/EmbeddedSceneDT.java modules/graphics/src/main/java/com/sun/javafx/tk/quantum/EmbeddedSceneDnD.java modules/graphics/src/main/java/com/sun/javafx/tk/quantum/EmbeddedSceneDragSource.java modules/graphics/src/main/java/com/sun/javafx/tk/quantum/EmbeddedSceneDropTarget.java modules/graphics/src/main/java/com/sun/javafx/tk/quantum/FxEventLoop.java modules/graphics/src/main/java/com/sun/javafx/tk/quantum/GlassScene.java modules/graphics/src/main/java/com/sun/javafx/tk/quantum/GlassSceneDnDEventHandler.java modules/graphics/src/main/java/com/sun/javafx/tk/quantum/QuantumClipboard.java modules/graphics/src/main/java/javafx/scene/Scene.java modules/swing/src/main/java/javafx/embed/swing/DataFlavorUtils.java modules/swing/src/main/java/javafx/embed/swing/JFXPanel.java modules/swing/src/main/java/javafx/embed/swing/SwingDnD.java modules/swing/src/main/java/javafx/embed/swing/SwingDragSource.java modules/swt/src/main/java/javafx/embed/swt/FXCanvas.java
diffstat 24 files changed, 871 insertions(+), 1207 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/graphics/src/main/java/com/sun/javafx/embed/EmbeddedSceneDSInterface.java	Thu Nov 14 14:22:18 2013 +0400
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.javafx.embed;
+
+import java.util.Set;
+
+import javafx.scene.input.TransferMode;
+
+/**
+ * Drag source interface. There are two implementations:
+ *   - EmbeddedSceneDS, which is used, when FX scene inside JFXPanel/FXCanvas is a drag source
+ *   - SwingDragSource, which is used for external drag sources
+ */
+public interface EmbeddedSceneDSInterface {
+
+    public Set<TransferMode> getSupportedActions();
+
+    public Object getData(String mimeType);
+
+    public String[] getMimeTypes();
+
+    public boolean isMimeTypeAvailable(String mimeType);
+
+    public void dragDropEnd(TransferMode performedAction);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/graphics/src/main/java/com/sun/javafx/embed/EmbeddedSceneDTInterface.java	Thu Nov 14 14:22:18 2013 +0400
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.javafx.embed;
+
+import javafx.scene.input.TransferMode;
+
+/**
+ * Embedded FX drop target.
+ */
+public interface EmbeddedSceneDTInterface {
+
+    public TransferMode handleDragEnter(int x, int y, int xAbs, int yAbs,
+                                        TransferMode recommendedDropAction,
+                                        EmbeddedSceneDSInterface dragSource);
+
+    public void handleDragLeave();
+
+    public TransferMode handleDragDrop(int x, int y, int xAbs, int yAbs,
+                                       TransferMode recommendedDropAction);
+
+    public TransferMode handleDragOver(int x, int y, int xAbs, int yAbs,
+                                       TransferMode recommendedDropAction);
+}
--- a/modules/graphics/src/main/java/com/sun/javafx/embed/EmbeddedSceneDragSourceInterface.java	Wed Nov 13 15:39:35 2013 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-/*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.javafx.embed;
-
-import java.util.Set;
-
-import javafx.scene.input.TransferMode;
-
-/**
- * Embedded FX drag source.
- */
-public interface EmbeddedSceneDragSourceInterface {
-
-    public Set<TransferMode> getSupportedActions();
-
-    public Object getData(String mimeType);
-
-    public String[] getMimeTypes();
-
-    public boolean isMimeTypeAvailable(String mimeType);
-
-    public void dragDropEnd(TransferMode performedAction);
-}
--- a/modules/graphics/src/main/java/com/sun/javafx/embed/EmbeddedSceneDragStartListenerInterface.java	Wed Nov 13 15:39:35 2013 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.javafx.embed;
-
-import javafx.scene.input.TransferMode;
-
-public interface EmbeddedSceneDragStartListenerInterface {
-    public void dragStarted(EmbeddedSceneDragSourceInterface dragSource,
-                            TransferMode dragAction);
-}
--- a/modules/graphics/src/main/java/com/sun/javafx/embed/EmbeddedSceneDropTargetInterface.java	Wed Nov 13 15:39:35 2013 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-/*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.javafx.embed;
-
-import javafx.scene.input.TransferMode;
-
-/**
- * Embedded FX drop target.
- */
-public interface EmbeddedSceneDropTargetInterface {
-
-    public TransferMode handleDragEnter(int x, int y, int xAbs, int yAbs,
-                                        TransferMode recommendedDropAction,
-                                        EmbeddedSceneDragSourceInterface dragSource);
-
-    public void handleDragLeave();
-
-    public TransferMode handleDragDrop(int x, int y, int xAbs, int yAbs,
-                                       TransferMode recommendedDropAction);
-
-    public TransferMode handleDragOver(int x, int y, int xAbs, int yAbs,
-                                       TransferMode recommendedDropAction);
-}
--- a/modules/graphics/src/main/java/com/sun/javafx/embed/EmbeddedSceneInterface.java	Wed Nov 13 15:39:35 2013 -0800
+++ b/modules/graphics/src/main/java/com/sun/javafx/embed/EmbeddedSceneInterface.java	Thu Nov 14 14:22:18 2013 +0400
@@ -78,9 +78,9 @@
     
     public boolean traverseOut(Direction dir);
 
-    public void setDragStartListener(EmbeddedSceneDragStartListenerInterface l);
+    public void setDragStartListener(HostDragStartListener l);
 
-    public EmbeddedSceneDropTargetInterface createDropTarget();
+    public EmbeddedSceneDTInterface createDropTarget();
 
     public void inputMethodEvent(EventType<InputMethodEvent> type,
                                  ObservableList<InputMethodTextRun> composed, String committed,
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/graphics/src/main/java/com/sun/javafx/embed/HostDragStartListener.java	Thu Nov 14 14:22:18 2013 +0400
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.javafx.embed;
+
+import javafx.scene.input.TransferMode;
+
+/*
+ * Interface, which is implemented by the host UI toolkit to track,
+ * when DnD is started in embedded FX scene.
+ */
+public interface HostDragStartListener {
+    public void dragStarted(EmbeddedSceneDSInterface dragSource, TransferMode dragAction);
+}
--- a/modules/graphics/src/main/java/com/sun/javafx/tk/quantum/AbstractEventLoop.java	Wed Nov 13 15:39:35 2013 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,122 +0,0 @@
-/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.javafx.tk.quantum;
-
-import java.util.concurrent.Callable;
-import java.util.concurrent.CountDownLatch;
-
-abstract class AbstractEventLoop {
-
-    static abstract class Task implements Runnable {
-
-        private final CountDownLatch latch = new CountDownLatch(1);
-
-        @Override
-        public void run() {
-            try {
-                doRun();
-            } finally {
-                latch.countDown();
-            }
-        }
-
-        protected abstract void doRun();
-
-        void await() throws InterruptedException {
-            latch.await();
-        }
-    };
-
-    static final class CallableTask<V> extends Task {
-
-        private V retValue;
-        private final Callable<V> c;
-        private Exception e;
-
-        CallableTask(final Callable<V> c) {
-            this.c = c;
-        }
-
-        @Override
-        public void doRun() {
-            try {
-                retValue = c.call();
-            } catch (Exception e) {
-                this.e = e;
-            }
-        }
-
-        V getResult() {
-            if (e == null) {
-                return retValue;
-            }
-            throw new RuntimeException(e);
-        }
-    }
-
-    static final class RunnableTask extends Task {
-
-        private final Runnable r;
-
-        RunnableTask(final Runnable r) {
-            this.r = r;
-        }
-
-        @Override
-        public void doRun() {
-            r.run();
-        }
-    }
-
-    public AbstractEventLoop() {
-    }
-
-    public void send(final Runnable r) {
-        final RunnableTask task = new RunnableTask(r);
-        await(task);
-    }
-
-    public <V> V send(final Callable<V> c) {
-        final CallableTask<V> task = new CallableTask<V>(c);
-        await(task);
-        return task.getResult();
-    }
-
-    protected abstract void schedule(Runnable r);
-
-    public abstract void start();
-
-    public abstract void stop();
-
-    private void await(final Task task) {
-        schedule(task);
-        try {
-            task.await();
-        } catch (InterruptedException e) {
-            throw new RuntimeException(e);
-        }
-    }
-}
--- a/modules/graphics/src/main/java/com/sun/javafx/tk/quantum/EmbeddedScene.java	Wed Nov 13 15:39:35 2013 -0800
+++ b/modules/graphics/src/main/java/com/sun/javafx/tk/quantum/EmbeddedScene.java	Thu Nov 14 14:22:18 2013 +0400
@@ -25,6 +25,7 @@
 
 package com.sun.javafx.tk.quantum;
 
+import com.sun.javafx.embed.HostDragStartListener;
 import javafx.application.Platform;
 import javafx.collections.ObservableList;
 import javafx.event.EventType;
@@ -38,8 +39,7 @@
 import java.security.PrivilegedAction;
 import com.sun.javafx.cursor.CursorFrame;
 import com.sun.javafx.embed.AbstractEvents;
-import com.sun.javafx.embed.EmbeddedSceneDragStartListenerInterface;
-import com.sun.javafx.embed.EmbeddedSceneDropTargetInterface;
+import com.sun.javafx.embed.EmbeddedSceneDTInterface;
 import com.sun.javafx.embed.EmbeddedSceneInterface;
 import com.sun.javafx.embed.HostInterface;
 import com.sun.javafx.scene.input.KeyCodeMap;
@@ -59,7 +59,7 @@
     private UploadingPainter        painter;
     private PaintRenderJob          paintRenderJob;
     
-    private final EmbeddedSceneDnD dndDelegate;    
+    private final EmbeddedSceneDnD embeddedDnD;
 
     volatile IntBuffer  texBits;
     volatile int        texLineStride; // pre-scaled
@@ -70,7 +70,7 @@
         sceneState = new EmbeddedState(this);
 
         this.host = host;
-        this.dndDelegate = new EmbeddedSceneDnD(this);
+        this.embeddedDnD = new EmbeddedSceneDnD(this);
 
         PaintCollector collector = PaintCollector.getInstance();
         painter = new UploadingPainter(this);
@@ -110,7 +110,7 @@
 
     @Override
     public TKClipboard createDragboard(boolean isDragSource) {
-        return dndDelegate.createDragboard();
+        return embeddedDnD.createDragboard(isDragSource);
     }
 
     @Override
@@ -345,13 +345,13 @@
     }
 
     @Override
-    public void setDragStartListener(EmbeddedSceneDragStartListenerInterface l) {
-        dndDelegate.setDragStartListener(l);
+    public void setDragStartListener(HostDragStartListener l) {
+        embeddedDnD.setDragStartListener(l);
     }
 
     @Override
-    public EmbeddedSceneDropTargetInterface createDropTarget() {
-        return dndDelegate.createDropTarget();
+    public EmbeddedSceneDTInterface createDropTarget() {
+        return embeddedDnD.createDropTarget();
     }
 
     @Override
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/graphics/src/main/java/com/sun/javafx/tk/quantum/EmbeddedSceneDS.java	Thu Nov 14 14:22:18 2013 +0400
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.javafx.tk.quantum;
+
+import com.sun.glass.ui.ClipboardAssistance;
+import com.sun.javafx.embed.EmbeddedSceneDSInterface;
+
+import java.util.Arrays;
+import java.util.Set;
+import java.util.concurrent.Callable;
+import javafx.scene.input.TransferMode;
+
+final class EmbeddedSceneDS implements EmbeddedSceneDSInterface {
+
+    private final EmbeddedSceneDnD dnd;
+    private final ClipboardAssistance assistant;
+    private final GlassSceneDnDEventHandler dndHandler;
+
+    public EmbeddedSceneDS(final EmbeddedSceneDnD dnd,
+                           final ClipboardAssistance assistant,
+                           final GlassSceneDnDEventHandler dndHandler) {
+        this.dnd = dnd;
+        this.assistant = assistant;
+        this.dndHandler = dndHandler;
+    }
+
+    @Override
+    public Set<TransferMode> getSupportedActions() {
+        assert dnd.isHostThread();
+        return dnd.executeOnFXThread(new Callable<Set<TransferMode>>() {
+            @Override
+            public Set<TransferMode> call() {
+                return QuantumClipboard.clipboardActionsToTransferModes(
+                        assistant.getSupportedSourceActions());
+            }
+        });
+    }
+
+    @Override
+    public Object getData(final String mimeType) {
+        assert dnd.isHostThread();
+        return dnd.executeOnFXThread(new Callable<Object>() {
+            @Override
+            public Object call() {
+                return assistant.getData(mimeType);
+            }
+        });
+    }
+
+    @Override
+    public String[] getMimeTypes() {
+        assert dnd.isHostThread();
+        return dnd.executeOnFXThread(new Callable<String[]>() {
+            @Override
+            public String[] call() {
+                return assistant.getMimeTypes();
+            }
+        });
+    }
+
+    @Override
+    public boolean isMimeTypeAvailable(final String mimeType) {
+        assert dnd.isHostThread();
+        return dnd.executeOnFXThread(new Callable<Boolean>() {
+            @Override
+            public Boolean call() {
+                return Arrays.asList(assistant.getMimeTypes()).contains(mimeType);
+            }
+        });
+    }
+
+    @Override
+    public void dragDropEnd(final TransferMode performedAction) {
+        assert dnd.isHostThread();
+        dnd.executeOnFXThread(new Callable<Void>() {
+            @Override
+            public Void call() {
+                try {
+                    dndHandler.handleDragEnd(performedAction, assistant);
+                } finally {
+                    dnd.onDragSourceReleased(EmbeddedSceneDS.this);
+                }
+                return null;
+            }
+        });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/graphics/src/main/java/com/sun/javafx/tk/quantum/EmbeddedSceneDT.java	Thu Nov 14 14:22:18 2013 +0400
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.javafx.tk.quantum;
+
+import com.sun.glass.ui.ClipboardAssistance;
+import com.sun.javafx.embed.EmbeddedSceneDSInterface;
+import com.sun.javafx.embed.EmbeddedSceneDTInterface;
+import java.util.concurrent.Callable;
+import javafx.application.Platform;
+import javafx.scene.input.TransferMode;
+
+final class EmbeddedSceneDT implements EmbeddedSceneDTInterface {
+
+    private final EmbeddedSceneDnD dnd;
+    private final GlassSceneDnDEventHandler dndHandler;
+    private EmbeddedSceneDSInterface dragSource;
+    private ClipboardAssistance assistant;
+
+    public EmbeddedSceneDT(final EmbeddedSceneDnD dnd,
+                           final GlassSceneDnDEventHandler dndHandler) {
+        this.dnd = dnd;
+        this.dndHandler = dndHandler;
+    }
+
+    private void close() {
+        dnd.onDropTargetReleased(this);
+        assistant = null;
+    }
+
+    @Override
+    public TransferMode handleDragEnter(final int x, final int y, final int xAbs,
+                                        final int yAbs,
+                                        final TransferMode recommendedDropAction,
+                                        final EmbeddedSceneDSInterface ds)
+    {
+        assert dnd.isHostThread();
+
+        return dnd.executeOnFXThread(new Callable<TransferMode>() {
+            @Override
+            public TransferMode call() {
+                assert dragSource == null;
+                assert assistant == null;
+
+                dragSource = ds;
+                assistant = new EmbeddedDTAssistant(dragSource);
+
+                return dndHandler.handleDragEnter(x, y, xAbs, yAbs,
+                                                  recommendedDropAction,
+                                                  assistant);
+            }
+        });
+    }
+
+    @Override
+    public void handleDragLeave() {
+        assert dnd.isHostThread();
+
+        dnd.executeOnFXThread(new Callable<Void>() {
+            @Override
+            public Void call() {
+                assert assistant != null;
+                try {
+                    dndHandler.handleDragLeave(assistant);
+                } finally {
+                    close();
+                }
+                return null;
+            }
+        });
+    }
+
+    @Override
+    public TransferMode handleDragDrop(final int x, final int y, final int xAbs,
+                                       final int yAbs,
+                                       final TransferMode recommendedDropAction) {
+        assert dnd.isHostThread();
+
+        return dnd.executeOnFXThread(new Callable<TransferMode>() {
+            @Override
+            public TransferMode call() {
+                assert assistant != null;
+                try {
+                    return dndHandler.handleDragDrop(x, y, xAbs, yAbs,
+                                                     recommendedDropAction,
+                                                     assistant);
+                } finally {
+                    close();
+                }
+            }
+        });
+    }
+
+    @Override
+    public TransferMode handleDragOver(final int x, final int y, final int xAbs,
+                                       final int yAbs,
+                                       final TransferMode recommendedDropAction) {
+        assert dnd.isHostThread();
+
+        return dnd.executeOnFXThread(new Callable<TransferMode>() {
+            @Override
+            public TransferMode call() {
+                assert assistant != null;
+                return dndHandler.handleDragOver(x, y, xAbs, yAbs,
+                                                 recommendedDropAction,
+                                                 assistant);
+            }
+        });
+    }
+
+    private static class EmbeddedDTAssistant extends ClipboardAssistance {
+
+        private EmbeddedSceneDSInterface dragSource;
+
+        EmbeddedDTAssistant(EmbeddedSceneDSInterface source) {
+            super("DND-Embedded");
+            dragSource = source;
+        }
+
+        @Override
+        public void flush() {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public Object getData(final String mimeType) {
+            return dragSource.getData(mimeType);
+        }
+
+        @Override
+        public int getSupportedSourceActions() {
+            return QuantumClipboard.transferModesToClipboardActions(dragSource.getSupportedActions());
+        }
+
+        @Override
+        public void setTargetAction(int actionDone) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public String[] getMimeTypes() {
+            return dragSource.getMimeTypes();
+        }
+    }
+}
--- a/modules/graphics/src/main/java/com/sun/javafx/tk/quantum/EmbeddedSceneDnD.java	Wed Nov 13 15:39:35 2013 -0800
+++ b/modules/graphics/src/main/java/com/sun/javafx/tk/quantum/EmbeddedSceneDnD.java	Thu Nov 14 14:22:18 2013 +0400
@@ -26,26 +26,31 @@
 package com.sun.javafx.tk.quantum;
 
 import com.sun.glass.ui.ClipboardAssistance;
-import com.sun.javafx.embed.EmbeddedSceneDragSourceInterface;
-import com.sun.javafx.embed.EmbeddedSceneDragStartListenerInterface;
-import com.sun.javafx.embed.EmbeddedSceneDropTargetInterface;
+import com.sun.javafx.embed.EmbeddedSceneDSInterface;
+import com.sun.javafx.embed.HostDragStartListener;
+import com.sun.javafx.embed.EmbeddedSceneDTInterface;
+
+import java.awt.EventQueue;
+import java.awt.SecondaryLoop;
 import java.util.concurrent.Callable;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
 
 import com.sun.javafx.tk.TKClipboard;
+
+import com.sun.javafx.tk.Toolkit;
 import javafx.application.Platform;
-import javafx.scene.input.Dragboard;
 import javafx.scene.input.TransferMode;
 
 final class EmbeddedSceneDnD {
 
     private final GlassSceneDnDEventHandler dndHandler;
 
-    private EmbeddedSceneDragStartListenerInterface dragStartListener;
-    private EmbeddedSceneDragSourceInterface fxDragSource;
-    private EmbeddedSceneDropTargetInterface fxDropTarget;
-    
-    private ClipboardAssistance clipboardAssistant;
-    
+    private HostDragStartListener dragStartListener;
+    private EmbeddedSceneDSInterface fxDragSource;
+    private EmbeddedSceneDTInterface fxDropTarget;
+
     private Thread hostThread;
 
     public EmbeddedSceneDnD(final GlassScene scene) {
@@ -54,14 +59,9 @@
     
     private void startDrag() {
         assert Platform.isFxApplicationThread();
+        assert fxDragSource != null;
 
-        assert fxDragSource == null;
-
-        fxDragSource = new EmbeddedSceneDragSource(this, dndHandler);
-        
-        final TransferMode dragAction = TransferMode.COPY;
-        
-        dragStartListener.dragStarted(fxDragSource, dragAction);
+        dragStartListener.dragStarted(fxDragSource, TransferMode.COPY);
     }
 
     private void setHostThread() {
@@ -74,189 +74,89 @@
         return (Thread.currentThread() == hostThread);
     }
     
-    public boolean isValid(EmbeddedSceneDragSourceInterface ds) {
+    public void onDragSourceReleased(final EmbeddedSceneDSInterface ds) {
+        assert fxDragSource == ds;
+
+        fxDragSource = null;
+        Toolkit.getToolkit().exitNestedEventLoop(this, null);
+    }
+
+    public void onDropTargetReleased(final EmbeddedSceneDTInterface dt) {
+        assert fxDropTarget == dt;
+
+        fxDropTarget = null;
+    }
+
+    /*
+     * This is a helper method to execute code on FX event thread. It
+     * can be implemented using AWT nested event loop, however it just
+     * blocks the current thread. This is done by intention, because
+     * we need to handle Swing events one by one. If we enter a nested
+     * event loop, various weird side-effects are observed, e.g.
+     * dragOver() in SwingDnD is executed before dragEnter() is finished
+     */
+    <T> T executeOnFXThread(final Callable<T> r) {
+        assert !Platform.isFxApplicationThread();
+
+        final AtomicReference<T> result = new AtomicReference<>();
+        final CountDownLatch l = new CountDownLatch(1);
+
+        Platform.runLater(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    result.set(r.call());
+                } catch (Exception z) {
+                    // ignore
+                } finally {
+                    l.countDown();
+                }
+            }
+        });
+
+        try {
+            l.await();
+        } catch (Exception z) {
+            // ignore
+        }
+
+        return result.get();
+    }
+
+    
+    // Should be called from Scene.DnDGesture.createDragboard only!
+    public TKClipboard createDragboard(boolean isDragSource) {
         assert Platform.isFxApplicationThread();
-        assert ds != null;
-        assert fxDragSource == ds;
-        assert clipboardAssistant != null;
-        return true;
+        assert fxDragSource == null;
+
+        assert isDragSource;
+        ClipboardAssistance assistant = new ClipboardAssistance("DND-Embedded") {
+            @Override
+            public void flush() {
+                super.flush();
+                startDrag(); // notify host
+                Toolkit.getToolkit().enterNestedEventLoop(EmbeddedSceneDnD.this); // block current thread
+            }
+        };
+        fxDragSource = new EmbeddedSceneDS(this, assistant, dndHandler);
+        return QuantumClipboard.getDragboardInstance(assistant, isDragSource);
+    }
+
+    public void setDragStartListener(HostDragStartListener l) {
+        setHostThread();
+        dragStartListener = l;
     }
     
-    public boolean isValid(EmbeddedSceneDropTargetInterface dt) {
-        assert Platform.isFxApplicationThread();
-        assert dt != null;
-        assert fxDropTarget == dt;
-        return true;
-    }
-    
-    public boolean isFxDragSource() {
-        assert Platform.isFxApplicationThread();
-
-        return (fxDragSource != null);
-    }
-
-    public void onDragSourceReleased(final EmbeddedSceneDragSourceInterface ds) {
-        assert isValid(ds);
-
-        fxDragSource = null;
-        clipboardAssistant = null;
-        
-        FxEventLoop.leaveNestedLoop();
-    }
-
-    public void onDropTargetReleased(final EmbeddedSceneDropTargetInterface dt) {
-        assert isValid(dt);
-
-        fxDropTarget = null;
-        if (!isFxDragSource()) {
-            clipboardAssistant = null;
-        }
-    }
-    
-    // Should be called from Scene.DnDGesture.createDragboard only!
-    public TKClipboard createDragboard() {
-        assert Platform.isFxApplicationThread();
-        assert fxDropTarget == null;
-        assert clipboardAssistant == null;
-        assert fxDragSource == null;
-        
-        clipboardAssistant = new ClipboardAssistanceImpl(null);
-        return QuantumClipboard.getDragboardInstance(clipboardAssistant);
-    }
-
-    public void setDragStartListener(EmbeddedSceneDragStartListenerInterface l) {
+    public EmbeddedSceneDTInterface createDropTarget() {
         setHostThread();
-        
-        assert isHostThread();
-        
-        this.dragStartListener = l;
-    }
-    
-    public EmbeddedSceneDropTargetInterface createDropTarget() {
-        setHostThread();
-
-        assert isHostThread();
-        assert fxDropTarget == null;
-
-        return FxEventLoop.sendEvent(new Callable<EmbeddedSceneDropTargetInterface>() {
-
+        return executeOnFXThread(new Callable<EmbeddedSceneDTInterface>() {
             @Override
-            public EmbeddedSceneDropTargetInterface call() {
-                fxDropTarget = new EmbeddedSceneDropTarget(EmbeddedSceneDnD.this,
-                                                           dndHandler);
-
+            public EmbeddedSceneDTInterface call() {
+                assert fxDropTarget == null;
+                fxDropTarget = new EmbeddedSceneDT(EmbeddedSceneDnD.this, dndHandler);
                 return fxDropTarget;
             }
         });
     }
-    
-    public ClipboardAssistance getClipboardAssistance(
-            final EmbeddedSceneDragSourceInterface source) {
-        assert Platform.isFxApplicationThread();
-        assert isFxDragSource() ? isValid(source) : true;
-        assert isFxDragSource() ? (clipboardAssistant != null) : true;
-        
-        if (clipboardAssistant == null) {
-            clipboardAssistant = new ClipboardAssistanceImpl(source);
-        }
-        return clipboardAssistant;
-    }
 
-    private class ClipboardAssistanceImpl extends ClipboardAssistance {
-        final EmbeddedSceneDragSourceInterface source;
-                
-        private boolean isValid() {
-            assert Platform.isFxApplicationThread();
-            assert EmbeddedSceneDnD.this.clipboardAssistant == this;
-            
-            return true;
-        }
-        
-        ClipboardAssistanceImpl(final EmbeddedSceneDragSourceInterface source) {
-            super("DND-Embedded");
-            
-            this.source = source;
-        }
-
-        @Override
-        public void flush() {
-            assert isValid();
-
-            super.flush();
-            
-            startDrag();
-
-            FxEventLoop.enterNestedLoop();
-        }
-
-        @Override
-        public void emptyCache() {
-            assert isValid();
-
-            super.emptyCache();
-        }
-
-        @Override
-        public Object getData(final String mimeType) {
-            assert isValid();
-
-            if (source == null) {
-                return super.getData(mimeType);
-            }
-
-            return source.getData(mimeType);
-        }
-
-        @Override
-        public void setData(final String mimeType, final Object data) {
-            assert isValid();
-            
-            if (source != null) {
-                return;
-            }
-
-            super.setData(mimeType, data);
-        }
-
-        @Override
-        public void setSupportedActions(final int supportedActions) {
-            assert isValid();
-            
-            if (source != null) {
-                return;
-            }
-
-            super.setSupportedActions(supportedActions);
-        }
-
-        @Override
-        public int getSupportedSourceActions() {
-            assert isValid();
-
-            if (source == null) {
-                return super.getSupportedSourceActions();
-            }
-
-            return QuantumClipboard.transferModesToClipboardActions(source.
-                    getSupportedActions());
-        }
-
-        @Override
-        public void setTargetAction(int actionDone) {
-            assert isValid();
-
-            throw new UnsupportedOperationException();
-        }
-
-        @Override
-        public String[] getMimeTypes() {
-            assert isValid();
-
-            if (source == null) {
-                return super.getMimeTypes();
-            }
-
-            return source.getMimeTypes();
-        }
-    }
 }
--- a/modules/graphics/src/main/java/com/sun/javafx/tk/quantum/EmbeddedSceneDragSource.java	Wed Nov 13 15:39:35 2013 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,117 +0,0 @@
-/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.javafx.tk.quantum;
-
-import com.sun.glass.ui.ClipboardAssistance;
-import com.sun.javafx.embed.EmbeddedSceneDragSourceInterface;
-import java.util.Arrays;
-import java.util.Set;
-import java.util.concurrent.Callable;
-import javafx.scene.input.TransferMode;
-
-final class EmbeddedSceneDragSource implements EmbeddedSceneDragSourceInterface {
-
-    private final EmbeddedSceneDnD dnd;
-    private final GlassSceneDnDEventHandler dndHandler;
-
-    public EmbeddedSceneDragSource(final EmbeddedSceneDnD dnd,
-                                   final GlassSceneDnDEventHandler dndHandler) {
-        this.dnd = dnd;
-        this.dndHandler = dndHandler;
-    }
-
-    private ClipboardAssistance getClipboardAssistance() {
-        assert dnd.isValid(this);
-        return dnd.getClipboardAssistance(this);
-    }
-
-    @Override
-    public Set<TransferMode> getSupportedActions() {
-        assert dnd.isHostThread();
-        return FxEventLoop.sendEvent(new Callable<Set<TransferMode>>() {
-
-            @Override
-            public Set<TransferMode> call() {
-                return QuantumClipboard.clipboardActionsToTransferModes(getClipboardAssistance().
-                        getSupportedSourceActions());
-            }
-        });
-    }
-
-    @Override
-    public Object getData(final String mimeType) {
-        assert dnd.isHostThread();
-        return FxEventLoop.sendEvent(new Callable() {
-
-            @Override
-            public Object call() {
-                return getClipboardAssistance().getData(mimeType);
-            }
-        });
-    }
-
-    @Override
-    public String[] getMimeTypes() {
-        assert dnd.isHostThread();
-        return FxEventLoop.sendEvent(new Callable<String[]>() {
-
-            @Override
-            public String[] call() {
-                return getClipboardAssistance().getMimeTypes();
-            }
-        });
-    }
-
-    @Override
-    public boolean isMimeTypeAvailable(final String mimeType) {
-        assert dnd.isHostThread();
-        return (boolean) FxEventLoop.sendEvent(new Callable<Boolean>() {
-
-            @Override
-            public Boolean call() {
-                return Arrays.asList(getClipboardAssistance().getMimeTypes()).
-                        contains(mimeType);
-            }
-        });
-    }
-
-    @Override
-    public void dragDropEnd(final TransferMode performedAction) {
-        assert dnd.isHostThread();
-        FxEventLoop.sendEvent(new Runnable() {
-
-            @Override
-            public void run() {
-                try {
-                    dndHandler.handleDragEnd(performedAction,
-                                             getClipboardAssistance());
-                } finally {
-                    dnd.onDragSourceReleased(EmbeddedSceneDragSource.this);
-                }
-            }
-        });
-    }
-}
--- a/modules/graphics/src/main/java/com/sun/javafx/tk/quantum/EmbeddedSceneDropTarget.java	Wed Nov 13 15:39:35 2013 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,149 +0,0 @@
-/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.javafx.tk.quantum;
-
-import com.sun.glass.ui.ClipboardAssistance;
-import com.sun.javafx.embed.EmbeddedSceneDragSourceInterface;
-import com.sun.javafx.embed.EmbeddedSceneDropTargetInterface;
-import java.util.concurrent.Callable;
-import javafx.application.Platform;
-import javafx.scene.input.TransferMode;
-
-final class EmbeddedSceneDropTarget implements EmbeddedSceneDropTargetInterface {
-
-    private final EmbeddedSceneDnD dnd;
-    private final GlassSceneDnDEventHandler dndHandler;
-    private EmbeddedSceneDragSourceInterface dragSource;
-    private int dndCounter;
-
-    public EmbeddedSceneDropTarget(final EmbeddedSceneDnD dnd,
-                                   final GlassSceneDnDEventHandler dndHandler) {
-        this.dnd = dnd;
-        this.dndHandler = dndHandler;
-    }
-
-    private boolean isDnDCounterValid() {
-        assert Platform.isFxApplicationThread();
-        assert dndCounter == 1;
-
-        return true;
-    }
-
-    private ClipboardAssistance getClipboardAssistance() {
-        assert isDnDCounterValid();
-        assert dnd.isValid(this);
-
-        return dnd.getClipboardAssistance(dragSource);
-    }
-
-    private void close() {
-        assert isDnDCounterValid();
-
-        --dndCounter;
-
-        dnd.onDropTargetReleased(this);
-    }
-
-    @Override
-    public TransferMode handleDragEnter(final int x, final int y, final int xAbs,
-                                        final int yAbs,
-                                        final TransferMode recommendedDropAction,
-                                        final EmbeddedSceneDragSourceInterface dragSource) {
-        assert dnd.isHostThread();
-
-        return FxEventLoop.sendEvent(new Callable<TransferMode>() {
-
-            @Override
-            public TransferMode call() {
-                ++dndCounter;
-
-                assert dnd.isFxDragSource() ? true
-                        : EmbeddedSceneDropTarget.this.dragSource == null;
-
-                EmbeddedSceneDropTarget.this.dragSource = dragSource;
-
-                return dndHandler.handleDragEnter(x, y, xAbs, yAbs,
-                                                  recommendedDropAction,
-                                                  getClipboardAssistance());
-            }
-        });
-    }
-
-    @Override
-    public void handleDragLeave() {
-        assert dnd.isHostThread();
-
-        FxEventLoop.sendEvent(new Runnable() {
-
-            @Override
-            public void run() {
-                try {
-                    dndHandler.handleDragLeave(getClipboardAssistance());
-                } finally {
-                    close();
-                }
-            }
-        });
-    }
-
-    @Override
-    public TransferMode handleDragDrop(final int x, final int y, final int xAbs,
-                                       final int yAbs,
-                                       final TransferMode recommendedDropAction) {
-        assert dnd.isHostThread();
-
-        return FxEventLoop.sendEvent(new Callable<TransferMode>() {
-
-            @Override
-            public TransferMode call() {
-                try {
-                    return dndHandler.handleDragDrop(x, y, xAbs, yAbs,
-                                                     recommendedDropAction,
-                                                     getClipboardAssistance());
-                } finally {
-                    close();
-                }
-            }
-        });
-    }
-
-    @Override
-    public TransferMode handleDragOver(final int x, final int y, final int xAbs,
-                                       final int yAbs,
-                                       final TransferMode recommendedDropAction) {
-        assert dnd.isHostThread();
-
-        return FxEventLoop.sendEvent(new Callable<TransferMode>() {
-
-            @Override
-            public TransferMode call() {
-                return dndHandler.handleDragOver(x, y, xAbs, yAbs,
-                                                 recommendedDropAction,
-                                                 getClipboardAssistance());
-            }
-        });
-    }
-}
--- a/modules/graphics/src/main/java/com/sun/javafx/tk/quantum/FxEventLoop.java	Wed Nov 13 15:39:35 2013 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,136 +0,0 @@
-/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.javafx.tk.quantum;
-
-import com.sun.javafx.tk.Toolkit;
-import javafx.application.Platform;
-
-import java.util.concurrent.Callable;
-
-final class FxEventLoop {
-
-    private final static class Impl extends AbstractEventLoop {
-
-        private final Object NESTED_EVENT_LOOP_KEY = new Object();
-
-        private Object nestedEventLoopToken;
-        private int depth;
-
-        @Override
-        public void send(final Runnable r) {
-            if (Platform.isFxApplicationThread()) {
-                r.run();
-                return;
-            }
-            super.send(r);
-        }
-
-        @Override
-        public <V> V send(final Callable<V> c) {
-            if (Platform.isFxApplicationThread()) {
-                try {
-                    return c.call();
-                } catch (Exception e) {
-                    throw new RuntimeException(e);
-                }
-            }
-            return super.send(c);
-        }
-
-        @Override
-        public void start() {
-            if (Platform.isFxApplicationThread()) {
-                // Don't allow nested nested loops
-                assert (depth == 0);
-
-                ++depth;
-                try {
-                    nestedEventLoopToken = Toolkit.getToolkit().
-                            enterNestedEventLoop(NESTED_EVENT_LOOP_KEY);
-                } finally {
-                    --depth;
-                }
-            } else {
-                Platform.runLater(new Runnable() {
-
-                    @Override
-                    public void run() {
-                        enterNestedLoop();
-                    }
-                });
-            }
-        }
-
-        @Override
-        public void stop() {
-            if (Platform.isFxApplicationThread()) {
-                Toolkit.getToolkit().exitNestedEventLoop(NESTED_EVENT_LOOP_KEY,
-                                                         nestedEventLoopToken);
-                nestedEventLoopToken = null;
-            } else {
-                send(new Runnable() {
-
-                    @Override
-                    public void run() {
-                        leaveNestedLoop();
-                    }
-                });
-            }
-        }
-
-        @Override
-        protected void schedule(Runnable r) {
-            Platform.runLater(r);
-        }
-
-        boolean isNestedLoopRunning() {
-            assert Platform.isFxApplicationThread();
-
-            return (depth != 0);
-        }
-    }
-    private final static Impl impl = new Impl();
-
-    public static void enterNestedLoop() {
-        impl.start();
-    }
-
-    public static void leaveNestedLoop() {
-        impl.stop();
-    }
-
-    public static void sendEvent(final Runnable e) {
-        impl.send(e);
-    }
-
-    public static <V> V sendEvent(final Callable<V> e) {
-        return impl.send(e);
-    }
-
-    public static boolean isNestedLoopRunning() {
-        return impl.isNestedLoopRunning();
-    }
-}
--- a/modules/graphics/src/main/java/com/sun/javafx/tk/quantum/GlassScene.java	Wed Nov 13 15:39:35 2013 -0800
+++ b/modules/graphics/src/main/java/com/sun/javafx/tk/quantum/GlassScene.java	Thu Nov 14 14:22:18 2013 +0400
@@ -65,8 +65,6 @@
     protected InputMethodRequests inputMethodRequests;
     private TKScenePaintListener scenePaintListener;
 
-    private TKClipboard dragSourceClipboard;
-
     private NGNode root;
     private NGCamera camera;
     protected Paint fillPaint;
@@ -241,25 +239,26 @@
     @Override
     public TKClipboard createDragboard(boolean isDragSource) {
         ClipboardAssistance assistant = new ClipboardAssistance(Clipboard.DND) {
-            @Override public void actionPerformed(final int performedAction) {
+            @Override
+            public void actionPerformed(final int performedAction) {
+                super.actionPerformed(performedAction);
                 AccessController.doPrivileged(new PrivilegedAction<Void>() {
                     @Override
                     public Void run() {
-                        if ((dragSourceClipboard != null) && (dragSourceListener != null)) {
-                            dragSourceListener.dragDropEnd(0, 0, 0, 0,
-                                    QuantumToolkit.clipboardActionToTransferMode(performedAction));
+                        try {
+                            if (dragSourceListener != null) {
+                                dragSourceListener.dragDropEnd(0, 0, 0, 0,
+                                        QuantumToolkit.clipboardActionToTransferMode(performedAction));
+                            }
+                        } finally {
+                            QuantumClipboard.releaseCurrentDragboard();
                         }
-                        dragSourceClipboard = null;
                         return null;
                     }
                 }, getAccessControlContext());
             }
         };
-        QuantumClipboard dragboard = QuantumClipboard.getDragboardInstance(assistant);
-        if (isDragSource) {
-            dragSourceClipboard = dragboard;
-        }
-        return dragboard;
+        return QuantumClipboard.getDragboardInstance(assistant, isDragSource);
     }
 
     protected final GlassStage getStage() {
--- a/modules/graphics/src/main/java/com/sun/javafx/tk/quantum/GlassSceneDnDEventHandler.java	Wed Nov 13 15:39:35 2013 -0800
+++ b/modules/graphics/src/main/java/com/sun/javafx/tk/quantum/GlassSceneDnDEventHandler.java	Thu Nov 14 14:22:18 2013 +0400
@@ -43,6 +43,8 @@
         this.scene = scene;
     }
 
+    // Drop target handlers
+
     public TransferMode handleDragEnter(final int x, final int y, final int xAbs, final int yAbs,
                                         final TransferMode recommendedTransferMode,
                                         final ClipboardAssistance dropTargetAssistant)
@@ -52,7 +54,8 @@
             @Override
             public TransferMode run() {
                 if (scene.dropTargetListener != null) {
-                    QuantumClipboard dragboard = QuantumClipboard.getDragboardInstance(dropTargetAssistant);
+                    QuantumClipboard dragboard =
+                            QuantumClipboard.getDragboardInstance(dropTargetAssistant, false);
                     return scene.dropTargetListener.dragEnter(x, y, xAbs, yAbs,
                             recommendedTransferMode, dragboard);
                 }
@@ -108,6 +111,12 @@
         }, scene.getAccessControlContext());
     }
 
+    // Drag source handlers
+
+    // This is a callback from the native platform, when a drag gesture is
+    // detected. This mechanism is currently not used in FX, as we have
+    // a custom gesture recognizer in Scene, and DnD is started with
+    // Toolkit.startDrag().
     public void handleDragStart(final int button, final int x, final int y, final int xAbs, final int yAbs,
                                 final ClipboardAssistance dragSourceAssistant)
     {
@@ -116,7 +125,8 @@
             @Override
             public Void run() {
                 if (scene.dragGestureListener != null) {
-                    QuantumClipboard dragboard = QuantumClipboard.getDragboardInstance(dragSourceAssistant);
+                    QuantumClipboard dragboard =
+                            QuantumClipboard.getDragboardInstance(dragSourceAssistant, true);
                     scene.dragGestureListener.dragGestureRecognized(
                             x, y, xAbs, yAbs, button, dragboard);
                 }
@@ -125,9 +135,9 @@
         }, scene.getAccessControlContext());
     }
 
-    // Used in case the drag has started from the handleDragStart() above - 
-    // it's delivered by Glass itself.
-    // Otherwise, see QuantumToolkit.createDragboard() and startDrag()
+    // This is a callback from the native platform, when the drag was started
+    // from handleDragStart() above, or when FX as a drag source is embedded
+    // to Swing/SWT.
     public void handleDragEnd(final TransferMode performedTransferMode,
                               final ClipboardAssistance dragSourceAssistant)
     {
@@ -135,9 +145,12 @@
         AccessController.doPrivileged(new PrivilegedAction<Void>() {
             @Override
             public Void run() {
-                if (scene.dragSourceListener != null) {
-                    scene.dragSourceListener.dragDropEnd(0, 0, 0, 0,
-                            performedTransferMode);
+                try {
+                    if (scene.dragSourceListener != null) {
+                        scene.dragSourceListener.dragDropEnd(0, 0, 0, 0, performedTransferMode);
+                    }
+                } finally {
+                    QuantumClipboard.releaseCurrentDragboard();
                 }
                 return null;
             }
--- a/modules/graphics/src/main/java/com/sun/javafx/tk/quantum/QuantumClipboard.java	Wed Nov 13 15:39:35 2013 -0800
+++ b/modules/graphics/src/main/java/com/sun/javafx/tk/quantum/QuantumClipboard.java	Thu Nov 14 14:22:18 2013 +0400
@@ -30,6 +30,7 @@
 import java.io.File;
 import java.io.FilePermission;
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.ObjectInput;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutput;
@@ -40,7 +41,6 @@
 import java.net.URL;
 import java.nio.ByteBuffer;
 import java.security.AccessControlContext;
-import java.security.AccessController;
 import java.security.AllPermission;
 import java.security.Permission;
 import java.util.ArrayList;
@@ -88,26 +88,6 @@
     private AccessControlContext accessContext = null;
 
     /**
-     * Disallow direct creation of QuantumClipboard
-     */
-    private QuantumClipboard() {
-    }
-
-    @Override public void setSecurityContext(AccessControlContext acc) {
-        if (accessContext != null) {
-            throw new RuntimeException("Clipboard security context has been already set!");
-        }
-        accessContext = acc;
-    }
-
-    private AccessControlContext getAccessControlContext() {
-        if (accessContext == null) {
-            throw new RuntimeException("Clipboard security context has not been set!");
-        }
-        return accessContext;
-    }
-
-    /**
      * Distinguishes between clipboard and dragboard. This is needed
      * because dragboard's flush() starts DnD operation so it mustn't be
      * called too early.
@@ -138,6 +118,28 @@
     private double dragOffsetX = 0;
     private double dragOffsetY = 0;
 
+    private static ClipboardAssistance currentDragboard;
+
+    /**
+     * Disallow direct creation of QuantumClipboard
+     */
+    private QuantumClipboard() {
+    }
+
+    @Override public void setSecurityContext(AccessControlContext acc) {
+        if (accessContext != null) {
+            throw new RuntimeException("Clipboard security context has been already set!");
+        }
+        accessContext = acc;
+    }
+
+    private AccessControlContext getAccessControlContext() {
+        if (accessContext == null) {
+            throw new RuntimeException("Clipboard security context has not been set!");
+        }
+        return accessContext;
+    }
+
     /**
      * Gets an instance of QuantumClipboard for the given assistant. This may be
      * a new instance after each call.
@@ -151,6 +153,15 @@
         return c;
     }
 
+    static ClipboardAssistance getCurrentDragboard() {
+        return currentDragboard;
+    }
+
+    static void releaseCurrentDragboard() {
+        assert currentDragboard != null;
+        currentDragboard = null;
+    }
+
     /**
      * Gets an instance of QuantumClipboard for the given assistant for usage
      * as dragboard during drag and drop. It doesn't flush the data implicitly
@@ -159,10 +170,13 @@
      * @param assistant
      * @return
      */
-    public static QuantumClipboard getDragboardInstance(ClipboardAssistance assistant) {
+    public static QuantumClipboard getDragboardInstance(ClipboardAssistance assistant, boolean isDragSource) {
         QuantumClipboard c = new QuantumClipboard();
         c.systemAssistant = assistant;
         c.isCaching = true;
+        if (isDragSource) {
+            currentDragboard = assistant;
+        }
         return c;
     }
 
@@ -212,12 +226,12 @@
     }
 
     @Override public Set<TransferMode> getTransferModes() {
-
         if (transferModesCache != null) {
             return EnumSet.copyOf(transferModesCache);
         }
 
-        final Set<TransferMode> tms = clipboardActionsToTransferModes(systemAssistant.getSupportedSourceActions());
+        ClipboardAssistance assistant = (currentDragboard != null) ? currentDragboard : systemAssistant;
+        final Set<TransferMode> tms = clipboardActionsToTransferModes(assistant.getSupportedSourceActions());
 
         return tms;
     }
@@ -270,12 +284,15 @@
             return null;
         }
 
+        ClipboardAssistance assistant =
+                (currentDragboard != null) ? currentDragboard : systemAssistant;
+
         if (dataFormat == DataFormat.IMAGE) {
             return readImage();
         } else if (dataFormat == DataFormat.URL) {
-            return systemAssistant.getData(Clipboard.URI_TYPE);
+            return assistant.getData(Clipboard.URI_TYPE);
         } else if (dataFormat == DataFormat.FILES) {
-            Object data = systemAssistant.getData(Clipboard.FILE_LIST_TYPE);
+            Object data = assistant.getData(Clipboard.FILE_LIST_TYPE);
             if (data == null) return Collections.emptyList();
             String[] paths = (String[]) data;
             List<File> list = new ArrayList<File>(paths.length);
@@ -286,7 +303,7 @@
         }
 
         for (String mimeType : dataFormat.getIdentifiers()) {
-            Object data = systemAssistant.getData(mimeType);
+            Object data = assistant.getData(mimeType);
             if (data instanceof ByteBuffer) {
                 try {
                     ByteBuffer bb = (ByteBuffer) data;
@@ -346,9 +363,12 @@
     }
 
     private Image readImage() {
-        Object rawData = systemAssistant.getData(Clipboard.RAW_IMAGE_TYPE);
+        ClipboardAssistance assistant =
+                (currentDragboard != null) ? currentDragboard : systemAssistant;
+
+        Object rawData = assistant.getData(Clipboard.RAW_IMAGE_TYPE);
         if (rawData == null) {
-            Object htmlData = systemAssistant.getData(Clipboard.HTML_TYPE);
+            Object htmlData = assistant.getData(Clipboard.HTML_TYPE);
             if (htmlData != null) {
                 String url = parseIMG(htmlData);
                 if (url != null) {
@@ -433,7 +453,6 @@
     }
 
     @Override public Set<DataFormat> getContentTypes() {
-
         Set<DataFormat> set = new HashSet<DataFormat>();
 
         if (dataCache != null) {
@@ -443,7 +462,10 @@
             return set;
         }
 
-        String[] types = systemAssistant.getMimeTypes();
+        ClipboardAssistance assistant =
+                (currentDragboard != null) ? currentDragboard : systemAssistant;
+
+        String[] types = assistant.getMimeTypes();
         if (types == null) {
             return set;
         }
@@ -459,7 +481,7 @@
                 // RT-16812 - IE puts images on the clipboard in a HTML IMG url
                 try {
                     //HTML header could be improperly formatted and we can get an exception here
-                    if (parseIMG(systemAssistant.getData(Clipboard.HTML_TYPE)) != null) {
+                    if (parseIMG(assistant.getData(Clipboard.HTML_TYPE)) != null) {
                         set.add(DataFormat.IMAGE);
                     }
                 } catch (Exception ex) {
@@ -487,7 +509,10 @@
             return false;
         }
 
-        String[] stypes = systemAssistant.getMimeTypes();
+        ClipboardAssistance assistant =
+                (currentDragboard != null) ? currentDragboard : systemAssistant;
+
+        String[] stypes = assistant.getMimeTypes();
         if (stypes == null) {
             return false;
         }
@@ -500,7 +525,7 @@
                 return true;
             } else if (dataFormat == DataFormat.IMAGE &&
                        t.equalsIgnoreCase(Clipboard.HTML_TYPE) &&
-                       parseIMG(systemAssistant.getData(Clipboard.HTML_TYPE)) != null) {
+                       parseIMG(assistant.getData(Clipboard.HTML_TYPE)) != null) {
                 return true;
             } else if (dataFormat == DataFormat.FILES &&
                     t.equalsIgnoreCase(Clipboard.FILE_LIST_TYPE)) {
@@ -587,9 +612,9 @@
                 }
             } else {
                 if (data instanceof Serializable) {
-                    if ((dataFormat != DataFormat.PLAIN_TEXT &&
-                            dataFormat != DataFormat.HTML) ||
-                            ! (data instanceof String)) {
+                    if ((dataFormat != DataFormat.PLAIN_TEXT && dataFormat != DataFormat.HTML) ||
+                        !(data instanceof String))
+                    {
                         try {
                             ByteArrayOutputStream bos = new ByteArrayOutputStream();
                             ObjectOutput out = new ObjectOutputStream(bos);
@@ -597,10 +622,22 @@
                             out.close();
                             data = ByteBuffer.wrap(bos.toByteArray());
                         } catch (IOException e) {
-                            throw new IllegalArgumentException("Could not "
-                                    + "serialize the data", e);
+                            throw new IllegalArgumentException("Could not serialize the data", e);
                         }
                     }
+                } else if (data instanceof InputStream) {
+                    ByteArrayOutputStream bout = new ByteArrayOutputStream();
+                    try (InputStream is = (InputStream)data) {
+                        // TODO: performance
+                        int i = is.read();
+                        while (i != -1) {
+                            bout.write(i);
+                            i = is.read();
+                        }
+                    } catch (IOException e) {
+                        throw new IllegalArgumentException("Could not serialize the data", e);
+                    }
+                    data = ByteBuffer.wrap(bout.toByteArray());
                 } else if (!(data instanceof ByteBuffer)) {
                     throw new IllegalArgumentException("Only serializable "
                             + "objects or ByteBuffer can be used as data "
--- a/modules/graphics/src/main/java/javafx/scene/Scene.java	Wed Nov 13 15:39:35 2013 -0800
+++ b/modules/graphics/src/main/java/javafx/scene/Scene.java	Thu Nov 14 14:22:18 2013 +0400
@@ -3046,6 +3046,11 @@
         }
 
         private void processTargetExit(DragEvent de) {
+            if (dragboard == null) {
+                // dragboard should have been created in processTargetEnterOver()
+                throw new NullPointerException("dragboard is null in processTargetExit()");
+            }
+
             if (currentTargets.size() > 0) {
                 potentialTarget = null;
                 tmpTargetWrapper.clear();
@@ -3063,7 +3068,8 @@
                     acceptedTransferMode, source, potentialTarget, de.getPickResult());
 
             if (dragboard == null) {
-                dragboard = createDragboard(de, false);
+                // dragboard should have been created in processTargetEnterOver()
+                throw new NullPointerException("dragboard is null in processTargetDrop()");
             }
 
             handleExitEnter(de, tmpTargetWrapper);
@@ -5649,24 +5655,19 @@
     }
 
 
-    Dragboard startDragAndDrop(EventTarget source,
-            TransferMode... transferModes) {
-
-        if (dndGesture.dragDetected != DragDetectedState.PROCESSING) {
+    Dragboard startDragAndDrop(EventTarget source, TransferMode... transferModes) {
+        if (dndGesture == null ||
+            (dndGesture.dragDetected != DragDetectedState.PROCESSING))
+        {
             throw new IllegalStateException("Cannot start drag and drop " +
                     "outside of DRAG_DETECTED event handler");
         }
 
-        if (dndGesture != null) {
-            Set<TransferMode> set = EnumSet.noneOf(TransferMode.class);
-            for (TransferMode tm : InputEventUtils.safeTransferModes(transferModes)) {
-                set.add(tm);
-            }
-            return dndGesture.startDrag(source, set);
-        }
-
-        throw new IllegalStateException("Cannot start drag and drop when "
-                + "mouse button is not pressed");
+        Set<TransferMode> set = EnumSet.noneOf(TransferMode.class);
+        for (TransferMode tm : InputEventUtils.safeTransferModes(transferModes)) {
+            set.add(tm);
+        }
+        return dndGesture.startDrag(source, set);
     }
 
     void startFullDrag(EventTarget source) {
--- a/modules/swing/src/main/java/javafx/embed/swing/DataFlavorUtils.java	Wed Nov 13 15:39:35 2013 -0800
+++ b/modules/swing/src/main/java/javafx/embed/swing/DataFlavorUtils.java	Thu Nov 14 14:22:18 2013 +0400
@@ -25,6 +25,9 @@
 
 package javafx.embed.swing;
 
+import javafx.scene.input.DataFormat;
+
+import java.io.ByteArrayOutputStream;
 import java.util.Set;
 import java.util.Map;
 import java.util.List;
@@ -35,19 +38,23 @@
 import java.awt.datatransfer.DataFlavor;
 import java.awt.datatransfer.Transferable;
 import java.awt.datatransfer.UnsupportedFlavorException;
+
 import java.io.ByteArrayInputStream;
+import java.io.File;
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.UnsupportedEncodingException;
-import java.io.File;
 
 
 final class DataFlavorUtils {
+
     static String getFxMimeType(final DataFlavor flavor) {
         return flavor.getPrimaryType() + "/" + flavor.getSubType();
     }
 
     static Object adjustFxData(final DataFlavor flavor, final Object fxData)
-            throws UnsupportedEncodingException {
+            throws UnsupportedEncodingException
+    {
         // TBD: Handle more data types!!!
         if (fxData instanceof String) {
             if (flavor.isRepresentationClassInputStream()) {
@@ -56,12 +63,17 @@
                         ? ((String) fxData).getBytes(encoding)
                         : ((String) fxData).getBytes());
             }
+            if (flavor.isRepresentationClassByteBuffer()) {
+                // ...
+            }
         }
         return fxData;
     }
 
     static Object adjustSwingData(final DataFlavor flavor,
-                                  final Object swingData) {
+                                  final String mimeType,
+                                  final Object swingData)
+    {
         if (flavor.isFlavorJavaFileListType()) {
             // RT-12663
             final List<File> fileList = (List<File>)swingData;
@@ -72,17 +84,37 @@
             }
             return paths;
         }
+        DataFormat dataFormat = DataFormat.lookupMimeType(mimeType);
+        if (DataFormat.PLAIN_TEXT.equals(dataFormat)) {
+            if (flavor.isFlavorTextType()) {
+                if (swingData instanceof InputStream) {
+                    InputStream in = (InputStream)swingData;
+                    // TBD: charset
+                    ByteArrayOutputStream out = new ByteArrayOutputStream();
+                    byte[] bb = new byte[64];
+                    try {
+                        int len = in.read(bb);
+                        while (len != -1) {
+                            out.write(bb, 0, len);
+                            len = in.read(bb);
+                        }
+                        out.close();
+                        return new String(out.toByteArray());
+                    } catch (Exception z) {
+                        // ignore
+                    }
+                }
+            } else if (swingData != null) {
+                return swingData.toString();
+            }
+        }
         return swingData;
     }
 
-    static Map<String, DataFlavor> adjustSwingDataFlavors(
-            final DataFlavor[] flavors) {
-
-        //
+    static Map<String, DataFlavor> adjustSwingDataFlavors(final DataFlavor[] flavors) {
         // Group data flavors by FX mime type.
-        //
         final Map<String, Set<DataFlavor>> mimeType2Flavors =
-                new HashMap<String, Set<DataFlavor>>(flavors.length);
+                new HashMap<>(flavors.length);
         for (DataFlavor flavor : flavors) {
             final String mimeType = getFxMimeType(flavor);
             if (mimeType2Flavors.containsKey(mimeType)) {
@@ -112,11 +144,8 @@
             }
         }
 
-        //
         // Choose the best data flavor corresponding to the given FX mime type
-        //
-        final Map<String, DataFlavor> mimeType2Flavor =
-                new HashMap<String, DataFlavor>();
+        final Map<String, DataFlavor> mimeType2Flavor = new HashMap<>();
         for (String mimeType : mimeType2Flavors.keySet()) {
             final DataFlavor[] mimeTypeFlavors = mimeType2Flavors.get(mimeType).
                     toArray(new DataFlavor[0]);
@@ -131,29 +160,38 @@
         return mimeType2Flavor;
     }
 
-    static Map<String, Object> readAllData(final Transferable t) {
-        final Map<String, DataFlavor> fxMimeType2DataFlavor =
-                adjustSwingDataFlavors(t.getTransferDataFlavors());
-        return readAllData(t, fxMimeType2DataFlavor);
+    private static Object readData(final Transferable t, final DataFlavor flavor) {
+        Object obj = null;
+        try {
+            obj = t.getTransferData(flavor);
+        } catch (UnsupportedFlavorException ex) {
+            // FIXME: report error
+            ex.printStackTrace(System.err);
+        } catch (IOException ex) {
+            // FIXME: report error
+            ex.printStackTrace(System.err);
+        }
+        return obj;
     }
-    
+
     static Map<String, Object> readAllData(final Transferable t,
-                                           final Map<String, DataFlavor> fxMimeType2DataFlavor) {
-        final Map<String, Object> fxMimeType2Data =
-                new HashMap<String, Object>();
-        
+                                           final Map<String, DataFlavor> fxMimeType2DataFlavor)
+    {
+        final Map<String, Object> fxMimeType2Data = new HashMap<>();
+        for (DataFlavor flavor : t.getTransferDataFlavors()) {
+            Object obj = readData(t, flavor);
+            if (obj != null) {
+                String mimeType = getFxMimeType(flavor);
+                obj = adjustSwingData(flavor, mimeType, obj);
+                fxMimeType2Data.put(mimeType, obj);
+            }
+        }
         for (Map.Entry<String, DataFlavor> e: fxMimeType2DataFlavor.entrySet()) {
-            Object obj = null;
-            try {
-                obj = t.getTransferData(e.getValue());
-            } catch (UnsupportedFlavorException ex) {
-                // FIXME: report error
-            } catch (IOException ex) {
-                // FIXME: report error
-            }
-
+            String mimeType = e.getKey();
+            DataFlavor flavor = e.getValue();
+            Object obj = readData(t, flavor);
             if (obj != null) {
-                obj = adjustSwingData(e.getValue(), obj);
+                obj = adjustSwingData(flavor, mimeType, obj);
                 fxMimeType2Data.put(e.getKey(), obj);
             }
         }
--- a/modules/swing/src/main/java/javafx/embed/swing/JFXPanel.java	Wed Nov 13 15:39:35 2013 -0800
+++ b/modules/swing/src/main/java/javafx/embed/swing/JFXPanel.java	Thu Nov 14 14:22:18 2013 +0400
@@ -134,7 +134,8 @@
     private volatile EmbeddedWindow stage;
     private volatile Scene scene;
 
-    private final SwingDnD dnd;
+    // Accessed on EDT only
+    private SwingDnD dnd;
 
     private EmbeddedStageInterface stagePeer;
     private EmbeddedSceneInterface scenePeer;
@@ -156,7 +157,7 @@
     private volatile int screenX = 0;
     private volatile int screenY = 0;
 
-    // accessed on EDT only
+    // Accessed on EDT only
     private BufferedImage pixelsIm;
 
     private volatile float opacity = 1.0f;
@@ -227,13 +228,6 @@
 
         setFocusable(true);
         setFocusTraversalKeysEnabled(false);
-
-        this.dnd = new SwingDnD(this, new SwingDnD.JFXPanelFacade() {
-            @Override
-            public EmbeddedSceneInterface getScene() {
-                return isFxEnabled() ? scenePeer : null;
-            }
-        });
     }
 
     /**
@@ -705,13 +699,21 @@
 
     private void setFxEnabled(boolean enabled) {
         if (!enabled) {
-            disableCount.incrementAndGet();
+            if (disableCount.incrementAndGet() == 1) {
+                if (dnd != null) {
+                    dnd.removeNotify();
+                }
+            }
         } else {
             if (disableCount.get() == 0) {
                 //should report a warning about an extra enable call ?
                 return;
             }
-            disableCount.decrementAndGet();
+            if (disableCount.decrementAndGet() == 0) {
+                if (dnd != null) {
+                    dnd.addNotify();
+                }
+            }
         }
     }
 
@@ -741,7 +743,6 @@
         super.addNotify();
 
         registerFinishListener();
-        dnd.addNotify();
         AccessController.doPrivileged(new PrivilegedAction<Void>() {
             public Void run() {
                 JFXPanel.this.getToolkit().addAWTEventListener(ungrabListener,
@@ -797,8 +798,6 @@
             }
         });
 
-        dnd.removeNotify();
-
         /* see CR 4867453 */
         getInputContext().removeNotify(this);
 
@@ -824,19 +823,28 @@
 
         @Override
         public void setEmbeddedScene(EmbeddedSceneInterface embeddedScene) {
+            if (scenePeer == embeddedScene) {
+                return;
+            }
             scenePeer = embeddedScene;
             if (scenePeer == null) {
+                SwingUtilities.invokeLater(new Runnable() {
+                    @Override
+                    public void run() {
+                        dnd.removeNotify();
+                        dnd = null;
+                    }
+                });
                 return;
             }
             if (pWidth > 0 && pHeight > 0) {
                 scenePeer.setSize(pWidth, pHeight);
             }
-
-            // DnD-related calls on 'scenePeer' should go from AWT EDT.
             SwingUtilities.invokeLater(new Runnable() {
-
                 @Override
                 public void run() {
+                    dnd = new SwingDnD(JFXPanel.this, scenePeer);
+                    dnd.addNotify();
                     if (scenePeer != null) {
                         scenePeer.setDragStartListener(dnd.getDragStartListener());
                     }
--- a/modules/swing/src/main/java/javafx/embed/swing/SwingDnD.java	Wed Nov 13 15:39:35 2013 -0800
+++ b/modules/swing/src/main/java/javafx/embed/swing/SwingDnD.java	Thu Nov 14 14:22:18 2013 +0400
@@ -25,7 +25,8 @@
 
 package javafx.embed.swing;
 
-import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+
 import java.util.Collections;
 import java.util.ArrayList;
 import java.util.EnumSet;
@@ -33,12 +34,12 @@
 import java.util.List;
 import java.util.Set;
 
+import com.sun.javafx.embed.EmbeddedSceneDSInterface;
+import com.sun.javafx.embed.HostDragStartListener;
 import javafx.scene.input.TransferMode;
 
 import com.sun.javafx.embed.EmbeddedSceneInterface;
-import com.sun.javafx.embed.EmbeddedSceneDragSourceInterface;
-import com.sun.javafx.embed.EmbeddedSceneDragStartListenerInterface;
-import com.sun.javafx.embed.EmbeddedSceneDropTargetInterface;
+import com.sun.javafx.embed.EmbeddedSceneDTInterface;
 import com.sun.javafx.tk.Toolkit;
 
 import javax.swing.JComponent;
@@ -48,7 +49,6 @@
 
 import java.awt.datatransfer.DataFlavor;
 import java.awt.datatransfer.Transferable;
-import java.awt.datatransfer.UnsupportedFlavorException;
 import java.awt.dnd.DnDConstants;
 import java.awt.dnd.DragGestureEvent;
 import java.awt.dnd.DragGestureRecognizer;
@@ -61,6 +61,7 @@
 import java.awt.dnd.DropTargetDragEvent;
 import java.awt.dnd.DropTargetDropEvent;
 import java.awt.dnd.DropTargetEvent;
+import java.awt.dnd.DropTargetListener;
 
 import java.awt.event.InputEvent;
 import java.awt.event.MouseAdapter;
@@ -71,102 +72,89 @@
  */
 final class SwingDnD {
 
-    private final JFXPanelFacade facade;
     private final Transferable dndTransferable = new DnDTransferable();
+
+    private final DragSource dragSource;
     private final DragSourceListener dragSourceListener;
+
+    // swingDragSource and fxDropTarget are used when DnD is initiated from
+    // Swing or external process, i.e. this SwingDnD is used as a drop target
     private SwingDragSource swingDragSource;
-    private EmbeddedSceneDragSourceInterface fxDragSource;
-    private EmbeddedSceneDropTargetInterface dropTarget;
+    private EmbeddedSceneDTInterface fxDropTarget;
+
+    // fxDragSource is used when DnD is initiated from FX, i.e. this
+    // SwingDnD acts as a drag source
+    private EmbeddedSceneDSInterface fxDragSource;
+
     private MouseEvent me;
 
-    interface JFXPanelFacade {
-
-        EmbeddedSceneInterface getScene();
-    }
-
-    SwingDnD(final JComponent comp, final JFXPanelFacade facade) {
-        this.facade = facade;
+    SwingDnD(final JComponent comp, final EmbeddedSceneInterface embeddedScene) {
 
         comp.addMouseListener(new MouseAdapter() {
-
             @Override
             public void mouseClicked(MouseEvent me) {
                 storeMouseEvent(me);
             }
-
             @Override
             public void mouseDragged(MouseEvent me) {
                 storeMouseEvent(me);
             }
-
             @Override
             public void mousePressed(MouseEvent me) {
                 storeMouseEvent(me);
             }
-
             @Override
             public void mouseReleased(MouseEvent me) {
                 storeMouseEvent(me);
             }
         });
 
+        dragSource = new DragSource();
         dragSourceListener = new DragSourceAdapter() {
-
             @Override
             public void dragDropEnd(final DragSourceDropEvent dsde) {
-                // Fix for RT-21836
-                if (fxDragSource == null) {
-                    return;
-                }
-
-                assert hasFxScene();
-
+                assert fxDragSource != null;
                 try {
-                    fxDragSource.dragDropEnd(dropActionToTransferMode(dsde.
-                            getDropAction()));
+                    fxDragSource.dragDropEnd(dropActionToTransferMode(dsde.getDropAction()));
                 } finally {
                     fxDragSource = null;
                 }
             }
         };
 
-        new DropTarget(comp, DnDConstants.ACTION_COPY | DnDConstants.ACTION_MOVE |
-                DnDConstants.ACTION_LINK, new DropTargetAdapter() {
-
+        DropTargetListener dtl = new DropTargetAdapter() {
             @Override
             public void dragEnter(final DropTargetDragEvent e) {
-                if (!hasFxScene()) {
-                    e.rejectDrag();
+                // This is a temporary workaround for JDK-8027913
+                if ((swingDragSource != null) || (fxDropTarget != null)) {
                     return;
                 }
 
-                if (fxDragSource == null) {
-                    // There is no FX drag source, create wrapper for external
-                    // drag source.
-                    assert swingDragSource == null;
-                    swingDragSource = new SwingDragSource(e);
-                }
+                assert swingDragSource == null;
+                swingDragSource = new SwingDragSource();
+                swingDragSource.updateContents(e);
+
+                assert fxDropTarget == null;
+                // Cache the Transferable data in advance, as it cannot be
+                // queried from drop(). See comments in dragOver() and in
+                // drop() below
+                fxDropTarget = embeddedScene.createDropTarget();
 
                 final Point orig = e.getLocation();
                 final Point screen = new Point(orig);
                 SwingUtilities.convertPointToScreen(screen, comp);
-                applyDragResult(getDropTarget().handleDragEnter(orig.x, orig.y,
-                                                                screen.x,
-                                                                screen.y,
-                                                                dropActionToTransferMode(e.
-                        getDropAction()), getDragSource()), e);
+                final TransferMode dr = fxDropTarget.handleDragEnter(
+                        orig.x, orig.y, screen.x, screen.y,
+                        dropActionToTransferMode(e.getDropAction()), swingDragSource);
+                applyDragResult(dr, e);
             }
 
             @Override
             public void dragExit(final DropTargetEvent e) {
-                if (!hasFxScene()) {
-                    // The drag has been already rejected in dragEnter(), but it doesn't
-                    // prevent dragExit(), dragOver() and drop() from being called
-                    return;
-                }
-                
+                assert swingDragSource != null;
+                assert fxDropTarget != null;
                 try {
-                    dropTarget.handleDragLeave();
+                    fxDropTarget.handleDragLeave();
                 } finally {
                     endDnD();
                 }
@@ -174,91 +162,90 @@
 
             @Override
             public void dragOver(final DropTargetDragEvent e) {
-                if (!hasFxScene()) {
-                    // The drag has been already rejected in dragEnter(), but it doesn't
-                    // prevent dragExit(), dragOver() and drop() from being called
-                    return;
-                }
+                assert swingDragSource != null;
+                // We cache Transferable data in advance, as we can't fetch
+                // it from drop(), see comments in drop() below. However,
+                // caching in every dragOver() is too expensive and also for
+                // some reason has a weird side-effect: e.acceptDrag() is
+                // ignored, and no drops are possible. So the workaround is
+                // to cache all the data in dragEnter() only
+                //
+                // swingDragSource.updateContents(e);
 
-                if (swingDragSource != null) {
-                    swingDragSource.updateContents(e);
-                }
-
+                assert fxDropTarget != null;
                 final Point orig = e.getLocation();
                 final Point screen = new Point(orig);
                 SwingUtilities.convertPointToScreen(screen, comp);
-                applyDragResult(dropTarget.handleDragOver(orig.x, orig.y,
-                                                          screen.x, screen.y,
-                                                          dropActionToTransferMode(e.
-                        getDropAction())), e);
+                final TransferMode dr = fxDropTarget.handleDragOver(
+                        orig.x, orig.y, screen.x, screen.y,
+                        dropActionToTransferMode(e.getDropAction()));
+                applyDragResult(dr, e);
             }
 
             @Override
             public void drop(final DropTargetDropEvent e) {
-                if (!hasFxScene()) {
-                    // The drag has been already rejected in dragEnter(), but it doesn't
-                    // prevent dragExit(), dragOver() and drop() from being called
-                    return;
-                }
+                assert swingDragSource != null;
+                // Don't call updateContents() from drop(). In AWT, it is possible to
+                // get data from the Transferable object in drop() only after the drop
+                // has been accepted. Here we first let FX handle drop(), then accept
+                // or reject AWT drop based the result. So instead of querying the
+                // Transferable object, we use data from swingDragSource, which was
+                // cached in dragEnter(), but not in dragOver(), see comments in
+                // dragOver() above
+                //
+                // swingDragSource.updateContents(e);
 
                 final Point orig = e.getLocation();
                 final Point screen = new Point(orig);
                 SwingUtilities.convertPointToScreen(screen, comp);
 
+                assert fxDropTarget != null;
                 try {
-                    final TransferMode dropResult =
-                            dropTarget.handleDragDrop(orig.x, orig.y, screen.x,
-                                                      screen.y,
-                                                      dropActionToTransferMode(e.
-                            getDropAction()));
+                    final TransferMode dropResult = fxDropTarget.handleDragDrop(
+                            orig.x, orig.y, screen.x, screen.y,
+                            dropActionToTransferMode(e.getDropAction()));
                     applyDropResult(dropResult, e);
-
                     e.dropComplete(dropResult != null);
                 } finally {
                     endDnD();
                 }
             }
-        });
+        };
+        comp.setDropTarget(new DropTarget(comp,
+                DnDConstants.ACTION_COPY | DnDConstants.ACTION_MOVE | DnDConstants.ACTION_LINK, dtl));
+
     }
 
     void addNotify() {
-        DragSource.getDefaultDragSource().addDragSourceListener(
-                dragSourceListener);
+        dragSource.addDragSourceListener(dragSourceListener);
     }
 
     void removeNotify() {
         // RT-22049: Multi-JFrame/JFXPanel app leaks JFXPanels
         // Don't forget to unregister drag source listener!
-        DragSource.getDefaultDragSource().removeDragSourceListener(
-                dragSourceListener);
+        dragSource.removeDragSourceListener(dragSourceListener);
     }
 
-    EmbeddedSceneDragStartListenerInterface getDragStartListener() {
-        return new EmbeddedSceneDragStartListenerInterface() {
-
+    HostDragStartListener getDragStartListener() {
+        return new HostDragStartListener() {
             @Override
-            public void dragStarted(
-                    final EmbeddedSceneDragSourceInterface dragSource,
-                    final TransferMode dragAction) {
+            public void dragStarted(final EmbeddedSceneDSInterface dragSource,
+                                    final TransferMode dragAction)
+            {
                 assert Toolkit.getToolkit().isFxUserThread();
                 assert dragSource != null;
                 
-                //
                 // The method is called from FX Scene just before entering
                 // nested event loop servicing DnD events.
                 // It should initialize DnD in AWT EDT.
-                //
-
                 SwingUtilities.invokeLater(new Runnable() {
-
                     @Override
                     public void run() {
                         assert fxDragSource == null;
                         assert swingDragSource == null;
-                        assert dropTarget == null;
+                        assert fxDropTarget == null;
                         
                         fxDragSource = dragSource;
-
                         startDrag(me, dndTransferable, dragSource.
                                 getSupportedActions(), dragAction);
                     }
@@ -267,93 +254,50 @@
         };
     }
 
-    private static void startDrag(final MouseEvent e, final Transferable t,
+    private void startDrag(final MouseEvent e, final Transferable t,
                                   final Set<TransferMode> sa,
-                                  final TransferMode dragAction) {
-
+                                  final TransferMode dragAction)
+    {
         assert sa.contains(dragAction);
-
-        //
         // This is a replacement for the default AWT drag gesture recognizer.
         // Not sure DragGestureRecognizer was ever supposed to be used this way.
-        //
-
         final class StubDragGestureRecognizer extends DragGestureRecognizer {
-
-            StubDragGestureRecognizer() {
-                super(DragSource.getDefaultDragSource(), e.getComponent());
-                super.setSourceActions(transferModesToDropActions(sa));
-                super.appendEvent(e);
+            StubDragGestureRecognizer(DragSource ds) {
+                super(ds, e.getComponent());
+                setSourceActions(transferModesToDropActions(sa));
+                appendEvent(e);
             }
-
             @Override
             protected void registerListeners() {
             }
-
             @Override
             protected void unregisterListeners() {
             }
         }
 
         final Point pt = new Point(e.getX(), e.getY());
-
         final int action = transferModeToDropAction(dragAction);
-
-        final DragGestureRecognizer dgs = new StubDragGestureRecognizer();
-
-        final List<InputEvent> events = Arrays.asList(new InputEvent[]{dgs.
-                    getTriggerEvent()});
-
-        final DragGestureEvent dse = new DragGestureEvent(dgs, action, pt,
-                                                          events);
-
+        final DragGestureRecognizer dgs = new StubDragGestureRecognizer(dragSource);
+        final List<InputEvent> events =
+                Arrays.asList(new InputEvent[] { dgs.getTriggerEvent() });
+        final DragGestureEvent dse = new DragGestureEvent(dgs, action, pt, events);
         dse.startDrag(null, t);
     }
 
-    private boolean hasFxScene() {
-        assert SwingUtilities.isEventDispatchThread();
-        return getFxScene() != null;
-    }
-
-    private EmbeddedSceneInterface getFxScene() {
-        return facade.getScene();
-    }
-
-    private EmbeddedSceneDragSourceInterface getDragSource() {
-        assert hasFxScene();
-
-        assert (swingDragSource == null) != (fxDragSource == null);
-
-        if (swingDragSource != null) {
-            return swingDragSource;
-        }
-        return fxDragSource;
-    }
-
-    private EmbeddedSceneDropTargetInterface getDropTarget() {
-        assert hasFxScene();
-
-        if (dropTarget == null) {
-            dropTarget = getFxScene().createDropTarget();
-        }
-        return dropTarget;
-    }
-    
     private void endDnD() {
-        assert dropTarget != null;
-        
-        dropTarget = null;
-        if (swingDragSource != null) {
-            swingDragSource = null;
-        }
+        assert swingDragSource != null;
+        assert fxDropTarget != null;
+        fxDropTarget = null;
+        swingDragSource = null;
     }
 
     private void storeMouseEvent(final MouseEvent me) {
         this.me = me;
     }
 
-    private static void applyDragResult(final TransferMode dragResult,
-                                        final DropTargetDragEvent e) {
+    private void applyDragResult(final TransferMode dragResult,
+                                 final DropTargetDragEvent e)
+    {
         if (dragResult == null) {
             e.rejectDrag();
         } else {
@@ -361,8 +305,9 @@
         }
     }
 
-    private static void applyDropResult(final TransferMode dropResult,
-                                        final DropTargetDropEvent e) {
+    private void applyDropResult(final TransferMode dropResult,
+                                 final DropTargetDropEvent e)
+    {
         if (dropResult == null) {
             e.rejectDrop();
         } else {
@@ -399,7 +344,8 @@
     }
 
     static Set<TransferMode> dropActionsToTransferModes(
-            final int dropActions) {
+            final int dropActions)
+    {
         final Set<TransferMode> tms = EnumSet.noneOf(TransferMode.class);
         if ((dropActions & DnDConstants.ACTION_COPY) != 0) {
             tms.add(TransferMode.COPY);
@@ -421,35 +367,28 @@
         return dropActions;
     }
 
-    //
-    // This is facade to export data from FX to outer world.
-    //
+    // Transferable wrapper over FX dragboard. All the calls are
+    // forwarded to FX and executed on the FX event thread.
     private final class DnDTransferable implements Transferable {
 
         @Override
-        public Object getTransferData(final DataFlavor flavor) throws
-                UnsupportedFlavorException, IOException {
-            checkSwingEventDispatchThread();
+        public Object getTransferData(final DataFlavor flavor)
+                throws UnsupportedEncodingException
+        {
+            assert fxDragSource != null;
+            assert SwingUtilities.isEventDispatchThread();
 
-            if (!hasFxScene()) {
-                return null;
-            }
-
-            final String mimeType = DataFlavorUtils.getFxMimeType(flavor);
-
-            return DataFlavorUtils.adjustFxData(flavor, getDragSource().getData(
-                    mimeType));
+            String mimeType = DataFlavorUtils.getFxMimeType(flavor);
+            return DataFlavorUtils.adjustFxData(
+                    flavor, fxDragSource.getData(mimeType));
         }
 
         @Override
         public DataFlavor[] getTransferDataFlavors() {
-            checkSwingEventDispatchThread();
+            assert fxDragSource != null;
+            assert SwingUtilities.isEventDispatchThread();
 
-            if (!hasFxScene()) {
-                return null;
-            }
-
-            final String mimeTypes[] = getDragSource().getMimeTypes();
+            final String mimeTypes[] = fxDragSource.getMimeTypes();
 
             final ArrayList<DataFlavor> flavors =
                     new ArrayList<DataFlavor>(mimeTypes.length);
@@ -468,20 +407,11 @@
 
         @Override
         public boolean isDataFlavorSupported(final DataFlavor flavor) {
-            checkSwingEventDispatchThread();
+            assert fxDragSource != null;
+            assert SwingUtilities.isEventDispatchThread();
 
-            if (!hasFxScene()) {
-                return false;
-            }
-
-            return getDragSource().isMimeTypeAvailable(DataFlavorUtils.
-                    getFxMimeType(flavor));
-        }
-    };
-
-    private static void checkSwingEventDispatchThread() {
-        if (!SwingUtilities.isEventDispatchThread()) {
-            throw new IllegalStateException();
+            return fxDragSource.isMimeTypeAvailable(
+                    DataFlavorUtils.getFxMimeType(flavor));
         }
     }
 }
--- a/modules/swing/src/main/java/javafx/embed/swing/SwingDragSource.java	Wed Nov 13 15:39:35 2013 -0800
+++ b/modules/swing/src/main/java/javafx/embed/swing/SwingDragSource.java	Thu Nov 14 14:22:18 2013 +0400
@@ -25,12 +25,12 @@
 
 package javafx.embed.swing;
 
-import com.sun.javafx.embed.EmbeddedSceneDragSourceInterface;
+import com.sun.javafx.embed.EmbeddedSceneDSInterface;
 import com.sun.javafx.tk.Toolkit;
 import java.awt.datatransfer.DataFlavor;
 import java.awt.datatransfer.Transferable;
-import java.awt.dnd.DnDConstants;
 import java.awt.dnd.DropTargetDragEvent;
+import java.awt.dnd.DropTargetDropEvent;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.Map;
@@ -40,45 +40,29 @@
 /**
  * Drag source to deliver data from Swing environment to embedded FX scene.
  */
-final class SwingDragSource implements EmbeddedSceneDragSourceInterface {
+final class SwingDragSource implements EmbeddedSceneDSInterface {
 
+    private int sourceActions;
     private Map<String, Object> mimeType2Data = Collections.EMPTY_MAP;
-    private int sourceActions;
-    private Set<TransferMode> cachedTransferModes;
-    
-    SwingDragSource(final DropTargetDragEvent e) {
-        setContents(e);
+
+    SwingDragSource() {
     }
     
     void updateContents(final DropTargetDragEvent e) {
-        updateSourceActions(e.getSourceActions());
+        sourceActions = e.getSourceActions();
         updateData(e.getTransferable());
     }
 
-    private void setContents(final DropTargetDragEvent e) {
-        this.sourceActions = DnDConstants.ACTION_NONE;
-        this.cachedTransferModes = null;
-        this.mimeType2Data = Collections.EMPTY_MAP;
-        updateContents(e);
+    void updateContents(final DropTargetDropEvent e) {
+        sourceActions = e.getSourceActions();
+        updateData(e.getTransferable());
     }
 
-    private void updateSourceActions(final int newSourceActions) {
-        if (newSourceActions != this.sourceActions) {
-            this.sourceActions = newSourceActions;
-            this.cachedTransferModes = null;
-        }
-    }
-
-    private void updateData(final Transferable t) {
+    private void updateData(Transferable t) {
         final Map<String, DataFlavor> mimeType2DataFlavor =
                 DataFlavorUtils.adjustSwingDataFlavors(
                 t.getTransferDataFlavors());
-        if (mimeType2DataFlavor.keySet().equals(mimeType2Data.keySet())) {
-            // Mime types have't changed. Assume data has not been
-            // changed as well, so don't need to reread it
-            return;
-        }
-        //
+
         // Read data from the given Transferable in advance. Need to do this
         // because we don't want Transferable#getTransferData() to be called
         // from DropTargetListener#drop().
@@ -99,7 +83,7 @@
         // SwingDragSource#getData() is called from FX user code and from
         // QuantumClipboard#getContent() (sik!). These calls usually take
         // place in the context of 
-        // EmbeddedSceneDropTargetInterface#handleDragDrop() method as the 
+        // EmbeddedSceneDTInterface#handleDragDrop() method as the
         // normal handling of DnD.
         // Instead of keeping reference to source Transferable we just read
         // all its data while in the context safe for calling
@@ -118,11 +102,7 @@
     @Override
     public Set<TransferMode> getSupportedActions() {
         assert Toolkit.getToolkit().isFxUserThread();
-        if (cachedTransferModes == null) {
-            cachedTransferModes =
-                    SwingDnD.dropActionsToTransferModes(sourceActions);
-        }
-        return cachedTransferModes;
+        return SwingDnD.dropActionsToTransferModes(sourceActions);
     }
 
     @Override
--- a/modules/swt/src/main/java/javafx/embed/swt/FXCanvas.java	Wed Nov 13 15:39:35 2013 -0800
+++ b/modules/swt/src/main/java/javafx/embed/swt/FXCanvas.java	Thu Nov 14 14:22:18 2013 +0400
@@ -39,15 +39,15 @@
 import com.sun.javafx.cursor.CursorFrame;
 import com.sun.javafx.cursor.CursorType;
 
+import com.sun.javafx.embed.EmbeddedSceneDSInterface;
+import com.sun.javafx.embed.HostDragStartListener;
 import javafx.application.Platform;
 import javafx.scene.Scene;
 import javafx.scene.input.TransferMode;
 
 import com.sun.javafx.application.PlatformImpl;
 import com.sun.javafx.embed.AbstractEvents;
-import com.sun.javafx.embed.EmbeddedSceneDragSourceInterface;
-import com.sun.javafx.embed.EmbeddedSceneDragStartListenerInterface;
-import com.sun.javafx.embed.EmbeddedSceneDropTargetInterface;
+import com.sun.javafx.embed.EmbeddedSceneDTInterface;
 import com.sun.javafx.embed.EmbeddedSceneInterface;
 import com.sun.javafx.embed.EmbeddedStageInterface;
 import com.sun.javafx.embed.HostInterface;
@@ -730,7 +730,7 @@
         }
 
         // Consider using dragAction
-        private DragSource createDragSource(final EmbeddedSceneDragSourceInterface fxDragSource, TransferMode dragAction) {
+        private DragSource createDragSource(final EmbeddedSceneDSInterface fxDragSource, TransferMode dragAction) {
             Transfer [] transfers = getTransferTypes(fxDragSource.getMimeTypes());
             if (transfers.length == 0) return null;
             int dragOperation = getDragActions(fxDragSource.getSupportedActions());
@@ -836,7 +836,7 @@
 
         DropTarget createDropTarget(EmbeddedSceneInterface embeddedScene) {
             final DropTarget dropTarget = new DropTarget(FXCanvas.this, DND.DROP_COPY | DND.DROP_LINK | DND.DROP_MOVE);
-            final EmbeddedSceneDropTargetInterface fxDropTarget = embeddedScene.createDropTarget();
+            final EmbeddedSceneDTInterface fxDropTarget = embeddedScene.createDropTarget();
             dropTarget.setTransfer(getAllTransfers());
             dropTarget.addDropListener(new DropTargetListener() {
                 Object data;
@@ -849,7 +849,7 @@
                 TransferData currentTransferData;
                 boolean ignoreLeave;
                 int detail = DND.DROP_NONE, operations = DND.DROP_NONE;
-                EmbeddedSceneDragSourceInterface fxDragSource = new EmbeddedSceneDragSourceInterface() {
+                EmbeddedSceneDSInterface fxDragSource = new EmbeddedSceneDSInterface() {
                     public Set<TransferMode> getSupportedActions() {
                         return getTransferModes(operations);
                     }
@@ -944,9 +944,9 @@
             if (pWidth > 0 && pHeight > 0) {
                 scenePeer.setSize(pWidth, pHeight);
             }
-            scenePeer.setDragStartListener(new EmbeddedSceneDragStartListenerInterface() {
+            scenePeer.setDragStartListener(new HostDragStartListener() {
                 @Override
-                public void dragStarted(final EmbeddedSceneDragSourceInterface fxDragSource, final TransferMode dragAction) {
+                public void dragStarted(final EmbeddedSceneDSInterface fxDragSource, final TransferMode dragAction) {
                     Platform.runLater(new Runnable ()  {
                         public void run () {
                             DragSource dragSource = createDragSource(fxDragSource, dragAction);