20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package java.awt;
27
28 import java.awt.event.*;
29
30 import java.awt.peer.ComponentPeer;
31
32 import java.lang.ref.WeakReference;
33 import java.lang.reflect.InvocationTargetException;
34
35 import java.security.AccessController;
36 import java.security.PrivilegedAction;
37
38 import java.util.EmptyStackException;
39
40 import sun.awt.dnd.SunDropTargetEvent;
41 import sun.util.logging.PlatformLogger;
42
43 import sun.awt.AppContext;
44 import sun.awt.AWTAutoShutdown;
45 import sun.awt.PeerEvent;
46 import sun.awt.SunToolkit;
47 import sun.awt.EventQueueItem;
48 import sun.awt.AWTAccessor;
49
50 import java.util.concurrent.locks.Condition;
51 import java.util.concurrent.locks.Lock;
52 import java.util.concurrent.atomic.AtomicInteger;
53
54 import java.security.AccessControlContext;
55
56 import sun.misc.SharedSecrets;
57 import sun.misc.JavaSecurityAccess;
58
59 /**
60 * <code>EventQueue</code> is a platform-independent class
61 * that queues events, both from the underlying peer classes
62 * and from trusted application classes.
63 * <p>
64 * It encapsulates asynchronous event dispatch machinery which
65 * extracts events from the queue and dispatches them by calling
66 * {@link #dispatchEvent(AWTEvent) dispatchEvent(AWTEvent)} method
67 * on this <code>EventQueue</code> with the event to be dispatched
68 * as an argument. The particular behavior of this machinery is
69 * implementation-dependent. The only requirements are that events
164
165 /*
166 * The time stamp of the last KeyEvent .
167 */
168 private long mostRecentKeyEventTime = System.currentTimeMillis();
169
170 /**
171 * The modifiers field of the current event, if the current event is an
172 * InputEvent or ActionEvent.
173 */
174 private WeakReference<AWTEvent> currentEvent;
175
176 /*
177 * Non-zero if a thread is waiting in getNextEvent(int) for an event of
178 * a particular ID to be posted to the queue.
179 */
180 private volatile int waitForID;
181
182 private final String name = "AWT-EventQueue-" + threadInitNumber.getAndIncrement();
183
184 private static final PlatformLogger eventLog = PlatformLogger.getLogger("java.awt.event.EventQueue");
185
186 static {
187 AWTAccessor.setEventQueueAccessor(
188 new AWTAccessor.EventQueueAccessor() {
189 public Thread getDispatchThread(EventQueue eventQueue) {
190 return eventQueue.getDispatchThread();
191 }
192 public boolean isDispatchThreadImpl(EventQueue eventQueue) {
193 return eventQueue.isDispatchThreadImpl();
194 }
195 public void removeSourceEvents(EventQueue eventQueue,
196 Object source,
197 boolean removeAllEvents)
198 {
199 eventQueue.removeSourceEvents(source, removeAllEvents);
200 }
201 public boolean noEvents(EventQueue eventQueue) {
202 return eventQueue.noEvents();
203 }
204 public void wakeup(EventQueue eventQueue, boolean isShutdown) {
205 eventQueue.wakeup(isShutdown);
206 }
207 public void invokeAndWait(Object source, Runnable r)
208 throws InterruptedException, InvocationTargetException
209 {
210 EventQueue.invokeAndWait(source, r);
211 }
212 });
213 }
214
215 public EventQueue() {
216 for (int i = 0; i < NUM_PRIORITIES; i++) {
217 queues[i] = new Queue();
218 }
219 /*
220 * NOTE: if you ever have to start the associated event dispatch
221 * thread at this point, be aware of the following problem:
222 * If this EventQueue instance is created in
223 * SunToolkit.createNewAppContext() the started dispatch thread
224 * may call AppContext.getAppContext() before createNewAppContext()
225 * completes thus causing mess in thread group to appcontext mapping.
226 */
227
228 pushPopLock = (Lock)AppContext.getAppContext().get(AppContext.EVENT_QUEUE_LOCK_KEY);
229 pushPopCond = (Condition)AppContext.getAppContext().get(AppContext.EVENT_QUEUE_COND_KEY);
230 }
231
667 * <td>Other</td>
668 * <td>MenuComponent</td>
669 * <td>source.dispatchEvent(AWTEvent)</td>
670 * </tr>
671 * <tr>
672 * <td>Other</td>
673 * <td>Other</td>
674 * <td>No action (ignored)</td>
675 * </tr>
676 * </table>
677 * <p> </p>
678 * @param event an instance of <code>java.awt.AWTEvent</code>,
679 * or a subclass of it
680 * @throws NullPointerException if <code>event</code> is <code>null</code>
681 * @since 1.2
682 */
683 protected void dispatchEvent(final AWTEvent event) {
684 final Object src = event.getSource();
685 final PrivilegedAction<Void> action = new PrivilegedAction<Void>() {
686 public Void run() {
687 dispatchEventImpl(event, src);
688 return null;
689 }
690 };
691
692 final AccessControlContext stack = AccessController.getContext();
693 final AccessControlContext srcAcc = getAccessControlContextFrom(src);
694 final AccessControlContext eventAcc = event.getAccessControlContext();
695 if (srcAcc == null) {
696 javaSecurityAccess.doIntersectionPrivilege(action, stack, eventAcc);
697 } else {
698 javaSecurityAccess.doIntersectionPrivilege(
699 new PrivilegedAction<Void>() {
700 public Void run() {
701 javaSecurityAccess.doIntersectionPrivilege(action, eventAcc);
702 return null;
703 }
704 }, stack, srcAcc);
705 }
706 }
707
827 * Any pending events are transferred to the new <code>EventQueue</code>
828 * for processing by it.
829 *
830 * @param newEventQueue an <code>EventQueue</code>
831 * (or subclass thereof) instance to be use
832 * @see java.awt.EventQueue#pop
833 * @throws NullPointerException if <code>newEventQueue</code> is <code>null</code>
834 * @since 1.2
835 */
836 public void push(EventQueue newEventQueue) {
837 if (eventLog.isLoggable(PlatformLogger.FINE)) {
838 eventLog.fine("EventQueue.push(" + newEventQueue + ")");
839 }
840
841 pushPopLock.lock();
842 try {
843 EventQueue topQueue = this;
844 while (topQueue.nextQueue != null) {
845 topQueue = topQueue.nextQueue;
846 }
847
848 if ((topQueue.dispatchThread != null) &&
849 (topQueue.dispatchThread.getEventQueue() == this))
850 {
851 newEventQueue.dispatchThread = topQueue.dispatchThread;
852 topQueue.dispatchThread.setEventQueue(newEventQueue);
853 }
854
855 // Transfer all events forward to new EventQueue.
856 while (topQueue.peekEvent() != null) {
857 try {
858 // Use getNextEventPrivate() as it doesn't call flushPendingEvents()
859 newEventQueue.postEventPrivate(topQueue.getNextEventPrivate());
860 } catch (InterruptedException ie) {
861 if (eventLog.isLoggable(PlatformLogger.FINE)) {
862 eventLog.fine("Interrupted push", ie);
863 }
864 }
865 }
866
867 // Wake up EDT waiting in getNextEvent(), so it can
958 * @return secondaryLoop A new secondary loop object, which can
959 * be used to launch a new nested event
960 * loop and dispatch events from this queue
961 *
962 * @see SecondaryLoop#enter
963 * @see SecondaryLoop#exit
964 *
965 * @since 1.7
966 */
967 public SecondaryLoop createSecondaryLoop() {
968 return createSecondaryLoop(null, null, 0);
969 }
970
971 SecondaryLoop createSecondaryLoop(Conditional cond, EventFilter filter, long interval) {
972 pushPopLock.lock();
973 try {
974 if (nextQueue != null) {
975 // Forward the request to the top of EventQueue stack
976 return nextQueue.createSecondaryLoop(cond, filter, interval);
977 }
978 if (dispatchThread == null) {
979 initDispatchThread();
980 }
981 return new WaitDispatchSupport(dispatchThread, cond, filter, interval);
982 } finally {
983 pushPopLock.unlock();
984 }
985 }
986
987 /**
988 * Returns true if the calling thread is
989 * {@link Toolkit#getSystemEventQueue the current AWT EventQueue}'s
990 * dispatch thread. Use this method to ensure that a particular
991 * task is being executed (or not being) there.
992 * <p>
993 * Note: use the {@link #invokeLater} or {@link #invokeAndWait}
994 * methods to execute a task in
995 * {@link Toolkit#getSystemEventQueue the current AWT EventQueue}'s
996 * dispatch thread.
997 * <p>
1001 * dispatch thread
1002 * @see #invokeLater
1003 * @see #invokeAndWait
1004 * @see Toolkit#getSystemEventQueue
1005 * @since 1.2
1006 */
1007 public static boolean isDispatchThread() {
1008 EventQueue eq = Toolkit.getEventQueue();
1009 return eq.isDispatchThreadImpl();
1010 }
1011
1012 final boolean isDispatchThreadImpl() {
1013 EventQueue eq = this;
1014 pushPopLock.lock();
1015 try {
1016 EventQueue next = eq.nextQueue;
1017 while (next != null) {
1018 eq = next;
1019 next = eq.nextQueue;
1020 }
1021 return (Thread.currentThread() == eq.dispatchThread);
1022 } finally {
1023 pushPopLock.unlock();
1024 }
1025 }
1026
1027 final void initDispatchThread() {
1028 pushPopLock.lock();
1029 try {
1030 AppContext appContext = AppContext.getAppContext();
1031 if (dispatchThread == null && !threadGroup.isDestroyed() && !appContext.isDisposed()) {
1032 dispatchThread = AccessController.doPrivileged(
1033 new PrivilegedAction<EventDispatchThread>() {
1034 public EventDispatchThread run() {
1035 EventDispatchThread t =
1036 new EventDispatchThread(threadGroup,
1037 name,
1038 EventQueue.this);
1039 t.setContextClassLoader(classLoader);
1040 t.setPriority(Thread.NORM_PRIORITY + 1);
1286 * Called from PostEventQueue.postEvent to notify that a new event
1287 * appeared. First it proceeds to the EventQueue on the top of the
1288 * stack, then notifies the associated dispatch thread if it exists
1289 * or starts a new one otherwise.
1290 */
1291 private void wakeup(boolean isShutdown) {
1292 pushPopLock.lock();
1293 try {
1294 if (nextQueue != null) {
1295 // Forward call to the top of EventQueue stack.
1296 nextQueue.wakeup(isShutdown);
1297 } else if (dispatchThread != null) {
1298 pushPopCond.signalAll();
1299 } else if (!isShutdown) {
1300 initDispatchThread();
1301 }
1302 } finally {
1303 pushPopLock.unlock();
1304 }
1305 }
1306 }
1307
1308 /**
1309 * The Queue object holds pointers to the beginning and end of one internal
1310 * queue. An EventQueue object is composed of multiple internal Queues, one
1311 * for each priority supported by the EventQueue. All Events on a particular
1312 * internal Queue have identical priority.
1313 */
1314 class Queue {
1315 EventQueueItem head;
1316 EventQueueItem tail;
1317 }
|
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package java.awt;
27
28 import java.awt.event.*;
29
30 import java.awt.peer.ComponentPeer;
31
32 import java.lang.ref.WeakReference;
33 import java.lang.reflect.InvocationTargetException;
34
35 import java.security.AccessController;
36 import java.security.PrivilegedAction;
37
38 import java.util.EmptyStackException;
39
40 import sun.awt.*;
41 import sun.awt.dnd.SunDropTargetEvent;
42 import sun.util.logging.PlatformLogger;
43
44 import java.util.concurrent.locks.Condition;
45 import java.util.concurrent.locks.Lock;
46 import java.util.concurrent.atomic.AtomicInteger;
47
48 import java.security.AccessControlContext;
49
50 import sun.misc.SharedSecrets;
51 import sun.misc.JavaSecurityAccess;
52
53 /**
54 * <code>EventQueue</code> is a platform-independent class
55 * that queues events, both from the underlying peer classes
56 * and from trusted application classes.
57 * <p>
58 * It encapsulates asynchronous event dispatch machinery which
59 * extracts events from the queue and dispatches them by calling
60 * {@link #dispatchEvent(AWTEvent) dispatchEvent(AWTEvent)} method
61 * on this <code>EventQueue</code> with the event to be dispatched
62 * as an argument. The particular behavior of this machinery is
63 * implementation-dependent. The only requirements are that events
158
159 /*
160 * The time stamp of the last KeyEvent .
161 */
162 private long mostRecentKeyEventTime = System.currentTimeMillis();
163
164 /**
165 * The modifiers field of the current event, if the current event is an
166 * InputEvent or ActionEvent.
167 */
168 private WeakReference<AWTEvent> currentEvent;
169
170 /*
171 * Non-zero if a thread is waiting in getNextEvent(int) for an event of
172 * a particular ID to be posted to the queue.
173 */
174 private volatile int waitForID;
175
176 private final String name = "AWT-EventQueue-" + threadInitNumber.getAndIncrement();
177
178 private FwDispatcher fwDispatcher;
179
180 private static final PlatformLogger eventLog = PlatformLogger.getLogger("java.awt.event.EventQueue");
181
182 static {
183 AWTAccessor.setEventQueueAccessor(
184 new AWTAccessor.EventQueueAccessor() {
185 public Thread getDispatchThread(EventQueue eventQueue) {
186 return eventQueue.getDispatchThread();
187 }
188 public boolean isDispatchThreadImpl(EventQueue eventQueue) {
189 return eventQueue.isDispatchThreadImpl();
190 }
191 public void removeSourceEvents(EventQueue eventQueue,
192 Object source,
193 boolean removeAllEvents)
194 {
195 eventQueue.removeSourceEvents(source, removeAllEvents);
196 }
197 public boolean noEvents(EventQueue eventQueue) {
198 return eventQueue.noEvents();
199 }
200 public void wakeup(EventQueue eventQueue, boolean isShutdown) {
201 eventQueue.wakeup(isShutdown);
202 }
203 public void invokeAndWait(Object source, Runnable r)
204 throws InterruptedException, InvocationTargetException
205 {
206 EventQueue.invokeAndWait(source, r);
207 }
208 public void setFwDispatcher(EventQueue eventQueue,
209 FwDispatcher dispatcher) {
210 eventQueue.setFwDispatcher(dispatcher);
211 }
212 });
213 }
214
215 public EventQueue() {
216 for (int i = 0; i < NUM_PRIORITIES; i++) {
217 queues[i] = new Queue();
218 }
219 /*
220 * NOTE: if you ever have to start the associated event dispatch
221 * thread at this point, be aware of the following problem:
222 * If this EventQueue instance is created in
223 * SunToolkit.createNewAppContext() the started dispatch thread
224 * may call AppContext.getAppContext() before createNewAppContext()
225 * completes thus causing mess in thread group to appcontext mapping.
226 */
227
228 pushPopLock = (Lock)AppContext.getAppContext().get(AppContext.EVENT_QUEUE_LOCK_KEY);
229 pushPopCond = (Condition)AppContext.getAppContext().get(AppContext.EVENT_QUEUE_COND_KEY);
230 }
231
667 * <td>Other</td>
668 * <td>MenuComponent</td>
669 * <td>source.dispatchEvent(AWTEvent)</td>
670 * </tr>
671 * <tr>
672 * <td>Other</td>
673 * <td>Other</td>
674 * <td>No action (ignored)</td>
675 * </tr>
676 * </table>
677 * <p> </p>
678 * @param event an instance of <code>java.awt.AWTEvent</code>,
679 * or a subclass of it
680 * @throws NullPointerException if <code>event</code> is <code>null</code>
681 * @since 1.2
682 */
683 protected void dispatchEvent(final AWTEvent event) {
684 final Object src = event.getSource();
685 final PrivilegedAction<Void> action = new PrivilegedAction<Void>() {
686 public Void run() {
687 if (fwDispatcher == null) {
688 dispatchEventImpl(event, src);
689 } else {
690 fwDispatcher.scheduleDispatch(new Runnable() {
691 @Override
692 public void run() {
693 dispatchEventImpl(event, src);
694 }
695 });
696 }
697 return null;
698 }
699 };
700
701 final AccessControlContext stack = AccessController.getContext();
702 final AccessControlContext srcAcc = getAccessControlContextFrom(src);
703 final AccessControlContext eventAcc = event.getAccessControlContext();
704 if (srcAcc == null) {
705 javaSecurityAccess.doIntersectionPrivilege(action, stack, eventAcc);
706 } else {
707 javaSecurityAccess.doIntersectionPrivilege(
708 new PrivilegedAction<Void>() {
709 public Void run() {
710 javaSecurityAccess.doIntersectionPrivilege(action, eventAcc);
711 return null;
712 }
713 }, stack, srcAcc);
714 }
715 }
716
836 * Any pending events are transferred to the new <code>EventQueue</code>
837 * for processing by it.
838 *
839 * @param newEventQueue an <code>EventQueue</code>
840 * (or subclass thereof) instance to be use
841 * @see java.awt.EventQueue#pop
842 * @throws NullPointerException if <code>newEventQueue</code> is <code>null</code>
843 * @since 1.2
844 */
845 public void push(EventQueue newEventQueue) {
846 if (eventLog.isLoggable(PlatformLogger.FINE)) {
847 eventLog.fine("EventQueue.push(" + newEventQueue + ")");
848 }
849
850 pushPopLock.lock();
851 try {
852 EventQueue topQueue = this;
853 while (topQueue.nextQueue != null) {
854 topQueue = topQueue.nextQueue;
855 }
856 if (topQueue.fwDispatcher != null) {
857 throw new RuntimeException("push() to queue with fwDispatcher");
858 }
859 if ((topQueue.dispatchThread != null) &&
860 (topQueue.dispatchThread.getEventQueue() == this))
861 {
862 newEventQueue.dispatchThread = topQueue.dispatchThread;
863 topQueue.dispatchThread.setEventQueue(newEventQueue);
864 }
865
866 // Transfer all events forward to new EventQueue.
867 while (topQueue.peekEvent() != null) {
868 try {
869 // Use getNextEventPrivate() as it doesn't call flushPendingEvents()
870 newEventQueue.postEventPrivate(topQueue.getNextEventPrivate());
871 } catch (InterruptedException ie) {
872 if (eventLog.isLoggable(PlatformLogger.FINE)) {
873 eventLog.fine("Interrupted push", ie);
874 }
875 }
876 }
877
878 // Wake up EDT waiting in getNextEvent(), so it can
969 * @return secondaryLoop A new secondary loop object, which can
970 * be used to launch a new nested event
971 * loop and dispatch events from this queue
972 *
973 * @see SecondaryLoop#enter
974 * @see SecondaryLoop#exit
975 *
976 * @since 1.7
977 */
978 public SecondaryLoop createSecondaryLoop() {
979 return createSecondaryLoop(null, null, 0);
980 }
981
982 SecondaryLoop createSecondaryLoop(Conditional cond, EventFilter filter, long interval) {
983 pushPopLock.lock();
984 try {
985 if (nextQueue != null) {
986 // Forward the request to the top of EventQueue stack
987 return nextQueue.createSecondaryLoop(cond, filter, interval);
988 }
989 if (fwDispatcher != null) {
990 return fwDispatcher.createSecondaryLoop();
991 }
992 if (dispatchThread == null) {
993 initDispatchThread();
994 }
995 return new WaitDispatchSupport(dispatchThread, cond, filter, interval);
996 } finally {
997 pushPopLock.unlock();
998 }
999 }
1000
1001 /**
1002 * Returns true if the calling thread is
1003 * {@link Toolkit#getSystemEventQueue the current AWT EventQueue}'s
1004 * dispatch thread. Use this method to ensure that a particular
1005 * task is being executed (or not being) there.
1006 * <p>
1007 * Note: use the {@link #invokeLater} or {@link #invokeAndWait}
1008 * methods to execute a task in
1009 * {@link Toolkit#getSystemEventQueue the current AWT EventQueue}'s
1010 * dispatch thread.
1011 * <p>
1015 * dispatch thread
1016 * @see #invokeLater
1017 * @see #invokeAndWait
1018 * @see Toolkit#getSystemEventQueue
1019 * @since 1.2
1020 */
1021 public static boolean isDispatchThread() {
1022 EventQueue eq = Toolkit.getEventQueue();
1023 return eq.isDispatchThreadImpl();
1024 }
1025
1026 final boolean isDispatchThreadImpl() {
1027 EventQueue eq = this;
1028 pushPopLock.lock();
1029 try {
1030 EventQueue next = eq.nextQueue;
1031 while (next != null) {
1032 eq = next;
1033 next = eq.nextQueue;
1034 }
1035 if (eq.fwDispatcher != null) {
1036 return eq.fwDispatcher.isDispatchThread();
1037 }
1038 return (Thread.currentThread() == eq.dispatchThread);
1039 } finally {
1040 pushPopLock.unlock();
1041 }
1042 }
1043
1044 final void initDispatchThread() {
1045 pushPopLock.lock();
1046 try {
1047 AppContext appContext = AppContext.getAppContext();
1048 if (dispatchThread == null && !threadGroup.isDestroyed() && !appContext.isDisposed()) {
1049 dispatchThread = AccessController.doPrivileged(
1050 new PrivilegedAction<EventDispatchThread>() {
1051 public EventDispatchThread run() {
1052 EventDispatchThread t =
1053 new EventDispatchThread(threadGroup,
1054 name,
1055 EventQueue.this);
1056 t.setContextClassLoader(classLoader);
1057 t.setPriority(Thread.NORM_PRIORITY + 1);
1303 * Called from PostEventQueue.postEvent to notify that a new event
1304 * appeared. First it proceeds to the EventQueue on the top of the
1305 * stack, then notifies the associated dispatch thread if it exists
1306 * or starts a new one otherwise.
1307 */
1308 private void wakeup(boolean isShutdown) {
1309 pushPopLock.lock();
1310 try {
1311 if (nextQueue != null) {
1312 // Forward call to the top of EventQueue stack.
1313 nextQueue.wakeup(isShutdown);
1314 } else if (dispatchThread != null) {
1315 pushPopCond.signalAll();
1316 } else if (!isShutdown) {
1317 initDispatchThread();
1318 }
1319 } finally {
1320 pushPopLock.unlock();
1321 }
1322 }
1323
1324 // The method is used by AWTAccessor for javafx/AWT single threaded mode.
1325 private void setFwDispatcher(FwDispatcher dispatcher) {
1326 if (nextQueue != null) {
1327 nextQueue.setFwDispatcher(dispatcher);
1328 } else {
1329 fwDispatcher = dispatcher;
1330 }
1331 }
1332 }
1333
1334 /**
1335 * The Queue object holds pointers to the beginning and end of one internal
1336 * queue. An EventQueue object is composed of multiple internal Queues, one
1337 * for each priority supported by the EventQueue. All Events on a particular
1338 * internal Queue have identical priority.
1339 */
1340 class Queue {
1341 EventQueueItem head;
1342 EventQueueItem tail;
1343 }
|