< prev index next >
src/java.desktop/share/classes/java/awt/SequencedEvent.java
Print this page
rev 51845 : 8204142: AWT hang occurs when sequenced events arrive out of sequence in multiple AppContexts
Summary: Synchronization of SequencedEvent events from different AppContexts fixed
@@ -25,10 +25,11 @@
package java.awt;
import java.security.AccessController;
import java.security.PrivilegedAction;
+import java.util.Iterator;
import java.util.LinkedList;
import sun.awt.AWTAccessor;
import sun.awt.AppContext;
import sun.awt.SunToolkit;
@@ -54,10 +55,11 @@
private static final LinkedList<SequencedEvent> list = new LinkedList<>();
private final AWTEvent nested;
private AppContext appContext;
private boolean disposed;
+ private final LinkedList<AWTEvent> pendingEvents = new LinkedList<>();
private static boolean fxAppThreadIsDispatchThread;
private Thread fxCheckSequenceThread;
static {
AWTAccessor.setSequencedEventAccessor(new AWTAccessor.SequencedEventAccessor() {
@@ -79,10 +81,38 @@
return null;
}
});
}
+ private static final class SequencedEventsFilter implements EventFilter {
+ private final SequencedEvent currentSequencedEvent;
+ private SequencedEventsFilter(SequencedEvent currentSequencedEvent) {
+ this.currentSequencedEvent = currentSequencedEvent;
+ }
+ @Override
+ public FilterAction acceptEvent(AWTEvent ev) {
+ if (ev.getID() == ID) {
+ // Move forward dispatching only if the event is previous
+ // in SequencedEvent.list. Otherwise, hold it for reposting later.
+ synchronized (SequencedEvent.class) {
+ Iterator<SequencedEvent> it = list.iterator();
+ while (it.hasNext()) {
+ SequencedEvent iev = it.next();
+ if (iev.equals(currentSequencedEvent)) {
+ break;
+ } else if (iev.equals(ev)) {
+ return FilterAction.ACCEPT;
+ }
+ }
+ }
+ currentSequencedEvent.pendingEvents.add(ev);
+ return FilterAction.REJECT;
+ }
+ return FilterAction.ACCEPT;
+ }
+ }
+
/**
* Constructs a new SequencedEvent which will dispatch the specified
* nested event.
*
* @param nested the AWTEvent which this SequencedEvent's dispatch()
@@ -133,11 +163,12 @@
if (getFirst() != this) {
if (EventQueue.isDispatchThread()) {
if (Thread.currentThread() instanceof EventDispatchThread) {
EventDispatchThread edt = (EventDispatchThread)
Thread.currentThread();
- edt.pumpEvents(ID, () -> !SequencedEvent.this.isFirstOrDisposed());
+ edt.pumpEventsForFilter(() -> !SequencedEvent.this.isFirstOrDisposed(),
+ new SequencedEventsFilter(this));
} else {
if (fxAppThreadIsDispatchThread) {
fxCheckSequenceThread.start();
try {
// check if event is dispatched or disposed
@@ -237,14 +268,10 @@
KeyboardFocusManager.getCurrentKeyboardFocusManager().
setCurrentSequencedEvent(null);
}
disposed = true;
}
- // Wake myself up
- if (appContext != null) {
- SunToolkit.postEvent(appContext, new SentEvent());
- }
SequencedEvent next = null;
synchronized (SequencedEvent.class) {
SequencedEvent.class.notifyAll();
@@ -261,7 +288,11 @@
}
// Wake up waiting threads
if (next != null && next.appContext != null) {
SunToolkit.postEvent(next.appContext, new SentEvent());
}
+
+ for(AWTEvent e : pendingEvents) {
+ SunToolkit.postEvent(appContext, e);
+ }
}
}
< prev index next >