home *** CD-ROM | disk | FTP | other *** search
Java Source | 1998-03-20 | 10.6 KB | 334 lines |
- /*
- * @(#)EventQueue.java 1.20 98/03/18
- *
- * Copyright 1996-1998 by Sun Microsystems, Inc.,
- * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
- * All rights reserved.
- *
- * This software is the confidential and proprietary information
- * of Sun Microsystems, Inc. ("Confidential Information"). You
- * shall not disclose such Confidential Information and shall use
- * it only in accordance with the terms of the license agreement
- * you entered into with Sun.
- */
-
- package java.awt;
-
- import java.awt.event.EventQueueListener;
- import java.awt.event.FocusEvent;
- import java.awt.event.KeyEvent;
- import java.awt.event.MouseEvent;
- import java.awt.event.PaintEvent;
- import java.awt.ActiveEvent;
- import java.util.EventListener;
- import java.util.EmptyStackException;
-
- /**
- * EventQueue is a platform-independent class that queues events, both
- * from the underlying peer classes and from trusted application classes.
- * There is only one EventQueue for the system.
- *
- * @version 1.20 03/18/98
- * @author Thomas Ball
- */
- public class EventQueue {
-
- // From Thread.java
- private static int threadInitNumber;
- private static synchronized int nextThreadNum() {
- return threadInitNumber++;
- }
-
- /* package-private variables are used to make push/pop faster. */
-
- /* The actual queue of events, implemented as a linked-list. */
- EventQueueItem queue;
-
- /* The multiplexed EventQueueListener list. */
- EventQueueListener eventQueueListener;
-
- /*
- * The next EventQueue on the stack, or null if this EventQueue is
- * on the top of the stack. If next is non-null, requests to post
- * an event are forwarded to next.
- */
- EventQueue next;
-
- /*
- * The previous EventQueue on the stack, or null if this is the
- * "base" EventQueue.
- */
- EventQueue prev;
-
- public EventQueue() {
- queue = null;
- String name = "AWT-EventQueue-" + nextThreadNum();
- new EventDispatchThread(name, this).start();
- }
-
- /**
- * Post a 1.1-style event to the EventQueue.
- *
- * @param theEvent an instance of java.awt.AWTEvent, or a
- * subclass of it.
- */
- public synchronized void postEvent(AWTEvent theEvent) {
- if (next != null) {
- // Forward event to top of EventQueue stack.
- next.postEvent(theEvent);
- return;
- }
-
- Object source = theEvent.getSource();
- EventQueueItem eqi = new EventQueueItem(theEvent);
- if (queue == null) {
- queue = eqi;
- notifyAll();
- } else {
- EventQueueItem q = queue;
- for (;;) {
- if (source instanceof Component &&
- q.id == eqi.id &&
- q.event.getSource().equals(source)) {
- AWTEvent coalescedEvent =
- ((Component)source).coalesceEvents(q.event, theEvent);
- if (coalescedEvent != null) {
- q.event = coalescedEvent;
- return;
- }
- }
- if (q.next != null) {
- q = q.next;
- } else {
- break;
- }
- }
- q.next = eqi;
- }
- notifyEventQueueListeners(theEvent);
- }
-
- /**
- * Remove an event from the queue and return it. This method will
- * block until an event has been posted by another thread.
- * @return the next AWTEvent
- * @exception InterruptedException
- * if another thread has interrupted this thread.
- */
- public synchronized AWTEvent getNextEvent() throws InterruptedException {
- while (queue == null) {
- wait();
- }
- EventQueueItem eqi = queue;
- queue = queue.next;
- return eqi.event;
- }
-
- /**
- * Return the first event without removing it.
- * @return the first event, which is either an instance of java.awt.Event
- * or java.awt.AWTEvent.
- */
- public synchronized AWTEvent peekEvent() {
- return (queue != null) ? queue.event : null;
- }
-
- /*
- * Return the first event of the specified type, if any.
- * @param id the id of the type of event desired.
- * @return the first event of the requested type,
- * which is either an instance of java.awt.Event
- * or java.awt.AWTEvent.
- */
- public synchronized AWTEvent peekEvent(int id) {
- EventQueueItem q = queue;
- for (; q != null; q = q.next) {
- if (q.id == id) {
- return q.event;
- }
- }
- return null;
- }
-
- /**
- * Dispatch an event to its source.
- *
- * @param theEvent an instance of java.awt.AWTEvent, or a
- * subclass of it.
- */
- protected void dispatchEvent(AWTEvent event) {
- Object src = event.getSource();
- if (event instanceof ActiveEvent) {
- // This could become the sole method of dispatching in time.
- ((ActiveEvent)event).dispatch();
- } else if (src instanceof Component) {
- ((Component)src).dispatchEvent(event);
- } else if (src instanceof MenuComponent) {
- ((MenuComponent)src).dispatchEvent(event);
- } else {
- System.err.println("unable to dispatch event: " + event);
- }
- }
-
- /**
- * Replace the existing EventQueue with the specified one.
- * Any pending events are transferred to the new EventQueue
- * for processing by it.
- *
- * @param an EventQueue (or subclass thereof) instance to be used.
- */
- public synchronized void push(EventQueue newEventQueue) {
- synchronized (newEventQueue) {
- newEventQueue.queue = queue; // may be null
- newEventQueue.prev = this;
- next = newEventQueue;
- }
- }
-
- /**
- * Stop dispatching events using this EventQueue instance.
- * Any pending events are transferred to the previous
- * EventQueue for processing by it. If called from the
- * initial EventQueue for this AWTContext, an
- * EmptyStackException is thrown.
- */
- protected synchronized void pop() throws EmptyStackException {
- synchronized (prev) {
- prev.queue = queue; // may be null
- prev.next = null;
- prev = null;
- next = null;
- }
- }
-
- /**
- * Returns true if the calling thread is this EventQueue's
- * dispatch thread. Use this call the ensure that a given
- * task is being executed (or not being) on the current
- * EventDispatchThread.
- *
- * @return true if running on this EventQueue's dispatch thread.
- */
- public static boolean isDispatchThread() {
- return (Thread.currentThread() instanceof EventDispatchThread);
- }
-
- /**
- * Adds an EventListener to receive AWTEvents from this
- * EventQueue. Listeners continue receiving events if a new
- * EventQueue is pushed or an existing one is popped.
- * <p>
- * Note: event listener use is not recommended for normal
- * application use, but are intended solely to support special
- * purpose facilities including support for accessibility,
- * event record/playback, and diagnostic tracing.
- *
- * @param l the event listener.
- * @see java.awt.EventQueueListener
- * @see java.awt.EventQueue#removeEventQueueListener
- * @since JDK1.2
- */
- public synchronized void addEventQueueListener(EventQueueListener l) {
- eventQueueListener = EventQueueMulticaster.add(eventQueueListener, l);
- }
-
- /**
- * Removes an EventListener so that it no longer receives
- * events from this EventQueue.
- * <p>
- * Note: event listener use is not recommended for normal
- * application use, but are intended solely to support special
- * purpose facilities including support for accessibility,
- * event record/playback, and diagnostic tracing.
- *
- * @param l the event listener.
- * @see java.awt.EventQueueListener
- * @see java.awt.EventQueue#addEventQueueListener
- * @since JDK1.2
- */
- public synchronized void removeEventQueueListener(EventQueueListener l) {
- eventQueueListener = EventQueueMulticaster.remove(eventQueueListener, l);
- }
-
- /**
- * This method notifies any EventQueueListeners that an event
- * has been posted to the EventQueue. If an EventQueue subclass
- * overrides postEvent, it <b>must</b> either call this method
- * or call <code>super.postEvent(event)</code>.
- *
- * @param theEvent the event which has been posted to the EventQueue.
- */
- protected void notifyEventQueueListeners(AWTEvent theEvent) {
- if (eventQueueListener != null) {
- eventQueueListener.eventPosted(theEvent);
- }
- }
-
- /*
- * Change the target of any pending KeyEvents because of a focus change.
- */
- synchronized void changeKeyEventFocus(Object newSource) {
- EventQueueItem q = queue;
- for (; q != null; q = q.next) {
- if (q.event instanceof KeyEvent) {
- q.event.setSource(newSource);
- }
- }
- }
-
- /*
- * Remove any pending events for the specified source object.
- * This method is normally called by the source's removeNotify method.
- */
- synchronized void removeSourceEvents(Object source) {
- EventQueueItem entry = queue;
- EventQueueItem prev = null;
- while (entry != null) {
- if (entry.event.getSource().equals(source)) {
- if (prev == null) {
- queue = entry.next;
- } else {
- prev.next = entry.next;
- }
- }
- prev = entry;
- entry = entry.next;
- }
- }
-
- static private class EventQueueMulticaster extends AWTEventMulticaster
- implements EventQueueListener {
- // Implementation cloned from AWTEventMulticaster.
-
- EventQueueMulticaster(EventListener a, EventListener b) {
- super(a, b);
- }
-
- static EventQueueListener add(EventQueueListener a,
- EventQueueListener b) {
- return (EventQueueListener)addInternal(a, b);
- }
-
- static EventQueueListener remove(EventQueueListener l,
- EventQueueListener oldl) {
- return (EventQueueListener) removeInternal(l, oldl);
- }
-
- public void eventPosted(AWTEvent e) {
- ((EventQueueListener)a).eventPosted(e);
- ((EventQueueListener)b).eventPosted(e);
- }
- }
- }
-
- class EventQueueItem {
- AWTEvent event;
- int id;
- EventQueueItem next;
-
- EventQueueItem(AWTEvent evt) {
- event = evt;
- id = evt.getID();
- }
- }
-