< 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,34 ****
--- 25,35 ----
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,63 ****
--- 55,65 ----
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,88 ****
--- 81,118 ----
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,143 ****
if (getFirst() != this) {
if (EventQueue.isDispatchThread()) {
if (Thread.currentThread() instanceof EventDispatchThread) {
EventDispatchThread edt = (EventDispatchThread)
Thread.currentThread();
! edt.pumpEvents(ID, () -> !SequencedEvent.this.isFirstOrDisposed());
} else {
if (fxAppThreadIsDispatchThread) {
fxCheckSequenceThread.start();
try {
// check if event is dispatched or disposed
--- 163,174 ----
if (getFirst() != this) {
if (EventQueue.isDispatchThread()) {
if (Thread.currentThread() instanceof EventDispatchThread) {
EventDispatchThread edt = (EventDispatchThread)
Thread.currentThread();
! edt.pumpEventsForFilter(() -> !SequencedEvent.this.isFirstOrDisposed(),
! new SequencedEventsFilter(this));
} else {
if (fxAppThreadIsDispatchThread) {
fxCheckSequenceThread.start();
try {
// check if event is dispatched or disposed
*** 237,250 ****
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();
--- 268,277 ----
*** 261,267 ****
--- 288,298 ----
}
// 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 >