From c7a136d3ef16cf20fcd5314036508e31870b4849 Mon Sep 17 00:00:00 2001
From: Bryce McKinlay <bryce@albatross.co.nz>
Date: Wed, 12 Jul 2000 03:32:07 +0000
Subject: Big AWT patch.

From-SVN: r34976
---
 libjava/java/awt/EventQueue.java | 259 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 259 insertions(+)
 create mode 100644 libjava/java/awt/EventQueue.java

(limited to 'libjava/java/awt/EventQueue.java')

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);
+	  }
+      }
+  }
+}
-- 
cgit v1.1