diff --git a/jdk/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java b/jdk/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java index a15eb46a1d1..fcbd9cb388e 100644 --- a/jdk/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java +++ b/jdk/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java @@ -77,8 +77,20 @@ public final class LWCToolkit extends LWToolkit { if (!GraphicsEnvironment.isHeadless()) { initIDs(); } + inAWT = AccessController.doPrivileged(new PrivilegedAction() { + @Override + public Boolean run() { + return !Boolean.parseBoolean(System.getProperty("javafx.embed.singleThread", "false")); + } + }); } + /* + * If true we operate in normal mode and nested runloop is executed in JavaRunLoopMode + * If false we operate in singleThreaded FX/AWT interop mode and nested loop uses NSDefaultRunLoopMode + */ + private static final boolean inAWT; + public LWCToolkit() { SunToolkit.setDataTransfererClassName("sun.lwawt.macosx.CDataTransferer"); @@ -701,7 +713,10 @@ public final class LWCToolkit extends LWToolkit { * * if false - all events come after exit form the nested loop */ - static native void doAWTRunLoop(long mediator, boolean processEvents); + static void doAWTRunLoop(long mediator, boolean processEvents) { + doAWTRunLoopImpl(mediator, processEvents, inAWT); + } + static private native void doAWTRunLoopImpl(long mediator, boolean processEvents, boolean inAWT); static native void stopAWTRunLoop(long mediator); private native boolean nativeSyncQueue(long timeout); diff --git a/jdk/src/macosx/native/sun/awt/CDropTargetContextPeer.m b/jdk/src/macosx/native/sun/awt/CDropTargetContextPeer.m index 0e64b072e5f..5621003bf5a 100644 --- a/jdk/src/macosx/native/sun/awt/CDropTargetContextPeer.m +++ b/jdk/src/macosx/native/sun/awt/CDropTargetContextPeer.m @@ -61,7 +61,6 @@ static CDropTarget* GetCDropTarget(jlong jdroptarget) { JNIEXPORT jlong JNICALL Java_sun_lwawt_macosx_CDropTargetContextPeer_startTransfer (JNIEnv *env, jobject jthis, jlong jdroptarget, jlong jformat) { - AWT_ASSERT_NOT_APPKIT_THREAD; jlong result = (jlong) 0L; diff --git a/jdk/src/macosx/native/sun/awt/LWCToolkit.m b/jdk/src/macosx/native/sun/awt/LWCToolkit.m index 47c72abbfa5..6f42c0f9535 100644 --- a/jdk/src/macosx/native/sun/awt/LWCToolkit.m +++ b/jdk/src/macosx/native/sun/awt/LWCToolkit.m @@ -295,11 +295,11 @@ AWT_ASSERT_APPKIT_THREAD; /* * Class: sun_lwawt_macosx_LWCToolkit - * Method: doAWTRunLoop + * Method: doAWTRunLoopImpl * Signature: (JZZ)V */ -JNIEXPORT void JNICALL Java_sun_lwawt_macosx_LWCToolkit_doAWTRunLoop -(JNIEnv *env, jclass clz, jlong mediator, jboolean processEvents) +JNIEXPORT void JNICALL Java_sun_lwawt_macosx_LWCToolkit_doAWTRunLoopImpl +(JNIEnv *env, jclass clz, jlong mediator, jboolean processEvents, jboolean inAWT) { AWT_ASSERT_APPKIT_THREAD; JNF_COCOA_ENTER(env); @@ -311,7 +311,7 @@ JNF_COCOA_ENTER(env); // Don't use acceptInputForMode because that doesn't setup autorelease pools properly BOOL isRunning = true; while (![mediatorObject shouldEndRunLoop] && isRunning) { - isRunning = [[NSRunLoop currentRunLoop] runMode:[JNFRunLoop javaRunLoopMode] + isRunning = [[NSRunLoop currentRunLoop] runMode:(inAWT ? [JNFRunLoop javaRunLoopMode] : NSDefaultRunLoopMode) beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.010]]; if (processEvents) { //We do not spin a runloop here as date is nil, so does not matter which mode to use @@ -340,7 +340,6 @@ JNF_COCOA_EXIT(env); JNIEXPORT void JNICALL Java_sun_lwawt_macosx_LWCToolkit_stopAWTRunLoop (JNIEnv *env, jclass clz, jlong mediator) { -AWT_ASSERT_NOT_APPKIT_THREAD; JNF_COCOA_ENTER(env); AWTRunLoopObject* mediatorObject = (AWTRunLoopObject*)jlong_to_ptr(mediator); diff --git a/jdk/src/share/classes/java/awt/EventQueue.java b/jdk/src/share/classes/java/awt/EventQueue.java index 5795c37ae91..bf7c426a426 100644 --- a/jdk/src/share/classes/java/awt/EventQueue.java +++ b/jdk/src/share/classes/java/awt/EventQueue.java @@ -37,16 +37,10 @@ import java.security.PrivilegedAction; import java.util.EmptyStackException; +import sun.awt.*; import sun.awt.dnd.SunDropTargetEvent; import sun.util.logging.PlatformLogger; -import sun.awt.AppContext; -import sun.awt.AWTAutoShutdown; -import sun.awt.PeerEvent; -import sun.awt.SunToolkit; -import sun.awt.EventQueueItem; -import sun.awt.AWTAccessor; - import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.atomic.AtomicInteger; @@ -181,6 +175,8 @@ public class EventQueue { private final String name = "AWT-EventQueue-" + threadInitNumber.getAndIncrement(); + private FwDispatcher fwDispatcher; + private static final PlatformLogger eventLog = PlatformLogger.getLogger("java.awt.event.EventQueue"); static { @@ -209,6 +205,10 @@ public class EventQueue { { EventQueue.invokeAndWait(source, r); } + public void setFwDispatcher(EventQueue eventQueue, + FwDispatcher dispatcher) { + eventQueue.setFwDispatcher(dispatcher); + } }); } @@ -684,7 +684,16 @@ public class EventQueue { final Object src = event.getSource(); final PrivilegedAction action = new PrivilegedAction() { public Void run() { - dispatchEventImpl(event, src); + if (fwDispatcher == null) { + dispatchEventImpl(event, src); + } else { + fwDispatcher.scheduleDispatch(new Runnable() { + @Override + public void run() { + dispatchEventImpl(event, src); + } + }); + } return null; } }; @@ -844,7 +853,9 @@ public class EventQueue { while (topQueue.nextQueue != null) { topQueue = topQueue.nextQueue; } - + if (topQueue.fwDispatcher != null) { + throw new RuntimeException("push() to queue with fwDispatcher"); + } if ((topQueue.dispatchThread != null) && (topQueue.dispatchThread.getEventQueue() == this)) { @@ -975,6 +986,9 @@ public class EventQueue { // Forward the request to the top of EventQueue stack return nextQueue.createSecondaryLoop(cond, filter, interval); } + if (fwDispatcher != null) { + return fwDispatcher.createSecondaryLoop(); + } if (dispatchThread == null) { initDispatchThread(); } @@ -1018,6 +1032,9 @@ public class EventQueue { eq = next; next = eq.nextQueue; } + if (eq.fwDispatcher != null) { + return eq.fwDispatcher.isDispatchThread(); + } return (Thread.currentThread() == eq.dispatchThread); } finally { pushPopLock.unlock(); @@ -1303,6 +1320,15 @@ public class EventQueue { pushPopLock.unlock(); } } + + // The method is used by AWTAccessor for javafx/AWT single threaded mode. + private void setFwDispatcher(FwDispatcher dispatcher) { + if (nextQueue != null) { + nextQueue.setFwDispatcher(dispatcher); + } else { + fwDispatcher = dispatcher; + } + } } /** diff --git a/jdk/src/share/classes/sun/awt/AWTAccessor.java b/jdk/src/share/classes/sun/awt/AWTAccessor.java index 1907ac4c7c1..781750b0f1c 100644 --- a/jdk/src/share/classes/sun/awt/AWTAccessor.java +++ b/jdk/src/share/classes/sun/awt/AWTAccessor.java @@ -484,6 +484,11 @@ public final class AWTAccessor { */ void invokeAndWait(Object source, Runnable r) throws InterruptedException, InvocationTargetException; + + /** + * Sets the delegate for the EventQueue used by FX/AWT single threaded mode + */ + public void setFwDispatcher(EventQueue eventQueue, FwDispatcher dispatcher); } /* diff --git a/jdk/src/share/classes/sun/awt/FwDispatcher.java b/jdk/src/share/classes/sun/awt/FwDispatcher.java new file mode 100644 index 00000000000..8ceb67e05b1 --- /dev/null +++ b/jdk/src/share/classes/sun/awt/FwDispatcher.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 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 sun.awt; + +import java.awt.*; + +/** + * An interface for the EventQueue delegate. + * This class is added to support JavaFX/AWT interop single threaded mode + * The delegate should be set in EventQueue by {@link EventQueue#setFwDispatcher(FwDispatcher)} + * If the delegate is not null, than it handles supported methods instead of the + * event queue. If it is null than the behaviour of an event queue does not change. + * + * @see EventQueue + * + * @author Petr Pchelko + * + * @since 1.8 + */ +public interface FwDispatcher { + /** + * Delegates the {@link EventQueue#isDispatchThread()} method + */ + boolean isDispatchThread(); + + /** + * Forwards a runnable to the delegate, which executes it on an appropriate thread. + * @param r - a runnable calling {@link EventQueue#dispatchEventImpl(java.awt.AWTEvent, Object)} + */ + void scheduleDispatch(Runnable r); + + /** + * Delegates the {@link java.awt.EventQueue#createSecondaryLoop()} method + */ + SecondaryLoop createSecondaryLoop(); +}