javafx-embed-swing/src/javafx/embed/swing/SwingFXUtils.java

Print this page

        

@@ -24,19 +24,30 @@
  */
 
 package javafx.embed.swing;
 
 import java.awt.AlphaComposite;
+import java.awt.EventQueue;
 import java.awt.Graphics2D;
+import java.awt.SecondaryLoop;
 import java.awt.image.BufferedImage;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
 import java.nio.IntBuffer;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.concurrent.atomic.AtomicBoolean;
+import javafx.application.Platform;
 import javafx.scene.image.Image;
 import javafx.scene.image.PixelFormat;
 import javafx.scene.image.PixelReader;
 import javafx.scene.image.PixelWriter;
 import javafx.scene.image.WritableImage;
 import javafx.scene.image.WritablePixelFormat;
+import com.sun.javafx.application.PlatformImpl;
+import com.sun.javafx.tk.Toolkit;
+import sun.awt.FwDispatcher;
 import sun.awt.image.IntegerComponentRaster;
 
 /**
  * This class provides utility methods for converting data types between
  * Swing/AWT and JavaFX formats.

@@ -178,6 +189,76 @@
                                              PixelFormat.getIntArgbPreInstance() :
                                              PixelFormat.getIntArgbInstance());
         pr.getPixels(0, 0, iw, ih, pf, data, offset, scan);
         return bimg;
     }
+
+    /**
+     * Invokes a runnable directly if called from the FX Application Thread,
+     * uses Platform.runLater otherwise
+     */
+    public static void runOnFxThread(Runnable runnable) {
+        if (Platform.isFxApplicationThread()) {
+            runnable.run();
+        } else {
+            Platform.runLater(runnable);
+        }
+    }
+
+    private static class FwSecondaryLoop implements SecondaryLoop {
+
+        private final AtomicBoolean isRunning = new AtomicBoolean(false);
+
+        @Override public boolean enter() {
+            if (isRunning.compareAndSet(false, true)) {
+                PlatformImpl.runAndWait(new Runnable() {
+                    @Override public void run() {
+                        Toolkit.getToolkit().enterNestedEventLoop(FwSecondaryLoop.this);
+                    }
+                });
+                return true;
+            }
+            return false;
+        }
+
+        @Override public boolean exit() {
+            if (isRunning.compareAndSet(true, false)) {
+                PlatformImpl.runAndWait(new Runnable() {
+                    @Override public void run() {
+                        Toolkit.getToolkit().exitNestedEventLoop(FwSecondaryLoop.this, null);
+                    }
+                });
+                return true;
+            }
+            return false;
+        }
+    }
+
+    private static class FXDispatcher implements FwDispatcher {
+        @Override public boolean isDispatchThread() {
+            return Platform.isFxApplicationThread();
+        }
+
+        @Override public void scheduleDispatch(Runnable runnable) {
+            runOnFxThread(runnable);
+        }
+
+        @Override public SecondaryLoop createSecondaryLoop() {
+            return new FwSecondaryLoop();
+        }
+    }
+
+    //Called with reflection from PlatformImpl to avoid dependency
+    public static void installFwEventQueue()
+            throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
+        EventQueue eq = AccessController.doPrivileged(
+                new PrivilegedAction<EventQueue>() {
+                    @Override public EventQueue run() {
+                        return java.awt.Toolkit.getDefaultToolkit().getSystemEventQueue();
+                    }
+                });
+
+        Method installDispatcher = eq.getClass().getDeclaredMethod("setFwDispatcher", FwDispatcher.class);
+        installDispatcher.setAccessible(true);
+        installDispatcher.invoke(eq, new FXDispatcher());
+    }
 }