< prev index next >
src/java.desktop/share/classes/java/awt/SequencedEvent.java
Print this page
@@ -1,7 +1,7 @@
/*
- * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2018, 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
@@ -25,11 +25,13 @@
package java.awt;
import java.security.AccessController;
import java.security.PrivilegedAction;
+import java.util.ArrayList;
import java.util.LinkedList;
+
import sun.awt.AWTAccessor;
import sun.awt.AppContext;
import sun.awt.SunToolkit;
/**
@@ -51,13 +53,15 @@
private static final int ID =
java.awt.event.FocusEvent.FOCUS_LAST + 1;
private static final LinkedList<SequencedEvent> list = new LinkedList<>();
+ private static final Object SEQUENCED_EVENT_KEY = new Object();
+
private final AWTEvent nested;
- private AppContext appContext;
- private boolean disposed;
+ private volatile AppContext appContext;
+ private volatile boolean disposed;
private static boolean fxAppThreadIsDispatchThread;
private Thread fxCheckSequenceThread;
static {
AWTAccessor.setSequencedEventAccessor(new AWTAccessor.SequencedEventAccessor() {
@@ -131,10 +135,12 @@
appContext = AppContext.getAppContext();
if (getFirst() != this) {
if (EventQueue.isDispatchThread()) {
if (Thread.currentThread() instanceof EventDispatchThread) {
+ getWaitingEvents().add(this);
+ dispatchWaitingEvents();
EventDispatchThread edt = (EventDispatchThread)
Thread.currentThread();
edt.pumpEvents(ID, () -> !SequencedEvent.this.isFirstOrDisposed());
} else {
if (fxAppThreadIsDispatchThread) {
@@ -173,10 +179,42 @@
dispose();
}
}
/**
+ * Dispatching waiting events if such event became first or disposed.
+ */
+ private static void dispatchWaitingEvents() {
+ ArrayList<SequencedEvent> waitingEvents = getWaitingEvents();
+ for (int i = 0; i < waitingEvents.size(); i++) {
+ SequencedEvent event = waitingEvents.get(i);
+ if (event.isFirstOrDisposed()) {
+ // found the first event, need to dispatch it/recheck the queue
+ waitingEvents.remove(i);
+ if (!event.disposed) {
+ event.dispatch();
+ }
+ i = 0; // start from the beginning
+ }
+ }
+ }
+
+ /**
+ * Returns the list of waiting events per-Appcontext.
+ */
+ @SuppressWarnings("unchecked")
+ private static ArrayList<SequencedEvent> getWaitingEvents() {
+ AppContext appContext = AppContext.getAppContext();
+ Object list = appContext.get(SEQUENCED_EVENT_KEY);
+ if (list == null) {
+ list = new ArrayList<>();
+ appContext.put(SEQUENCED_EVENT_KEY, list);
+ }
+ return (ArrayList<SequencedEvent>) list;
+ }
+
+ /**
* true only if event exists and nested source appContext is disposed.
*/
private static final boolean isOwnerAppContextDisposed(SequencedEvent se) {
if (se != null) {
Object target = se.nested.getSource();
@@ -239,29 +277,52 @@
}
disposed = true;
}
// Wake myself up
if (appContext != null) {
- SunToolkit.postEvent(appContext, new SentEvent());
+ SunToolkit.postEvent(appContext, new Wakeup());
}
SequencedEvent next = null;
synchronized (SequencedEvent.class) {
SequencedEvent.class.notifyAll();
if (list.getFirst() == this) {
list.removeFirst();
-
+ } else {
+ list.remove(this);
+ }
if (!list.isEmpty()) {
next = list.getFirst();
}
+ }
+ // Wake up waiting threads
+ if (next != null) {
+ if (next.appContext != null) {
+ SunToolkit.postEvent(next.appContext, new Wakeup());
} else {
- list.remove(this);
+ // Appcontext of the next event still unknown, try all
+ for (AppContext appContext : AppContext.getAppContexts()) {
+ SunToolkit.postEvent(appContext, new Wakeup());
}
}
- // Wake up waiting threads
- if (next != null && next.appContext != null) {
- SunToolkit.postEvent(next.appContext, new SentEvent());
+ }
+ }
+
+ /**
+ * This event is used to wakeup the EDT if it waiting for a SequencedEvent.
+ */
+ private static final class Wakeup extends AWTEvent implements ActiveEvent {
+
+ private static final long serialVersionUID = -4585374989028949074L;
+
+ Wakeup() {
+ super(new Object(), SequencedEvent.ID);
+ }
+
+ @Override
+ public void dispatch() {
+ dispatchWaitingEvents();
}
}
}
< prev index next >