--- old/src/java.desktop/share/classes/java/awt/SequencedEvent.java 2017-09-23 12:29:46.209565600 +0530 +++ new/src/java.desktop/share/classes/java/awt/SequencedEvent.java 2017-09-23 12:29:45.146928400 +0530 @@ -25,6 +25,8 @@ package java.awt; +import java.security.AccessController; +import java.security.PrivilegedAction; import java.util.LinkedList; import sun.awt.AWTAccessor; import sun.awt.AppContext; @@ -55,6 +57,8 @@ private AppContext appContext; private boolean disposed; + private static boolean fxAppThreadIsDispatchThread; + private Thread fxCheckSequenceThread; static { AWTAccessor.setSequencedEventAccessor(new AWTAccessor.SequencedEventAccessor() { public AWTEvent getNested(AWTEvent sequencedEvent) { @@ -68,6 +72,13 @@ return new SequencedEvent(event); } }); + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + fxAppThreadIsDispatchThread = + "true".equals(System.getProperty("javafx.embed.singleThread")); + return null; + } + }); } /** @@ -83,6 +94,21 @@ // All AWTEvents that are wrapped in SequencedEvents are (at // least currently) implicitly generated by the system SunToolkit.setSystemGenerated(nested); + + if (fxAppThreadIsDispatchThread) { + fxCheckSequenceThread = new Thread() { + @Override + public void run() { + while(!isFirstOrDisposed()) { + try { + Thread.sleep(100); + } catch (InterruptedException e) { + break; + } + } + } + }; + } synchronized (SequencedEvent.class) { list.add(this); } @@ -106,13 +132,29 @@ if (getFirst() != this) { if (EventQueue.isDispatchThread()) { - EventDispatchThread edt = (EventDispatchThread) - Thread.currentThread(); - edt.pumpEvents(SentEvent.ID, new Conditional() { - public boolean evaluate() { - return !SequencedEvent.this.isFirstOrDisposed(); + if (Thread.currentThread() instanceof EventDispatchThread) { + EventDispatchThread edt = (EventDispatchThread) + Thread.currentThread(); + edt.pumpEvents(SentEvent.ID, new Conditional() { + public boolean evaluate() { + return !SequencedEvent.this.isFirstOrDisposed(); + } + }); + } else { + if (fxAppThreadIsDispatchThread) { + fxCheckSequenceThread.start(); + try { + // check if event is dispatched or disposed + // but since this user app thread is same as + // dispatch thread in fx when run with + // javafx.embed.singleThread=true + // we do not wait infinitely to avoid deadlock + // as dispatch will ultimately be done by this thread + fxCheckSequenceThread.join(500); + } catch (InterruptedException e) { + } } - }); + } } else { while(!isFirstOrDisposed()) { synchronized (SequencedEvent.class) { --- old/src/java.desktop/share/classes/java/awt/DefaultKeyboardFocusManager.java 2017-09-23 12:29:53.071270100 +0530 +++ new/src/java.desktop/share/classes/java/awt/DefaultKeyboardFocusManager.java 2017-09-23 12:29:51.889731100 +0530 @@ -30,6 +30,8 @@ import java.awt.peer.ComponentPeer; import java.awt.peer.LightweightPeer; import java.lang.ref.WeakReference; +import java.security.AccessController; +import java.security.PrivilegedAction; import java.util.LinkedList; import java.util.Iterator; import java.util.ListIterator; @@ -77,6 +79,8 @@ private boolean consumeNextKeyTyped; private Component restoreFocusTo; + private static boolean fxAppThreadIsDispatchThread; + static { AWTAccessor.setDefaultKeyboardFocusManagerAccessor( new AWTAccessor.DefaultKeyboardFocusManagerAccessor() { @@ -84,6 +88,13 @@ dkfm.consumeNextKeyTyped(e); } }); + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + fxAppThreadIsDispatchThread = + "true".equals(System.getProperty("javafx.embed.singleThread")); + return null; + } + }); } private static class TypeAheadMarker { @@ -264,13 +275,41 @@ } SunToolkit.postEvent(targetAppContext, se); if (EventQueue.isDispatchThread()) { - EventDispatchThread edt = (EventDispatchThread) - Thread.currentThread(); - edt.pumpEvents(SentEvent.ID, new Conditional() { + if (Thread.currentThread() instanceof EventDispatchThread) { + EventDispatchThread edt = (EventDispatchThread) + Thread.currentThread(); + edt.pumpEvents(SentEvent.ID, new Conditional() { public boolean evaluate() { return !se.dispatched && !targetAppContext.isDisposed(); } }); + } else { + if (fxAppThreadIsDispatchThread) { + Thread fxCheckDispatchThread = new Thread() { + @Override + public void run() { + while (!se.dispatched && !targetAppContext.isDisposed()) { + try { + Thread.sleep(100); + } catch (InterruptedException e) { + break; + } + } + } + }; + fxCheckDispatchThread.start(); + try { + // check if event is dispatched or disposed + // but since this user app thread is same as + // dispatch thread in fx when run with + // javafx.embed.singleThread=true + // we do not wait infinitely to avoid deadlock + // as dispatch will ultimately be done by this thread + fxCheckDispatchThread.join(500); + } catch (InterruptedException ex) { + } + } + } } else { synchronized (se) { while (!se.dispatched && !targetAppContext.isDisposed()) {