--- old/javafx-embed-swing/src/javafx/embed/swing/SwingFXUtils.java 2013-05-21 17:35:14.000000000 +0400 +++ new/javafx-embed-swing/src/javafx/embed/swing/SwingFXUtils.java 2013-05-21 17:35:14.000000000 +0400 @@ -26,15 +26,26 @@ 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; /** @@ -180,4 +191,74 @@ 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() { + @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()); + } }