home *** CD-ROM | disk | FTP | other *** search
/ Java 1.2 How-To / JavaHowTo.iso / 3rdParty / jbuilder / unsupported / JDK1.2beta3 / SOURCE / SRC.ZIP / java / awt / EventQueue.java < prev    next >
Encoding:
Java Source  |  1998-03-20  |  10.6 KB  |  334 lines

  1. /*
  2.  * @(#)EventQueue.java    1.20 98/03/18
  3.  *
  4.  * Copyright 1996-1998 by Sun Microsystems, Inc.,
  5.  * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
  6.  * All rights reserved.
  7.  *
  8.  * This software is the confidential and proprietary information
  9.  * of Sun Microsystems, Inc. ("Confidential Information").  You
  10.  * shall not disclose such Confidential Information and shall use
  11.  * it only in accordance with the terms of the license agreement
  12.  * you entered into with Sun.
  13.  */
  14.  
  15. package java.awt;
  16.  
  17. import java.awt.event.EventQueueListener;
  18. import java.awt.event.FocusEvent;
  19. import java.awt.event.KeyEvent;
  20. import java.awt.event.MouseEvent;
  21. import java.awt.event.PaintEvent;
  22. import java.awt.ActiveEvent;
  23. import java.util.EventListener;
  24. import java.util.EmptyStackException;
  25.  
  26. /**
  27.  * EventQueue is a platform-independent class that queues events, both
  28.  * from the underlying peer classes and from trusted application classes.
  29.  * There is only one EventQueue for the system.
  30.  *
  31.  * @version 1.20 03/18/98
  32.  * @author Thomas Ball
  33.  */
  34. public class EventQueue {
  35.  
  36.     // From Thread.java
  37.     private static int threadInitNumber;
  38.     private static synchronized int nextThreadNum() {
  39.     return threadInitNumber++;
  40.     }
  41.  
  42.     /* package-private variables are used to make push/pop faster. */
  43.  
  44.     /* The actual queue of events, implemented as a linked-list. */
  45.     EventQueueItem queue;
  46.  
  47.     /* The multiplexed EventQueueListener list. */
  48.     EventQueueListener eventQueueListener;
  49.  
  50.     /*
  51.      * The next EventQueue on the stack, or null if this EventQueue is
  52.      * on the top of the stack.  If next is non-null, requests to post
  53.      * an event are forwarded to next.
  54.      */
  55.     EventQueue next;
  56.  
  57.     /*
  58.      * The previous EventQueue on the stack, or null if this is the
  59.      * "base" EventQueue.
  60.      */
  61.     EventQueue prev;
  62.  
  63.     public EventQueue() {
  64.         queue = null;
  65.         String name = "AWT-EventQueue-" + nextThreadNum();
  66.         new EventDispatchThread(name, this).start();
  67.     }
  68.  
  69.     /**
  70.      * Post a 1.1-style event to the EventQueue.
  71.      *
  72.      * @param theEvent an instance of java.awt.AWTEvent, or a
  73.      * subclass of it.
  74.      */
  75.     public synchronized void postEvent(AWTEvent theEvent) {
  76.         if (next != null) {
  77.             // Forward event to top of EventQueue stack.
  78.             next.postEvent(theEvent);
  79.             return;
  80.         }
  81.  
  82.         Object source = theEvent.getSource();
  83.         EventQueueItem eqi = new EventQueueItem(theEvent);
  84.         if (queue == null) {
  85.             queue = eqi;
  86.             notifyAll();
  87.         } else {
  88.             EventQueueItem q = queue;
  89.             for (;;) {
  90.                 if (source instanceof Component &&
  91.                     q.id == eqi.id &&
  92.                     q.event.getSource().equals(source)) {
  93.                     AWTEvent coalescedEvent = 
  94.                         ((Component)source).coalesceEvents(q.event, theEvent);
  95.                     if (coalescedEvent != null) {
  96.                         q.event = coalescedEvent;
  97.                         return;
  98.                     }
  99.                 }
  100.                 if (q.next != null) {
  101.                     q = q.next;
  102.                 } else {
  103.                     break;
  104.                 }
  105.             }
  106.             q.next = eqi;
  107.         }
  108.         notifyEventQueueListeners(theEvent);
  109.     }
  110.  
  111.     /**
  112.      * Remove an event from the queue and return it.  This method will
  113.      * block until an event has been posted by another thread.
  114.      * @return the next AWTEvent
  115.      * @exception InterruptedException 
  116.      *            if another thread has interrupted this thread.
  117.      */
  118.     public synchronized AWTEvent getNextEvent() throws InterruptedException {
  119.         while (queue == null) {
  120.             wait();
  121.         }
  122.         EventQueueItem eqi = queue;
  123.         queue = queue.next;
  124.         return eqi.event;
  125.     }
  126.  
  127.     /**
  128.      * Return the first event without removing it.
  129.      * @return the first event, which is either an instance of java.awt.Event
  130.      * or java.awt.AWTEvent.
  131.      */
  132.     public synchronized AWTEvent peekEvent() {
  133.         return (queue != null) ? queue.event : null;
  134.     }
  135.  
  136.     /*
  137.      * Return the first event of the specified type, if any.
  138.      * @param id the id of the type of event desired.
  139.      * @return the first event of the requested type, 
  140.      * which is either an instance of java.awt.Event
  141.      * or java.awt.AWTEvent.
  142.      */
  143.     public synchronized AWTEvent peekEvent(int id) {
  144.         EventQueueItem q = queue;
  145.         for (; q != null; q = q.next) {
  146.             if (q.id == id) {
  147.                 return q.event;
  148.             }
  149.         }
  150.         return null;
  151.     }
  152.  
  153.     /**
  154.      * Dispatch an event to its source.
  155.      *
  156.      * @param theEvent an instance of java.awt.AWTEvent, or a
  157.      * subclass of it.
  158.      */
  159.     protected void dispatchEvent(AWTEvent event) {
  160.         Object src = event.getSource();
  161.         if (event instanceof ActiveEvent) {
  162.             // This could become the sole method of dispatching in time.
  163.             ((ActiveEvent)event).dispatch();
  164.         } else if (src instanceof Component) {
  165.             ((Component)src).dispatchEvent(event);
  166.         } else if (src instanceof MenuComponent) {
  167.             ((MenuComponent)src).dispatchEvent(event);
  168.         } else {
  169.             System.err.println("unable to dispatch event: " + event);
  170.         }
  171.     }
  172.  
  173.     /**
  174.      * Replace the existing EventQueue with the specified one.
  175.      * Any pending events are transferred to the new EventQueue
  176.      * for processing by it.
  177.      *
  178.      * @param an EventQueue (or subclass thereof) instance to be used.
  179.      */
  180.     public synchronized void push(EventQueue newEventQueue) {
  181.         synchronized (newEventQueue) {
  182.             newEventQueue.queue = queue;  // may be null
  183.             newEventQueue.prev = this;
  184.             next = newEventQueue;
  185.         }
  186.     }
  187.  
  188.     /**
  189.      * Stop dispatching events using this EventQueue instance.
  190.      * Any pending events are transferred to the previous
  191.      * EventQueue for processing by it.  If called from the
  192.      * initial EventQueue for this AWTContext, an
  193.      * EmptyStackException is thrown.
  194.      */
  195.     protected synchronized void pop() throws EmptyStackException {
  196.         synchronized (prev) {
  197.             prev.queue = queue;   // may be null
  198.             prev.next = null;
  199.             prev = null;
  200.             next = null;
  201.         }
  202.     }
  203.  
  204.     /**
  205.      * Returns true if the calling thread is this EventQueue's
  206.      * dispatch thread.  Use this call the ensure that a given
  207.      * task is being executed (or not being) on the current
  208.      * EventDispatchThread.
  209.      *
  210.      * @return true if running on this EventQueue's dispatch thread.
  211.      */
  212.     public static boolean isDispatchThread() {
  213.         return (Thread.currentThread() instanceof EventDispatchThread);
  214.     }
  215.  
  216.     /**
  217.      * Adds an EventListener to receive AWTEvents from this 
  218.      * EventQueue.  Listeners continue receiving events if a new 
  219.      * EventQueue is pushed or an existing one is popped.  
  220.      * <p>
  221.      * Note:  event listener use is not recommended for normal 
  222.      * application use, but are intended solely to support special 
  223.      * purpose facilities including support for accessibility,
  224.      * event record/playback, and diagnostic tracing.  
  225.      *
  226.      * @param    l   the event listener.
  227.      * @see      java.awt.EventQueueListener
  228.      * @see      java.awt.EventQueue#removeEventQueueListener
  229.      * @since    JDK1.2
  230.      */
  231.     public synchronized void addEventQueueListener(EventQueueListener l) {
  232.         eventQueueListener = EventQueueMulticaster.add(eventQueueListener, l);
  233.     }
  234.  
  235.     /**
  236.      * Removes an EventListener so that it no longer receives 
  237.      * events from this EventQueue.
  238.      * <p>
  239.      * Note:  event listener use is not recommended for normal 
  240.      * application use, but are intended solely to support special 
  241.      * purpose facilities including support for accessibility,
  242.      * event record/playback, and diagnostic tracing.  
  243.      *
  244.      * @param    l   the event listener.
  245.      * @see      java.awt.EventQueueListener
  246.      * @see      java.awt.EventQueue#addEventQueueListener
  247.      * @since    JDK1.2
  248.      */
  249.     public synchronized void removeEventQueueListener(EventQueueListener l) {
  250.         eventQueueListener = EventQueueMulticaster.remove(eventQueueListener, l);
  251.     }
  252.  
  253.     /**
  254.      * This method notifies any EventQueueListeners that an event
  255.      * has been posted to the EventQueue.  If an EventQueue subclass
  256.      * overrides postEvent, it <b>must</b> either call this method
  257.      * or call <code>super.postEvent(event)</code>.
  258.      *
  259.      * @param theEvent the event which has been posted to the EventQueue.
  260.      */
  261.     protected void notifyEventQueueListeners(AWTEvent theEvent) {
  262.         if (eventQueueListener != null) {
  263.             eventQueueListener.eventPosted(theEvent);
  264.         }
  265.     }
  266.  
  267.     /*
  268.      * Change the target of any pending KeyEvents because of a focus change.
  269.      */
  270.     synchronized void changeKeyEventFocus(Object newSource) {
  271.         EventQueueItem q = queue;
  272.         for (; q != null; q = q.next) {
  273.             if (q.event instanceof KeyEvent) {
  274.                 q.event.setSource(newSource);
  275.             }
  276.         }
  277.     }
  278.  
  279.     /*
  280.      * Remove any pending events for the specified source object.
  281.      * This method is normally called by the source's removeNotify method.
  282.      */
  283.     synchronized void removeSourceEvents(Object source) {
  284.         EventQueueItem entry = queue;
  285.         EventQueueItem prev = null;
  286.         while (entry != null) {
  287.             if (entry.event.getSource().equals(source)) {
  288.                 if (prev == null) {
  289.                     queue = entry.next;
  290.                 } else {
  291.                     prev.next = entry.next;
  292.                 }
  293.             }
  294.             prev = entry;
  295.             entry = entry.next;
  296.         }
  297.     }
  298.  
  299.     static private class EventQueueMulticaster extends AWTEventMulticaster
  300.         implements EventQueueListener {
  301.         // Implementation cloned from AWTEventMulticaster.
  302.  
  303.         EventQueueMulticaster(EventListener a, EventListener b) {
  304.             super(a, b);
  305.         }
  306.  
  307.         static EventQueueListener add(EventQueueListener a, 
  308.                                       EventQueueListener b) {
  309.             return (EventQueueListener)addInternal(a, b);
  310.         }
  311.  
  312.         static EventQueueListener remove(EventQueueListener l, 
  313.                                          EventQueueListener oldl) {
  314.             return (EventQueueListener) removeInternal(l, oldl);
  315.         }
  316.  
  317.         public void eventPosted(AWTEvent e) {
  318.             ((EventQueueListener)a).eventPosted(e);
  319.             ((EventQueueListener)b).eventPosted(e);
  320.         }
  321.     }
  322. }
  323.  
  324. class EventQueueItem {
  325.     AWTEvent event;
  326.     int      id;
  327.     EventQueueItem next;
  328.  
  329.     EventQueueItem(AWTEvent evt) {
  330.         event = evt;
  331.         id = evt.getID();
  332.     }
  333. }
  334.