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.java100
1 files changed, 96 insertions, 4 deletions
diff --git a/libjava/java/awt/EventQueue.java b/libjava/java/awt/EventQueue.java
index fd1c8062d71..a2356cc6393 100644
--- a/libjava/java/awt/EventQueue.java
+++ b/libjava/java/awt/EventQueue.java
@@ -1,4 +1,5 @@
-/* Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation
+/* EventQueue.java --
+ Copyright (C) 1999, 2000, 2001, 2002, 2003, 2005 Free Software Foundation
This file is part of GNU Classpath.
@@ -37,9 +38,12 @@ exception statement from your version. */
package java.awt;
+import gnu.java.awt.ClasspathToolkit;
+
import java.awt.event.ActionEvent;
import java.awt.event.InputEvent;
import java.awt.event.InvocationEvent;
+import java.awt.event.WindowEvent;
import java.lang.reflect.InvocationTargetException;
import java.util.EmptyStackException;
@@ -71,6 +75,35 @@ public class EventQueue
private long lastWhen = System.currentTimeMillis();
private EventDispatchThread dispatchThread = new EventDispatchThread(this);
+ private boolean shutdown = false;
+
+ private long lastNativeQueueAccess = 0;
+ private long humanLatencyThreshold = 100;
+
+ synchronized void setShutdown (boolean b)
+ {
+ shutdown = b;
+ }
+
+ synchronized boolean isShutdown ()
+ {
+ if (shutdown)
+ return true;
+
+ // 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 (peekEvent() == null
+ && ((ClasspathToolkit) Toolkit.getDefaultToolkit()).nativeQueueEmpty())
+ {
+ Frame[] frames = Frame.getFrames();
+ for (int i = 0; i < frames.length; ++i)
+ if (frames[i].isDisplayable())
+ return false;
+ return true;
+ }
+ return false;
+ }
/**
* Initializes a new instance of <code>EventQueue</code>.
@@ -93,9 +126,51 @@ public class EventQueue
{
if (next != null)
return next.getNextEvent();
+
+ ClasspathToolkit tk = ((ClasspathToolkit) Toolkit.getDefaultToolkit());
+ long curr = System.currentTimeMillis();
+
+ if (! tk.nativeQueueEmpty() &&
+ (curr - lastNativeQueueAccess > humanLatencyThreshold))
+ {
+ tk.iterateNativeQueue(this, false);
+ lastNativeQueueAccess = curr;
+ }
while (next_in == next_out)
- wait();
+ {
+ // Only the EventDispatchThread associated with the top of the stack is
+ // allowed to get events from the native source; everyone else just
+ // waits on the head of the queue.
+
+ if (isDispatchThread())
+ {
+ // We are not allowed to return null from this method, yet it
+ // is possible that we actually have run out of native events
+ // in the enclosing while() loop, and none of the native events
+ // happened to cause AWT events. We therefore ought to check
+ // the isShutdown() condition here, before risking a "native
+ // wait". If we check it before entering this function we may
+ // wait forever for events after the shutdown condition has
+ // arisen.
+
+ if (isShutdown())
+ throw new InterruptedException();
+
+ tk.iterateNativeQueue(this, true);
+ lastNativeQueueAccess = System.currentTimeMillis();
+ }
+ else
+ {
+ try
+ {
+ wait();
+ }
+ catch (InterruptedException ie)
+ {
+ }
+ }
+ }
AWTEvent res = queue[next_out];
@@ -215,6 +290,22 @@ public class EventQueue
next_out = 0;
next_in = oldQueue.length;
}
+
+ if (dispatchThread == null || !dispatchThread.isAlive())
+ {
+ dispatchThread = new EventDispatchThread(this);
+ dispatchThread.start();
+ }
+
+ // Window events might represent the closing of a window, which
+ // might cause the end of the dispatch thread's life, so we'll wake
+ // it up here to give it a chance to check for shutdown.
+
+ if (!isDispatchThread()
+ || (evt.getID() == WindowEvent.WINDOW_CLOSED)
+ || (evt.getID() == WindowEvent.WINDOW_CLOSING))
+ ((ClasspathToolkit) Toolkit.getDefaultToolkit()).wakeNativeQueue();
+
notify();
}
@@ -386,9 +477,10 @@ public class EventQueue
next_in = 0;
next_out = 0;
- // Tell our EventDispatchThread that it can end execution
- dispatchThread.interrupt ();
+ ((ClasspathToolkit) Toolkit.getDefaultToolkit()).wakeNativeQueue();
+ setShutdown(true);
dispatchThread = null;
+ this.notifyAll();
}
}
}