< 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 >