aboutsummaryrefslogtreecommitdiff
path: root/libjava/java/awt/EventQueue.java
diff options
context:
space:
mode:
Diffstat (limited to 'libjava/java/awt/EventQueue.java')
-rw-r--r--libjava/java/awt/EventQueue.java259
1 files changed, 259 insertions, 0 deletions
diff --git a/libjava/java/awt/EventQueue.java b/libjava/java/awt/EventQueue.java
new file mode 100644
index 0000000..0a60d69
--- /dev/null
+++ b/libjava/java/awt/EventQueue.java
@@ -0,0 +1,259 @@
+/* Copyright (C) 2000 Free Software Foundation
+
+ This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+details. */
+
+package java.awt;
+
+import java.awt.event.*;
+import java.util.EmptyStackException;
+import java.lang.reflect.InvocationTargetException;
+
+/* 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. Check FIXME's.
+ */
+
+/** @author Bryce McKinlay */
+
+public class EventQueue
+{
+ private static final int INITIAL_QUEUE_DEPTH = 8;
+ private AWTEvent[] queue = new AWTEvent[INITIAL_QUEUE_DEPTH];
+
+ private int next_in = 0; // Index where next event will be added to queue
+ private int next_out = 0; // Index of next event to be removed from queue
+
+ private EventQueue next;
+ private EventQueue prev;
+
+ private EventDispatchThread dispatchThread = new EventDispatchThread(this);
+
+ public EventQueue()
+ {
+ }
+
+ public synchronized AWTEvent getNextEvent()
+ throws InterruptedException
+ {
+ if (next != null)
+ return next.getNextEvent();
+
+ while (next_in == next_out)
+ wait();
+
+ AWTEvent res = queue[next_out];
+
+ if (++next_out == queue.length)
+ next_out = 0;
+ return res;
+ }
+
+ /** @specnote Does not block. Returns null if there are no events on the
+ * queue.
+ */
+ public synchronized AWTEvent peekEvent()
+ {
+ if (next != null)
+ return next.peekEvent();
+
+ if (next_in != next_out)
+ return queue[next_out];
+ else return null;
+ }
+
+ /** @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);
+
+ int i = next_out;
+ while (i != next_in)
+ {
+ AWTEvent qevt = queue[i];
+ if (qevt.id == id)
+ return qevt;
+ }
+ return null;
+ }
+
+ public synchronized void postEvent(AWTEvent evt)
+ {
+ if (next != null)
+ {
+ next.postEvent(evt);
+ return;
+ }
+ // FIXME: Security checks?
+
+ /* Check for any events already on the queue with the same source
+ and ID. */
+ int i = next_out;
+ while (i != next_in)
+ {
+ AWTEvent qevt = queue[i];
+ Object src;
+ if (qevt.id == evt.id
+ && (src = qevt.getSource()) == evt.getSource()
+ && src instanceof Component)
+ {
+ /* If there are, call coalesceEvents on the source component
+ to see if they can be combined. */
+ Component srccmp = (Component) src;
+ AWTEvent coalesced_evt = srccmp.coalesceEvents(qevt, evt);
+ if (coalesced_evt != null)
+ {
+ /* Yes. Replace the existing event with the combined event. */
+ queue[i] = coalesced_evt;
+ return;
+ }
+ break;
+ }
+ if (++i == queue.length)
+ i = 0;
+ }
+
+ queue[next_in] = evt;
+ if (++next_in == queue.length)
+ next_in = 0;
+
+ if (next_in == next_out)
+ {
+ /* Queue is full. Extend it. */
+ AWTEvent[] oldQueue = queue;
+ queue = new AWTEvent[queue.length * 2];
+
+ int len = oldQueue.length - next_out;
+ System.arraycopy(oldQueue, next_out, queue, 0, len);
+ if (next_out != 0)
+ System.arraycopy(oldQueue, 0, queue, len, next_out);
+
+ next_out = 0;
+ next_in = oldQueue.length;
+ }
+ notify();
+ }
+
+ /** @since JDK1.2 */
+ public static void invokeAndWait(Runnable runnable)
+ throws InterruptedException, InvocationTargetException
+ {
+ // FIXME: Is this an appropriate way to access the event queue?
+ EventQueue eq = Toolkit.systemEventQueue;
+ Thread current = Thread.currentThread();
+ if (current == eq.dispatchThread)
+ throw new Error("Can't call invokeAndWait from event dispatch thread");
+
+ InvocationEvent ie =
+ new InvocationEvent(eq, runnable, current, true);
+
+ eq.postEvent(ie);
+
+ synchronized (current)
+ {
+ current.wait();
+ }
+
+ Exception exception;
+
+ if ((exception = ie.getException()) != null)
+ throw new InvocationTargetException(exception);
+ }
+
+ /** @since JDK1.2 */
+ static void invokeLater(Runnable runnable)
+ {
+ // FIXME: Is this an appropriate way to access the event queue?
+ EventQueue eq = Toolkit.systemEventQueue;
+
+ InvocationEvent ie =
+ new InvocationEvent(eq, runnable, null, false);
+
+ eq.postEvent(ie);
+ }
+
+ static boolean isDispatchThread()
+ {
+ // FIXME: Is this an appropriate way to access the event queue?
+ EventQueue eq = Toolkit.systemEventQueue;
+ return (Thread.currentThread() == eq.dispatchThread);
+ }
+
+ /** Allows a custom EventQueue implementation to replace this one.
+ * All pending events are transferred to the new queue. Calls to postEvent,
+ * getNextEvent, and peekEvent are forwarded to the pushed queue until it
+ * is removed with a pop().
+ */
+ public synchronized void push(EventQueue newEventQueue)
+ {
+ int i = next_out;
+ while (i != next_in)
+ {
+ newEventQueue.postEvent(queue[i]);
+ next_out = i;
+ if (++i == queue.length)
+ i = 0;
+ }
+
+ next = newEventQueue;
+ newEventQueue.prev = this;
+ }
+
+ /** Transfer any pending events from this queue back to the parent queue that
+ * was previously push()ed. Event dispatch from this queue is suspended. */
+ protected void pop() throws EmptyStackException
+ {
+ if (prev == null)
+ throw new EmptyStackException();
+
+ // Don't synchronize both this and prev at the same time, or deadlock could
+ // occur.
+ synchronized (prev)
+ {
+ prev.next = null;
+ }
+
+ synchronized (this)
+ {
+ int i = next_out;
+ while (i != next_in)
+ {
+ prev.postEvent(queue[i]);
+ next_out = i;
+ if (++i == queue.length)
+ i = 0;
+ }
+ }
+ }
+
+ protected void dispatchEvent(AWTEvent evt)
+ {
+ 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);
+ }
+ }
+ }
+}