diff options
Diffstat (limited to 'libjava/classpath/java/awt/EventQueue.java')
-rw-r--r-- | libjava/classpath/java/awt/EventQueue.java | 658 |
1 files changed, 0 insertions, 658 deletions
diff --git a/libjava/classpath/java/awt/EventQueue.java b/libjava/classpath/java/awt/EventQueue.java deleted file mode 100644 index cb52ae0..0000000 --- a/libjava/classpath/java/awt/EventQueue.java +++ /dev/null @@ -1,658 +0,0 @@ -/* EventQueue.java -- - Copyright (C) 1999, 2000, 2001, 2002, 2003, 2005 Free Software Foundation - -This file is part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - - -package java.awt; - -import gnu.java.awt.LowPriorityEvent; -import gnu.java.awt.peer.NativeEventLoopRunningEvent; - -import java.awt.event.ActionEvent; -import java.awt.event.InputEvent; -import java.awt.event.InputMethodEvent; -import java.awt.event.InvocationEvent; -import java.awt.event.PaintEvent; -import java.awt.peer.ComponentPeer; -import java.awt.peer.LightweightPeer; -import java.lang.reflect.InvocationTargetException; -import java.util.EmptyStackException; - -/* Written using on-line Java 2 Platform Standard Edition v1.3 API - * Specification, as well as "The Java Class Libraries", 2nd edition - * (Addison-Wesley, 1998). - * Status: Believed complete, but untested. - */ - -/** - * This class manages a queue of <code>AWTEvent</code> objects that - * are posted to it. The AWT system uses only one event queue for all - * events. - * - * @author Bryce McKinlay - * @author Aaron M. Renn (arenn@urbanophile.com) - */ -public class EventQueue -{ - /** - * Indicates events that are processed with normal priority. This is normally - * all events except PaintEvents. - */ - private static final int NORM_PRIORITY = 0; - - /** - * Indicates events that are processed with lowes priority. This is normally - * all PaintEvents and LowPriorityEvents. - */ - private static final int LOW_PRIORITY = 1; - - /** - * Implements the actual queue. EventQueue has 2 internal queues for - * different priorities: - * 1 PaintEvents are always dispatched with low priority. - * 2. All other events are dispatched with normal priority. - * - * This makes sure that the actual painting (output) is performed _after_ all - * available input has been processed and that the paint regions are - * coalesced as much as possible. - */ - private class Queue - { - /** - * The first item in the queue. This is where events are popped from. - */ - AWTEvent queueHead; - - /** - * The last item. This is where events are posted to. - */ - AWTEvent queueTail; - } - - /** - * The three internal event queues. - * - * @see Queue - */ - private Queue[] queues; - - private EventQueue next; - private EventQueue prev; - private AWTEvent currentEvent; - private long lastWhen = System.currentTimeMillis(); - - private EventDispatchThread dispatchThread = new EventDispatchThread(this); - private boolean nativeLoopRunning = false; - - private boolean isShutdown () - { - // This is the exact self-shutdown condition specified in J2SE: - // http://java.sun.com/j2se/1.4.2/docs/api/java/awt/doc-files/AWTThreadIssues.html - - if (nativeLoopRunning) - return false; - - if (peekEvent() != null) - return false; - - if (Frame.hasDisplayableFrames()) - return false; - - return true; - } - - /** - * Initializes a new instance of <code>EventQueue</code>. - */ - public EventQueue() - { - queues = new Queue[2]; - queues[NORM_PRIORITY] = new Queue(); - queues[LOW_PRIORITY] = new Queue(); - } - - /** - * 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 - { - if (next != null) - return next.getNextEvent(); - - AWTEvent res = getNextEventImpl(true); - - while (res == null) - { - if (isShutdown()) - { - // Explicitly set dispathThread to null. If we don't do - // this, there is a race condition where dispatchThread - // can be != null even after the event dispatch thread has - // stopped running. If that happens, then the - // dispatchThread == null check in postEventImpl will - // fail, and a new event dispatch thread will not be - // created, leaving invokeAndWaits waiting indefinitely. - dispatchThread = null; - - // Interrupt the event dispatch thread. - throw new InterruptedException(); - } - - wait(); - res = getNextEventImpl(true); - } - - return res; - } - - /** - * Fetches and possibly removes the next event from the internal queues. - * This method returns immediately. When all queues are empty, this returns - * <code>null</code>: - * - * @param remove <true> when the event should be removed from the queue, - * <code>false</code> otherwise - * - * @return the next event or <code>null</code> when all internal queues - * are empty - */ - private AWTEvent getNextEventImpl(boolean remove) - { - AWTEvent next = null; - for (int i = 0; i < queues.length && next == null; i++) - { - Queue q = queues[i]; - if (q.queueHead != null) - { - // Got an event, remove it. - next = q.queueHead; - if (remove) - { - // Unlink event from the queue. - q.queueHead = next.queueNext; - if (q.queueHead == null) - q.queueTail = null; - next.queueNext = null; - } - } - } - return next; - } - - /** - * 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. - * @specnote Does not block. Returns null if there are no events on the - * queue. - */ - public synchronized AWTEvent peekEvent() - { - if (next != null) - return next.peekEvent(); - - return getNextEventImpl(false); - } - - /** - * Returns the next event in the queue that has the specified id - * without removing it from the queue. - * This method will block until an event is available or until the thread - * is interrupted. - * - * @param id The event id to return. - * - * @return The next event in the queue. - * - * @specnote Does not block. Returns null if there are no matching events - * on the queue. - */ - public synchronized AWTEvent peekEvent(int id) - { - if (next != null) - return next.peekEvent(id); - - AWTEvent evt = null; - for (int i = 0; i < queues.length && evt == null; i++) - { - Queue q = queues[i]; - evt = q.queueHead; - while (evt != null && evt.id != id) - evt = evt.queueNext; - // At this point we either have found an event (evt != null -> exit - // for loop), or we have found no event (evt == null -> search next - // internal queue). - } - return evt; - } - - /** - * Posts a new event to the queue. - * - * @param evt The event to post to the queue. - * - * @exception NullPointerException If event is null. - */ - public void postEvent(AWTEvent evt) - { - postEventImpl(evt); - } - - /** - * Sorts events to their priority and calls - * {@link #postEventImpl(AWTEvent, int)}. - * - * @param evt the event to post - */ - private synchronized final void postEventImpl(AWTEvent evt) - { - int priority = NORM_PRIORITY; - if (evt instanceof PaintEvent || evt instanceof LowPriorityEvent) - priority = LOW_PRIORITY; - // TODO: Maybe let Swing RepaintManager events also be processed with - // low priority. - if (evt instanceof NativeEventLoopRunningEvent) - { - nativeLoopRunning = ((NativeEventLoopRunningEvent) evt).isRunning(); - notify(); - return; - } - postEventImpl(evt, priority); - } - - /** - * Actually performs the event posting. This is needed because the - * RI doesn't use the public postEvent() method when transferring events - * between event queues in push() and pop(). - * - * @param evt the event to post - * @param priority the priority of the event - */ - private final void postEventImpl(AWTEvent evt, int priority) - { - if (evt == null) - throw new NullPointerException(); - - if (next != null) - { - next.postEvent(evt); - return; - } - - Object source = evt.getSource(); - - Queue q = queues[priority]; - if (source instanceof Component) - { - // For PaintEvents, ask the ComponentPeer to coalesce the event - // when the component is heavyweight. - Component comp = (Component) source; - ComponentPeer peer = comp.peer; - if (peer != null && evt instanceof PaintEvent - && ! (peer instanceof LightweightPeer)) - peer.coalescePaintEvent((PaintEvent) evt); - - // Check for any events already on the queue with the same source - // and ID. - AWTEvent previous = null; - for (AWTEvent qevt = q.queueHead; qevt != null; qevt = qevt.queueNext) - { - Object src = qevt.getSource(); - if (qevt.id == evt.id && src == comp) - { - // If there are, call coalesceEvents on the source component - // to see if they can be combined. - Component srccmp = (Component) src; - AWTEvent coalescedEvt = srccmp.coalesceEvents(qevt, evt); - if (coalescedEvt != null) - { - // Yes. Replace the existing event with the combined event. - if (qevt != coalescedEvt) - { - if (previous != null) - { - assert previous.queueNext == qevt; - previous.queueNext = coalescedEvt; - } - else - { - assert q.queueHead == qevt; - q.queueHead = coalescedEvt; - } - coalescedEvt.queueNext = qevt.queueNext; - if (q.queueTail == qevt) - q.queueTail = coalescedEvt; - qevt.queueNext = null; - } - return; - } - } - previous = qevt; - } - } - - if (q.queueHead == null) - { - // We have an empty queue. Set this event both as head and as tail. - q.queueHead = evt; - q.queueTail = evt; - } - else - { - // Note: queueTail should not be null here. - q.queueTail.queueNext = evt; - q.queueTail = evt; - } - - if (dispatchThread == null || !dispatchThread.isAlive()) - { - dispatchThread = new EventDispatchThread(this); - dispatchThread.start(); - } - - notify(); - } - - /** - * Causes runnable to have its run method called in the dispatch thread of the - * EventQueue. This will happen after all pending events are processed. The - * call blocks until this has happened. This method will throw an Error if - * called from the event dispatcher thread. - * - * @exception InterruptedException If another thread has interrupted - * this thread. - * @exception InvocationTargetException If an exception is thrown when running - * runnable. - * - * @since 1.2 - */ - public static void invokeAndWait(Runnable runnable) - throws InterruptedException, InvocationTargetException - { - if (isDispatchThread ()) - throw new Error("Can't call invokeAndWait from event dispatch thread"); - - EventQueue eq = Toolkit.getDefaultToolkit().getSystemEventQueue(); - Object notifyObject = new Object(); - - InvocationEvent ie = - new InvocationEvent(eq, runnable, notifyObject, true); - - synchronized (notifyObject) - { - eq.postEvent(ie); - notifyObject.wait(); - } - - Exception exception; - - if ((exception = ie.getException()) != null) - throw new InvocationTargetException(exception); - } - - /** - * This arranges for runnable to have its run method called in the - * dispatch thread of the EventQueue. This will happen after all - * pending events are processed. - * - * @since 1.2 - */ - public static void invokeLater(Runnable runnable) - { - EventQueue eq = Toolkit.getDefaultToolkit().getSystemEventQueue(); - - InvocationEvent ie = - new InvocationEvent(eq, runnable, null, false); - - eq.postEvent(ie); - } - - /** - * Return true if the current thread is the current AWT event dispatch - * thread. - */ - public static boolean isDispatchThread() - { - EventQueue eq = Toolkit.getDefaultToolkit().getSystemEventQueue(); - - /* Find last EventQueue in chain */ - while (eq.next != null) - eq = eq.next; - - return (Thread.currentThread() == eq.dispatchThread); - } - - /** - * Return the event currently being dispatched by the event - * dispatch thread. If the current thread is not the event - * dispatch thread, this method returns null. - * - * @since 1.4 - */ - public static AWTEvent getCurrentEvent() - { - EventQueue eq = Toolkit.getDefaultToolkit().getSystemEventQueue(); - Thread ct = Thread.currentThread(); - - /* Find out if this thread is the dispatch thread for any of the - EventQueues in the chain */ - while (ct != eq.dispatchThread) - { - // Try next EventQueue, if any - if (eq.next == null) - return null; // Not an event dispatch thread - eq = eq.next; - } - - return eq.currentEvent; - } - - /** - * Allows a custom EventQueue implementation to replace this one. - * All pending events are transferred to the new queue. Calls to postEvent, - * getNextEvent, and peekEvent and others are forwarded to the pushed queue - * until it is removed with a pop(). - * - * @exception NullPointerException if newEventQueue is null. - */ - public synchronized void push(EventQueue newEventQueue) - { - if (newEventQueue == null) - throw new NullPointerException (); - - /* Make sure we are at the top of the stack because callers can - only get a reference to the one at the bottom using - Toolkit.getDefaultToolkit().getSystemEventQueue() */ - if (next != null) - { - next.push (newEventQueue); - return; - } - - /* Make sure we have a live dispatch thread to drive the queue */ - if (dispatchThread == null) - dispatchThread = new EventDispatchThread(this); - - synchronized (newEventQueue) - { - // The RI transfers the events without calling the new eventqueue's - // push(), but using getNextEvent(). - while (peekEvent() != null) - { - try - { - newEventQueue.postEventImpl(getNextEvent()); - } - catch (InterruptedException ex) - { - // What should we do with this? - ex.printStackTrace(); - } - } - newEventQueue.prev = this; - } - - next = newEventQueue; - } - - /** Transfer any pending events from this queue back to the parent queue that - * was previously push()ed. Event dispatch from this queue is suspended. - * - * @exception EmptyStackException If no previous push was made on this - * EventQueue. - */ - protected void pop() throws EmptyStackException - { - /* The order is important here, we must get the prev lock first, - or deadlock could occur as callers usually get here following - prev's next pointer, and thus obtain prev's lock before trying - to get this lock. */ - EventQueue previous = prev; - if (previous == null) - throw new EmptyStackException(); - synchronized (previous) - { - synchronized (this) - { - EventQueue nextQueue = next; - if (nextQueue != null) - { - nextQueue.pop(); - } - else - { - previous.next = null; - - // The RI transfers the events without calling the new eventqueue's - // push(), so this should be OK and most effective. - while (peekEvent() != null) - { - try - { - previous.postEventImpl(getNextEvent()); - } - catch (InterruptedException ex) - { - // What should we do with this? - ex.printStackTrace(); - } - } - prev = null; - // Tell our EventDispatchThread that it can end - // execution. - if (dispatchThread != null) - { - dispatchThread.interrupt(); - dispatchThread = null; - } - } - } - } - } - - /** - * Dispatches an event. The manner in which the event is dispatched depends - * upon the type of the event and the type of the event's source object. - * - * @exception NullPointerException If event is null. - */ - protected void dispatchEvent(AWTEvent evt) - { - currentEvent = evt; - - if (evt instanceof InputEvent) - lastWhen = ((InputEvent) evt).getWhen(); - else if (evt instanceof ActionEvent) - lastWhen = ((ActionEvent) evt).getWhen(); - else if (evt instanceof InvocationEvent) - lastWhen = ((InvocationEvent) evt).getWhen(); - - if (evt instanceof ActiveEvent) - { - ActiveEvent active_evt = (ActiveEvent) evt; - active_evt.dispatch(); - } - else - { - Object source = evt.getSource(); - - if (source instanceof Component) - { - Component srccmp = (Component) source; - srccmp.dispatchEvent(evt); - } - else if (source instanceof MenuComponent) - { - MenuComponent srccmp = (MenuComponent) source; - srccmp.dispatchEvent(evt); - } - } - } - - /** - * Returns the timestamp of the most recent event that had a timestamp, or - * the initialization time of the event queue if no events have been fired. - * At present, only <code>InputEvent</code>s, <code>ActionEvent</code>s, - * <code>InputMethodEvent</code>s, and <code>InvocationEvent</code>s have - * timestamps, but this may be added to other events in future versions. - * If this is called by the event dispatching thread, it can be any - * (sequential) value, but to other threads, the safest bet is to return - * System.currentTimeMillis(). - * - * @return the most recent timestamp - * @see InputEvent#getWhen() - * @see ActionEvent#getWhen() - * @see InvocationEvent#getWhen() - * @see InputMethodEvent#getWhen() - * @since 1.4 - */ - public static long getMostRecentEventTime() - { - EventQueue eq = Toolkit.getDefaultToolkit().getSystemEventQueue(); - if (Thread.currentThread() != eq.dispatchThread) - return System.currentTimeMillis(); - return eq.lastWhen; - } -} |