1. /*
  2. * @(#)EventQueue.java 1.55 01/11/29
  3. *
  4. * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package java.awt;
  8. import java.awt.event.PaintEvent;
  9. import java.awt.event.InvocationEvent;
  10. import java.awt.event.KeyEvent;
  11. import java.awt.event.MouseEvent;
  12. import java.awt.ActiveEvent;
  13. import java.util.EmptyStackException;
  14. import java.lang.reflect.InvocationTargetException;
  15. import sun.awt.MagicEvent;
  16. import sun.awt.SunToolkit;
  17. /**
  18. * EventQueue is a platform-independent class that queues events, both
  19. * from the underlying peer classes and from trusted application classes.
  20. * There is only one EventQueue for each AppContext.
  21. *
  22. * @version 1.55 11/29/01
  23. * @author Thomas Ball
  24. * @author Fred Ecks
  25. * @author David Mendenhall
  26. */
  27. public class EventQueue {
  28. // From Thread.java
  29. private static int threadInitNumber;
  30. private static synchronized int nextThreadNum() {
  31. return threadInitNumber++;
  32. }
  33. private static final int LOW_PRIORITY = 0;
  34. private static final int NORM_PRIORITY = 1;
  35. private static final int HIGH_PRIORITY = 2;
  36. private static final int NUM_PRIORITIES = HIGH_PRIORITY + 1;
  37. /*
  38. * We maintain one Queue for each priority that the EventQueue supports.
  39. * That is, the EventQueue object is actually implemented as
  40. * NUM_PRIORITIES queues and all Events on a particular internal Queue
  41. * have identical priority. Events are pulled off the EventQueue starting
  42. * with the Queue of highest priority. We progress in decreasing order
  43. * across all Queues.
  44. */
  45. private Queue[] queues = new Queue[NUM_PRIORITIES];
  46. /*
  47. * The next EventQueue on the stack, or null if this EventQueue is
  48. * on the top of the stack. If nextQueue is non-null, requests to post
  49. * an event are forwarded to nextQueue.
  50. */
  51. private EventQueue nextQueue;
  52. /*
  53. * The previous EventQueue on the stack, or null if this is the
  54. * "base" EventQueue.
  55. */
  56. private EventQueue previousQueue;
  57. private EventDispatchThread dispatchThread;
  58. /*
  59. * Debugging flag -- set true and recompile to enable checking.
  60. */
  61. private final static boolean debug = false;
  62. public EventQueue() {
  63. for (int i = 0; i < NUM_PRIORITIES; i++) {
  64. queues[i] = new Queue();
  65. }
  66. String name = "AWT-EventQueue-" + nextThreadNum();
  67. dispatchThread = new EventDispatchThread(name, this);
  68. dispatchThread.setPriority(Thread.NORM_PRIORITY + 1);
  69. dispatchThread.start();
  70. }
  71. /**
  72. * Post a 1.1-style event to the EventQueue. If there is an
  73. * existing event on the queue with the same ID and event source,
  74. * the source Component's coalesceEvents method will be called.
  75. *
  76. * @param theEvent an instance of java.awt.AWTEvent, or a
  77. * subclass of it.
  78. */
  79. public void postEvent(AWTEvent theEvent) {
  80. ((SunToolkit)Toolkit.getDefaultToolkit()).flushPendingEvents();
  81. postEventPrivate(theEvent);
  82. }
  83. /**
  84. * Post a 1.1-style event to the EventQueue. If there is an
  85. * existing event on the queue with the same ID and event source,
  86. * the source Component's coalesceEvents method will be called.
  87. *
  88. * @param theEvent an instance of java.awt.AWTEvent, or a
  89. * subclass of it.
  90. */
  91. final void postEventPrivate(AWTEvent theEvent) {
  92. synchronized(this) {
  93. if (nextQueue != null) {
  94. // Forward event to top of EventQueue stack.
  95. nextQueue.postEventPrivate(theEvent);
  96. } else if (theEvent instanceof MagicEvent &&
  97. (((MagicEvent)theEvent).getFlags() &
  98. MagicEvent.PRIORITY_EVENT) != 0) {
  99. postEvent(theEvent, HIGH_PRIORITY);
  100. } else if (theEvent.getID() == PaintEvent.PAINT ||
  101. theEvent.getID() == PaintEvent.UPDATE) {
  102. postEvent(theEvent, LOW_PRIORITY);
  103. } else {
  104. postEvent(theEvent, NORM_PRIORITY);
  105. }
  106. }
  107. }
  108. /**
  109. * Posts the event to the internal Queue of specified priority,
  110. * coalescing as appropriate.
  111. */
  112. private void postEvent(AWTEvent theEvent, int priority) {
  113. EventQueueItem newItem = new EventQueueItem(theEvent);
  114. if (queues[priority].head == null) {
  115. boolean shouldNotify = noEvents();
  116. queues[priority].head = queues[priority].tail = newItem;
  117. if (shouldNotify) {
  118. notifyAll();
  119. }
  120. } else {
  121. Object source = theEvent.getSource();
  122. // For Component source events, traverse the entire list,
  123. // trying to coalesce events
  124. if (source instanceof Component) {
  125. EventQueueItem q = queues[priority].head;
  126. // fix bug 4301264, do not coalesce mouse move/drag events
  127. // across other types of mouse events.
  128. if (theEvent.id == Event.MOUSE_MOVE ||
  129. theEvent.id == Event.MOUSE_DRAG) {
  130. EventQueueItem qm;
  131. for(qm = q; qm != null; qm = qm.next) {
  132. if ((qm.event instanceof MouseEvent) &&
  133. qm.id != theEvent.id) {
  134. q = qm;
  135. }
  136. }
  137. }
  138. for (;;) {
  139. if (q.id == newItem.id && q.source == source) {
  140. AWTEvent coalescedEvent =
  141. ((Component)source).coalesceEvents(q.event,
  142. theEvent);
  143. if (coalescedEvent != null) {
  144. q.event = coalescedEvent;
  145. return;
  146. }
  147. }
  148. if (q.next != null) {
  149. q = q.next;
  150. } else {
  151. break;
  152. }
  153. }
  154. }
  155. // The event was not coalesced or has non-Component source.
  156. // Insert it at the end of the appropriate Queue.
  157. queues[priority].tail.next = newItem;
  158. queues[priority].tail = newItem;
  159. }
  160. }
  161. /**
  162. * @return whether an event is pending on any of the separate Queues
  163. */
  164. private boolean noEvents() {
  165. for (int i = 0; i < NUM_PRIORITIES; i++) {
  166. if (queues[i].head != null) {
  167. return false;
  168. }
  169. }
  170. return true;
  171. }
  172. /**
  173. * Remove an event from the EventQueue and return it. This method will
  174. * block until an event has been posted by another thread.
  175. * @return the next AWTEvent
  176. * @exception InterruptedException
  177. * if another thread has interrupted this thread.
  178. */
  179. public synchronized AWTEvent getNextEvent() throws InterruptedException {
  180. do {
  181. for (int i = NUM_PRIORITIES - 1; i >= 0; i--) {
  182. if (queues[i].head != null) {
  183. EventQueueItem eqi = queues[i].head;
  184. queues[i].head = eqi.next;
  185. if (eqi.next == null) {
  186. queues[i].tail = null;
  187. }
  188. return eqi.event;
  189. }
  190. }
  191. wait();
  192. } while(true);
  193. }
  194. /**
  195. * Return the first event on the EventQueue without removing it.
  196. * @return the first event
  197. */
  198. public synchronized AWTEvent peekEvent() {
  199. for (int i = NUM_PRIORITIES - 1; i >= 0; i--) {
  200. if (queues[i].head != null) {
  201. return queues[i].head.event;
  202. }
  203. }
  204. return null;
  205. }
  206. /**
  207. * Return the first event with the specified id, if any.
  208. * @param id the id of the type of event desired.
  209. * @return the first event of the specified id
  210. */
  211. public synchronized AWTEvent peekEvent(int id) {
  212. for (int i = NUM_PRIORITIES - 1; i >= 0; i--) {
  213. EventQueueItem q = queues[i].head;
  214. for (; q != null; q = q.next) {
  215. if (q.id == id) {
  216. return q.event;
  217. }
  218. }
  219. }
  220. return null;
  221. }
  222. /**
  223. * Dispatch an event. The manner in which the event is
  224. * dispatched depends upon the type of the event and the
  225. * type of the event's source
  226. * object:
  227. * <p> </p>
  228. * <table border>
  229. * <tr>
  230. * <th>Event Type</th>
  231. * <th>Source Type</th>
  232. * <th>Dispatched To</th>
  233. * </tr>
  234. * <tr>
  235. * <td>ActiveEvent</td>
  236. * <td>Any</td>
  237. * <td>event.dispatch()</td>
  238. * </tr>
  239. * <tr>
  240. * <td>Other</td>
  241. * <td>Component</td>
  242. * <td>source.dispatchEvent(AWTEvent)</td>
  243. * </tr>
  244. * <tr>
  245. * <td>Other</td>
  246. * <td>MenuComponent</td>
  247. * <td>source.dispatchEvent(AWTEvent)</td>
  248. * </tr>
  249. * <tr>
  250. * <td>Other</td>
  251. * <td>Other</td>
  252. * <td>No action (ignored)</td>
  253. * </tr>
  254. * </table>
  255. * <p> </p>
  256. * @param theEvent an instance of java.awt.AWTEvent, or a
  257. * subclass of it.
  258. */
  259. protected void dispatchEvent(AWTEvent event) {
  260. Object src = event.getSource();
  261. if (event instanceof ActiveEvent) {
  262. // This could become the sole method of dispatching in time.
  263. ((ActiveEvent)event).dispatch();
  264. } else if (src instanceof Component) {
  265. ((Component)src).dispatchEvent(event);
  266. } else if (src instanceof MenuComponent) {
  267. ((MenuComponent)src).dispatchEvent(event);
  268. } else {
  269. System.err.println("unable to dispatch event: " + event);
  270. }
  271. }
  272. /**
  273. * Replace the existing EventQueue with the specified one.
  274. * Any pending events are transferred to the new EventQueue
  275. * for processing by it.
  276. *
  277. * @param an EventQueue (or subclass thereof) instance to be used.
  278. * @see java.awt.EventQueue#pop
  279. */
  280. public synchronized void push(EventQueue newEventQueue) {
  281. if (debug) {
  282. System.out.println("EventQueue.push(" + newEventQueue + ")");
  283. }
  284. if (nextQueue != null) {
  285. nextQueue.push(newEventQueue);
  286. return;
  287. }
  288. synchronized (newEventQueue) {
  289. // Transfer all events forward to new EventQueue.
  290. while (peekEvent() != null) {
  291. try {
  292. newEventQueue.postEventPrivate(getNextEvent());
  293. } catch (InterruptedException ie) {
  294. if (debug) {
  295. System.err.println("interrupted push:");
  296. ie.printStackTrace(System.err);
  297. }
  298. }
  299. }
  300. newEventQueue.previousQueue = this;
  301. }
  302. nextQueue = newEventQueue;
  303. }
  304. /**
  305. * Stop dispatching events using this EventQueue instance.
  306. * Any pending events are transferred to the previous
  307. * EventQueue for processing by it.
  308. *
  309. * @exception if no previous push was made on this EventQueue.
  310. * @see java.awt.EventQueue#push
  311. */
  312. protected void pop() throws EmptyStackException {
  313. if (debug) {
  314. System.out.println("EventQueue.pop(" + this + ")");
  315. }
  316. // To prevent deadlock, we lock on the previous EventQueue before
  317. // this one. This uses the same locking order as everything else
  318. // in EventQueue.java, so deadlock isn't possible.
  319. EventQueue prev = previousQueue;
  320. synchronized ((prev != null) ? prev : this) {
  321. synchronized(this) {
  322. if (nextQueue != null) {
  323. nextQueue.pop();
  324. return;
  325. }
  326. if (previousQueue == null) {
  327. throw new EmptyStackException();
  328. }
  329. // Transfer all events back to previous EventQueue.
  330. previousQueue.nextQueue = null;
  331. while (peekEvent() != null) {
  332. try {
  333. previousQueue.postEventPrivate(getNextEvent());
  334. } catch (InterruptedException ie) {
  335. if (debug) {
  336. System.err.println("interrupted pop:");
  337. ie.printStackTrace(System.err);
  338. }
  339. }
  340. }
  341. previousQueue = null;
  342. }
  343. }
  344. dispatchThread.stopDispatching(); // Must be done outside synchronized
  345. // block to avoid possible deadlock
  346. }
  347. /**
  348. * Returns true if the calling thread is the current AWT EventQueue's
  349. * dispatch thread. Use this call the ensure that a given
  350. * task is being executed (or not being) on the current AWT
  351. * EventDispatchThread.
  352. *
  353. * @return true if running on the current AWT EventQueue's dispatch thread.
  354. */
  355. public static boolean isDispatchThread() {
  356. EventQueue eq = Toolkit.getEventQueue();
  357. EventQueue next = eq.nextQueue;
  358. while (next != null) {
  359. eq = next;
  360. next = eq.nextQueue;
  361. }
  362. return (Thread.currentThread() == eq.dispatchThread);
  363. }
  364. /*
  365. * Get the EventDispatchThread for this EventQueue.
  366. */
  367. final EventDispatchThread getDispatchThread() {
  368. return dispatchThread;
  369. }
  370. /*
  371. * Change the target of any pending KeyEvents because of a focus change.
  372. */
  373. final synchronized void changeKeyEventFocus(Object newSource) {
  374. for (int i = 0; i < NUM_PRIORITIES; i++) {
  375. EventQueueItem q = queues[i].head;
  376. for (; q != null; q = q.next) {
  377. if (q.event instanceof KeyEvent) {
  378. q.event.setSource(newSource);
  379. }
  380. }
  381. }
  382. }
  383. /*
  384. * Remove any pending events for the specified source object.
  385. * This method is normally called by the source's removeNotify method.
  386. */
  387. final synchronized void removeSourceEvents(Object source) {
  388. for (int i = 0; i < NUM_PRIORITIES; i++) {
  389. EventQueueItem entry = queues[i].head;
  390. EventQueueItem prev = null;
  391. while (entry != null) {
  392. if (entry.source == source) {
  393. if (prev == null) {
  394. queues[i].head = entry.next;
  395. } else {
  396. prev.next = entry.next;
  397. }
  398. } else {
  399. prev = entry;
  400. }
  401. entry = entry.next;
  402. }
  403. queues[i].tail = prev;
  404. }
  405. }
  406. /**
  407. * Causes <i>runnable</i> to have its run() method called in the dispatch
  408. * thread of the EventQueue. This will happen after all pending events
  409. * are processed.
  410. *
  411. * @param runnable the Runnable whose run() method should be executed
  412. * synchronously on the EventQueue
  413. * @see #invokeAndWait
  414. * @since JDK1.2
  415. */
  416. public static void invokeLater(Runnable runnable) {
  417. Toolkit.getEventQueue().postEvent(
  418. new InvocationEvent(Toolkit.getDefaultToolkit(), runnable));
  419. }
  420. /**
  421. * Causes <i>runnable</i> to have its run() method called in the dispatch
  422. * thread of the EventQueue. This will happen after all pending events
  423. * are processed. The call blocks until this has happened. This method
  424. * will throw an Error if called from the event dispatcher thread.
  425. *
  426. * @param runnable the Runnable whose run() method should be executed
  427. * synchronously on the EventQueue
  428. * @exception InterruptedException if another thread has
  429. * interrupted this thread
  430. * @exception InvocationTargetException if an exception is thrown
  431. * when running <i>runnable</i>
  432. * @see #invokeLater
  433. * @since JDK1.2
  434. */
  435. public static void invokeAndWait(Runnable runnable)
  436. throws InterruptedException, InvocationTargetException {
  437. if (EventQueue.isDispatchThread()) {
  438. throw new Error("Cannot call invokeAndWait from the event dispatcher thread");
  439. }
  440. class AWTInvocationLock {}
  441. Object lock = new AWTInvocationLock();
  442. EventQueue queue = Toolkit.getEventQueue();
  443. InvocationEvent event =
  444. new InvocationEvent(Toolkit.getDefaultToolkit(), runnable, lock,
  445. true);
  446. synchronized (lock) {
  447. Toolkit.getEventQueue().postEvent(event);
  448. lock.wait();
  449. }
  450. Exception eventException = event.getException();
  451. if (eventException != null) {
  452. throw new InvocationTargetException(eventException);
  453. }
  454. }
  455. }
  456. /**
  457. * The Queue object holds pointers to the beginning and end of one internal
  458. * queue. An EventQueue object is composed of multiple internal Queues, one
  459. * for each priority supported by the EventQueue. All Events on a particular
  460. * internal Queue have identical priority.
  461. */
  462. class Queue {
  463. EventQueueItem head;
  464. EventQueueItem tail;
  465. }
  466. class EventQueueItem {
  467. AWTEvent event;
  468. int id;
  469. Object source;
  470. EventQueueItem next;
  471. EventQueueItem(AWTEvent evt) {
  472. event = evt;
  473. id = evt.getID();
  474. source = evt.getSource();
  475. }
  476. }