/[classpath]/classpath/java/awt/EventQueue.java
ViewVC logotype

Diff of /classpath/java/awt/EventQueue.java

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.5 by mark, Sun Jan 13 15:45:15 2002 UTC revision 1.6 by tromey, Wed Jan 16 04:20:15 2002 UTC
# Line 1  Line 1 
1  /* EventQueue.java -- Event queuing mechanism  /* Copyright (C) 1999, 2000, 2001, 2002  Free Software Foundation
    Copyright (C) 1999 Free Software Foundation, Inc.  
2    
3  This file is part of GNU Classpath.  This file is part of GNU Classpath.
4    
# Line 27  executable file might be covered by the Line 26  executable file might be covered by the
26    
27  package java.awt;  package java.awt;
28    
29  /**  import java.awt.event.*;
30    * This class manages a queue of <code>AWTEvent</code> objects that  import java.util.EmptyStackException;
31    * are posted to it.  The AWT system uses only one event queue for all  import java.lang.reflect.InvocationTargetException;
32    * events.  
33    *  /* Written using on-line Java 2 Platform Standard Edition v1.3 API
34    * @author Aaron M. Renn (arenn@urbanophile.com)   * Specification, as well as "The Java Class Libraries", 2nd edition
35    */   * (Addison-Wesley, 1998).
36  public class EventQueue   * Status:  Believed complete, but untested. Check FIXME's.
 {  
   
 /*  
  * Instance Methods  
  */  
   
 // The queue.  We added a package protected field to AWTEvent to make it  
 // a convenient linked list.  
 private AWTEvent queue;  
   
 /*************************************************************************/  
   
 /*  
  * Constructors  
37   */   */
38    
39  /**  /**
40    * Initializes a new instance of <code>EventQueue</code>.   * This class manages a queue of <code>AWTEvent</code> objects that
41    */   * are posted to it.  The AWT system uses only one event queue for all
42  public   * events.
43  EventQueue()   *
44     * @author Bryce McKinlay
45     * @author Aaron M. Renn (arenn@urbanophile.com)
46     */
47    public class EventQueue
48  {  {
49    EventDispatcher ed = new EventDispatcher(this);    private static final int INITIAL_QUEUE_DEPTH = 8;
50    Thread t = new Thread(ed);    private AWTEvent[] queue = new AWTEvent[INITIAL_QUEUE_DEPTH];
   t.start();  
 }  
51    
52  /*************************************************************************/    private int next_in = 0; // Index where next event will be added to queue
53      private int next_out = 0; // Index of next event to be removed from queue
54    
55  /*    private EventQueue next;
56   * Instance Variables    private EventQueue prev;
  */  
57    
58  /**    private EventDispatchThread dispatchThread = new EventDispatchThread(this);
59    * Posts a new event to the queue.  
60    *    /**
61    * @param event The event to post to the queue.     * Initializes a new instance of <code>EventQueue</code>.
62    */     */
63  public synchronized void    public EventQueue()
64  postEvent(AWTEvent event)    {
65  {    }
66    if (queue == null)  
67      queue = event;    /**
68    else     * Returns the next event in the queue.  This method will block until
69      {     * an event is available or until the thread is interrupted.
70        AWTEvent end = queue;     *
71        while (end.next != null)     * @return The next event in the queue.
72          end = end.next;     *
73       * @exception InterruptedException If this thread is interrupted while
74        end.next = queue;     * waiting for an event to be posted to the queue.
75      }     */
76    notify();    public synchronized AWTEvent getNextEvent()
77  }      throws InterruptedException
78      {
79  /*************************************************************************/      if (next != null)
80          return next.getNextEvent();
81    
82  /**      while (next_in == next_out)
   * Returns the next event in the queue.  This method will block until  
   * an event is available or until the thread is interrupted.  
   *  
   * @return The next event in the queue.  
   *  
   * @exception InterruptedException If this thread is interrupted while  
   * waiting for an event to be posted to the queue.  
   */  
 public synchronized AWTEvent  
 getNextEvent() throws InterruptedException  
 {  
   for (;;)  
     {  
       if (queue != null)  
         {  
           AWTEvent evt = queue;  
           queue = queue.next;  
           evt.next = null;  
           return(evt);  
         }  
83        wait();        wait();
     }  
 }  
   
 /*************************************************************************/  
84    
85  /**      AWTEvent res = queue[next_out];
   * Returns the next event in the queue without removing it from the queue.  
   * This method will block until an event is available or until the thread  
   * is interrupted.  
   *  
   * @return The next event in the queue.  
   */  
 public synchronized AWTEvent  
 peekEvent()  
 {  
   for (;;)  
     {  
       if (queue != null)  
         {  
           // We are taking a chance that the user doesn't repost the same  
           // event back to the queue, but AWTEvent isn't cloneable so we  
           // don't have much choice.  If this becomes a problem we'll have  
           // to write a wrapper class for enqueuing.  
           return(queue);  
         }  
   
       try  
         {  
           wait();  
         }  
       catch(InterruptedException e) {  }  
     }  
 }  
   
 /*************************************************************************/  
86    
87  /**      if (++next_out == queue.length)
88    * Returns the next event in the queue that has the specified id        next_out = 0;
89    * without removing it from the queue.      return res;
90    * This method will block until an event is available or until the thread    }
91    * is interrupted.  
92    *    /**
93    * @param id The event id to return.     * Returns the next event in the queue without removing it from the queue.
94    *     * This method will block until an event is available or until the thread
95    * @return The next event in the queue.     * is interrupted.
96    */     *
97  public synchronized AWTEvent     * @return The next event in the queue.
98  peekEvent(int id)     * @specnote Does not block. Returns null if there are no events on the
99  {     *            queue.
100    for(;;)     */
101      {    public synchronized AWTEvent peekEvent()
102        if (queue != null)    {
103          {      if (next != null)
104            AWTEvent evt = queue;        return next.peekEvent();
105            while (evt != null)  
106              {      if (next_in != next_out)
107                if (evt.getID() == id)        return queue[next_out];
108                   return(evt);      else return null;
109                evt = evt.next;    }
110              }  
111          }    /**
112       * Returns the next event in the queue that has the specified id
113        try     * without removing it from the queue.
114          {     * This method will block until an event is available or until the thread
115            wait();     * is interrupted.
116          }     *
117        catch(InterruptedException e) {  }     * @param id The event id to return.
118      }     *
119       * @return The next event in the queue.
120       *
121       * @specnote Does not block. Returns null if there are no matching events
122       *            on the queue.
123       */
124      public synchronized AWTEvent peekEvent(int id)
125      {
126        if (next != null)
127          return next.peekEvent(id);
128    
129        int i = next_out;
130        while (i != next_in)
131          {
132            AWTEvent qevt = queue[i];
133            if (qevt.id == id)
134              return qevt;
135          }
136        return null;
137      }
138    
139      /**
140       * Posts a new event to the queue.
141       *
142       * @param event The event to post to the queue.
143       */
144      public synchronized void postEvent(AWTEvent evt)
145      {
146        if (next != null)
147          {
148            next.postEvent(evt);
149            return;
150          }
151        // FIXME: Security checks?
152    
153        /* Check for any events already on the queue with the same source
154           and ID. */      
155        int i = next_out;
156        while (i != next_in)
157          {
158            AWTEvent qevt = queue[i];
159            Object src;
160            if (qevt.id == evt.id
161                && (src = qevt.getSource()) == evt.getSource()
162                && src instanceof Component)
163              {
164                /* If there are, call coalesceEvents on the source component
165                   to see if they can be combined. */
166                Component srccmp = (Component) src;
167                AWTEvent coalesced_evt = srccmp.coalesceEvents(qevt, evt);
168                if (coalesced_evt != null)
169                  {
170                    /* Yes. Replace the existing event with the combined event. */
171                    queue[i] = coalesced_evt;
172                    return;
173                  }
174                break;
175              }
176            if (++i == queue.length)
177              i = 0;
178          }
179    
180        queue[next_in] = evt;    
181        if (++next_in == queue.length)
182          next_in = 0;
183    
184        if (next_in == next_out)
185          {
186            /* Queue is full. Extend it. */
187            AWTEvent[] oldQueue = queue;
188            queue = new AWTEvent[queue.length * 2];
189    
190            int len = oldQueue.length - next_out;
191            System.arraycopy(oldQueue, next_out, queue, 0, len);
192            if (next_out != 0)
193              System.arraycopy(oldQueue, 0, queue, len, next_out);
194    
195            next_out = 0;
196            next_in = oldQueue.length;
197          }
198        notify();
199      }
200    
201      /** @since JDK1.2 */
202      public static void invokeAndWait(Runnable runnable)
203        throws InterruptedException, InvocationTargetException
204      {
205        EventQueue eq = Toolkit.getDefaultToolkit().getSystemEventQueue();
206        Thread current = Thread.currentThread();
207        if (current == eq.dispatchThread)
208          throw new Error("Can't call invokeAndWait from event dispatch thread");
209    
210        InvocationEvent ie =
211          new InvocationEvent(eq, runnable, current, true);
212    
213        synchronized (current)
214          {
215            eq.postEvent(ie);
216            current.wait();
217          }
218    
219        Exception exception;
220    
221        if ((exception = ie.getException()) != null)
222          throw new InvocationTargetException(exception);
223      }
224    
225      /** @since JDK1.2 */
226      public static void invokeLater(Runnable runnable)
227      {
228        EventQueue eq = Toolkit.getDefaultToolkit().getSystemEventQueue();
229    
230        InvocationEvent ie =
231          new InvocationEvent(eq, runnable, null, false);
232    
233        eq.postEvent(ie);
234      }
235    
236      public static boolean isDispatchThread()
237      {
238        EventQueue eq = Toolkit.getDefaultToolkit().getSystemEventQueue();
239        return (Thread.currentThread() == eq.dispatchThread);
240      }
241    
242      /** Allows a custom EventQueue implementation to replace this one.
243        * All pending events are transferred to the new queue. Calls to postEvent,
244        * getNextEvent, and peekEvent are forwarded to the pushed queue until it
245        * is removed with a pop().
246        */
247      public synchronized void push(EventQueue newEventQueue)
248      {
249        int i = next_out;
250        while (i != next_in)
251          {
252            newEventQueue.postEvent(queue[i]);
253            next_out = i;
254            if (++i == queue.length)
255              i = 0;
256          }
257    
258        next = newEventQueue;
259        newEventQueue.prev = this;    
260      }
261    
262      /** Transfer any pending events from this queue back to the parent queue that
263        * was previously push()ed. Event dispatch from this queue is suspended. */
264      protected void pop() throws EmptyStackException
265      {
266        if (prev == null)
267          throw new EmptyStackException();
268    
269        // Don't synchronize both this and prev at the same time, or deadlock could
270        // occur.
271        synchronized (prev)
272          {
273            prev.next = null;
274          }
275    
276        synchronized (this)
277          {
278            int i = next_out;
279            while (i != next_in)
280              {
281                prev.postEvent(queue[i]);
282                next_out = i;
283                if (++i == queue.length)
284                  i = 0;
285              }
286          }
287      }
288    
289      protected void dispatchEvent(AWTEvent evt)
290      {
291        if (evt instanceof ActiveEvent)
292          {
293            ActiveEvent active_evt = (ActiveEvent) evt;
294            active_evt.dispatch();
295          }
296        else
297          {
298            Object source = evt.getSource();
299    
300            if (source instanceof Component)
301              {
302                Component srccmp = (Component) source;
303                srccmp.dispatchEvent(evt);
304              }
305            else if (source instanceof MenuComponent)
306              {
307                MenuComponent srccmp = (MenuComponent) source;
308                srccmp.dispatchEvent(evt);
309              }
310          }
311      }
312  }  }
   
 } // class EventQueue  
   

Legend:
Removed from v.1.5  
changed lines
  Added in v.1.6

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26