FSF GCC merge 02/23/03
[official-gcc.git] / libjava / java / awt / EventQueue.java
blob6b64fb7ee3b950c56d1ee14828d55e52f5ff6107
1 /* Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation
3 This file is part of GNU Classpath.
5 GNU Classpath is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
8 any later version.
10 GNU Classpath is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNU Classpath; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18 02111-1307 USA.
20 Linking this library statically or dynamically with other modules is
21 making a combined work based on this library. Thus, the terms and
22 conditions of the GNU General Public License cover the whole
23 combination.
25 As a special exception, the copyright holders of this library give you
26 permission to link this library with independent modules to produce an
27 executable, regardless of the license terms of these independent
28 modules, and to copy and distribute the resulting executable under
29 terms of your choice, provided that you also meet, for each linked
30 independent module, the terms and conditions of the license of that
31 module. An independent module is a module which is not derived from
32 or based on this library. If you modify this library, you may extend
33 this exception to your version of the library, but you are not
34 obligated to do so. If you do not wish to do so, delete this
35 exception statement from your version. */
38 package java.awt;
40 import java.awt.event.*;
41 import java.util.EmptyStackException;
42 import java.lang.reflect.InvocationTargetException;
44 /* Written using on-line Java 2 Platform Standard Edition v1.3 API
45 * Specification, as well as "The Java Class Libraries", 2nd edition
46 * (Addison-Wesley, 1998).
47 * Status: Believed complete, but untested. Check FIXME's.
50 /**
51 * This class manages a queue of <code>AWTEvent</code> objects that
52 * are posted to it. The AWT system uses only one event queue for all
53 * events.
55 * @author Bryce McKinlay
56 * @author Aaron M. Renn (arenn@urbanophile.com)
58 public class EventQueue
60 private static final int INITIAL_QUEUE_DEPTH = 8;
61 private AWTEvent[] queue = new AWTEvent[INITIAL_QUEUE_DEPTH];
63 private int next_in = 0; // Index where next event will be added to queue
64 private int next_out = 0; // Index of next event to be removed from queue
66 private EventQueue next;
67 private EventQueue prev;
69 private EventDispatchThread dispatchThread = new EventDispatchThread(this);
71 /**
72 * Initializes a new instance of <code>EventQueue</code>.
74 public EventQueue()
78 /**
79 * Returns the next event in the queue. This method will block until
80 * an event is available or until the thread is interrupted.
82 * @return The next event in the queue.
84 * @exception InterruptedException If this thread is interrupted while
85 * waiting for an event to be posted to the queue.
87 public synchronized AWTEvent getNextEvent()
88 throws InterruptedException
90 if (next != null)
91 return next.getNextEvent();
93 while (next_in == next_out)
94 wait();
96 AWTEvent res = queue[next_out];
98 if (++next_out == queue.length)
99 next_out = 0;
100 return res;
104 * Returns the next event in the queue without removing it from the queue.
105 * This method will block until an event is available or until the thread
106 * is interrupted.
108 * @return The next event in the queue.
109 * @specnote Does not block. Returns null if there are no events on the
110 * queue.
112 public synchronized AWTEvent peekEvent()
114 if (next != null)
115 return next.peekEvent();
117 if (next_in != next_out)
118 return queue[next_out];
119 else return null;
123 * Returns the next event in the queue that has the specified id
124 * without removing it from the queue.
125 * This method will block until an event is available or until the thread
126 * is interrupted.
128 * @param id The event id to return.
130 * @return The next event in the queue.
132 * @specnote Does not block. Returns null if there are no matching events
133 * on the queue.
135 public synchronized AWTEvent peekEvent(int id)
137 if (next != null)
138 return next.peekEvent(id);
140 int i = next_out;
141 while (i != next_in)
143 AWTEvent qevt = queue[i];
144 if (qevt.id == id)
145 return qevt;
147 return null;
151 * Posts a new event to the queue.
153 * @param event The event to post to the queue.
155 * @exception NullPointerException If event is null.
157 public synchronized void postEvent(AWTEvent evt)
159 if (next != null)
161 next.postEvent(evt);
162 return;
164 // FIXME: Security checks?
166 /* Check for any events already on the queue with the same source
167 and ID. */
168 int i = next_out;
169 while (i != next_in)
171 AWTEvent qevt = queue[i];
172 Object src;
173 if (qevt.id == evt.id
174 && (src = qevt.getSource()) == evt.getSource()
175 && src instanceof Component)
177 /* If there are, call coalesceEvents on the source component
178 to see if they can be combined. */
179 Component srccmp = (Component) src;
180 AWTEvent coalesced_evt = srccmp.coalesceEvents(qevt, evt);
181 if (coalesced_evt != null)
183 /* Yes. Replace the existing event with the combined event. */
184 queue[i] = coalesced_evt;
185 return;
187 break;
189 if (++i == queue.length)
190 i = 0;
193 queue[next_in] = evt;
194 if (++next_in == queue.length)
195 next_in = 0;
197 if (next_in == next_out)
199 /* Queue is full. Extend it. */
200 AWTEvent[] oldQueue = queue;
201 queue = new AWTEvent[queue.length * 2];
203 int len = oldQueue.length - next_out;
204 System.arraycopy(oldQueue, next_out, queue, 0, len);
205 if (next_out != 0)
206 System.arraycopy(oldQueue, 0, queue, len, next_out);
208 next_out = 0;
209 next_in = oldQueue.length;
211 notify();
215 * Causes runnable to have its run method called in the dispatch thread of the
216 * EventQueue. This will happen after all pending events are processed. The
217 * call blocks until this has happened. This method will throw an Error if
218 * called from the event dispatcher thread.
220 * @exception InterruptedException If another thread has interrupted
221 * this thread.
222 * @exception InvocationTargetException If an exception is thrown when running
223 * runnable.
225 * @since 1.2
227 public static void invokeAndWait(Runnable runnable)
228 throws InterruptedException, InvocationTargetException
230 EventQueue eq = Toolkit.getDefaultToolkit().getSystemEventQueue();
231 Thread current = Thread.currentThread();
232 if (current == eq.dispatchThread)
233 throw new Error("Can't call invokeAndWait from event dispatch thread");
235 InvocationEvent ie =
236 new InvocationEvent(eq, runnable, current, true);
238 synchronized (current)
240 eq.postEvent(ie);
241 current.wait();
244 Exception exception;
246 if ((exception = ie.getException()) != null)
247 throw new InvocationTargetException(exception);
250 /** @since JDK1.2 */
251 public static void invokeLater(Runnable runnable)
253 EventQueue eq = Toolkit.getDefaultToolkit().getSystemEventQueue();
255 InvocationEvent ie =
256 new InvocationEvent(eq, runnable, null, false);
258 eq.postEvent(ie);
261 public static boolean isDispatchThread()
263 EventQueue eq = Toolkit.getDefaultToolkit().getSystemEventQueue();
264 return (Thread.currentThread() == eq.dispatchThread);
267 /** Allows a custom EventQueue implementation to replace this one.
268 * All pending events are transferred to the new queue. Calls to postEvent,
269 * getNextEvent, and peekEvent are forwarded to the pushed queue until it
270 * is removed with a pop().
272 * @exception NullPointerException if newEventQueue is null.
274 public synchronized void push(EventQueue newEventQueue)
276 int i = next_out;
277 while (i != next_in)
279 newEventQueue.postEvent(queue[i]);
280 next_out = i;
281 if (++i == queue.length)
282 i = 0;
285 next = newEventQueue;
286 newEventQueue.prev = this;
289 /** Transfer any pending events from this queue back to the parent queue that
290 * was previously push()ed. Event dispatch from this queue is suspended.
292 * @exception EmptyStackException If no previous push was made on this
293 * EventQueue.
295 protected void pop() throws EmptyStackException
297 if (prev == null)
298 throw new EmptyStackException();
300 // Don't synchronize both this and prev at the same time, or deadlock could
301 // occur.
302 synchronized (prev)
304 prev.next = null;
307 synchronized (this)
309 int i = next_out;
310 while (i != next_in)
312 prev.postEvent(queue[i]);
313 next_out = i;
314 if (++i == queue.length)
315 i = 0;
321 * Dispatches an event. The manner in which the event is dispatched depends
322 * upon the type of the event and the type of the event's source object.
324 * @exception NullPointerException If event is null.
326 protected void dispatchEvent(AWTEvent evt)
328 if (evt instanceof ActiveEvent)
330 ActiveEvent active_evt = (ActiveEvent) evt;
331 active_evt.dispatch();
333 else
335 Object source = evt.getSource();
337 if (source instanceof Component)
339 Component srccmp = (Component) source;
340 srccmp.dispatchEvent(evt);
342 else if (source instanceof MenuComponent)
344 MenuComponent srccmp = (MenuComponent) source;
345 srccmp.dispatchEvent(evt);
351 * Returns the timestamp of the most recent event that had a timestamp, or
352 * the initialization time of the event queue if no events have been fired.
353 * At present, only <code>InputEvent</code>s, <code>ActionEvent</code>s,
354 * <code>InputMethodEvent</code>s, and <code>InvocationEvent</code>s have
355 * timestamps, but this may be added to other events in future versions.
356 * If this is called by the event dispatching thread, it can be any
357 * (sequential) value, but to other threads, the safest bet is to return
358 * System.currentTimeMillis().
360 * @return the most recent timestamp
361 * @see InputEvent#getWhen()
362 * @see ActionEvent#getWhen()
363 * @see InvocationEvent#getWhen()
364 * @see InputMethodEvent#getWhen()
365 * @since 1.4
367 public static long getMostRecentEventTime()
369 // XXX For now, this ONLY does the current time.
370 return System.currentTimeMillis();
372 } // class EventQueue