gt:         EventQueueItem[] cache = ((Component)e.getSource()).eventCache;
context: /*
   * Copyright 1996-2008 Sun Microsystems, Inc.  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.  Sun designates this
   * particular file as subject to the "Classpath" exception as provided
   * by Sun in the LICENSE file that accompanied this code.
   *
   * This code is distributed in the hope that it will be useful, but WITHOUT
   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   * version 2 for more details (a copy is included in the LICENSE file that
   * accompanied this code).
   *
   * You should have received a copy of the GNU General Public License version
   * 2 along with this work; if not, write to the Free Software Foundation,
   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   *
   * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   * CA 95054 USA or visit www.sun.com if you need additional information or
   * have any questions.
   */
  
  package java.awt;
  
  import java.awt.event.*;
  
  import java.awt.peer.ComponentPeer;
  
  import java.lang.ref.WeakReference;
  import java.lang.reflect.InvocationTargetException;
  
  import java.security.AccessController;
  import java.security.PrivilegedAction;
  
  import java.util.EmptyStackException;
  import sun.util.logging.PlatformLogger;
  
  import sun.awt.AppContext;
  import sun.awt.AWTAutoShutdown;
  import sun.awt.PeerEvent;
  import sun.awt.SunToolkit;
  import sun.awt.EventQueueItem;
  import sun.awt.AWTAccessor;
  
  import java.util.concurrent.locks.Condition;
  import java.util.concurrent.locks.Lock;
  
  /**
   * <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>&nbsp;A is enqueued
   *        to the <code>EventQueue</code> before
   *        <code>AWTEvent</code>&nbsp;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#Autoshutdown"
   * >AWT Threading Issues</a>.
   *
   * @author Thomas Ball
   * @author Fred Ecks
   * @author David Mendenhall
   *
   * @since       1.1
   */
  public class EventQueue {
  
      // 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;
  
      /*
       * A single lock to synchronize the push()/pop() and related operations with
       * all the EventQueues from the AppContext. Synchronization on any particular
       * event queue(s) is not enough: we should lock the whole stack.
       */
      private final Lock pushPopLock;
      private final Condition pushPopCond;
  
      private EventDispatchThread dispatchThread;
  
      private final ThreadGroup threadGroup =
          Thread.currentThread().getThreadGroup();
      private final ClassLoader classLoader =
          Thread.currentThread().getContextClassLoader();
  
      /*
       * 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();
  
      private static final PlatformLogger eventLog = PlatformLogger.getLogger("java.awt.event.EventQueue");
  
      static {
          AWTAccessor.setEventQueueAccessor(
              new AWTAccessor.EventQueueAccessor() {
                  public Thread getDispatchThread(EventQueue eventQueue) {
                      return eventQueue.getDispatchThread();
                  }
                  public boolean isDispatchThreadImpl(EventQueue eventQueue) {
                      return eventQueue.isDispatchThreadImpl();
                  }
              });
      }
  
      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.
           */
  
          pushPopLock = (Lock)AppContext.getAppContext().get(AppContext.EVENT_QUEUE_LOCK_KEY);
          pushPopCond = (Condition)AppContext.getAppContext().get(AppContext.EVENT_QUEUE_COND_KEY);
      }
  
      /**
       * 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;
          pushPopLock.lock();
          try {
              if (dispatchThread == null && nextQueue == null) {
                  if (theEvent.getSource() == AWTAutoShutdown.getInstance()) {
                      return;
                  } else {
                      initDispatchThread();
                  }
              }
              if (nextQueue != null) {
                  // Forward event to top of EventQueue stack.
                  nextQueue.postEventPrivate(theEvent);
                  return;
              }
              postEvent(theEvent, getPriority(theEvent));
          } finally {
              pushPopLock.unlock();
          }
      }
  
      private static int getPriority(AWTEvent theEvent) {
          if (theEvent instanceof PeerEvent &&
              (((PeerEvent)theEvent).getFlags() &
                  PeerEvent.ULTIMATE_PRIORITY_EVENT) != 0)
          {
              return ULTIMATE_PRIORITY;
          }
  
          if (theEvent instanceof PeerEvent &&
              (((PeerEvent)theEvent).getFlags() &
                  PeerEvent.PRIORITY_EVENT) != 0)
          {
              return HIGH_PRIORITY;
          }
  
          if (theEvent instanceof PeerEvent &&
              (((PeerEvent)theEvent).getFlags() &
                  PeerEvent.LOW_PRIORITY_EVENT) != 0)
          {
              return LOW_PRIORITY;
          }
  
          int id = theEvent.getID();
          if (id == PaintEvent.PAINT || id == PaintEvent.UPDATE) {
              return LOW_PRIORITY;
          }
          return 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 (coalesceEvent(theEvent, priority)) {
              return;
          }
  
          EventQueueItem newItem = new EventQueueItem(theEvent);
  
          cacheEQItem(newItem);
  
          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);
                  }
                  pushPopCond.signalAll();
              } else if (notifyID) {
                  pushPopCond.signalAll();
              }
          } else {
              // 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) {
                  pushPopCond.signalAll();
              }
          }
      }
  
      private boolean coalescePaintEvent(PaintEvent e) {
          ComponentPeer sourcePeer = ((Component)e.getSource()).peer;
          if (sourcePeer != null) {
              sourcePeer.coalescePaintEvent(e);
          }
          EventQueueItem[] cache = ((Component)e.getSource()).eventCache;
          if (cache == null) {
              return false;
          }
          int index = eventToCacheIndex(e);
  
          if (index != -1 && cache[index] != null) {
              PaintEvent merged = mergePaintEvents(e, (PaintEvent)cache[index].event);
              if (merged != null) {
                  cache[index].event = merged;
                  return true;
              }
          }
          return false;
      }
  
      private PaintEvent mergePaintEvents(PaintEvent a, PaintEvent b) {
          Rectangle aRect = a.getUpdateRect();
          Rectangle bRect = b.getUpdateRect();
          if (bRect.contains(aRect)) {
              return b;
          }
          if (aRect.contains(bRect)) {
              return a;
          }
          return null;
      }
  
      private boolean coalesceMouseEvent(MouseEvent e) {
          EventQueueItem[] cache = ((Component)e.getSource()).eventCache;
          if (cache == null) {
              return false;
          }
          int index = eventToCacheIndex(e);
          if (index != -1 && cache[index] != null) {
              cache[index].event = e;
              return true;
          }
          return false;
      }
  
      private boolean coalescePeerEvent(PeerEvent e) {
  