source: trunk/src/gcc/libjava/java/awt/EventQueue.java@ 1389

Last change on this file since 1389 was 2, checked in by bird, 23 years ago

Initial revision

  • Property cvs2svn:cvs-rev set to 1.1
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 8.8 KB
Line 
1/* Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation
2
3This file is part of GNU Classpath.
4
5GNU Classpath is free software; you can redistribute it and/or modify
6it under the terms of the GNU General Public License as published by
7the Free Software Foundation; either version 2, or (at your option)
8any later version.
9
10GNU Classpath is distributed in the hope that it will be useful, but
11WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with GNU Classpath; see the file COPYING. If not, write to the
17Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
1802111-1307 USA.
19
20Linking this library statically or dynamically with other modules is
21making a combined work based on this library. Thus, the terms and
22conditions of the GNU General Public License cover the whole
23combination.
24
25As a special exception, the copyright holders of this library give you
26permission to link this library with independent modules to produce an
27executable, regardless of the license terms of these independent
28modules, and to copy and distribute the resulting executable under
29terms of your choice, provided that you also meet, for each linked
30independent module, the terms and conditions of the license of that
31module. An independent module is a module which is not derived from
32or based on this library. If you modify this library, you may extend
33this exception to your version of the library, but you are not
34obligated to do so. If you do not wish to do so, delete this
35exception statement from your version. */
36
37
38package java.awt;
39
40import java.awt.event.*;
41import java.util.EmptyStackException;
42import java.lang.reflect.InvocationTargetException;
43
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.
48 */
49
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.
54 *
55 * @author Bryce McKinlay
56 * @author Aaron M. Renn ([email protected])
57 */
58public class EventQueue
59{
60 private static final int INITIAL_QUEUE_DEPTH = 8;
61 private AWTEvent[] queue = new AWTEvent[INITIAL_QUEUE_DEPTH];
62
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
65
66 private EventQueue next;
67 private EventQueue prev;
68
69 private EventDispatchThread dispatchThread = new EventDispatchThread(this);
70
71 /**
72 * Initializes a new instance of <code>EventQueue</code>.
73 */
74 public EventQueue()
75 {
76 }
77
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.
81 *
82 * @return The next event in the queue.
83 *
84 * @exception InterruptedException If this thread is interrupted while
85 * waiting for an event to be posted to the queue.
86 */
87 public synchronized AWTEvent getNextEvent()
88 throws InterruptedException
89 {
90 if (next != null)
91 return next.getNextEvent();
92
93 while (next_in == next_out)
94 wait();
95
96 AWTEvent res = queue[next_out];
97
98 if (++next_out == queue.length)
99 next_out = 0;
100 return res;
101 }
102
103 /**
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.
107 *
108 * @return The next event in the queue.
109 * @specnote Does not block. Returns null if there are no events on the
110 * queue.
111 */
112 public synchronized AWTEvent peekEvent()
113 {
114 if (next != null)
115 return next.peekEvent();
116
117 if (next_in != next_out)
118 return queue[next_out];
119 else return null;
120 }
121
122 /**
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.
127 *
128 * @param id The event id to return.
129 *
130 * @return The next event in the queue.
131 *
132 * @specnote Does not block. Returns null if there are no matching events
133 * on the queue.
134 */
135 public synchronized AWTEvent peekEvent(int id)
136 {
137 if (next != null)
138 return next.peekEvent(id);
139
140 int i = next_out;
141 while (i != next_in)
142 {
143 AWTEvent qevt = queue[i];
144 if (qevt.id == id)
145 return qevt;
146 }
147 return null;
148 }
149
150 /**
151 * Posts a new event to the queue.
152 *
153 * @param event The event to post to the queue.
154 */
155 public synchronized void postEvent(AWTEvent evt)
156 {
157 if (next != null)
158 {
159 next.postEvent(evt);
160 return;
161 }
162 // FIXME: Security checks?
163
164 /* Check for any events already on the queue with the same source
165 and ID. */
166 int i = next_out;
167 while (i != next_in)
168 {
169 AWTEvent qevt = queue[i];
170 Object src;
171 if (qevt.id == evt.id
172 && (src = qevt.getSource()) == evt.getSource()
173 && src instanceof Component)
174 {
175 /* If there are, call coalesceEvents on the source component
176 to see if they can be combined. */
177 Component srccmp = (Component) src;
178 AWTEvent coalesced_evt = srccmp.coalesceEvents(qevt, evt);
179 if (coalesced_evt != null)
180 {
181 /* Yes. Replace the existing event with the combined event. */
182 queue[i] = coalesced_evt;
183 return;
184 }
185 break;
186 }
187 if (++i == queue.length)
188 i = 0;
189 }
190
191 queue[next_in] = evt;
192 if (++next_in == queue.length)
193 next_in = 0;
194
195 if (next_in == next_out)
196 {
197 /* Queue is full. Extend it. */
198 AWTEvent[] oldQueue = queue;
199 queue = new AWTEvent[queue.length * 2];
200
201 int len = oldQueue.length - next_out;
202 System.arraycopy(oldQueue, next_out, queue, 0, len);
203 if (next_out != 0)
204 System.arraycopy(oldQueue, 0, queue, len, next_out);
205
206 next_out = 0;
207 next_in = oldQueue.length;
208 }
209 notify();
210 }
211
212 /** @since JDK1.2 */
213 public static void invokeAndWait(Runnable runnable)
214 throws InterruptedException, InvocationTargetException
215 {
216 EventQueue eq = Toolkit.getDefaultToolkit().getSystemEventQueue();
217 Thread current = Thread.currentThread();
218 if (current == eq.dispatchThread)
219 throw new Error("Can't call invokeAndWait from event dispatch thread");
220
221 InvocationEvent ie =
222 new InvocationEvent(eq, runnable, current, true);
223
224 synchronized (current)
225 {
226 eq.postEvent(ie);
227 current.wait();
228 }
229
230 Exception exception;
231
232 if ((exception = ie.getException()) != null)
233 throw new InvocationTargetException(exception);
234 }
235
236 /** @since JDK1.2 */
237 public static void invokeLater(Runnable runnable)
238 {
239 EventQueue eq = Toolkit.getDefaultToolkit().getSystemEventQueue();
240
241 InvocationEvent ie =
242 new InvocationEvent(eq, runnable, null, false);
243
244 eq.postEvent(ie);
245 }
246
247 public static boolean isDispatchThread()
248 {
249 EventQueue eq = Toolkit.getDefaultToolkit().getSystemEventQueue();
250 return (Thread.currentThread() == eq.dispatchThread);
251 }
252
253 /** Allows a custom EventQueue implementation to replace this one.
254 * All pending events are transferred to the new queue. Calls to postEvent,
255 * getNextEvent, and peekEvent are forwarded to the pushed queue until it
256 * is removed with a pop().
257 */
258 public synchronized void push(EventQueue newEventQueue)
259 {
260 int i = next_out;
261 while (i != next_in)
262 {
263 newEventQueue.postEvent(queue[i]);
264 next_out = i;
265 if (++i == queue.length)
266 i = 0;
267 }
268
269 next = newEventQueue;
270 newEventQueue.prev = this;
271 }
272
273 /** Transfer any pending events from this queue back to the parent queue that
274 * was previously push()ed. Event dispatch from this queue is suspended. */
275 protected void pop() throws EmptyStackException
276 {
277 if (prev == null)
278 throw new EmptyStackException();
279
280 // Don't synchronize both this and prev at the same time, or deadlock could
281 // occur.
282 synchronized (prev)
283 {
284 prev.next = null;
285 }
286
287 synchronized (this)
288 {
289 int i = next_out;
290 while (i != next_in)
291 {
292 prev.postEvent(queue[i]);
293 next_out = i;
294 if (++i == queue.length)
295 i = 0;
296 }
297 }
298 }
299
300 protected void dispatchEvent(AWTEvent evt)
301 {
302 if (evt instanceof ActiveEvent)
303 {
304 ActiveEvent active_evt = (ActiveEvent) evt;
305 active_evt.dispatch();
306 }
307 else
308 {
309 Object source = evt.getSource();
310
311 if (source instanceof Component)
312 {
313 Component srccmp = (Component) source;
314 srccmp.dispatchEvent(evt);
315 }
316 else if (source instanceof MenuComponent)
317 {
318 MenuComponent srccmp = (MenuComponent) source;
319 srccmp.dispatchEvent(evt);
320 }
321 }
322 }
323}
Note: See TracBrowser for help on using the repository browser.