From df161c9fcc1bc90d03e374e0eb8148424d4c5577 Mon Sep 17 00:00:00 2001
From: Sven Gothel <sgothel@jausoft.com>
Date: Mon, 26 Jul 2010 18:20:50 -0700
Subject: Fix OSX 2: Newt EDT (MainThread) and I/O methods ; Build
 jogl.build.number

---
 src/newt/classes/com/jogamp/newt/Display.java      |  60 ++++--
 .../com/jogamp/newt/impl/macosx/MacDisplay.java    |  65 +++---
 .../com/jogamp/newt/impl/macosx/MacWindow.java     |   7 +-
 .../com/jogamp/newt/util/DefaultEDTUtil.java       | 228 ++++++++++++++++++++
 src/newt/classes/com/jogamp/newt/util/EDTUtil.java | 202 +-----------------
 .../classes/com/jogamp/newt/util/MainThread.java   | 231 +++++++++++++++------
 6 files changed, 470 insertions(+), 323 deletions(-)
 create mode 100644 src/newt/classes/com/jogamp/newt/util/DefaultEDTUtil.java

(limited to 'src/newt/classes')

diff --git a/src/newt/classes/com/jogamp/newt/Display.java b/src/newt/classes/com/jogamp/newt/Display.java
index deb4c7abe..91fff890c 100644
--- a/src/newt/classes/com/jogamp/newt/Display.java
+++ b/src/newt/classes/com/jogamp/newt/Display.java
@@ -39,10 +39,13 @@ import com.jogamp.newt.event.*;
 import com.jogamp.newt.impl.event.*;
 import com.jogamp.newt.impl.Debug;
 import com.jogamp.newt.util.EDTUtil;
+import com.jogamp.newt.util.MainThread;
+import com.jogamp.newt.util.DefaultEDTUtil;
 import java.util.*;
 
 public abstract class Display {
     public static final boolean DEBUG = Debug.debug("Display");
+    public static final boolean DEBUG_TEST_EDT_MAINTHREAD = Debug.debug("TestEDTMainThread"); // JAU EDT Test ..
 
     private static Class getDisplayClass(String type) 
         throws ClassNotFoundException 
@@ -181,21 +184,34 @@ public abstract class Display {
     public boolean runCreateAndDestroyOnEDT() { 
         return true; 
     }
+
     public EDTUtil getEDTUtil() {
         if( null == edtUtil ) {
             synchronized (this) {
                 if( null == edtUtil ) {
                     if(NewtFactory.useEDT()) {
                         final Display f_dpy = this;
-                        Thread current = Thread.currentThread();
-                        edtUtil = new EDTUtil(current.getThreadGroup(), 
-                                              "Display_"+getFQName(),
-                                              new Runnable() {
-                                                  public void run() {
-                                                      if(null!=f_dpy.getGraphicsDevice()) {
-                                                          f_dpy.dispatchMessages();
-                                                      } } } );
-                        edt = edtUtil.start();
+                        if ( ! DEBUG_TEST_EDT_MAINTHREAD ) {
+                            Thread current = Thread.currentThread();
+                            edtUtil = new DefaultEDTUtil(current.getThreadGroup(), 
+                                                  "Display_"+getFQName(),
+                                                  new Runnable() {
+                                                      public void run() {
+                                                          if(null!=f_dpy.getGraphicsDevice()) {
+                                                              f_dpy.dispatchMessages();
+                                                          } } } );
+                        } else {
+                            // Begin JAU EDT Test ..
+                            MainThread.addPumpMessage(this, 
+                                                  new Runnable() {
+                                                      public void run() {
+                                                          if(null!=f_dpy.getGraphicsDevice()) {
+                                                              f_dpy.dispatchMessages();
+                                                          } } } );
+                            edtUtil = MainThread.getSingleton();
+                            // End JAU EDT Test ..
+                        }
+                        edtUtil.start();
                     }
                 }
             }
@@ -203,6 +219,16 @@ public abstract class Display {
         return edtUtil;
     }
 
+    protected void releaseEDTUtil() {
+        if(null!=edtUtil) { 
+            if ( DEBUG_TEST_EDT_MAINTHREAD ) {
+                MainThread.removePumpMessage(this); // JAU EDT Test ..
+            }
+            edtUtil.waitUntilStopped();
+            edtUtil=null;
+        }
+    }
+
     public void runOnEDTIfAvail(boolean wait, final Runnable task) {
         EDTUtil _edtUtil = getEDTUtil();
         if(runCreateAndDestroyOnEDT() && null!=_edtUtil) {
@@ -223,21 +249,16 @@ public abstract class Display {
                 System.err.println("Display.destroy("+getFQName()+") REMOVE: "+this+" "+getThreadName());
             }
             final Display f_dpy = this;
-            final EDTUtil f_edt = edtUtil;
+            final EDTUtil f_edtUtil = edtUtil;
             runOnEDTIfAvail(true, new Runnable() {
                 public void run() {
                     f_dpy.closeNative();
-                    if(null!=f_edt) {
-                        f_edt.stop();
+                    if(null!=f_edtUtil) {
+                        f_edtUtil.stop();
                     }
                 }
             } );
-
-            if(null!=edtUtil) { 
-                edtUtil.waitUntilStopped();
-                edtUtil=null;
-                edt=null;
-            }
+            releaseEDTUtil();
             aDevice = null;
         } else {
             if(DEBUG) {
@@ -316,7 +337,7 @@ public abstract class Display {
     private Object eventsLock = new Object();
     private LinkedList/*<NEWTEvent>*/ events = new LinkedList();
 
-    protected void dispatchMessages() {
+    public void dispatchMessages() {
         if(0==refCount) return; // in destruction ..
 
         LinkedList/*<NEWTEvent>*/ _events = null;
@@ -383,7 +404,6 @@ public abstract class Display {
     }
 
     protected EDTUtil edtUtil = null;
-    protected Thread  edt = null;
     protected String name;
     protected String type;
     protected int refCount;
diff --git a/src/newt/classes/com/jogamp/newt/impl/macosx/MacDisplay.java b/src/newt/classes/com/jogamp/newt/impl/macosx/MacDisplay.java
index 699b675dd..11f825282 100644
--- a/src/newt/classes/com/jogamp/newt/impl/macosx/MacDisplay.java
+++ b/src/newt/classes/com/jogamp/newt/impl/macosx/MacDisplay.java
@@ -38,6 +38,7 @@ import javax.media.nativewindow.macosx.*;
 import com.jogamp.common.util.ReflectionUtil;
 import com.jogamp.newt.*;
 import com.jogamp.newt.impl.*;
+import com.jogamp.newt.util.EDTUtil;
 import com.jogamp.newt.util.MainThread;
 
 public class MacDisplay extends Display {
@@ -60,15 +61,8 @@ public class MacDisplay extends Display {
     public MacDisplay() {
     }
 
-    class DispatchAction implements Runnable {
-        public void run() {
-            dispatchMessages0();
-        }
-    }
-    private DispatchAction dispatchAction = new DispatchAction();
-
     protected void dispatchMessagesNative() {
-        runOnMainThread(false, dispatchAction);
+        dispatchMessages0();
     }
     
     protected void createNative() {
@@ -77,44 +71,33 @@ public class MacDisplay extends Display {
 
     protected void closeNative() { }
 
-    /*public boolean runCreateAndDestroyOnEDT() { 
-        return false; 
-    }
     public EDTUtil getEDTUtil() {
-        return null;
-    }*/
-
-    protected static void runOnMainThread(boolean wait, Runnable r) {
-        if (MainThread.isRunning()) {
-            MainThread.invoke(wait, r);
-        } else if(!runOnAWTEDT(wait, r)) {
-            throw new NativeWindowException("Neither MainThread is running nor AWT EDT available");
+        if( null == edtUtil ) {
+            synchronized (this) {
+                if( null == edtUtil ) {
+                    if(NewtFactory.useEDT()) {
+                        final Display f_dpy = this;
+                        MainThread.addPumpMessage(this, 
+                                              new Runnable() {
+                                                  public void run() {
+                                                      if(null!=f_dpy.getGraphicsDevice()) {
+                                                          f_dpy.dispatchMessages();
+                                                      } } } );
+                        edtUtil = MainThread.getSingleton();
+                        edtUtil.start();
+                    }
+                }
+            }
         }
+        return edtUtil;
     }
 
-    protected static boolean runOnAWTEDT(boolean wait, Runnable r) {
-        ClassLoader cl = MacDisplay.class.getClassLoader();
-        if(ReflectionUtil.isClassAvailable("java.awt.EventQueue", cl)) {
-            try {
-                if(wait) {
-                    ReflectionUtil.callStaticMethod(
-                        "java.awt.EventQueue",
-                        "invokeAndWait",
-                        new Class[]  { java.lang.Runnable.class },
-                        new Object[] { r }, cl );
-                } else {
-                    ReflectionUtil.callStaticMethod(
-                        "java.awt.EventQueue",
-                        "invokeLater",
-                        new Class[]  { java.lang.Runnable.class },
-                        new Object[] { r }, cl );
-                }
-            } catch (Exception e) {
-                throw new NativeWindowException(e);
-            }
-            return true;
+    protected void releaseEDTUtil() {
+        if(null!=edtUtil) { 
+            MainThread.removePumpMessage(this);
+            edtUtil.waitUntilStopped();
+            edtUtil=null;
         }
-        return false;
     }
 
     private static native boolean initNSApplication0();
diff --git a/src/newt/classes/com/jogamp/newt/impl/macosx/MacWindow.java b/src/newt/classes/com/jogamp/newt/impl/macosx/MacWindow.java
index 8f5041253..a8e6febf5 100644
--- a/src/newt/classes/com/jogamp/newt/impl/macosx/MacWindow.java
+++ b/src/newt/classes/com/jogamp/newt/impl/macosx/MacWindow.java
@@ -165,6 +165,7 @@ public class MacWindow extends Window {
             windowHandle = 0;
             nsViewLock.unlock();
         }
+        windowDestroyed(); // No OSX hook for DidClose, so do it here
     }
     
     public long getWindowHandle() {
@@ -406,8 +407,8 @@ public class MacWindow extends Window {
         }
 
         try {
-            MacDisplay.runOnMainThread(true, new Runnable() {
-                public void run() {
+            //runOnEDTIfAvail(true, new Runnable() {
+            //    public void run() {
                     if(0!=windowHandle) {
                         // save the view .. close the window
                         surfaceHandle = changeContentView0(parentWindowHandle, windowHandle, 0);
@@ -433,7 +434,7 @@ public class MacWindow extends Window {
                     setTitle0(windowHandle, getTitle());
                     // don't make the window visible on window creation
                     // makeKeyAndOrderFront0(windowHandle);
-                } } );
+             //   } } );
         } catch (Exception ie) {
             ie.printStackTrace();
         }
diff --git a/src/newt/classes/com/jogamp/newt/util/DefaultEDTUtil.java b/src/newt/classes/com/jogamp/newt/util/DefaultEDTUtil.java
new file mode 100644
index 000000000..87dfdb9d8
--- /dev/null
+++ b/src/newt/classes/com/jogamp/newt/util/DefaultEDTUtil.java
@@ -0,0 +1,228 @@
+/*
+ * Copyright (c) 2009 Sun Microsystems, Inc. All Rights Reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * 
+ * - Redistribution of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * 
+ * - Redistribution in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * 
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * 
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
+ * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
+ * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
+ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
+ * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ * 
+ * You acknowledge that this software is not designed or intended for use
+ * in the design, construction, operation or maintenance of any nuclear
+ * facility.
+ */
+
+package com.jogamp.newt.util;
+
+import com.jogamp.common.util.RunnableTask;
+import com.jogamp.newt.Display;
+import com.jogamp.newt.impl.Debug;
+import java.util.*;
+
+public class DefaultEDTUtil implements EDTUtil {
+    public static final boolean DEBUG = Debug.debug("EDT");
+
+    private ThreadGroup threadGroup; 
+    private volatile boolean shouldStop = false;
+    private EventDispatchThread edt = null;
+    private Object edtLock = new Object();
+    private ArrayList tasks = new ArrayList(); // one shot tasks
+    private String name;
+    private Runnable pumpMessages;
+
+    public DefaultEDTUtil(ThreadGroup tg, String name, Runnable pumpMessages) {
+        this.threadGroup = tg;
+        this.name=new String(Thread.currentThread().getName()+"-"+"EDT-"+name);
+        this.pumpMessages=pumpMessages;
+    }
+
+    public void start() {
+        synchronized(edtLock) { 
+            if(null==edt) {
+                edt = new EventDispatchThread(threadGroup, name);
+            }
+            if(!edt.isRunning()) {
+                shouldStop = false;
+                edt.start();
+            }
+            edtLock.notifyAll();
+        }
+    }
+
+    public void stop() {
+        synchronized(edtLock) { 
+            if(null!=edt && edt.isRunning()) {
+                shouldStop = true;
+            }
+            edtLock.notifyAll();
+            if(DEBUG) {
+                System.out.println(Thread.currentThread()+": EDT signal STOP");
+            }
+        }
+    }
+
+    public boolean isCurrentThreadEDT() {
+        return null!=edt && edt == Thread.currentThread();
+    }
+
+    public boolean isRunning() {
+        return null!=edt && edt.isRunning() ;
+    }
+
+    private void invokeLater(Runnable task) {
+        synchronized(edtLock) {
+            if(null!=edt && edt.isRunning() && edt != Thread.currentThread() ) {
+                tasks.add(task);
+                edtLock.notifyAll();
+            } else {
+                // if !running or isEDTThread, do it right away
+                task.run();
+            }
+        }
+    }
+
+    public void invoke(boolean wait, Runnable task) {
+        if(task == null) {
+            return;
+        }
+        boolean doWait = wait && null!=edt && edt.isRunning() && edt != Thread.currentThread();
+        Object lock = new Object();
+        RunnableTask rTask = new RunnableTask(task, doWait?lock:null, true);
+        Throwable throwable = null;
+        synchronized(lock) {
+            invokeLater(rTask);
+            if( doWait ) {
+                try {
+                    lock.wait();
+                } catch (InterruptedException ie) {
+                    throwable = ie;
+                }
+            }
+        }
+        if(null==throwable) {
+            throwable = rTask.getThrowable();
+        }
+        if(null!=throwable) {
+            throw new RuntimeException(throwable);
+        }
+    }
+
+    public void waitUntilIdle() {
+        synchronized(edtLock) {
+            if(null!=edt && edt.isRunning() && tasks.size()>0 && edt != Thread.currentThread() ) {
+                try {
+                    edtLock.wait();
+                } catch (InterruptedException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+    }
+
+    public void waitUntilStopped() {
+        synchronized(edtLock) {
+            while(null!=edt && edt.isRunning() && edt != Thread.currentThread() ) {
+                try {
+                    edtLock.wait();
+                } catch (InterruptedException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+    }
+
+    class EventDispatchThread extends Thread {
+        boolean isRunning = false;
+
+        public EventDispatchThread(ThreadGroup tg, String name) {
+            super(tg, name);
+        }
+
+        public synchronized boolean isRunning() {
+            return isRunning;
+        }
+
+        public void start() throws IllegalThreadStateException {
+            synchronized(this) {
+                isRunning = true;
+            }
+            super.start();
+        }
+
+        /** 
+         * Utilizing edtLock only for local resources and task execution,
+         * not for event dispatching.
+         */
+        public void run() {
+            if(DEBUG) {
+                System.out.println(Thread.currentThread()+": EDT run() START");
+            }
+            try {
+                while(!shouldStop) {
+                    // wait for something todo
+                    while(!shouldStop && tasks.size()==0) {
+                        synchronized(edtLock) {
+                            if(!shouldStop && tasks.size()==0) {
+                                try {
+                                    edtLock.wait(defaultEDTPollGranularity);
+                                } catch (InterruptedException e) {
+                                    e.printStackTrace();
+                                }
+                            }
+                        }
+                        pumpMessages.run(); // event dispatch
+                    }
+                    if(!shouldStop && tasks.size()>0) {
+                        synchronized(edtLock) {
+                            if(!shouldStop && tasks.size()>0) {
+                                Runnable task = (Runnable) tasks.remove(0);
+                                task.run(); // FIXME: could be run outside of lock
+                                edtLock.notifyAll();
+                            }
+                        }
+                        pumpMessages.run(); // event dispatch
+                    }
+                }
+            } catch (Throwable t) {
+                // handle errors ..
+                shouldStop = true;
+                throw new RuntimeException(t);
+            } finally {
+                synchronized(this) {
+                    isRunning = !shouldStop;
+                }
+                if(!isRunning) {
+                    synchronized(edtLock) {
+                        edtLock.notifyAll();
+                    }
+                }
+                if(DEBUG) {
+                    System.out.println(Thread.currentThread()+": EDT run() EXIT");
+                }
+            }
+        }
+    }
+}
+
diff --git a/src/newt/classes/com/jogamp/newt/util/EDTUtil.java b/src/newt/classes/com/jogamp/newt/util/EDTUtil.java
index 2e339fd45..1af102f43 100644
--- a/src/newt/classes/com/jogamp/newt/util/EDTUtil.java
+++ b/src/newt/classes/com/jogamp/newt/util/EDTUtil.java
@@ -38,208 +38,24 @@ package com.jogamp.newt.util;
 
 import com.jogamp.common.util.RunnableTask;
 import com.jogamp.newt.Display;
-import com.jogamp.newt.impl.Debug;
 import java.util.*;
 
-public class EDTUtil {
-    public static final boolean DEBUG = Debug.debug("EDT");
+public interface EDTUtil {
 
-    private ThreadGroup threadGroup; 
-    private volatile boolean shouldStop = false;
-    private EventDispatchThread edt = null;
-    private Object edtLock = new Object();
-    private ArrayList tasks = new ArrayList(); // one shot tasks
-    private String name;
-    private Runnable pumpMessages;
-    private long edtPollGranularity = 10; // 10ms, 1/100s
+    public static final long defaultEDTPollGranularity = 10; // 10ms, 1/100s
 
-    public EDTUtil(ThreadGroup tg, String name, Runnable pumpMessages) {
-        this.threadGroup = tg;
-        this.name=new String(Thread.currentThread().getName()+"-"+"EDT-"+name);
-        this.pumpMessages=pumpMessages;
-    }
+    public void start();
 
-    public String getName() { return name; }
+    public void stop();
 
-    public ThreadGroup getThreadGroup() { return threadGroup; }
+    public boolean isCurrentThreadEDT();
 
-    /**
-     * @return The started Runnable, which handles the run-loop.
-     */
-    public Thread start() {
-        synchronized(edtLock) { 
-            if(null==edt) {
-                edt = new EventDispatchThread(threadGroup, name);
-            }
-            if(!edt.isRunning()) {
-                shouldStop = false;
-                edt.start();
-            }
-            edtLock.notifyAll();
-        }
-        return edt;
-    }
+    public boolean isRunning();
 
-    public void stop() {
-        synchronized(edtLock) { 
-            if(null!=edt && edt.isRunning()) {
-                shouldStop = true;
-            }
-            edtLock.notifyAll();
-            if(DEBUG) {
-                System.out.println(Thread.currentThread()+": EDT signal STOP");
-            }
-        }
-    }
+    public void invoke(boolean wait, Runnable task);
 
-    public Thread getEDT() {
-        return edt;
-    }
+    public void waitUntilIdle();
 
-    public boolean isThreadEDT(Thread thread) {
-        return null!=edt && edt == thread;
-    }
-
-    public boolean isCurrentThreadEDT() {
-        return null!=edt && edt == Thread.currentThread();
-    }
-
-    public boolean isRunning() {
-        return null!=edt && edt.isRunning() ;
-    }
-
-    private void invokeLater(Runnable task) {
-        synchronized(edtLock) {
-            if(null!=edt && edt.isRunning() && edt != Thread.currentThread() ) {
-                tasks.add(task);
-                edtLock.notifyAll();
-            } else {
-                // if !running or isEDTThread, do it right away
-                task.run();
-            }
-        }
-    }
-
-    public void invoke(boolean wait, Runnable task) {
-        if(task == null) {
-            return;
-        }
-        boolean doWait = wait && null!=edt && edt.isRunning() && edt != Thread.currentThread();
-        Object lock = new Object();
-        RunnableTask rTask = new RunnableTask(task, doWait?lock:null, true);
-        Throwable throwable = null;
-        synchronized(lock) {
-            invokeLater(rTask);
-            if( doWait ) {
-                try {
-                    lock.wait();
-                } catch (InterruptedException ie) {
-                    throwable = ie;
-                }
-            }
-        }
-        if(null==throwable) {
-            throwable = rTask.getThrowable();
-        }
-        if(null!=throwable) {
-            throw new RuntimeException(throwable);
-        }
-    }
-
-    public void waitUntilIdle() {
-        synchronized(edtLock) {
-            if(null!=edt && edt.isRunning() && tasks.size()>0 && edt != Thread.currentThread() ) {
-                try {
-                    edtLock.wait();
-                } catch (InterruptedException e) {
-                    e.printStackTrace();
-                }
-            }
-        }
-    }
-
-    public void waitUntilStopped() {
-        synchronized(edtLock) {
-            while(null!=edt && edt.isRunning() && edt != Thread.currentThread() ) {
-                try {
-                    edtLock.wait();
-                } catch (InterruptedException e) {
-                    e.printStackTrace();
-                }
-            }
-        }
-    }
-
-    class EventDispatchThread extends Thread {
-        boolean isRunning = false;
-
-        public EventDispatchThread(ThreadGroup tg, String name) {
-            super(tg, name);
-        }
-
-        public synchronized boolean isRunning() {
-            return isRunning;
-        }
-
-        public void start() throws IllegalThreadStateException {
-            synchronized(this) {
-                isRunning = true;
-            }
-            super.start();
-        }
-
-        /** 
-         * Utilizing edtLock only for local resources and task execution,
-         * not for event dispatching.
-         */
-        public void run() {
-            if(DEBUG) {
-                System.out.println(Thread.currentThread()+": EDT run() START");
-            }
-            try {
-                while(!shouldStop) {
-                    // wait for something todo
-                    while(!shouldStop && tasks.size()==0) {
-                        synchronized(edtLock) {
-                            if(!shouldStop && tasks.size()==0) {
-                                try {
-                                    edtLock.wait(edtPollGranularity);
-                                } catch (InterruptedException e) {
-                                    e.printStackTrace();
-                                }
-                            }
-                        }
-                        pumpMessages.run(); // event dispatch
-                    }
-                    if(!shouldStop && tasks.size()>0) {
-                        synchronized(edtLock) {
-                            if(!shouldStop && tasks.size()>0) {
-                                Runnable task = (Runnable) tasks.remove(0);
-                                task.run();
-                                edtLock.notifyAll();
-                            }
-                        }
-                        pumpMessages.run(); // event dispatch
-                    }
-                }
-            } catch (Throwable t) {
-                // handle errors ..
-                shouldStop = true;
-                throw new RuntimeException(t);
-            } finally {
-                synchronized(this) {
-                    isRunning = !shouldStop;
-                }
-                if(!isRunning) {
-                    synchronized(edtLock) {
-                        edtLock.notifyAll();
-                    }
-                }
-                if(DEBUG) {
-                    System.out.println(Thread.currentThread()+": EDT run() EXIT");
-                }
-            }
-        }
-    }
+    public void waitUntilStopped();
 }
 
diff --git a/src/newt/classes/com/jogamp/newt/util/MainThread.java b/src/newt/classes/com/jogamp/newt/util/MainThread.java
index cbd520104..ed78c808d 100644
--- a/src/newt/classes/com/jogamp/newt/util/MainThread.java
+++ b/src/newt/classes/com/jogamp/newt/util/MainThread.java
@@ -81,21 +81,33 @@ import com.jogamp.newt.impl.macosx.MacDisplay;
  </PRE>
  * Which starts 4 threads, each with a window and OpenGL rendering.<br>
  */
-public class MainThread {
+public class MainThread implements EDTUtil {
     private static AccessControlContext localACC = AccessController.getContext();
-    public static final boolean USE_MAIN_THREAD = NativeWindowFactory.TYPE_MACOSX.equals(NativeWindowFactory.getNativeWindowType(false)) ||
-                                                  Debug.getBooleanProperty("newt.MainThread.force", true, localACC);
+    public static final boolean  MAIN_THREAD_CRITERIA = ( !NativeWindowFactory.isAWTAvailable() &&
+                                                           NativeWindowFactory.TYPE_MACOSX.equals(NativeWindowFactory.getNativeWindowType(false)) 
+                                                        ) || Debug.getBooleanProperty("newt.MainThread.force", true, localACC);
 
     protected static final boolean DEBUG = Debug.debug("MainThread");
 
+    private static MainThread singletonMainThread = new MainThread(); // one singleton MainThread
+
     private static boolean isExit=false;
     private static volatile boolean isRunning=false;
     private static Object taskWorkerLock=new Object();
     private static boolean shouldStop;
     private static ArrayList tasks;
-    private static ArrayList tasksBlock;
     private static Thread mainThread;
 
+    private static Timer pumpMessagesTimer=null;
+    private static TimerTask pumpMessagesTimerTask=null;
+    private static Map/*<Display, Runnable>*/ pumpMessageDisplayMap = new HashMap();
+
+    private static boolean useMainThread = false;
+    private static Class cAWTEventQueue=null;
+    private static Method mAWTInvokeAndWait=null;
+    private static Method mAWTInvokeLater=null;
+    private static Method mAWTIsDispatchThread=null;
+
     static class MainAction extends Thread {
         private String mainClassName;
         private String[] mainClassArgs;
@@ -109,9 +121,9 @@ public class MainThread {
         }
 
         public void run() {
-            if ( USE_MAIN_THREAD ) {
+            if ( useMainThread ) {
                 // we have to start first to provide the service ..
-                MainThread.waitUntilRunning();
+                singletonMainThread.waitUntilRunning();
             }
 
             // start user app ..
@@ -136,9 +148,9 @@ public class MainThread {
 
             if(DEBUG) System.err.println("MainAction.run(): "+Thread.currentThread().getName()+" user app fin");
 
-            if ( USE_MAIN_THREAD ) {
-                MainThread.exit();
-                if(DEBUG) System.err.println("MainAction.run(): "+Thread.currentThread().getName()+" MainThread fin - exit");
+            if ( useMainThread ) {
+                singletonMainThread.stop();
+                if(DEBUG) System.err.println("MainAction.run(): "+Thread.currentThread().getName()+" MainThread fin - stop");
                 System.exit(0);
             }
         }
@@ -147,7 +159,9 @@ public class MainThread {
 
     /** Your new java application main entry, which pipelines your application */
     public static void main(String[] args) {
-        if(DEBUG) System.err.println("MainThread.main(): "+Thread.currentThread().getName()+" USE_MAIN_THREAD "+ USE_MAIN_THREAD );
+        useMainThread = MAIN_THREAD_CRITERIA;
+
+        if(DEBUG) System.err.println("MainThread.main(): "+Thread.currentThread().getName()+" useMainThread "+ useMainThread );
 
         if(args.length==0) {
             return;
@@ -161,35 +175,144 @@ public class MainThread {
 
         NEWTJNILibLoader.loadNEWT();
         
-        shouldStop = false;
-        tasks = new ArrayList();
-        tasksBlock = new ArrayList();
-        mainThread = Thread.currentThread();
-
         mainAction = new MainAction(mainClassName, mainClassArgs);
 
         if(NativeWindowFactory.TYPE_MACOSX.equals(NativeWindowFactory.getNativeWindowType(false))) {
             MacDisplay.initSingleton();
         }
 
-        if ( USE_MAIN_THREAD ) {
+        if ( useMainThread ) {
+            shouldStop = false;
+            tasks = new ArrayList();
+            mainThread = Thread.currentThread();
+
             // dispatch user's main thread ..
             mainAction.start();
 
             // do our main thread task scheduling
-            run();
+            singletonMainThread.run();
         } else {
             // run user's main in this thread 
             mainAction.run();
         }
     }
 
+    public static final MainThread getSingleton() {
+        return singletonMainThread;
+    }
+
+    public static Runnable removePumpMessage(Display dpy) {
+        synchronized(pumpMessageDisplayMap) {
+            return (Runnable) pumpMessageDisplayMap.remove(dpy);
+        }
+    }
+
+    public static void addPumpMessage(Display dpy, Runnable pumpMessage) {
+        if ( useMainThread ) {
+            return; // error ?
+        }
+        if(null == pumpMessagesTimer) {
+            synchronized (MainThread.class) {
+                if(null == pumpMessagesTimer) {
+                    pumpMessagesTimer = new Timer();
+                    pumpMessagesTimerTask = new TimerTask() {
+                        public void run() {
+                            synchronized(pumpMessageDisplayMap) {
+                                for(Iterator i = pumpMessageDisplayMap.values().iterator(); i.hasNext(); ) {
+                                    ((Runnable) i.next()).run();
+                                }
+                            }
+                        }
+                    };
+                    pumpMessagesTimer.scheduleAtFixedRate(pumpMessagesTimerTask, 0, defaultEDTPollGranularity);
+                }
+            }
+        }
+        synchronized(pumpMessageDisplayMap) {
+            pumpMessageDisplayMap.put(dpy, pumpMessage);
+        }
+    }
+
+    private void initAWTReflection() {
+        if(null == cAWTEventQueue) {
+            ClassLoader cl = MacDisplay.class.getClassLoader();
+            cAWTEventQueue = ReflectionUtil.getClass("java.awt.EventQueue", true, cl);
+            mAWTInvokeAndWait = ReflectionUtil.getMethod(cAWTEventQueue, "invokeAndWait", new Class[] { java.lang.Runnable.class }, cl);
+            mAWTInvokeLater = ReflectionUtil.getMethod(cAWTEventQueue, "invokeLater", new Class[] { java.lang.Runnable.class }, cl);
+            mAWTIsDispatchThread = ReflectionUtil.getMethod(cAWTEventQueue, "isDispatchThread", new Class[] { }, cl);
+        }
+    }
+
+    public void start() {
+        // nop
+    }
+
+    public void stop() {
+        if(DEBUG) System.err.println("MainThread.stop(): "+Thread.currentThread().getName()+" start");
+        synchronized(taskWorkerLock) { 
+            if(isRunning) {
+                shouldStop = true;
+            }
+            taskWorkerLock.notifyAll();
+        }
+        if(DEBUG) System.err.println("MainThread.stop(): "+Thread.currentThread().getName()+" end");
+    }
+
+    public boolean isCurrentThreadEDT() {
+        if(NativeWindowFactory.isAWTAvailable()) {
+            initAWTReflection();
+            return ((Boolean) ReflectionUtil.callMethod(null, mAWTIsDispatchThread, null) ).booleanValue();
+        }
+        return isRunning() && mainThread == Thread.currentThread() ;
+    }
+
+    public boolean isRunning() {
+        if( useMainThread ) {
+            synchronized(taskWorkerLock) { 
+                return isRunning;
+            }
+        }
+        return true; // AWT is always running
+    }
+
+    private void invokeLater(Runnable task) {
+        synchronized(taskWorkerLock) {
+            if(isRunning() && mainThread != Thread.currentThread()) {
+                tasks.add(task);
+                taskWorkerLock.notifyAll();
+            } else {
+                // if !running or isEDTThread, do it right away
+                task.run();
+            }
+        }
+    }
+
     /** invokes the given Runnable */
-    public static void invoke(boolean wait, Runnable r) {
+    public void invoke(boolean wait, Runnable r) {
         if(r == null) {
             return;
         }
 
+        if(NativeWindowFactory.isAWTAvailable()) {
+            initAWTReflection();
+
+            // handover to AWT MainThread ..
+            try {
+                if ( ((Boolean) ReflectionUtil.callMethod(null, mAWTIsDispatchThread, null) ).booleanValue() ) {
+                    r.run();
+                    return;
+                }
+                if(wait) {
+                    ReflectionUtil.callMethod(null, mAWTInvokeAndWait, new Object[] { r });
+                } else {
+                    ReflectionUtil.callMethod(null, mAWTInvokeLater, new Object[] { r });
+                }
+            } catch (Exception e) {
+                throw new NativeWindowException(e);
+            }
+            return;
+        }
+
         // if this main thread is not being used or
         // if this is already the main thread .. just execute.
         if( !isRunning() || mainThread == Thread.currentThread() ) {
@@ -197,42 +320,35 @@ public class MainThread {
             return;
         }
 
-        synchronized(taskWorkerLock) {
-            tasks.add(r);
-            if(wait) {
-                tasksBlock.add(r);
-            }
-            taskWorkerLock.notifyAll();
-            if(wait) {
-                while(tasksBlock.size()>0) {
-                    try {
-                        taskWorkerLock.wait();
-                    } catch (InterruptedException e) {
-                        e.printStackTrace();
-                    }
+        boolean doWait = wait && isRunning() && mainThread != Thread.currentThread();
+        Object lock = new Object();
+        RunnableTask rTask = new RunnableTask(r, doWait?lock:null, true);
+        Throwable throwable = null;
+        synchronized(lock) {
+            invokeLater(rTask);
+            if( doWait ) {
+                try {
+                    lock.wait();
+                } catch (InterruptedException ie) {
+                    throwable = ie;
                 }
             }
         }
+        if(null==throwable) {
+            throwable = rTask.getThrowable();
+        }
+        if(null!=throwable) {
+            throw new RuntimeException(throwable);
+        }
     }
 
-    public static void exit() {
-        if(DEBUG) System.err.println("MainThread.exit(): "+Thread.currentThread().getName()+" start");
-        synchronized(taskWorkerLock) { 
-            if(isRunning) {
-                shouldStop = true;
-            }
-            taskWorkerLock.notifyAll();
-        }
-        if(DEBUG) System.err.println("MainThread.exit(): "+Thread.currentThread().getName()+" end");
+    public void waitUntilIdle() {
     }
 
-    public static boolean isRunning() {
-        synchronized(taskWorkerLock) { 
-            return isRunning;
-        }
+    public void waitUntilStopped() {
     }
 
-    private static void waitUntilRunning() {
+    private void waitUntilRunning() {
         synchronized(taskWorkerLock) {
             if(isExit) return;
 
@@ -246,7 +362,7 @@ public class MainThread {
         }
     }
 
-    public static void run() {
+    public void run() {
         if(DEBUG) System.err.println("MainThread.run(): "+Thread.currentThread().getName());
         synchronized(taskWorkerLock) {
             isRunning = true;
@@ -254,8 +370,6 @@ public class MainThread {
         }
         while(!shouldStop) {
             try {
-                ArrayList localTasks=null;
-
                 // wait for something todo ..
                 synchronized(taskWorkerLock) {
                     while(!shouldStop && tasks.size()==0) {
@@ -265,29 +379,14 @@ public class MainThread {
                             e.printStackTrace();
                         }
                     }
-                    // seq. process all tasks until no blocking one exists in the list
-                    for(Iterator i = tasks.iterator(); tasksBlock.size()>0 && i.hasNext(); ) {
-                        Runnable task = (Runnable) i.next();
-                        task.run();
-                        i.remove();
-                        tasksBlock.remove(task);
-                    }
 
                     // take over the tasks ..
-                    if(tasks.size()>0) {
-                        localTasks = tasks;
-                        tasks = new ArrayList();
+                    if(!shouldStop && tasks.size()>0) {
+                        Runnable task = (Runnable) tasks.remove(0);
+                        task.run(); // FIXME: could be run outside of lock
                     }
                     taskWorkerLock.notifyAll();
                 }
-
-                // seq. process all unblocking tasks ..
-                if(null!=localTasks) {
-                    for(Iterator i = localTasks.iterator(); i.hasNext(); ) {
-                        Runnable task = (Runnable) i.next();
-                        task.run();
-                    }
-                }
             } catch (Throwable t) {
                 // handle errors ..
                 t.printStackTrace();
-- 
cgit v1.2.3