- /*
 - * @(#)EventQueue.java 1.96 04/06/28
 - *
 - * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
 - * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 - */
 - package java.awt;
 - import java.awt.event.ActionEvent;
 - import java.awt.event.FocusEvent;
 - import java.awt.event.InputEvent;
 - import java.awt.event.InputMethodEvent;
 - import java.awt.event.InvocationEvent;
 - import java.awt.event.KeyEvent;
 - import java.awt.event.MouseEvent;
 - import java.awt.event.PaintEvent;
 - import java.awt.event.WindowEvent;
 - import java.awt.ActiveEvent;
 - import java.awt.peer.ComponentPeer;
 - import java.awt.peer.LightweightPeer;
 - import java.util.EmptyStackException;
 - import java.lang.ref.WeakReference;
 - import java.lang.reflect.InvocationTargetException;
 - import java.security.AccessController;
 - import java.security.PrivilegedAction;
 - import sun.awt.PeerEvent;
 - import sun.awt.SunToolkit;
 - import sun.awt.DebugHelper;
 - import sun.awt.AWTAutoShutdown;
 - import sun.awt.AppContext;
 - /**
 - * <code>EventQueue</code> is a platform-independent class
 - * that queues events, both from the underlying peer classes
 - * and from trusted application classes.
 - * <p>
 - * It encapsulates asynchronous event dispatch machinery which
 - * extracts events from the queue and dispatches them by calling
 - * {@link #dispatchEvent(AWTEvent) dispatchEvent(AWTEvent)} method
 - * on this <code>EventQueue</code> with the event to be dispatched
 - * as an argument. The particular behavior of this machinery is
 - * implementation-dependent. The only requirements are that events
 - * which were actually enqueued to this queue (note that events
 - * being posted to the <code>EventQueue</code> can be coalesced)
 - * are dispatched:
 - * <dl>
 - * <dt> Sequentially.
 - * <dd> That is, it is not permitted that several events from
 - * this queue are dispatched simultaneously.
 - * <dt> In the same order as they are enqueued.
 - * <dd> That is, if <code>AWTEvent</code> A is enqueued
 - * to the <code>EventQueue</code> before
 - * <code>AWTEvent</code> B then event B will not be
 - * dispatched before event A.
 - * </dl>
 - * <p>
 - * Some browsers partition applets in different code bases into
 - * separate contexts, and establish walls between these contexts.
 - * In such a scenario, there will be one <code>EventQueue</code>
 - * per context. Other browsers place all applets into the same
 - * context, implying that there will be only a single, global
 - * <code>EventQueue</code> for all applets. This behavior is
 - * implementation-dependent. Consult your browser's documentation
 - * for more information.
 - * <p>
 - * For information on the threading issues of the event dispatch
 - * machinery, see <a href="doc-files/AWTThreadIssues.html">AWT Threading
 - * Issues</a>.
 - *
 - * @author Thomas Ball
 - * @author Fred Ecks
 - * @author David Mendenhall
 - *
 - * @version 1.96, 06/28/04
 - * @since 1.1
 - */
 - public class EventQueue {
 - private static final DebugHelper dbg = DebugHelper.create(EventQueue.class);
 - // From Thread.java
 - private static int threadInitNumber;
 - private static synchronized int nextThreadNum() {
 - return threadInitNumber++;
 - }
 - private static final int LOW_PRIORITY = 0;
 - private static final int NORM_PRIORITY = 1;
 - private static final int HIGH_PRIORITY = 2;
 - private static final int ULTIMATE_PRIORITY = 3;
 - private static final int NUM_PRIORITIES = ULTIMATE_PRIORITY + 1;
 - /*
 - * We maintain one Queue for each priority that the EventQueue supports.
 - * That is, the EventQueue object is actually implemented as
 - * NUM_PRIORITIES queues and all Events on a particular internal Queue
 - * have identical priority. Events are pulled off the EventQueue starting
 - * with the Queue of highest priority. We progress in decreasing order
 - * across all Queues.
 - */
 - private Queue[] queues = new Queue[NUM_PRIORITIES];
 - /*
 - * The next EventQueue on the stack, or null if this EventQueue is
 - * on the top of the stack. If nextQueue is non-null, requests to post
 - * an event are forwarded to nextQueue.
 - */
 - private EventQueue nextQueue;
 - /*
 - * The previous EventQueue on the stack, or null if this is the
 - * "base" EventQueue.
 - */
 - private EventQueue previousQueue;
 - private EventDispatchThread dispatchThread;
 - private final ThreadGroup threadGroup =
 - Thread.currentThread().getThreadGroup();
 - private final ClassLoader classLoader =
 - Thread.currentThread().getContextClassLoader();
 - /*
 - * Debugging flag -- set true and recompile to enable checking.
 - */
 - private final static boolean debug = false;
 - /*
 - * The time stamp of the last dispatched InputEvent or ActionEvent.
 - */
 - private long mostRecentEventTime = System.currentTimeMillis();
 - /**
 - * The modifiers field of the current event, if the current event is an
 - * InputEvent or ActionEvent.
 - */
 - private WeakReference currentEvent;
 - /*
 - * Non-zero if a thread is waiting in getNextEvent(int) for an event of
 - * a particular ID to be posted to the queue.
 - */
 - private int waitForID;
 - private final String name = "AWT-EventQueue-" + nextThreadNum();
 - public EventQueue() {
 - for (int i = 0; i < NUM_PRIORITIES; i++) {
 - queues[i] = new Queue();
 - }
 - /*
 - * NOTE: if you ever have to start the associated event dispatch
 - * thread at this point, be aware of the following problem:
 - * If this EventQueue instance is created in
 - * SunToolkit.createNewAppContext() the started dispatch thread
 - * may call AppContext.getAppContext() before createNewAppContext()
 - * completes thus causing mess in thread group to appcontext mapping.
 - */
 - }
 - /**
 - * Posts a 1.1-style event to the <code>EventQueue</code>.
 - * If there is an existing event on the queue with the same ID
 - * and event source, the source <code>Component</code>'s
 - * <code>coalesceEvents</code> method will be called.
 - *
 - * @param theEvent an instance of <code>java.awt.AWTEvent</code>,
 - * or a subclass of it
 - * @throws NullPointerException if <code>theEvent</code> is <code>null</code>
 - */
 - public void postEvent(AWTEvent theEvent) {
 - SunToolkit.flushPendingEvents();
 - postEventPrivate(theEvent);
 - }
 - /**
 - * Posts a 1.1-style event to the <code>EventQueue</code>.
 - * If there is an existing event on the queue with the same ID
 - * and event source, the source <code>Component</code>'s
 - * <code>coalesceEvents</code> method will be called.
 - *
 - * @param theEvent an instance of <code>java.awt.AWTEvent</code>,
 - * or a subclass of it
 - */
 - final void postEventPrivate(AWTEvent theEvent) {
 - theEvent.isPosted = true;
 - synchronized(this) {
 - int id = theEvent.getID();
 - if (nextQueue != null) {
 - // Forward event to top of EventQueue stack.
 - nextQueue.postEventPrivate(theEvent);
 - } else if (theEvent instanceof PeerEvent &&
 - (((PeerEvent)theEvent).getFlags() &
 - PeerEvent.ULTIMATE_PRIORITY_EVENT) != 0) {
 - postEvent(theEvent, ULTIMATE_PRIORITY);
 - } else if (theEvent instanceof PeerEvent &&
 - (((PeerEvent)theEvent).getFlags() &
 - PeerEvent.PRIORITY_EVENT) != 0) {
 - postEvent(theEvent, HIGH_PRIORITY);
 - } else if (id == PaintEvent.PAINT ||
 - id == PaintEvent.UPDATE) {
 - postEvent(theEvent, LOW_PRIORITY);
 - } else {
 - postEvent(theEvent, NORM_PRIORITY);
 - }
 - }
 - }
 - /**
 - * Posts the event to the internal Queue of specified priority,
 - * coalescing as appropriate.
 - *
 - * @param theEvent an instance of <code>java.awt.AWTEvent</code>,
 - * or a subclass of it
 - * @param priority the desired priority of the event
 - */
 - private void postEvent(AWTEvent theEvent, int priority) {
 - if (dispatchThread == null) {
 - if (theEvent.getSource() == AWTAutoShutdown.getInstance()) {
 - return;
 - } else {
 - initDispatchThread();
 - }
 - }
 - Object source = theEvent.getSource();
 - // Expanding RepaintArea
 - if (source instanceof Component) {
 - ComponentPeer sourcePeer = ((Component)source).peer;
 - if (sourcePeer != null && theEvent instanceof PaintEvent &&
 - !(sourcePeer instanceof LightweightPeer)) {
 - sourcePeer.coalescePaintEvent((PaintEvent)theEvent);
 - }
 - }
 - EventQueueItem newItem = new EventQueueItem(theEvent);
 - boolean notifyID = (theEvent.getID() == this.waitForID);
 - if (queues[priority].head == null) {
 - boolean shouldNotify = noEvents();
 - queues[priority].head = queues[priority].tail = newItem;
 - if (shouldNotify) {
 - if (theEvent.getSource() != AWTAutoShutdown.getInstance()) {
 - AWTAutoShutdown.getInstance().notifyThreadBusy(dispatchThread);
 - }
 - notifyAll();
 - } else if (notifyID) {
 - notifyAll();
 - }
 - } else {
 - boolean isPeerEvent = theEvent instanceof PeerEvent;
 - // For Component source events, traverse the entire list,
 - // trying to coalesce events
 - if (source instanceof Component) {
 - EventQueueItem q = queues[priority].head;
 - if (theEvent.id == Event.MOUSE_MOVE ||
 - theEvent.id == Event.MOUSE_DRAG) {
 - EventQueueItem qm;
 - for(qm = q; qm != null; qm = qm.next) {
 - if ((qm.event instanceof MouseEvent) &&
 - qm.id != theEvent.id) {
 - q = qm;
 - }
 - }
 - }
 - for (; q != null; q = q.next) {
 - // Give Component.coalesceEvents a chance
 - if (q.event.getSource() == source && q.id == newItem.id) {
 - AWTEvent coalescedEvent = ((Component)source).coalesceEvents(q.event, theEvent);
 - if (isPeerEvent && coalescedEvent == null && q.event instanceof PeerEvent) {
 - coalescedEvent = ((PeerEvent)q.event).coalesceEvents((PeerEvent)theEvent);
 - }
 - if (coalescedEvent != null) {
 - // Remove debugging statement because
 - // calling AWTEvent.toString here causes a
 - // deadlock.
 - q.event = coalescedEvent;
 - return;
 - }
 - }
 - }
 - }
 - // The event was not coalesced or has non-Component source.
 - // Insert it at the end of the appropriate Queue.
 - queues[priority].tail.next = newItem;
 - queues[priority].tail = newItem;
 - if (notifyID) {
 - notifyAll();
 - }
 - }
 - }
 - /**
 - * Returns whether an event is pending on any of the separate
 - * Queues.
 - * @return whether an event is pending on any of the separate Queues
 - */
 - private boolean noEvents() {
 - for (int i = 0; i < NUM_PRIORITIES; i++) {
 - if (queues[i].head != null) {
 - return false;
 - }
 - }
 - return true;
 - }
 - /**
 - * Removes an event from the <code>EventQueue</code> and
 - * returns it. This method will block until an event has
 - * been posted by another thread.
 - * @return the next <code>AWTEvent</code>
 - * @exception InterruptedException
 - * if another thread has interrupted this thread
 - */
 - public AWTEvent getNextEvent() throws InterruptedException {
 - do {
 - /*
 - * SunToolkit.flushPendingEvents must be called outside
 - * of the synchronized block to avoid deadlock when
 - * event queues are nested with push()/pop().
 - */
 - SunToolkit.flushPendingEvents();
 - synchronized (this) {
 - for (int i = NUM_PRIORITIES - 1; i >= 0; i--) {
 - if (queues[i].head != null) {
 - EventQueueItem eqi = queues[i].head;
 - queues[i].head = eqi.next;
 - if (eqi.next == null) {
 - queues[i].tail = null;
 - }
 - return eqi.event;
 - }
 - }
 - AWTAutoShutdown.getInstance().notifyThreadFree(dispatchThread);
 - wait();
 - }
 - } while(true);
 - }
 - AWTEvent getNextEvent(int id) throws InterruptedException {
 - do {
 - /*
 - * SunToolkit.flushPendingEvents must be called outside
 - * of the synchronized block to avoid deadlock when
 - * event queues are nested with push()/pop().
 - */
 - SunToolkit.flushPendingEvents();
 - synchronized (this) {
 - for (int i = 0; i < NUM_PRIORITIES; i++) {
 - for (EventQueueItem entry = queues[i].head, prev = null;
 - entry != null; prev = entry, entry = entry.next)
 - {
 - if (entry.id == id) {
 - if (prev == null) {
 - queues[i].head = entry.next;
 - } else {
 - prev.next = entry.next;
 - }
 - if (queues[i].tail == entry) {
 - queues[i].tail = prev;
 - }
 - return entry.event;
 - }
 - }
 - }
 - this.waitForID = id;
 - wait();
 - this.waitForID = 0;
 - }
 - } while(true);
 - }
 - /**
 - * Returns the first event on the <code>EventQueue</code>
 - * without removing it.
 - * @return the first event
 - */
 - public synchronized AWTEvent peekEvent() {
 - for (int i = NUM_PRIORITIES - 1; i >= 0; i--) {
 - if (queues[i].head != null) {
 - return queues[i].head.event;
 - }
 - }
 - return null;
 - }
 - /**
 - * Returns the first event with the specified id, if any.
 - * @param id the id of the type of event desired
 - * @return the first event of the specified id or <code>null</code>
 - * if there is no such event
 - */
 - public synchronized AWTEvent peekEvent(int id) {
 - for (int i = NUM_PRIORITIES - 1; i >= 0; i--) {
 - EventQueueItem q = queues[i].head;
 - for (; q != null; q = q.next) {
 - if (q.id == id) {
 - return q.event;
 - }
 - }
 - }
 - return null;
 - }
 - /**
 - * Dispatches an event. The manner in which the event is
 - * dispatched depends upon the type of the event and the
 - * type of the event's source object:
 - * <p> </p>
 - * <table border=1 summary="Event types, source types, and dispatch methods">
 - * <tr>
 - * <th>Event Type</th>
 - * <th>Source Type</th>
 - * <th>Dispatched To</th>
 - * </tr>
 - * <tr>
 - * <td>ActiveEvent</td>
 - * <td>Any</td>
 - * <td>event.dispatch()</td>
 - * </tr>
 - * <tr>
 - * <td>Other</td>
 - * <td>Component</td>
 - * <td>source.dispatchEvent(AWTEvent)</td>
 - * </tr>
 - * <tr>
 - * <td>Other</td>
 - * <td>MenuComponent</td>
 - * <td>source.dispatchEvent(AWTEvent)</td>
 - * </tr>
 - * <tr>
 - * <td>Other</td>
 - * <td>Other</td>
 - * <td>No action (ignored)</td>
 - * </tr>
 - * </table>
 - * <p> </p>
 - * @param event an instance of <code>java.awt.AWTEvent</code>,
 - * or a subclass of it
 - * @throws NullPointerException if <code>event</code> is <code>null</code>
 - */
 - protected void dispatchEvent(AWTEvent event) {
 - event.isPosted = true;
 - Object src = event.getSource();
 - if (event instanceof ActiveEvent) {
 - // This could become the sole method of dispatching in time.
 - setCurrentEventAndMostRecentTimeImpl(event);
 - ((ActiveEvent)event).dispatch();
 - } else if (src instanceof Component) {
 - ((Component)src).dispatchEvent(event);
 - event.dispatched();
 - } else if (src instanceof MenuComponent) {
 - ((MenuComponent)src).dispatchEvent(event);
 - } else if (src instanceof AWTAutoShutdown) {
 - if (noEvents()) {
 - dispatchThread.stopDispatching();
 - }
 - } else {
 - System.err.println("unable to dispatch event: " + event);
 - }
 - }
 - /**
 - * Returns the timestamp of the most recent event that had a timestamp, and
 - * that was dispatched from the <code>EventQueue</code> associated with the
 - * calling thread. If an event with a timestamp is currently being
 - * dispatched, its timestamp will be returned. If no events have yet
 - * been dispatched, the EventQueue's initialization time will be
 - * returned instead.In the current version of
 - * the JDK, only <code>InputEvent</code>s,
 - * <code>ActionEvent</code>s, and <code>InvocationEvent</code>s have
 - * timestamps; however, future versions of the JDK may add timestamps to
 - * additional event types. Note that this method should only be invoked
 - * from an application's event dispatching thread. If this method is
 - * invoked from another thread, the current system time (as reported by
 - * <code>System.currentTimeMillis()</code>) will be returned instead.
 - *
 - * @return the timestamp of the last <code>InputEvent</code>,
 - * <code>ActionEvent</code>, or <code>InvocationEvent</code> to be
 - * dispatched, or <code>System.currentTimeMillis()</code> if this
 - * method is invoked on a thread other than an event dispatching
 - * thread
 - * @see java.awt.event.InputEvent#getWhen
 - * @see java.awt.event.ActionEvent#getWhen
 - * @see java.awt.event.InvocationEvent#getWhen
 - *
 - * @since 1.4
 - */
 - public static long getMostRecentEventTime() {
 - return Toolkit.getEventQueue().getMostRecentEventTimeImpl();
 - }
 - private synchronized long getMostRecentEventTimeImpl() {
 - return (Thread.currentThread() == dispatchThread)
 - ? mostRecentEventTime
 - : System.currentTimeMillis();
 - }
 - /**
 - * @return most recent event time on all threads.
 - */
 - synchronized long getMostRecentEventTimeEx() {
 - return mostRecentEventTime;
 - }
 - /**
 - * Returns the the event currently being dispatched by the
 - * <code>EventQueue</code> associated with the calling thread. This is
 - * useful if a method needs access to the event, but was not designed to
 - * receive a reference to it as an argument. Note that this method should
 - * only be invoked from an application's event dispatching thread. If this
 - * method is invoked from another thread, null will be returned.
 - *
 - * @return the event currently being dispatched, or null if this method is
 - * invoked on a thread other than an event dispatching thread
 - * @since 1.4
 - */
 - public static AWTEvent getCurrentEvent() {
 - return Toolkit.getEventQueue().getCurrentEventImpl();
 - }
 - private synchronized AWTEvent getCurrentEventImpl() {
 - return (Thread.currentThread() == dispatchThread)
 - ? ((AWTEvent)currentEvent.get())
 - : null;
 - }
 - /**
 - * Replaces the existing <code>EventQueue</code> with the specified one.
 - * Any pending events are transferred to the new <code>EventQueue</code>
 - * for processing by it.
 - *
 - * @param newEventQueue an <code>EventQueue</code>
 - * (or subclass thereof) instance to be use
 - * @see java.awt.EventQueue#pop
 - * @throws NullPointerException if <code>newEventQueue</code> is <code>null</code>
 - */
 - public synchronized void push(EventQueue newEventQueue) {
 - if (debug) {
 - System.out.println("EventQueue.push(" + newEventQueue + ")");
 - }
 - if (nextQueue != null) {
 - nextQueue.push(newEventQueue);
 - return;
 - }
 - synchronized (newEventQueue) {
 - // Transfer all events forward to new EventQueue.
 - while (peekEvent() != null) {
 - try {
 - newEventQueue.postEventPrivate(getNextEvent());
 - } catch (InterruptedException ie) {
 - if (debug) {
 - System.err.println("interrupted push:");
 - ie.printStackTrace(System.err);
 - }
 - }
 - }
 - newEventQueue.previousQueue = this;
 - }
 - /*
 - * Stop the event dispatch thread associated with the currently
 - * active event queue, so that after the new queue is pushed
 - * on the top this event dispatch thread won't prevent AWT from
 - * being automatically shut down.
 - * Use stopDispatchingLater() to avoid deadlock: stopDispatching()
 - * waits for the dispatch thread to exit, so if the dispatch
 - * thread attempts to synchronize on this EventQueue object
 - * it will never exit since we already hold this lock.
 - */
 - if (dispatchThread != null) {
 - dispatchThread.stopDispatchingLater();
 - }
 - nextQueue = newEventQueue;
 - AppContext appContext = AppContext.getAppContext();
 - if (appContext.get(AppContext.EVENT_QUEUE_KEY) == this) {
 - appContext.put(AppContext.EVENT_QUEUE_KEY, newEventQueue);
 - }
 - }
 - /**
 - * Stops dispatching events using this <code>EventQueue</code>.
 - * Any pending events are transferred to the previous
 - * <code>EventQueue</code> for processing.
 - * <p>
 - * Warning: To avoid deadlock, do not declare this method
 - * synchronized in a subclass.
 - *
 - * @exception EmptyStackException if no previous push was made
 - * on this <code>EventQueue</code>
 - * @see java.awt.EventQueue#push
 - */
 - protected void pop() throws EmptyStackException {
 - if (debug) {
 - System.out.println("EventQueue.pop(" + this + ")");
 - }
 - // To prevent deadlock, we lock on the previous EventQueue before
 - // this one. This uses the same locking order as everything else
 - // in EventQueue.java, so deadlock isn't possible.
 - EventQueue prev = previousQueue;
 - synchronized ((prev != null) ? prev : this) {
 - synchronized(this) {
 - if (nextQueue != null) {
 - nextQueue.pop();
 - return;
 - }
 - if (previousQueue == null) {
 - throw new EmptyStackException();
 - }
 - // Transfer all events back to previous EventQueue.
 - previousQueue.nextQueue = null;
 - while (peekEvent() != null) {
 - try {
 - previousQueue.postEventPrivate(getNextEvent());
 - } catch (InterruptedException ie) {
 - if (debug) {
 - System.err.println("interrupted pop:");
 - ie.printStackTrace(System.err);
 - }
 - }
 - }
 - AppContext appContext = AppContext.getAppContext();
 - if (appContext.get(AppContext.EVENT_QUEUE_KEY) == this) {
 - appContext.put(AppContext.EVENT_QUEUE_KEY, previousQueue);
 - }
 - previousQueue = null;
 - }
 - }
 - EventDispatchThread dt = this.dispatchThread;
 - if (dt != null) {
 - dt.stopDispatching(); // Must be done outside synchronized
 - // block to avoid possible deadlock
 - }
 - }
 - /**
 - * Returns true if the calling thread is the current AWT
 - * <code>EventQueue</code>'s dispatch thread. Use this
 - * call the ensure that a given
 - * task is being executed (or not being) on the current AWT
 - * <code>EventDispatchThread</code>.
 - *
 - * @return true if running on the current AWT
 - * <code>EventQueue</code>'s dispatch thread
 - */
 - public static boolean isDispatchThread() {
 - EventQueue eq = Toolkit.getEventQueue();
 - EventQueue next = eq.nextQueue;
 - while (next != null) {
 - eq = next;
 - next = eq.nextQueue;
 - }
 - return (Thread.currentThread() == eq.dispatchThread);
 - }
 - final void initDispatchThread() {
 - synchronized (this) {
 - if (dispatchThread == null && !threadGroup.isDestroyed()) {
 - dispatchThread = (EventDispatchThread)
 - AccessController.doPrivileged(new PrivilegedAction() {
 - public Object run() {
 - EventDispatchThread t =
 - new EventDispatchThread(threadGroup,
 - name,
 - EventQueue.this);
 - t.setContextClassLoader(classLoader);
 - t.setPriority(Thread.NORM_PRIORITY + 1);
 - t.setDaemon(false);
 - return t;
 - }
 - });
 - AWTAutoShutdown.getInstance().notifyThreadBusy(dispatchThread);
 - dispatchThread.start();
 - }
 - }
 - }
 - final void detachDispatchThread() {
 - dispatchThread = null;
 - }
 - /*
 - * Gets the <code>EventDispatchThread</code> for this
 - * <code>EventQueue</code>.
 - * @return the event dispatch thread associated with this event queue
 - * or <code>null</code> if this event queue doesn't have a
 - * working thread associated with it
 - * @see java.awt.EventQueue#initDispatchThread
 - * @see java.awt.EventQueue#detachDispatchThread
 - */
 - final EventDispatchThread getDispatchThread() {
 - return dispatchThread;
 - }
 - /*
 - * Removes any pending events for the specified source object.
 - * If removeAllEvents parameter is <code>true</code> then all
 - * events for the specified source object are removed, if it
 - * is <code>false</code> then <code>SequencedEvent</code>, <code>SentEvent</code>,
 - * <code>FocusEvent</code>, <code>WindowEvent</code>, <code>KeyEvent</code>,
 - * and <code>InputMethodEvent</code> are kept in the queue, but all other
 - * events are removed.
 - *
 - * This method is normally called by the source's
 - * <code>removeNotify</code> method.
 - */
 - final void removeSourceEvents(Object source, boolean removeAllEvents) {
 - SunToolkit.flushPendingEvents();
 - synchronized (this) {
 - for (int i = 0; i < NUM_PRIORITIES; i++) {
 - EventQueueItem entry = queues[i].head;
 - EventQueueItem prev = null;
 - while (entry != null) {
 - if ((entry.event.getSource() == source)
 - && (removeAllEvents
 - || ! (entry.event instanceof SequencedEvent
 - || entry.event instanceof SentEvent
 - || entry.event instanceof FocusEvent
 - || entry.event instanceof WindowEvent
 - || entry.event instanceof KeyEvent
 - || entry.event instanceof InputMethodEvent)))
 - {
 - if (entry.event instanceof SequencedEvent) {
 - ((SequencedEvent)entry.event).dispose();
 - }
 - if (entry.event instanceof SentEvent) {
 - ((SentEvent)entry.event).dispose();
 - }
 - if (prev == null) {
 - queues[i].head = entry.next;
 - } else {
 - prev.next = entry.next;
 - }
 - } else {
 - prev = entry;
 - }
 - entry = entry.next;
 - }
 - queues[i].tail = prev;
 - }
 - }
 - }
 - static void setCurrentEventAndMostRecentTime(AWTEvent e) {
 - Toolkit.getEventQueue().setCurrentEventAndMostRecentTimeImpl(e);
 - }
 - private synchronized void setCurrentEventAndMostRecentTimeImpl(AWTEvent e)
 - {
 - if (Thread.currentThread() != dispatchThread) {
 - return;
 - }
 - currentEvent = new WeakReference(e);
 - // This series of 'instanceof' checks should be replaced with a
 - // polymorphic type (for example, an interface which declares a
 - // getWhen() method). However, this would require us to make such
 - // a type public, or to place it in sun.awt. Both of these approaches
 - // have been frowned upon. So for now, we hack.
 - //
 - // In tiger, we will probably give timestamps to all events, so this
 - // will no longer be an issue.
 - if (e instanceof InputEvent) {
 - InputEvent ie = (InputEvent)e;
 - mostRecentEventTime = ie.getWhen();
 - } else if (e instanceof InputMethodEvent) {
 - InputMethodEvent ime = (InputMethodEvent)e;
 - mostRecentEventTime = ime.getWhen();
 - } else if (e instanceof ActionEvent) {
 - ActionEvent ae = (ActionEvent)e;
 - mostRecentEventTime = ae.getWhen();
 - } else if (e instanceof InvocationEvent) {
 - InvocationEvent ie = (InvocationEvent)e;
 - mostRecentEventTime = ie.getWhen();
 - }
 - }
 - /**
 - * Causes <code>runnable</code> to have its <code>run</code>
 - * method called in the dispatch thread of the <code>EventQueue</code>.
 - * This will happen after all pending events are processed.
 - *
 - * @param runnable the <code>Runnable</code> whose <code>run</code>
 - * method should be executed
 - * synchronously on the <code>EventQueue</code>
 - * @see #invokeAndWait
 - * @since 1.2
 - */
 - public static void invokeLater(Runnable runnable) {
 - Toolkit.getEventQueue().postEvent(
 - new InvocationEvent(Toolkit.getDefaultToolkit(), runnable));
 - }
 - /**
 - * Causes <code>runnable</code> to have its <code>run</code>
 - * method called in the dispatch thread of the <code>EventQueue</code>.
 - * This will happen after all pending events are processed.
 - * The call blocks until this has happened. This method
 - * will throw an Error if called from the event dispatcher thread.
 - *
 - * @param runnable the <code>Runnable</code> whose <code>run</code>
 - * method should be executed
 - * synchronously on the <code>EventQueue</code>
 - * @exception InterruptedException if another thread has
 - * interrupted this thread
 - * @exception InvocationTargetException if an throwable is thrown
 - * when running <code>runnable</code>
 - * @see #invokeLater
 - * @since 1.2
 - */
 - public static void invokeAndWait(Runnable runnable)
 - throws InterruptedException, InvocationTargetException {
 - if (EventQueue.isDispatchThread()) {
 - throw new Error("Cannot call invokeAndWait from the event dispatcher thread");
 - }
 - class AWTInvocationLock {}
 - Object lock = new AWTInvocationLock();
 - InvocationEvent event =
 - new InvocationEvent(Toolkit.getDefaultToolkit(), runnable, lock,
 - true);
 - synchronized (lock) {
 - Toolkit.getEventQueue().postEvent(event);
 - lock.wait();
 - }
 - Throwable eventThrowable = event.getThrowable();
 - if (eventThrowable != null) {
 - throw new InvocationTargetException(eventThrowable);
 - }
 - }
 - /*
 - * Called from PostEventQueue.postEvent to notify that a new event
 - * appeared. First it proceeds to the EventQueue on the top of the
 - * stack, then notifies the associated dispatch thread if it exists
 - * or starts a new one otherwise.
 - */
 - private void wakeup(boolean isShutdown) {
 - synchronized(this) {
 - if (nextQueue != null) {
 - // Forward call to the top of EventQueue stack.
 - nextQueue.wakeup(isShutdown);
 - } else if (dispatchThread != null) {
 - notifyAll();
 - } else if (!isShutdown) {
 - initDispatchThread();
 - }
 - }
 - }
 - }
 - /**
 - * The Queue object holds pointers to the beginning and end of one internal
 - * queue. An EventQueue object is composed of multiple internal Queues, one
 - * for each priority supported by the EventQueue. All Events on a particular
 - * internal Queue have identical priority.
 - */
 - class Queue {
 - EventQueueItem head;
 - EventQueueItem tail;
 - }
 - class EventQueueItem {
 - AWTEvent event;
 - int id;
 - EventQueueItem next;
 - EventQueueItem(AWTEvent evt) {
 - event = evt;
 - id = evt.getID();
 - }
 - }