Index: gnu/java/awt/ClasspathToolkit.java =================================================================== RCS file: /cvsroot/classpath/classpath/gnu/java/awt/ClasspathToolkit.java,v retrieving revision 1.8 diff -u -r1.8 ClasspathToolkit.java --- gnu/java/awt/ClasspathToolkit.java 11 Jan 2005 22:07:32 -0000 1.8 +++ gnu/java/awt/ClasspathToolkit.java 18 Jan 2005 09:32:17 -0000 @@ -367,5 +367,5 @@ public abstract boolean nativeQueueEmpty(); public abstract void wakeNativeQueue(); - public abstract void iterateNativeQueue(EventQueue locked); + public abstract void iterateNativeQueue(EventQueue locked, boolean block); } Index: gnu/java/awt/peer/gtk/GtkToolkit.java =================================================================== RCS file: /cvsroot/classpath/classpath/gnu/java/awt/peer/gtk/GtkToolkit.java,v retrieving revision 1.63 diff -u -r1.63 GtkToolkit.java --- gnu/java/awt/peer/gtk/GtkToolkit.java 11 Jan 2005 22:07:32 -0000 1.63 +++ gnu/java/awt/peer/gtk/GtkToolkit.java 18 Jan 2005 09:32:17 -0000 @@ -656,6 +656,6 @@ public native boolean nativeQueueEmpty(); public native void wakeNativeQueue(); - public native void iterateNativeQueue(EventQueue locked); + public native void iterateNativeQueue(EventQueue locked, boolean block); } // class GtkToolkit Index: include/gnu_java_awt_peer_gtk_GtkToolkit.h =================================================================== RCS file: /cvsroot/classpath/classpath/include/gnu_java_awt_peer_gtk_GtkToolkit.h,v retrieving revision 1.7 diff -u -r1.7 gnu_java_awt_peer_gtk_GtkToolkit.h --- include/gnu_java_awt_peer_gtk_GtkToolkit.h 11 Jan 2005 15:06:03 -0000 1.7 +++ include/gnu_java_awt_peer_gtk_GtkToolkit.h 18 Jan 2005 09:32:17 -0000 @@ -18,7 +18,7 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkToolkit_loadSystemColors (JNIEnv *env, jobject, jintArray); JNIEXPORT jboolean JNICALL Java_gnu_java_awt_peer_gtk_GtkToolkit_nativeQueueEmpty (JNIEnv *env, jobject); JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkToolkit_wakeNativeQueue (JNIEnv *env, jobject); -JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkToolkit_iterateNativeQueue (JNIEnv *env, jobject, jobject); +JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkToolkit_iterateNativeQueue (JNIEnv *env, jobject, jobject, jboolean); #ifdef __cplusplus } Index: java/awt/EventQueue.java =================================================================== RCS file: /cvsroot/classpath/classpath/java/awt/EventQueue.java,v retrieving revision 1.19 diff -u -r1.19 EventQueue.java --- java/awt/EventQueue.java 11 Jan 2005 15:06:04 -0000 1.19 +++ java/awt/EventQueue.java 18 Jan 2005 09:32:17 -0000 @@ -76,6 +76,9 @@ 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; @@ -122,6 +125,16 @@ { 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) { @@ -143,7 +156,8 @@ if (isShutdown()) throw new InterruptedException(); - ((ClasspathToolkit) Toolkit.getDefaultToolkit()).iterateNativeQueue(this); + tk.iterateNativeQueue(this, true); + lastNativeQueueAccess = System.currentTimeMillis(); } else { Index: javax/swing/Timer.java =================================================================== RCS file: /cvsroot/classpath/classpath/javax/swing/Timer.java,v retrieving revision 1.14 diff -u -r1.14 Timer.java --- javax/swing/Timer.java 22 Oct 2004 17:46:47 -0000 1.14 +++ javax/swing/Timer.java 18 Jan 2005 09:32:17 -0000 @@ -72,6 +72,14 @@ /** DOCUMENT ME! */ private Waker waker; + private Runnable drainer = new Runnable() + { + public void run() + { + drainEvents(); + } + }; + /** * DOCUMENT ME! */ @@ -81,14 +89,7 @@ { queue++; if (queue == 1) - SwingUtilities.invokeLater(new Runnable() - { - public void run() - { - drainEvents(); - } - }); - + SwingUtilities.invokeLater(drainer); } } Index: native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkGenericPeer.c =================================================================== RCS file: /cvsroot/classpath/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkGenericPeer.c,v retrieving revision 1.3 diff -u -r1.3 gnu_java_awt_peer_gtk_GtkGenericPeer.c --- native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkGenericPeer.c 28 Oct 2004 20:58:25 -0000 1.3 +++ native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkGenericPeer.c 18 Jan 2005 09:32:17 -0000 @@ -56,6 +56,13 @@ gtk_widget_destroy (GTK_WIDGET (ptr)); gdk_threads_leave (); + + /* + * Wake up the main thread, to make sure it re-checks the window + * destruction condition. + */ + + g_main_context_wakeup (NULL); } JNIEXPORT void JNICALL Index: native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkToolkit.c =================================================================== RCS file: /cvsroot/classpath/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkToolkit.c,v retrieving revision 1.8 diff -u -r1.8 gnu_java_awt_peer_gtk_GtkToolkit.c --- native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkToolkit.c 11 Jan 2005 15:06:04 -0000 1.8 +++ native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkToolkit.c 18 Jan 2005 09:32:17 -0000 @@ -40,6 +40,8 @@ #include "gnu_java_awt_peer_gtk_GtkToolkit.h" #include "gthread-jni.h" +#include + #ifdef JVM_SUN struct state_table *native_state_table; struct state_table *native_global_ref_table; @@ -298,12 +300,27 @@ dpi_conversion_factor = PANGO_SCALE * 72.0 / (int_dpi / PANGO_SCALE); } +static int +within_human_latency_tolerance(struct timeval *init) +{ + struct timeval curr; + unsigned long milliseconds_elapsed; + + gettimeofday(&curr, NULL); + + milliseconds_elapsed = (((curr.tv_sec * 1000) + (curr.tv_usec / 1000)) + - ((init->tv_sec * 1000) + (init->tv_usec / 1000))); + + return milliseconds_elapsed < 100; +} + JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkToolkit_iterateNativeQueue (JNIEnv *env, jobject self __attribute__((unused)), - jobject lockedQueue) + jobject lockedQueue, + jboolean block) { /* We're holding an EventQueue lock, and we're about to acquire the GDK * lock before dropping the EventQueue lock. This can deadlock if someone @@ -313,21 +330,30 @@ * acquiring the GDK lock and calling back into * EventQueue.getNextEvent(). */ + + struct timeval init; + gettimeofday(&init, NULL); + gdk_threads_enter (); (*env)->MonitorExit (env, lockedQueue); - /* It is quite important that this be a do .. while loop. The first pass - * should do an iteration w/o a test so that it sleeps when there really - * aren't any events; and the loop should continue for as many events as - * there are to avoid pointless thrashing up and down through JNI (it - * runs very slowly when this is not a loop). - */ - do + if (block) { - gtk_main_iteration(); + + /* If we're blocking-when-empty, we want a do .. while loop. */ + do + gtk_main_iteration (); + while (within_human_latency_tolerance (&init) + && gtk_events_pending ()); } - while (gtk_events_pending()); - + else + { + /* If we're not blocking-when-empty, we want a while loop. */ + while (within_human_latency_tolerance (&init) + && gtk_events_pending ()) + gtk_main_iteration (); + } + (*env)->MonitorEnter (env, lockedQueue); gdk_threads_leave (); }