OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [libjava/] [classpath/] [java/] [awt/] [EventQueue.java] - Blame information for rev 14

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 14 jlechner
/* EventQueue.java --
2
   Copyright (C) 1999, 2000, 2001, 2002, 2003, 2005  Free Software Foundation
3
 
4
This file is part of GNU Classpath.
5
 
6
GNU Classpath is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2, or (at your option)
9
any later version.
10
 
11
GNU Classpath is distributed in the hope that it will be useful, but
12
WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
General Public License for more details.
15
 
16
You should have received a copy of the GNU General Public License
17
along with GNU Classpath; see the file COPYING.  If not, write to the
18
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
02110-1301 USA.
20
 
21
Linking this library statically or dynamically with other modules is
22
making a combined work based on this library.  Thus, the terms and
23
conditions of the GNU General Public License cover the whole
24
combination.
25
 
26
As a special exception, the copyright holders of this library give you
27
permission to link this library with independent modules to produce an
28
executable, regardless of the license terms of these independent
29
modules, and to copy and distribute the resulting executable under
30
terms of your choice, provided that you also meet, for each linked
31
independent module, the terms and conditions of the license of that
32
module.  An independent module is a module which is not derived from
33
or based on this library.  If you modify this library, you may extend
34
this exception to your version of the library, but you are not
35
obligated to do so.  If you do not wish to do so, delete this
36
exception statement from your version. */
37
 
38
 
39
package java.awt;
40
 
41
import java.awt.event.ActionEvent;
42
import java.awt.event.InputEvent;
43
import java.awt.event.InputMethodEvent;
44
import java.awt.event.InvocationEvent;
45
import java.lang.reflect.InvocationTargetException;
46
import java.util.EmptyStackException;
47
 
48
/* Written using on-line Java 2 Platform Standard Edition v1.3 API
49
 * Specification, as well as "The Java Class Libraries", 2nd edition
50
 * (Addison-Wesley, 1998).
51
 * Status:  Believed complete, but untested.
52
 */
53
 
54
/**
55
 * This class manages a queue of <code>AWTEvent</code> objects that
56
 * are posted to it.  The AWT system uses only one event queue for all
57
 * events.
58
 *
59
 * @author Bryce McKinlay
60
 * @author Aaron M. Renn (arenn@urbanophile.com)
61
 */
62
public class EventQueue
63
{
64
  private static final int INITIAL_QUEUE_DEPTH = 8;
65
  private AWTEvent[] queue = new AWTEvent[INITIAL_QUEUE_DEPTH];
66
 
67
  private int next_in = 0; // Index where next event will be added to queue
68
  private int next_out = 0; // Index of next event to be removed from queue
69
 
70
  private EventQueue next;
71
  private EventQueue prev;
72
  private AWTEvent currentEvent;
73
  private long lastWhen = System.currentTimeMillis();
74
 
75
  private EventDispatchThread dispatchThread = new EventDispatchThread(this);
76
  private boolean shutdown = false;
77
 
78
  synchronized private void setShutdown (boolean b)
79
  {
80
    shutdown = b;
81
  }
82
 
83
  synchronized boolean isShutdown ()
84
  {
85
    if (shutdown)
86
      return true;
87
 
88
    // This is the exact self-shutdown condition specified in J2SE:
89
    // http://java.sun.com/j2se/1.4.2/docs/api/java/awt/doc-files/AWTThreadIssues.html
90
 
91
    // FIXME: check somewhere that the native queue is empty
92
    if (peekEvent() == null)
93
      {
94
        Frame[] frames = Frame.getFrames();
95
        for (int i = 0; i < frames.length; ++i)
96
          if (frames[i].isDisplayable())
97
            return false;
98
        return true;
99
      }
100
    return false;
101
  }
102
 
103
  /**
104
   * Initializes a new instance of <code>EventQueue</code>.
105
   */
106
  public EventQueue()
107
  {
108
  }
109
 
110
  /**
111
   * Returns the next event in the queue.  This method will block until
112
   * an event is available or until the thread is interrupted.
113
   *
114
   * @return The next event in the queue.
115
   *
116
   * @exception InterruptedException If this thread is interrupted while
117
   * waiting for an event to be posted to the queue.
118
   */
119
  public synchronized AWTEvent getNextEvent()
120
    throws InterruptedException
121
  {
122
    if (next != null)
123
      return next.getNextEvent();
124
 
125
    while (next_in == next_out)
126
      {
127
        // We are not allowed to return null from this method, yet it
128
        // is possible that we actually have run out of native events
129
        // in the enclosing while() loop, and none of the native events
130
        // happened to cause AWT events. We therefore ought to check
131
        // the isShutdown() condition here, before risking a "native
132
        // wait". If we check it before entering this function we may
133
        // wait forever for events after the shutdown condition has
134
        // arisen.
135
 
136
        if (isShutdown())
137
          throw new InterruptedException();
138
 
139
        wait();
140
      }
141
 
142
    AWTEvent res = queue[next_out];
143
 
144
    if (++next_out == queue.length)
145
      next_out = 0;
146
    return res;
147
  }
148
 
149
  /**
150
   * Returns the next event in the queue without removing it from the queue.
151
   * This method will block until an event is available or until the thread
152
   * is interrupted.
153
   *
154
   * @return The next event in the queue.
155
   * @specnote Does not block. Returns null if there are no events on the
156
   *            queue.
157
   */
158
  public synchronized AWTEvent peekEvent()
159
  {
160
    if (next != null)
161
      return next.peekEvent();
162
 
163
    if (next_in != next_out)
164
      return queue[next_out];
165
    else
166
      return null;
167
  }
168
 
169
  /**
170
   * Returns the next event in the queue that has the specified id
171
   * without removing it from the queue.
172
   * This method will block until an event is available or until the thread
173
   * is interrupted.
174
   *
175
   * @param id The event id to return.
176
   *
177
   * @return The next event in the queue.
178
   *
179
   * @specnote Does not block. Returns null if there are no matching events
180
   *            on the queue.
181
   */
182
  public synchronized AWTEvent peekEvent(int id)
183
  {
184
    if (next != null)
185
      return next.peekEvent(id);
186
 
187
    int i = next_out;
188
    while (i != next_in)
189
      {
190
        AWTEvent qevt = queue[i];
191
        if (qevt.id == id)
192
          return qevt;
193
      }
194
    return null;
195
  }
196
 
197
  /**
198
   * Posts a new event to the queue.
199
   *
200
   * @param evt The event to post to the queue.
201
   *
202
   * @exception NullPointerException If event is null.
203
   */
204
  public synchronized void postEvent(AWTEvent evt)
205
  {
206
    if (evt == null)
207
      throw new NullPointerException();
208
 
209
    if (next != null)
210
      {
211
        next.postEvent(evt);
212
        return;
213
      }
214
 
215
    /* Check for any events already on the queue with the same source
216
       and ID. */
217
    int i = next_out;
218
    while (i != next_in)
219
      {
220
        AWTEvent qevt = queue[i];
221
        Object src;
222
        if (qevt.id == evt.id
223
            && (src = qevt.getSource()) == evt.getSource()
224
            && src instanceof Component)
225
          {
226
            /* If there are, call coalesceEvents on the source component
227
               to see if they can be combined. */
228
            Component srccmp = (Component) src;
229
            AWTEvent coalesced_evt = srccmp.coalesceEvents(qevt, evt);
230
            if (coalesced_evt != null)
231
              {
232
                /* Yes. Replace the existing event with the combined event. */
233
                queue[i] = coalesced_evt;
234
                return;
235
              }
236
            break;
237
          }
238
        if (++i == queue.length)
239
          i = 0;
240
      }
241
 
242
    queue[next_in] = evt;
243
    if (++next_in == queue.length)
244
      next_in = 0;
245
 
246
    if (next_in == next_out)
247
      {
248
        /* Queue is full. Extend it. */
249
        AWTEvent[] oldQueue = queue;
250
        queue = new AWTEvent[queue.length * 2];
251
 
252
        int len = oldQueue.length - next_out;
253
        System.arraycopy(oldQueue, next_out, queue, 0, len);
254
        if (next_out != 0)
255
          System.arraycopy(oldQueue, 0, queue, len, next_out);
256
 
257
        next_out = 0;
258
        next_in = oldQueue.length;
259
      }
260
 
261
    if (dispatchThread == null || !dispatchThread.isAlive())
262
      {
263
        dispatchThread = new EventDispatchThread(this);
264
        dispatchThread.start();
265
      }
266
 
267
    notify();
268
  }
269
 
270
  /**
271
   * Causes runnable to have its run method called in the dispatch thread of the
272
   * EventQueue. This will happen after all pending events are processed. The
273
   * call blocks until this has happened. This method will throw an Error if
274
   * called from the event dispatcher thread.
275
   *
276
   * @exception InterruptedException If another thread has interrupted
277
   * this thread.
278
   * @exception InvocationTargetException If an exception is thrown when running
279
   * runnable.
280
   *
281
   * @since 1.2
282
   */
283
  public static void invokeAndWait(Runnable runnable)
284
    throws InterruptedException, InvocationTargetException
285
  {
286
    if (isDispatchThread ())
287
      throw new Error("Can't call invokeAndWait from event dispatch thread");
288
 
289
    EventQueue eq = Toolkit.getDefaultToolkit().getSystemEventQueue();
290
    Thread current = Thread.currentThread();
291
 
292
    InvocationEvent ie =
293
      new InvocationEvent(eq, runnable, current, true);
294
 
295
    synchronized (current)
296
      {
297
        eq.postEvent(ie);
298
        current.wait();
299
      }
300
 
301
    Exception exception;
302
 
303
    if ((exception = ie.getException()) != null)
304
      throw new InvocationTargetException(exception);
305
  }
306
 
307
  /**
308
   * This arranges for runnable to have its run method called in the
309
   * dispatch thread of the EventQueue.  This will happen after all
310
   * pending events are processed.
311
   *
312
   * @since 1.2
313
   */
314
  public static void invokeLater(Runnable runnable)
315
  {
316
    EventQueue eq = Toolkit.getDefaultToolkit().getSystemEventQueue();
317
 
318
    InvocationEvent ie =
319
      new InvocationEvent(eq, runnable, null, false);
320
 
321
    eq.postEvent(ie);
322
  }
323
 
324
  /**
325
   * Return true if the current thread is the current AWT event dispatch
326
   * thread.
327
   */
328
  public static boolean isDispatchThread()
329
  {
330
    EventQueue eq = Toolkit.getDefaultToolkit().getSystemEventQueue();
331
 
332
    /* Find last EventQueue in chain */
333
    while (eq.next != null)
334
      eq = eq.next;
335
 
336
    return (Thread.currentThread() == eq.dispatchThread);
337
  }
338
 
339
  /**
340
   * Return the event currently being dispatched by the event
341
   * dispatch thread.  If the current thread is not the event
342
   * dispatch thread, this method returns null.
343
   *
344
   * @since 1.4
345
   */
346
  public static AWTEvent getCurrentEvent()
347
  {
348
    EventQueue eq = Toolkit.getDefaultToolkit().getSystemEventQueue();
349
    Thread ct = Thread.currentThread();
350
 
351
    /* Find out if this thread is the dispatch thread for any of the
352
       EventQueues in the chain */
353
    while (ct != eq.dispatchThread)
354
      {
355
        // Try next EventQueue, if any
356
        if (eq.next == null)
357
           return null;  // Not an event dispatch thread
358
        eq = eq.next;
359
      }
360
 
361
    return eq.currentEvent;
362
  }
363
 
364
  /**
365
   * Allows a custom EventQueue implementation to replace this one.
366
   * All pending events are transferred to the new queue. Calls to postEvent,
367
   * getNextEvent, and peekEvent and others are forwarded to the pushed queue
368
   * until it is removed with a pop().
369
   *
370
   * @exception NullPointerException if newEventQueue is null.
371
   */
372
  public synchronized void push(EventQueue newEventQueue)
373
  {
374
    if (newEventQueue == null)
375
      throw new NullPointerException ();
376
 
377
    /* Make sure we are at the top of the stack because callers can
378
       only get a reference to the one at the bottom using
379
       Toolkit.getDefaultToolkit().getSystemEventQueue() */
380
    if (next != null)
381
      {
382
        next.push (newEventQueue);
383
        return;
384
      }
385
 
386
    /* Make sure we have a live dispatch thread to drive the queue */
387
    if (dispatchThread == null)
388
      dispatchThread = new EventDispatchThread(this);
389
 
390
    int i = next_out;
391
    while (i != next_in)
392
      {
393
        newEventQueue.postEvent(queue[i]);
394
        next_out = i;
395
        if (++i == queue.length)
396
          i = 0;
397
      }
398
 
399
    next = newEventQueue;
400
    newEventQueue.prev = this;
401
  }
402
 
403
  /** Transfer any pending events from this queue back to the parent queue that
404
    * was previously push()ed. Event dispatch from this queue is suspended.
405
    *
406
    * @exception EmptyStackException If no previous push was made on this
407
    * EventQueue.
408
    */
409
  protected void pop() throws EmptyStackException
410
  {
411
    if (prev == null)
412
      throw new EmptyStackException();
413
 
414
    /* The order is important here, we must get the prev lock first,
415
       or deadlock could occur as callers usually get here following
416
       prev's next pointer, and thus obtain prev's lock before trying
417
       to get this lock. */
418
    synchronized (prev)
419
      {
420
        prev.next = next;
421
        if (next != null)
422
          next.prev = prev;
423
 
424
        synchronized (this)
425
          {
426
            int i = next_out;
427
            while (i != next_in)
428
              {
429
                prev.postEvent(queue[i]);
430
                next_out = i;
431
                if (++i == queue.length)
432
                  i = 0;
433
              }
434
            // Empty the queue so it can be reused
435
            next_in = 0;
436
            next_out = 0;
437
 
438
            setShutdown(true);
439
            dispatchThread = null;
440
            this.notifyAll();
441
          }
442
      }
443
  }
444
 
445
  /**
446
   * Dispatches an event. The manner in which the event is dispatched depends
447
   * upon the type of the event and the type of the event's source object.
448
   *
449
   * @exception NullPointerException If event is null.
450
   */
451
  protected void dispatchEvent(AWTEvent evt)
452
  {
453
    currentEvent = evt;
454
 
455
    if (evt instanceof InputEvent)
456
      lastWhen = ((InputEvent) evt).getWhen();
457
    else if (evt instanceof ActionEvent)
458
      lastWhen = ((ActionEvent) evt).getWhen();
459
    else if (evt instanceof InvocationEvent)
460
      lastWhen = ((InvocationEvent) evt).getWhen();
461
 
462
    if (evt instanceof ActiveEvent)
463
      {
464
        ActiveEvent active_evt = (ActiveEvent) evt;
465
        active_evt.dispatch();
466
      }
467
    else
468
      {
469
        Object source = evt.getSource();
470
 
471
        if (source instanceof Component)
472
          {
473
            Component srccmp = (Component) source;
474
            srccmp.dispatchEvent(evt);
475
          }
476
        else if (source instanceof MenuComponent)
477
          {
478
            MenuComponent srccmp = (MenuComponent) source;
479
            srccmp.dispatchEvent(evt);
480
          }
481
      }
482
  }
483
 
484
  /**
485
   * Returns the timestamp of the most recent event that had a timestamp, or
486
   * the initialization time of the event queue if no events have been fired.
487
   * At present, only <code>InputEvent</code>s, <code>ActionEvent</code>s,
488
   * <code>InputMethodEvent</code>s, and <code>InvocationEvent</code>s have
489
   * timestamps, but this may be added to other events in future versions.
490
   * If this is called by the event dispatching thread, it can be any
491
   * (sequential) value, but to other threads, the safest bet is to return
492
   * System.currentTimeMillis().
493
   *
494
   * @return the most recent timestamp
495
   * @see InputEvent#getWhen()
496
   * @see ActionEvent#getWhen()
497
   * @see InvocationEvent#getWhen()
498
   * @see InputMethodEvent#getWhen()
499
   * @since 1.4
500
   */
501
  public static long getMostRecentEventTime()
502
  {
503
    EventQueue eq = Toolkit.getDefaultToolkit().getSystemEventQueue();
504
    if (Thread.currentThread() != eq.dispatchThread)
505
      return System.currentTimeMillis();
506
    return eq.lastWhen;
507
  }
508
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.