Jogamp
GLAutoDrawable: setAnimator/getAnimator/invoke/display changes; NEWT: Adding native...
authorSven Gothel <sgothel@jausoft.com>
Sat, 26 Jun 2010 03:59:48 +0000 (06:59 +0300)
committerSven Gothel <sgothel@jausoft.com>
Sat, 26 Jun 2010 03:59:48 +0000 (06:59 +0300)
Support for native repaint, which shall call display() in case no animator is running.
GLAutoDrawable invoke(GLRunnable) impl. handles case if invoked on animator thread,
or no animator thread is running (issueing a display() call).
The impl resides in GLDrawableHelper.

GLEventListener's init() and glViewport()/reshape() method must be called before the 1st display()
and after a dispose() call. It could miss the 1st display() call if added
after the setVisible(true) call - due to the native repainting.
The impl resides in GLDrawableHelper.

The Animator un-/registers itself at the GLAutoDrawable via setAnimator.

NEWT Window reparent always issues a resize() and display() call.

NEWT native Window uses direct send.*Event for input events (again),
instead of enqueueing it for performance.

NEWT Window implements all status change and Java native event callbacks,
instead of having duplicated code in all implementations.

NewtCanvasAWT if the Newt window is focused, the AWT/Swing component[s] will loose the focus.

55 files changed:
make/build-junit.xml
make/scripts/java-run-all.sh
make/scripts/java-win64-dbg.bat
make/scripts/java-win64.bat
src/jogl/classes/com/jogamp/opengl/impl/GLDrawableHelper.java
src/jogl/classes/com/jogamp/opengl/impl/GLPbufferImpl.java
src/jogl/classes/com/jogamp/opengl/util/Animator.java
src/jogl/classes/javax/media/opengl/GLAutoDrawable.java
src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
src/junit/com/jogamp/test/junit/jogl/awt/TestAWT01GLn.java
src/junit/com/jogamp/test/junit/jogl/awt/TestSwingAWT01GLn.java
src/junit/com/jogamp/test/junit/jogl/demos/es1/RedSquare.java
src/junit/com/jogamp/test/junit/jogl/demos/gl2/gears/Gears.java
src/junit/com/jogamp/test/junit/jogl/demos/gl2/gears/TestGearsAWT.java
src/junit/com/jogamp/test/junit/jogl/demos/gl2/gears/TestGearsNEWT.java
src/junit/com/jogamp/test/junit/jogl/demos/gl2/gears/TestGearsNewtAWTWrapper.java
src/junit/com/jogamp/test/junit/jogl/drawable/TestDrawable01NEWT.java
src/junit/com/jogamp/test/junit/jogl/offscreen/TestOffscreen01NEWT.java
src/junit/com/jogamp/test/junit/jogl/texture/TestTexture01AWT.java
src/junit/com/jogamp/test/junit/newt/TestGLWindows01NEWT.java
src/junit/com/jogamp/test/junit/newt/TestGLWindows02NEWTAnimated.java [new file with mode: 0755]
src/junit/com/jogamp/test/junit/newt/TestListenerCom01AWT.java
src/junit/com/jogamp/test/junit/newt/TestWindows01NEWT.java
src/junit/com/jogamp/test/junit/newt/parenting/GLRunnableDummy.java [moved from src/junit/com/jogamp/test/junit/newt/GLRunnableDummy.java with 96% similarity]
src/junit/com/jogamp/test/junit/newt/parenting/KeyAction.java [moved from src/junit/com/jogamp/test/junit/newt/KeyAction.java with 97% similarity]
src/junit/com/jogamp/test/junit/newt/parenting/TestParenting01NEWT.java [moved from src/junit/com/jogamp/test/junit/newt/TestParenting01NEWT.java with 99% similarity]
src/junit/com/jogamp/test/junit/newt/parenting/TestParenting01aAWT.java [moved from src/junit/com/jogamp/test/junit/newt/TestParenting01aAWT.java with 93% similarity]
src/junit/com/jogamp/test/junit/newt/parenting/TestParenting01bAWT.java [moved from src/junit/com/jogamp/test/junit/newt/TestParenting01bAWT.java with 98% similarity]
src/junit/com/jogamp/test/junit/newt/parenting/TestParenting01cAWT.java [moved from src/junit/com/jogamp/test/junit/newt/TestParenting01cAWT.java with 75% similarity]
src/junit/com/jogamp/test/junit/newt/parenting/TestParenting01cSwingAWT.java [moved from src/junit/com/jogamp/test/junit/newt/TestParenting01cSwingAWT.java with 97% similarity]
src/junit/com/jogamp/test/junit/newt/parenting/TestParenting02AWT.java [moved from src/junit/com/jogamp/test/junit/newt/TestParenting02AWT.java with 98% similarity]
src/junit/com/jogamp/test/junit/newt/parenting/TestParenting02NEWT.java [moved from src/junit/com/jogamp/test/junit/newt/TestParenting02NEWT.java with 97% similarity]
src/junit/com/jogamp/test/junit/newt/parenting/WindowAction.java [moved from src/junit/com/jogamp/test/junit/newt/WindowAction.java with 97% similarity]
src/nativewindow/classes/com/jogamp/nativewindow/impl/RecursiveToolkitLock.java
src/newt/classes/com/jogamp/newt/Display.java
src/newt/classes/com/jogamp/newt/Window.java
src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java
src/newt/classes/com/jogamp/newt/event/NEWTEvent.java
src/newt/classes/com/jogamp/newt/event/NEWTEventConsumer.java [new file with mode: 0644]
src/newt/classes/com/jogamp/newt/event/TraceWindowAdapter.java
src/newt/classes/com/jogamp/newt/event/WindowAdapter.java
src/newt/classes/com/jogamp/newt/event/WindowUpdateEvent.java [new file with mode: 0755]
src/newt/classes/com/jogamp/newt/event/awt/AWTNewtEventFactory.java
src/newt/classes/com/jogamp/newt/event/awt/AWTParentWindowAdapter.java
src/newt/classes/com/jogamp/newt/event/awt/AWTWindowAdapter.java
src/newt/classes/com/jogamp/newt/impl/awt/AWTWindow.java
src/newt/classes/com/jogamp/newt/impl/macosx/MacWindow.java
src/newt/classes/com/jogamp/newt/impl/opengl/kd/KDWindow.java
src/newt/classes/com/jogamp/newt/impl/windows/WindowsWindow.java
src/newt/classes/com/jogamp/newt/impl/x11/X11Window.java
src/newt/classes/com/jogamp/newt/opengl/GLWindow.java
src/newt/classes/com/jogamp/newt/util/Insets.java [moved from src/newt/classes/com/jogamp/newt/Insets.java with 99% similarity]
src/newt/native/WindowsWindow.c
src/newt/native/X11Window.c

index 9b7f489..75215b0 100644 (file)
@@ -24,7 +24,7 @@
         <property name="java.dir.test"        value="com/jogamp/test"/>
         <property name="java.part.test"       value="${java.dir.test}/**"/>
 
-        <property name="batchtest.timeout"    value="60000"/>
+        <property name="batchtest.timeout"    value="120000"/>
 
     </target>
     
index 0188ae5..f99a496 100755 (executable)
@@ -44,7 +44,7 @@ uname -a | grep -i Darwin && MOSX=1
 # D_ARGS="-Dnewt.debug=all -Dnativewindow.debug=all"
 # D_ARGS="-Djogl.debug=all -Dnewt.debug=all -Dnativewindow.debug=all"
 # D_ARGS="-Dnewt.debug=all"
-D_ARGS="-Dnewt.debug.Window"
+D_ARGS="-Dnewt.debug.Window"
 # D_ARGS="-Dnewt.debug.Display"
 # D_ARGS="-Djogl.debug=all -Djogl.debug.DynamicLookup=true -Djogamp.debug.NativeLibrary=true"
 # D_ARGS="-Djogl.debug=all"
index 5f20012..a80ec9b 100644 (file)
@@ -13,4 +13,10 @@ set CP_ALL=.;%BLD_DIR%\jogl\jogl.all.jar;%BLD_DIR%\nativewindow\nativewindow.all
 \r
 echo CP_ALL %CP_ALL%\r
 \r
-%J2RE_HOME%\bin\java -classpath %CP_ALL% "-Djava.library.path=%LIB_DIR%" "-Dnativewindow.debug=all" "-Djogl.debug=all" "-Dnewt.debug=all" "-Dsun.java2d.noddraw=true" "-Dsun.awt.noerasebackground=true" %1 %2 %3 %4 %5 %6 %7 %8 %9 > java-win64-dbg.log 2>&1\r
+REM set D_ARGS="-Djogamp.debug.JNILibLoader=true" "-Djogamp.debug.NativeLibrary=true" "-Djogamp.debug.NativeLibrary.Lookup=true" "-Djogl.debug.GLProfile=true"\r
+REM set D_ARGS="-Djogl.debug=all -Dnewt.debug=all -Dnativewindow.debug=all"\r
+set D_ARGS="-Dnewt.debug.Window"\r
+\r
+set X_ARGS="-Dsun.java2d.noddraw=true" "-Dsun.awt.noerasebackground=true"\r
+\r
+%J2RE_HOME%\bin\java -classpath %CP_ALL% "-Djava.library.path=%LIB_DIR%" %D_ARGS% %X_ARGS% %1 %2 %3 %4 %5 %6 %7 %8 %9 > java-win64-dbg.log 2>&1\r
index f0d068b..7ce8757 100644 (file)
@@ -10,7 +10,8 @@ set BLD_DIR=..\%BLD_SUB%
 set LIB_DIR=%BLD_DIR%\lib;..\..\gluegen\%BLD_SUB%\obj\r
 \r
 set CP_ALL=.;%BLD_DIR%\jogl\jogl.all.jar;%BLD_DIR%\nativewindow\nativewindow.all.jar;%BLD_DIR%\newt\newt.all.jar;%BLD_DIR%\jogl\jogl.test.jar;..\..\gluegen\%BLD_SUB%\gluegen-rt.jar;..\..\gluegen\make\lib\junit.jar;%ANT_PATH%\lib\ant.jar;%ANT_PATH%\lib\ant-junit.jar\r
-\r
 echo CP_ALL %CP_ALL%\r
 \r
-%J2RE_HOME%\bin\java -classpath %CP_ALL% "-Djava.library.path=%LIB_DIR%" "-Dsun.java2d.noddraw=true" "-Dsun.awt.noerasebackground=true" %1 %2 %3 %4 %5 %6 %7 %8 %9 > java-win64.log 2>&1\r
+set X_ARGS="-Dsun.java2d.noddraw=true" "-Dsun.awt.noerasebackground=true"\r
+\r
+%J2RE_HOME%\bin\java -classpath %CP_ALL% "-Djava.library.path=%LIB_DIR%" %X_ARGS% %1 %2 %3 %4 %5 %6 %7 %8 %9 > java-win64.log 2>&1\r
index 8fefe14..1e954af 100644 (file)
@@ -46,75 +46,123 @@ import javax.media.opengl.*;
     methods to be able to share it between GLCanvas and GLJPanel. */
 
 public class GLDrawableHelper {
-  private volatile List listeners = new ArrayList();
   private static final boolean DEBUG = Debug.debug("GLDrawableHelper");
   private static final boolean VERBOSE = Debug.verbose();
-  private static final boolean NVIDIA_CRASH_WORKAROUND = Debug.isPropertyDefined("jogl.nvidia.crash.workaround", true);
+  private Object listenersLock = new Object();
+  private List listeners = new ArrayList();
+  private Set listenersToBeInit = new HashSet();
   private boolean autoSwapBufferMode = true;
+  private Object glRunnablesLock = new Object();
   private ArrayList glRunnables = new ArrayList(); // one shot GL tasks
+  private Thread animatorThread = null; // default
 
   public GLDrawableHelper() {
   }
 
-  public synchronized String toString() {
+  public String toString() {
     StringBuffer sb = new StringBuffer();
-    sb.append("GLEventListeners num "+listeners.size()+" [");
-    for (Iterator iter = listeners.iterator(); iter.hasNext(); ) {
-      sb.append(iter.next()+", ");
+    synchronized(listenersLock) {
+        sb.append("GLEventListeners num "+listeners.size()+" [");
+        for (Iterator iter = listeners.iterator(); iter.hasNext(); ) {
+          Object l = iter.next();
+          sb.append(l);
+          sb.append("[init ");
+          sb.append( !listenersToBeInit.contains(l) );
+          sb.append("], ");
+        }
     }
     sb.append("]");
     return sb.toString();
   }
 
-  public synchronized void addGLEventListener(GLEventListener listener) {
+  public void addGLEventListener(GLEventListener listener) {
     addGLEventListener(-1, listener);
   }
 
-  public synchronized void addGLEventListener(int index, GLEventListener listener) {
-    if(0>index) {
-        index = listeners.size();
+  public void addGLEventListener(int index, GLEventListener listener) {
+    synchronized(listenersLock) {
+        if(0>index) {
+            index = listeners.size();
+        }
+        listenersToBeInit.add(listener);
+        listeners.add(index, listener);
     }
-    List newListeners = (List) ((ArrayList) listeners).clone();
-    newListeners.add(index, listener);
-    listeners = newListeners;
   }
   
-  public synchronized void removeGLEventListener(GLEventListener listener) {
-    List newListeners = (List) ((ArrayList) listeners).clone();
-    newListeners.remove(listener);
-    listeners = newListeners;
+  public void removeGLEventListener(GLEventListener listener) {
+    synchronized(listenersLock) {
+        listeners.remove(listener);
+        listenersToBeInit.remove(listener);
+    }
   }
 
-  public synchronized void dispose(GLAutoDrawable drawable) {
-    for (Iterator iter = listeners.iterator(); iter.hasNext(); ) {
-      ((GLEventListener) iter.next()).dispose(drawable);
+  public void dispose(GLAutoDrawable drawable) {
+    synchronized(listenersLock) {
+        for (Iterator iter = listeners.iterator(); iter.hasNext(); ) {
+          GLEventListener listener = (GLEventListener) iter.next() ;
+          listener.dispose(drawable);
+          listenersToBeInit.add(listener);
+        }
     }
   }
 
+  private final boolean init(GLEventListener l, GLAutoDrawable drawable, boolean sendReshape) {
+      if(listenersToBeInit.remove(l)) {
+          l.init(drawable);
+          if(sendReshape) {
+              reshape(l, drawable, 0, 0, drawable.getWidth(), drawable.getHeight(), true /* setViewport */);
+          }
+          return true;
+      }
+      return false;
+  }
+
   public void init(GLAutoDrawable drawable) {
-    for (Iterator iter = listeners.iterator(); iter.hasNext(); ) {
-      ((GLEventListener) iter.next()).init(drawable);
+    synchronized(listenersLock) {
+        for (Iterator iter = listeners.iterator(); iter.hasNext(); ) {
+          GLEventListener listener = (GLEventListener) iter.next() ;
+          if ( ! init( listener, drawable, false ) ) {
+            throw new GLException("GLEventListener "+listener+" already initialized: "+drawable);
+          }
+        }
     }
   }
 
   public void display(GLAutoDrawable drawable) {
-    for (Iterator iter = listeners.iterator(); iter.hasNext(); ) {
-      ((GLEventListener) iter.next()).display(drawable);
+    synchronized(listenersLock) {
+        for (Iterator iter = listeners.iterator(); iter.hasNext(); ) {
+          GLEventListener listener = (GLEventListener) iter.next() ;
+          // GLEventListener may need to be init, 
+          // in case this one is added after the realization of the GLAutoDrawable
+          init( listener, drawable, true ) ; 
+          listener.display(drawable);
+        }
     }
     execGLRunnables(drawable);
   }
 
-  public void reshape(GLAutoDrawable drawable,
-                      int x, int y, int width, int height) {
-    for (Iterator iter = listeners.iterator(); iter.hasNext(); ) {
-      ((GLEventListener) iter.next()).reshape(drawable, x, y, width, height);
+  private final void reshape(GLEventListener listener, GLAutoDrawable drawable,
+                             int x, int y, int width, int height, boolean setViewport) {
+    if(setViewport) {
+        drawable.getGL().glViewport(x, y, width, height);
+    }
+    listener.reshape(drawable, x, y, width, height);
+  }
+
+  public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
+    synchronized(listenersLock) {
+        int i=0;
+        for (Iterator iter = listeners.iterator(); iter.hasNext(); i++) {
+          reshape((GLEventListener) iter.next(), drawable, x, y, width, height, 0==i);
+        }
     }
   }
 
   private void execGLRunnables(GLAutoDrawable drawable) {
     if(glRunnables.size()>0) {
+        // swap one-shot list asap
         ArrayList _glRunnables = null;
-        synchronized(glRunnables) {
+        synchronized(glRunnablesLock) {
             if(glRunnables.size()>0) {
                 _glRunnables = glRunnables;
                 glRunnables = new ArrayList();
@@ -128,23 +176,38 @@ public class GLDrawableHelper {
     }
   }
 
-  private void invokeLater(GLRunnable glRunnable) {
-    synchronized(glRunnables) {
-        glRunnables.add(glRunnable);
-        glRunnables.notifyAll();
+  public void setAnimator(Thread animator) throws GLException {
+    synchronized(glRunnablesLock) {
+        if(animator!=animatorThread && null!=animator && null!=animatorThread) {
+            throw new GLException("Trying to register animator thread "+animator+", where "+animatorThread+" is already registered. Unregister first.");
+        }
+        animatorThread = animator;
+    }
+  }
+
+  public Thread getAnimator() {
+    synchronized(glRunnablesLock) {
+        return animatorThread;
     }
   }
 
-  public void invoke(boolean wait, GLRunnable glRunnable) {
-    if(glRunnable == null) {
+  public void invoke(GLAutoDrawable drawable, boolean wait, GLRunnable glRunnable) {
+    if( null == drawable || null == glRunnable ) {
         return;
     }
-    Object lock = new Object();
-    GLRunnableTask rTask = new GLRunnableTask(glRunnable, wait?lock:null/*, true*/);
     Throwable throwable = null;
+    Object lock = new Object();
+    GLRunnableTask rTask = null;
     synchronized(lock) {
-        invokeLater(rTask);
-        if( wait ) {
+        boolean callDisplay;
+        synchronized(glRunnablesLock) {
+            callDisplay = null == animatorThread || animatorThread == Thread.currentThread() ;
+            rTask = new GLRunnableTask(glRunnable, ( !callDisplay && wait ) ? lock : null);
+            glRunnables.add(rTask);
+        }
+        if( callDisplay ) {
+            drawable.display();
+        } else if( wait ) {
             try {
                 lock.wait();
             } catch (InterruptedException ie) {
index 071ac13..c2efb3f 100644 (file)
@@ -138,8 +138,16 @@ public class GLPbufferImpl implements GLPbuffer {
     drawableHelper.removeGLEventListener(listener);
   }
 
+  public void setAnimator(Thread animator) {
+    drawableHelper.setAnimator(animator);
+  }
+
+  public Thread getAnimator() {
+    return drawableHelper.getAnimator();
+  }
+
   public void invoke(boolean wait, GLRunnable glRunnable) {
-    drawableHelper.invoke(wait, glRunnable);
+    drawableHelper.invoke(this, wait, glRunnable);
   }
 
   public void setContext(GLContext ctx) {
index 15b9d5e..66d3d5b 100755 (executable)
@@ -218,6 +218,9 @@ public class Animator {
         } else {
             thread = new Thread(threadGroup, runnable);
         }
+        for(Iterator iter = drawables.iterator(); iter.hasNext(); ) {
+            ((GLAutoDrawable) iter.next()).setAnimator(thread);
+        }
         thread.start();
     }
 
@@ -241,15 +244,16 @@ public class Animator {
         // dependencies on the Animator's internal thread. Currently we
         // use a couple of heuristics to determine whether we should do
         // the blocking wait().
-        if (impl.skipWaitForStop(thread)) {
-            return;
-        }
-
-        while (shouldStop && thread != null) {
-            try {
-                wait();
-            } catch (InterruptedException ie) {
+        if (!impl.skipWaitForStop(thread)) {
+            while (shouldStop && thread != null) {
+                try {
+                    wait();
+                } catch (InterruptedException ie) {
+                }
             }
         }
+        for(Iterator iter = drawables.iterator(); iter.hasNext(); ) {
+            ((GLAutoDrawable) iter.next()).setAnimator(null);
+        }
     }
 }
index 7236aa5..1b5c56c 100644 (file)
@@ -161,14 +161,49 @@ public interface GLAutoDrawable extends GLDrawable {
       during this update cycle. */
   public void removeGLEventListener(GLEventListener listener);
 
+  /**
+   * <p>
+   * Indicates whether a running animator thread is periodically issuing {@link #display()} calls or not.</p><br>
+   * <p>
+   * This method shall be called by an animator implementation only,<br>
+   * e.g. {@link com.jogamp.opengl.util.Animator#start()}, passing the animator thread,<br>
+   * and {@link com.jogamp.opengl.util.Animator#start()}, passing <code>null</code>.</p><br>
+   * <p>
+   * Impacts {@link #display()} and {@link #invoke(boolean, GLRunnable)} semantics.</p><br>
+   *
+   * @param animator <code>null</code> reference indicates no running animator thread 
+   *                 issues {@link #display()} calls on this <code>GLAutoDrawable</code>,<br>
+   *                 a valid reference indicates a running animator thread 
+   *                 periodically issuing {@link #display()} calls.
+   *
+   * @throws GLException if a running animator thread is already registered and you try to register a different one without unregistering the previous one.
+   * @see #display()
+   * @see #invoke(boolean, GLRunnable)
+   */ 
+  public void setAnimator(Thread animator) throws GLException;
+
+  /**
+   * @return the value of the registered animator thread
+   *
+   * @see #setAnimator(Thread)
+   */
+  public Thread getAnimator();
+
   /** 
-   * Enqueues the one-shot {@link javax.media.opengl.GLRunnable} into the queue,
-   * which will be executed at the next {@link #display()} call.
    * <p>
-   * Warning: We cannot verify if the caller runs in the same thread 
-   * as the display caller, hence we cannot avoid a deadlock
-   * in such case. You have to know what you are doing, 
-   * ie call this only in a I/O event listener, or such.<br></p>
+   * Enqueues a one-shot {@link javax.media.opengl.GLRunnable},
+   * which will be executed with the next {@link #display()} call.</p><br>
+   * <p>
+   * If {@link #setAnimator(Thread)} has not registered no running animator thread, the default,<br>
+   * or if the current thread is the animator thread,<br>
+   * a {@link #display()} call has to be issued after enqueueing the <code>GLRunnable</code>.<br>
+   * No extra synchronization must be performed in case <code>wait</code> is true, since it is executed in the current thread.</p><br>
+   * <p>
+   * If {@link #setAnimator(Thread)} has registered a valid animator thread,<br>
+   * no call of {@link #display()} must be issued, since the animator thread performs it.<br>
+   * If <code>wait</code> is true, the implementation must wait until the <code>GLRunnable</code> is excecuted.</p><br>
+   *
+   * @see #setAnimator(Thread)
    * @see #display()
    * @see javax.media.opengl.GLRunnable
    */   
@@ -190,28 +225,37 @@ public interface GLAutoDrawable extends GLDrawable {
       routine may be called manually. */
   public void destroy();
 
-  /** <p>Causes OpenGL rendering to be performed for this GLAutoDrawable
-      in the following order:
-      <ul>
-        <li> Calling {@link GLEventListener#display display(..)} for all
-             registered {@link GLEventListener}s. </li>
-        <li> Execute and dismiss all one-shot {@link javax.media.opengl.GLRunnable},
-             enqueued via {@link #invoke(boolean, GLRunnable)}.</li>
-      </ul></p>
-      <p> 
-      Called automatically by the
-      window system toolkit upon receiving a repaint() request.</p> 
-      <p> 
-      This routine may be called manually for better control over the
-      rendering process. It is legal to call another GLAutoDrawable's
-      display method from within the {@link GLEventListener#display
-      display(..)} callback.</p>
-      <p>
-      In case of a new generated OpenGL context, 
-      the implementation shall call {@link GLEventListener#init init(..)} for all
-      registered {@link GLEventListener}s <i>before</i> making the 
-      actual {@link GLEventListener#display display(..)} calls,
-      in case this has not been done yet.</p> */
+  /** 
+   * <p>
+   * Causes OpenGL rendering to be performed for this GLAutoDrawable
+   * in the following order:
+   * <ul>
+   *     <li> Calling {@link GLEventListener#display display(..)} for all
+   *          registered {@link GLEventListener}s. </li>
+   *     <li> Executes all one-shot {@link javax.media.opengl.GLRunnable},
+   *          enqueued via {@link #invoke(boolean, GLRunnable)}.</li>
+   * </ul></p>
+   * <p> 
+   * Called automatically by the
+   * window system toolkit upon receiving a repaint() request, 
+   * except a running animator thread is registered with {@link #setAnimator(Thread)}.</p> <br>
+   * <p> 
+   * Maybe called periodically by a running animator thread,<br>
+   * which must register itself with {@link #setAnimator(Thread)}.</p> <br>
+   * <p> 
+   * This routine may be called manually for better control over the
+   * rendering process. It is legal to call another GLAutoDrawable's
+   * display method from within the {@link GLEventListener#display
+   * display(..)} callback.</p>
+   * <p>
+   * In case of a new generated OpenGL context, 
+   * the implementation shall call {@link GLEventListener#init init(..)} for all
+   * registered {@link GLEventListener}s <i>before</i> making the 
+   * actual {@link GLEventListener#display display(..)} calls,
+   * in case this has not been done yet.</p>
+   *
+   * @see #setAnimator(Thread)
+   */
   public void display();
 
   /** Enables or disables automatic buffer swapping for this drawable.
index 2dafd69..f150b25 100644 (file)
@@ -378,7 +378,9 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable {
       return;
     }
 
-    display();
+    if( null == getAnimator() ) {
+        display();
+    }
   }
 
   /** Overridden to track when this component is added to a container.
@@ -492,8 +494,16 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable {
     drawableHelper.removeGLEventListener(listener);
   }
 
+  public void setAnimator(Thread animator) {
+    drawableHelper.setAnimator(animator);
+  }
+
+  public Thread getAnimator() {
+    return drawableHelper.getAnimator();
+  }
+
   public void invoke(boolean wait, GLRunnable glRunnable) {
-    drawableHelper.invoke(wait, glRunnable);
+    drawableHelper.invoke(this, wait, glRunnable);
   }
 
   public void setContext(GLContext ctx) {
@@ -640,10 +650,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable {
       if (sendReshape) {
         // Note: we ignore the given x and y within the parent component
         // since we are drawing directly into this heavyweight component.
-        int width = getWidth();
-        int height = getHeight();
-        getGL().glViewport(0, 0, width, height);
-        drawableHelper.reshape(GLCanvas.this, 0, 0, width, height);
+        drawableHelper.reshape(GLCanvas.this, 0, 0, getWidth(), getHeight());
         sendReshape = false;
       }
 
index 73962e9..d0d97fe 100644 (file)
@@ -380,8 +380,16 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable {
     drawableHelper.removeGLEventListener(listener);
   }
 
+  public void setAnimator(Thread animator) {
+    drawableHelper.setAnimator(animator);
+  }
+
+  public Thread getAnimator() {
+    return drawableHelper.getAnimator();
+  }
+
   public void invoke(boolean wait, GLRunnable glRunnable) {
-    drawableHelper.invoke(wait, glRunnable);
+    drawableHelper.invoke(this, wait, glRunnable);
   }
 
   public GLContext createContext(GLContext shareWith) {
@@ -585,9 +593,8 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable {
       }
       if (sendReshape) {
         if (DEBUG||VERBOSE) {
-          System.err.println("display: glViewport(" + viewportX + "," + viewportY + " " + panelWidth + "x" + panelHeight + ")");
+          System.err.println("display: reshape(" + viewportX + "," + viewportY + " " + panelWidth + "x" + panelHeight + ")");
         }
-        getGL().getGL2().glViewport(viewportX, viewportY, panelWidth, panelHeight);
         drawableHelper.reshape(GLJPanel.this, viewportX, viewportY, panelWidth, panelHeight);
         sendReshape = false;
       }
index 1652acd..f102185 100755 (executable)
@@ -48,6 +48,10 @@ import org.junit.After;
 import org.junit.Test;
 
 public class TestAWT01GLn {
+    static {
+        GLProfile.initSingleton();
+    }
+
     Frame frame=null;
     GLCanvas glCanvas=null;
 
index ed8a5dd..6144a63 100755 (executable)
@@ -56,6 +56,10 @@ import static javax.swing.SwingUtilities.*;
  * @author Michael Bien
  */
 public class TestSwingAWT01GLn {
+    static {
+        GLProfile.initSingleton();
+    }
+
 
     private Window[] windows;
 
index 9b8982e..be416f0 100755 (executable)
@@ -44,6 +44,7 @@ public class RedSquare implements GLEventListener {
     private FloatBuffer vertices;
 
     public void init(GLAutoDrawable drawable) {
+        System.out.println("RedSquare: Init");
         GL _gl = drawable.getGL();
 
         if(glDebugEmu) {
@@ -119,6 +120,7 @@ public class RedSquare implements GLEventListener {
     }
 
     public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
+        System.out.println("RedSquare: Reshape");
         GL2ES1 gl = drawable.getGL().getGL2ES1();
         // Set location in front of camera
         gl.glMatrixMode(gl.GL_PROJECTION);
@@ -147,6 +149,7 @@ public class RedSquare implements GLEventListener {
     }
 
     public void dispose(GLAutoDrawable drawable) {
+        System.out.println("RedSquare: Dispose");
         GL2ES1 gl = drawable.getGL().getGL2ES1();
         if(debug) {
             System.out.println(Thread.currentThread()+" RedSquare.dispose: "+gl.getContext());
@@ -163,8 +166,4 @@ public class RedSquare implements GLEventListener {
             System.out.println(Thread.currentThread()+" RedSquare.dispose: FIN");
         }
     }
-
-    public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) {
-    }
-
 }
index 1fa49be..ef5cf13 100644 (file)
@@ -25,6 +25,7 @@ public class Gears implements GLEventListener {
   private boolean mouseRButtonDown = false;
 
   public void init(GLAutoDrawable drawable) {
+    System.out.println("Gears: Init");
     // Use debug pipeline
     // drawable.setGL(new DebugGL(drawable.getGL()));
 
@@ -77,6 +78,7 @@ public class Gears implements GLEventListener {
   }
     
   public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
+    System.out.println("Gears: Reshape");
     GL2 gl = drawable.getGL().getGL2();
 
     float h = (float)height / (float)width;
@@ -91,6 +93,7 @@ public class Gears implements GLEventListener {
   }
 
   public void dispose(GLAutoDrawable drawable) {
+    System.out.println("Gears: Dispose");
   }
 
   public void display(GLAutoDrawable drawable) {
@@ -144,8 +147,6 @@ public class Gears implements GLEventListener {
     gl.glPopMatrix();
   }
 
-  public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) {}
-
   public static void gear(GL2 gl,
                           float inner_radius,
                           float outer_radius,
index 2df3f0d..b191dbb 100755 (executable)
@@ -51,6 +51,10 @@ import org.junit.After;
 import org.junit.Test;
 
 public class TestGearsAWT {
+    static {
+        GLProfile.initSingleton();
+    }
+
     static GLProfile glp;
     static int width, height;
 
index e50ffbd..bafa8a1 100755 (executable)
@@ -48,6 +48,10 @@ import org.junit.After;
 import org.junit.Test;
 
 public class TestGearsNEWT {
+    static {
+        GLProfile.initSingleton();
+    }
+
     static GLProfile glp;
     static int width, height;
 
index 51977d6..316c9ed 100755 (executable)
@@ -49,6 +49,10 @@ import org.junit.After;
 import org.junit.Test;
 
 public class TestGearsNewtAWTWrapper {
+    static {
+        GLProfile.initSingleton();
+    }
+
     static GLProfile glp;
     static int width, height;
 
index cd0c7c0..8a9c960 100755 (executable)
@@ -45,6 +45,10 @@ import com.jogamp.newt.*;
 import java.io.IOException;
 
 public class TestDrawable01NEWT {
+    static {
+        GLProfile.initSingleton();
+    }
+
     static GLProfile glp;
     static GLDrawableFactory factory;
     static int width, height;
index bae7270..ad198fc 100755 (executable)
@@ -57,6 +57,10 @@ import com.jogamp.test.junit.jogl.demos.es1.RedSquare;
 import java.io.IOException;
 
 public class TestOffscreen01NEWT {
+    static {
+        GLProfile.initSingleton();
+    }
+
     static GLProfile glpDefault;
     static GLDrawableFactory glDrawableFactory;
     static int width, height;
index 7fdbd59..b34023b 100755 (executable)
@@ -56,6 +56,10 @@ import org.junit.BeforeClass;
 import org.junit.Test;
 
 public class TestTexture01AWT {
+    static {
+        GLProfile.initSingleton();
+    }
+
     static GLProfile glp;
     static GLCapabilities caps;
     BufferedImage textureImage;
index 4fd7744..3a36a11 100755 (executable)
@@ -47,8 +47,8 @@ import org.junit.Test;
 import javax.media.nativewindow.*;
 import javax.media.opengl.*;
 
-import com.jogamp.opengl.util.Animator;
 import com.jogamp.newt.*;
+import com.jogamp.newt.event.*;
 import com.jogamp.newt.opengl.*;
 import java.io.IOException;
 
@@ -56,9 +56,13 @@ import com.jogamp.test.junit.util.MiscUtils;
 import com.jogamp.test.junit.jogl.demos.gl2.gears.Gears;
 
 public class TestGLWindows01NEWT {
+    static {
+        GLProfile.initSingleton();
+    }
+
     static GLProfile glp;
     static int width, height;
-    static long duration = 100; // ms
+    static long durationPerTest = 100; // ms
 
     @BeforeClass
     public static void initClass() {
@@ -67,7 +71,11 @@ public class TestGLWindows01NEWT {
         glp = GLProfile.getDefault();
     }
 
-    static GLWindow createWindow(Screen screen, GLCapabilities caps, int width, int height, boolean onscreen, boolean undecorated) {
+    static GLWindow createWindow(Screen screen, GLCapabilities caps, 
+                                 int width, int height, boolean onscreen, boolean undecorated,
+                                 boolean addGLEventListenerAfterVisible) 
+        throws InterruptedException
+    {
         Assert.assertNotNull(caps);
         caps.setOnscreen(onscreen);
         // System.out.println("Requested: "+caps);
@@ -84,12 +92,23 @@ public class TestGLWindows01NEWT {
             glWindow = GLWindow.create(caps, onscreen && undecorated);
         }
         Assert.assertNotNull(glWindow);
+        Assert.assertEquals(false,glWindow.isVisible());
         Assert.assertEquals(false,glWindow.isNativeWindowValid());
+
+        GLEventListener demo = new Gears();
+        setDemoFields(demo, glWindow);
+        if(!addGLEventListenerAfterVisible) {
+            glWindow.addGLEventListener(demo);
+        }
+        glWindow.addWindowListener(new TraceWindowAdapter());
+
         glWindow.setSize(width, height);
-        Assert.assertEquals(false,glWindow.isVisible());
+
         glWindow.setVisible(true);
         Assert.assertEquals(true,glWindow.isVisible());
         Assert.assertEquals(true,glWindow.isNativeWindowValid());
+        while(glWindow.getTotalFrames()<1) { Thread.sleep(100); }
+        Assert.assertEquals(1,glWindow.getTotalFrames()); // native expose ..
         // Assert.assertEquals(width,glWindow.getWidth());
         // Assert.assertEquals(height,glWindow.getHeight());
         // System.out.println("Created: "+glWindow);
@@ -105,9 +124,10 @@ public class TestGLWindows01NEWT {
         Assert.assertTrue(caps.getRedBits()>5);
         Assert.assertEquals(caps.isOnscreen(),onscreen);
 
-        GLEventListener demo = new Gears();
-        setDemoFields(demo, glWindow);
-        glWindow.addGLEventListener(demo);
+        if(addGLEventListenerAfterVisible) {
+            glWindow.addGLEventListener(demo);
+            glWindow.display();
+        }
 
         return glWindow;
     }
@@ -115,17 +135,21 @@ public class TestGLWindows01NEWT {
     static void destroyWindow(GLWindow glWindow, boolean deep) {
         if(null!=glWindow) {
             glWindow.destroy(deep);
+            Assert.assertEquals(false,glWindow.isNativeWindowValid());
         }
     }
 
     @Test
-    public void testWindowNativeRecreate01Simple() throws InterruptedException {
+    public void testWindowNativeRecreate01aSimple() throws InterruptedException {
         GLCapabilities caps = new GLCapabilities(glp);
         Assert.assertNotNull(caps);
-        GLWindow window = createWindow(null, caps, width, height, true /* onscreen */, false /* undecorated */);
+        GLWindow window = createWindow(null, caps, width, height, 
+                                       true /* onscreen */, false /* undecorated */, 
+                                       false /*addGLEventListenerAfterVisible*/);
 
-        window.display();
-        window.destroy();
+        Assert.assertEquals(true,window.isNativeWindowValid());
+        Assert.assertEquals(true,window.isVisible());
+        window.destroy(false);
         Assert.assertEquals(false,window.isNativeWindowValid());
         Assert.assertEquals(false,window.isVisible());
 
@@ -136,28 +160,70 @@ public class TestGLWindows01NEWT {
         window.setVisible(true);
         Assert.assertEquals(true,window.isNativeWindowValid());
         Assert.assertEquals(true,window.isVisible());
+
+        window.setVisible(false);
+        Assert.assertEquals(true,window.isNativeWindowValid());
+        Assert.assertEquals(false,window.isVisible());
+
+        destroyWindow(window, true);
+    }
+
+    @Test
+    public void testWindowNativeRecreate01bSimple() throws InterruptedException {
+        GLCapabilities caps = new GLCapabilities(glp);
+        Assert.assertNotNull(caps);
+        GLWindow window = createWindow(null, caps, width, height, 
+                                       true /* onscreen */, false /* undecorated */, 
+                                       true /*addGLEventListenerAfterVisible*/);
+
+        Assert.assertEquals(true,window.isNativeWindowValid());
+        Assert.assertEquals(true,window.isVisible());
+        window.destroy(false);
+        Assert.assertEquals(false,window.isNativeWindowValid());
+        Assert.assertEquals(false,window.isVisible());
+
         window.display();
+        Assert.assertEquals(false,window.isNativeWindowValid());
+        Assert.assertEquals(false,window.isVisible());
+
+        window.setVisible(true);
+        Assert.assertEquals(true,window.isNativeWindowValid());
+        Assert.assertEquals(true,window.isVisible());
 
-        Animator animator = new Animator(window);
-        animator.start();
-        while(animator.isAnimating() && animator.getDuration()<duration) {
+        window.setVisible(false);
+        Assert.assertEquals(true,window.isNativeWindowValid());
+        Assert.assertEquals(false,window.isVisible());
+
+        destroyWindow(window, true);
+    }
+
+    @Test
+    public void testWindowDecor01aSimple() throws InterruptedException {
+        GLCapabilities caps = new GLCapabilities(glp);
+        Assert.assertNotNull(caps);
+        GLWindow window = createWindow(null, caps, width, height, 
+                                       true /* onscreen */, false /* undecorated */, 
+                                       false /*addGLEventListenerAfterVisible*/);
+        System.out.println("Created: "+window);
+        while(window.getDuration()<durationPerTest) {
             Thread.sleep(100);
         }
-        animator.stop();
+        System.out.println("duration: "+window.getDuration());
         destroyWindow(window, true);
     }
 
     @Test
-    public void testWindowDecor01Simple() throws InterruptedException {
+    public void testWindowDecor01bSimple() throws InterruptedException {
         GLCapabilities caps = new GLCapabilities(glp);
         Assert.assertNotNull(caps);
-        GLWindow window = createWindow(null, caps, width, height, true /* onscreen */, false /* undecorated */);
-        Animator animator = new Animator(window);
-        animator.start();
-        while(animator.isAnimating() && animator.getDuration()<duration) {
+        GLWindow window = createWindow(null, caps, width, height, 
+                                       true /* onscreen */, false /* undecorated */, 
+                                       true /*addGLEventListenerAfterVisible*/);
+        System.out.println("Created: "+window);
+        while(window.getDuration()<durationPerTest) {
             Thread.sleep(100);
         }
-        animator.stop();
+        System.out.println("duration: "+window.getDuration());
         destroyWindow(window, true);
     }
 
@@ -165,13 +231,13 @@ public class TestGLWindows01NEWT {
     public void testWindowDecor02DestroyWinTwiceA() throws InterruptedException {
         GLCapabilities caps = new GLCapabilities(glp);
         Assert.assertNotNull(caps);
-        GLWindow window = createWindow(null, caps, width, height, true /* onscreen */, false /* undecorated */);
-        Animator animator = new Animator(window);
-        animator.start();
-        while(animator.isAnimating() && animator.getDuration()<duration) {
+        GLWindow window = createWindow(null, caps, width, height, 
+                                       true /* onscreen */, false /* undecorated */, 
+                                       false /*addGLEventListenerAfterVisible*/);
+        while(window.getDuration()<durationPerTest) {
             Thread.sleep(100);
         }
-        animator.stop();
+        System.out.println("duration: "+window.getDuration());
         destroyWindow(window, false);
         destroyWindow(window, true);
     }
@@ -189,28 +255,26 @@ public class TestGLWindows01NEWT {
 
         Screen screen1  = NewtFactory.createScreen(display1, 0); // screen 0
         Assert.assertNotNull(screen1);
-        GLWindow window1 = createWindow(screen1, caps, width, height, true /* onscreen */, false /* undecorated */);
+        GLWindow window1 = createWindow(screen1, caps, width, height, 
+                                       true /* onscreen */, false /* undecorated */, 
+                                       false /*addGLEventListenerAfterVisible*/);
         Assert.assertNotNull(window1);
 
         Screen screen2  = NewtFactory.createScreen(display2, 0); // screen 0
         Assert.assertNotNull(screen2);
-        GLWindow window2 = createWindow(screen2, caps, width, height, true /* onscreen */, false /* undecorated */);
+        GLWindow window2 = createWindow(screen2, caps, width, height, 
+                                       true /* onscreen */, false /* undecorated */, 
+                                       false /*addGLEventListenerAfterVisible*/);
         Assert.assertNotNull(window2);
 
-        Animator animator1 = new Animator(window1);
-        animator1.start();
-        Animator animator2 = new Animator(window2);
-        animator2.start();
-        while(animator1.isAnimating() && animator1.getDuration()<duration) {
+        while(window1.getDuration()<durationPerTest) {
             Thread.sleep(100);
         }
+        System.out.println("duration1: "+window1.getDuration());
+        System.out.println("duration2: "+window2.getDuration());
 
-        animator2.stop();
-        Assert.assertEquals(false, animator2.isAnimating());
         destroyWindow(window2, true);
 
-        animator1.stop();
-        Assert.assertEquals(false, animator1.isAnimating());
         destroyWindow(window1, true);
     }
 
@@ -222,7 +286,21 @@ public class TestGLWindows01NEWT {
         }
     }
 
+    static int atoi(String a) {
+        int i=0;
+        try {
+            i = Integer.parseInt(a);
+        } catch (Exception ex) { ex.printStackTrace(); }
+        return i;
+    }
+
     public static void main(String args[]) throws IOException {
+        for(int i=0; i<args.length; i++) {
+            if(args[i].equals("-time")) {
+                durationPerTest = atoi(args[++i]);
+            }
+        }
+        System.out.println("durationPerTest: "+durationPerTest);
         String tstname = TestGLWindows01NEWT.class.getName();
         org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(new String[] {
             tstname,
diff --git a/src/junit/com/jogamp/test/junit/newt/TestGLWindows02NEWTAnimated.java b/src/junit/com/jogamp/test/junit/newt/TestGLWindows02NEWTAnimated.java
new file mode 100755 (executable)
index 0000000..0677bc8
--- /dev/null
@@ -0,0 +1,230 @@
+/*
+ * Copyright (c) 2010 Sven Gothel. 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 Sven Gothel 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
+ * SVEN GOTHEL HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+package com.jogamp.test.junit.newt;
+
+import java.lang.reflect.*;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Test;
+
+import javax.media.nativewindow.*;
+import javax.media.opengl.*;
+
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.newt.*;
+import com.jogamp.newt.event.*;
+import com.jogamp.newt.opengl.*;
+import java.io.IOException;
+
+import com.jogamp.test.junit.util.MiscUtils;
+import com.jogamp.test.junit.jogl.demos.gl2.gears.Gears;
+
+public class TestGLWindows02NEWTAnimated {
+    static {
+        GLProfile.initSingleton();
+    }
+
+    static GLProfile glp;
+    static int width, height;
+    static long durationPerTest = 100; // ms
+
+    @BeforeClass
+    public static void initClass() {
+        width  = 640;
+        height = 480;
+        glp = GLProfile.getDefault();
+    }
+
+    static GLWindow createWindow(Screen screen, GLCapabilities caps, int width, int height, boolean onscreen, boolean undecorated) {
+        Assert.assertNotNull(caps);
+        caps.setOnscreen(onscreen);
+        // System.out.println("Requested: "+caps);
+
+        //
+        // Create native windowing resources .. X11/Win/OSX
+        // 
+        GLWindow glWindow;
+        if(null!=screen) {
+            Window window = NewtFactory.createWindow(screen, caps, onscreen && undecorated);
+            Assert.assertNotNull(window);
+            glWindow = GLWindow.create(window);
+        } else {
+            glWindow = GLWindow.create(caps, onscreen && undecorated);
+        }
+        Assert.assertNotNull(glWindow);
+        GLEventListener demo = new Gears();
+        setDemoFields(demo, glWindow);
+        glWindow.addGLEventListener(demo);
+        glWindow.addWindowListener(new TraceWindowAdapter());
+        Assert.assertEquals(false,glWindow.isNativeWindowValid());
+
+        glWindow.setSize(width, height);
+        Assert.assertEquals(false,glWindow.isVisible());
+        glWindow.setVisible(true);
+        Assert.assertEquals(true,glWindow.isVisible());
+        Assert.assertEquals(true,glWindow.isNativeWindowValid());
+        // Assert.assertEquals(width,glWindow.getWidth());
+        // Assert.assertEquals(height,glWindow.getHeight());
+        // System.out.println("Created: "+glWindow);
+
+        //
+        // Create native OpenGL resources .. XGL/WGL/CGL .. 
+        // equivalent to GLAutoDrawable methods: setVisible(true)
+        // 
+        caps = (GLCapabilities) glWindow.getGraphicsConfiguration().getNativeGraphicsConfiguration().getChosenCapabilities();
+        Assert.assertNotNull(caps);
+        Assert.assertTrue(caps.getGreenBits()>5);
+        Assert.assertTrue(caps.getBlueBits()>5);
+        Assert.assertTrue(caps.getRedBits()>5);
+        Assert.assertEquals(caps.isOnscreen(),onscreen);
+
+        return glWindow;
+    }
+
+    static void destroyWindow(GLWindow glWindow, boolean deep) {
+        if(null!=glWindow) {
+            glWindow.destroy(deep);
+        }
+    }
+
+    @Test
+    public void testWindowDecor01Simple() throws InterruptedException {
+        GLCapabilities caps = new GLCapabilities(glp);
+        Assert.assertNotNull(caps);
+        GLWindow window = createWindow(null, caps, width, height, true /* onscreen */, false /* undecorated */);
+        Animator animator = new Animator(window);
+        animator.start();
+        while(animator.isAnimating() && animator.getDuration()<durationPerTest) {
+            Thread.sleep(100);
+        }
+        animator.stop();
+        destroyWindow(window, true);
+    }
+
+    @Test
+    public void testWindowDecor02DestroyWinTwiceA() throws InterruptedException {
+        GLCapabilities caps = new GLCapabilities(glp);
+        Assert.assertNotNull(caps);
+        GLWindow window = createWindow(null, caps, width, height, true /* onscreen */, false /* undecorated */);
+        Animator animator = new Animator(window);
+        animator.start();
+        while(animator.isAnimating() && animator.getDuration()<durationPerTest) {
+            Thread.sleep(100);
+        }
+        animator.stop();
+        destroyWindow(window, false);
+        destroyWindow(window, true);
+    }
+
+    @Test
+    public void testWindowDecor03TwoWin() throws InterruptedException {
+        GLCapabilities caps = new GLCapabilities(glp);
+        Assert.assertNotNull(caps);
+
+        Display display1 = NewtFactory.createDisplay(null); // local display
+        Assert.assertNotNull(display1);
+        Display display2 = NewtFactory.createDisplay(null); // local display
+        Assert.assertNotNull(display2);
+        Assert.assertEquals(display1, display2); // must be equal: same thread - same display
+
+        Screen screen1  = NewtFactory.createScreen(display1, 0); // screen 0
+        Assert.assertNotNull(screen1);
+        GLWindow window1 = createWindow(screen1, caps, width, height, true /* onscreen */, false /* undecorated */);
+        Assert.assertNotNull(window1);
+
+        Screen screen2  = NewtFactory.createScreen(display2, 0); // screen 0
+        Assert.assertNotNull(screen2);
+        GLWindow window2 = createWindow(screen2, caps, width-10, height-10, true /* onscreen */, false /* undecorated */);
+        Assert.assertNotNull(window2);
+
+        Animator animator1 = new Animator(window1);
+        animator1.start();
+        Animator animator2 = new Animator(window2);
+        animator2.start();
+        while(animator1.isAnimating() && animator1.getDuration()<durationPerTest) {
+            Thread.sleep(100);
+        }
+
+        animator2.stop();
+        Assert.assertEquals(false, animator2.isAnimating());
+        destroyWindow(window2, false);
+
+        animator1.stop();
+        Assert.assertEquals(false, animator1.isAnimating());
+        destroyWindow(window1, true);
+    }
+
+    public static void setDemoFields(GLEventListener demo, GLWindow glWindow) {
+        Assert.assertNotNull(demo);
+        Assert.assertNotNull(glWindow);
+        if(!MiscUtils.setFieldIfExists(demo, "window", glWindow.getInnerWindow())) {
+            MiscUtils.setFieldIfExists(demo, "glWindow", glWindow);
+        }
+    }
+
+    static int atoi(String a) {
+        int i=0;
+        try {
+            i = Integer.parseInt(a);
+        } catch (Exception ex) { ex.printStackTrace(); }
+        return i;
+    }
+
+    public static void main(String args[]) throws IOException {
+        for(int i=0; i<args.length; i++) {
+            if(args[i].equals("-time")) {
+                durationPerTest = atoi(args[++i]);
+            }
+        }
+        String tstname = TestGLWindows02NEWTAnimated.class.getName();
+        org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(new String[] {
+            tstname,
+            "filtertrace=true",
+            "haltOnError=false",
+            "haltOnFailure=false",
+            "showoutput=true",
+            "outputtoformatters=true",
+            "logfailedtests=true",
+            "logtestlistenerevents=true",
+            "formatter=org.apache.tools.ant.taskdefs.optional.junit.PlainJUnitResultFormatter",
+            "formatter=org.apache.tools.ant.taskdefs.optional.junit.XMLJUnitResultFormatter,TEST-"+tstname+".xml" } );
+    }
+
+}
index 495b8bb..5a67bbc 100755 (executable)
@@ -65,9 +65,12 @@ import com.jogamp.test.junit.jogl.demos.es1.RedSquare;
 import com.jogamp.test.junit.jogl.demos.gl2.gears.Gears;
 
 public class TestListenerCom01AWT {
+    static {
+        GLProfile.initSingleton();
+    }
+
     static int width, height;
     static long durationPerTest = 500;
-    static long waitReparent = 300;
     static boolean verbose = false;
 
     @BeforeClass
@@ -152,8 +155,6 @@ public class TestListenerCom01AWT {
         for(int i=0; i<args.length; i++) {
             if(args[i].equals("-time")) {
                 durationPerTest = atoi(args[++i]);
-            } else if(args[i].equals("-wait")) {
-                waitReparent = atoi(args[++i]);
             }
         }
         String tstname = TestListenerCom01AWT.class.getName();
index 58ea235..89d9c1c 100755 (executable)
@@ -120,6 +120,7 @@ public class TestWindows01NEWT {
 
         window.setVisible(true);
         Assert.assertEquals(true,window.isNativeWindowValid());
+        Assert.assertEquals(true,window.isVisible());
 
         Thread.sleep(100); // 100 ms
         destroyWindow(display, screen, window);
@@ -30,7 +30,7 @@
  * SVEN GOTHEL HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
  */
 
-package com.jogamp.test.junit.newt;
+package com.jogamp.test.junit.newt.parenting;
 
 import org.junit.Assert;
 import org.junit.Before;
@@ -47,7 +47,7 @@ public class GLRunnableDummy implements GLRunnable {
     float d=0.001f;
 
     public void run(GLAutoDrawable drawable) {
-        // nop ..
+        System.out.println("Red: "+r);
         GL2ES1 gl = drawable.getGL().getGL2ES1();
         gl.glClearColor(r, g, b, 1f);
         r+=d;
@@ -31,7 +31,7 @@
  * SVEN GOTHEL HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
  */
 
-package com.jogamp.test.junit.newt;
+package com.jogamp.test.junit.newt.parenting;
 
 import com.jogamp.newt.event.*;
 
@@ -30,7 +30,7 @@
  * SVEN GOTHEL HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
  */
 
-package com.jogamp.test.junit.newt;
+package com.jogamp.test.junit.newt.parenting;
 
 import java.lang.reflect.*;
 import java.util.ArrayList;
@@ -60,6 +60,10 @@ import com.jogamp.test.junit.jogl.demos.es1.RedSquare;
 import com.jogamp.test.junit.jogl.demos.gl2.gears.Gears;
 
 public class TestParenting01NEWT {
+    static {
+        GLProfile.initSingleton();
+    }
+
     static int width, height;
     static long durationPerTest = 500;
     static long waitReparent = 0;
@@ -30,7 +30,7 @@
  * SVEN GOTHEL HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
  */
 
-package com.jogamp.test.junit.newt;
+package com.jogamp.test.junit.newt.parenting;
 
 import java.lang.reflect.*;
 import java.util.ArrayList;
@@ -47,6 +47,7 @@ import org.junit.Test;
 import java.awt.Button;
 import java.awt.BorderLayout;
 import java.awt.Canvas;
+import java.awt.Container;
 import java.awt.Frame;
 import java.awt.Dimension;
 
@@ -66,6 +67,10 @@ import com.jogamp.test.junit.jogl.demos.es1.RedSquare;
 import com.jogamp.test.junit.jogl.demos.gl2.gears.Gears;
 
 public class TestParenting01aAWT {
+    static {
+        GLProfile.initSingleton();
+    }
+
     static int width, height;
     static long durationPerTest = 800;
     static long waitReparent = 0;
@@ -101,13 +106,26 @@ public class TestParenting01aAWT {
         Assert.assertEquals(false, glWindow1.isNativeWindowValid());
         Assert.assertNull(glWindow1.getParentNativeWindow());
 
-        Frame frame = new Frame("AWT Parent Frame");
-        Assert.assertNotNull(frame);
-        frame.add(newtCanvasAWT);
-        frame.setSize(width, height);
+        Frame frame1 = new Frame("AWT Parent Frame");
+        frame1.setLayout(new BorderLayout());
+        frame1.add(new Button("North"), BorderLayout.NORTH);
+        frame1.add(new Button("South"), BorderLayout.SOUTH);
+        frame1.add(new Button("East"), BorderLayout.EAST);
+        frame1.add(new Button("West"), BorderLayout.WEST);
+
+        Container container1 = new Container();
+        container1.setLayout(new BorderLayout());
+        container1.add(new Button("north"), BorderLayout.NORTH);
+        container1.add(new Button("south"), BorderLayout.SOUTH);
+        container1.add(new Button("east"), BorderLayout.EAST);
+        container1.add(new Button("west"), BorderLayout.WEST);
+        container1.add(newtCanvasAWT, BorderLayout.CENTER);
+
+        frame1.add(container1, BorderLayout.CENTER);
+        frame1.setSize(width, height);
 
         // visible test
-        frame.setVisible(true);
+        frame1.setVisible(true);
         Assert.assertEquals(newtCanvasAWT.getNativeWindow(),glWindow1.getParentNativeWindow());
 
         Animator animator1 = new Animator(glWindow1);
@@ -118,17 +136,17 @@ public class TestParenting01aAWT {
         animator1.stop();
         Assert.assertEquals(false, animator1.isAnimating());
 
-        frame.setVisible(false);
+        frame1.setVisible(false);
         Assert.assertEquals(false, glWindow1.isDestroyed());
 
-        frame.setVisible(true);
+        frame1.setVisible(true);
         Assert.assertEquals(false, glWindow1.isDestroyed());
 
-        frame.remove(newtCanvasAWT);
+        frame1.remove(newtCanvasAWT);
         // Assert.assertNull(glWindow1.getParentNativeWindow());
         Assert.assertEquals(false, glWindow1.isDestroyed());
 
-        frame.dispose();
+        frame1.dispose();
         Assert.assertEquals(false, glWindow1.isDestroyed());
 
         glWindow1.destroy(true);
@@ -30,7 +30,7 @@
  * SVEN GOTHEL HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
  */
 
-package com.jogamp.test.junit.newt;
+package com.jogamp.test.junit.newt.parenting;
 
 import java.lang.reflect.*;
 import java.util.ArrayList;
@@ -66,6 +66,10 @@ import com.jogamp.test.junit.jogl.demos.es1.RedSquare;
 import com.jogamp.test.junit.jogl.demos.gl2.gears.Gears;
 
 public class TestParenting01bAWT {
+    static {
+        GLProfile.initSingleton();
+    }
+
     static int width, height;
     static long durationPerTest = 800;
     static long waitReparent = 0;
@@ -30,7 +30,7 @@
  * SVEN GOTHEL HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
  */
 
-package com.jogamp.test.junit.newt;
+package com.jogamp.test.junit.newt.parenting;
 
 import java.lang.reflect.*;
 import java.util.ArrayList;
@@ -67,6 +67,10 @@ import com.jogamp.test.junit.jogl.demos.es1.RedSquare;
 import com.jogamp.test.junit.jogl.demos.gl2.gears.Gears;
 
 public class TestParenting01cAWT {
+    static {
+        GLProfile.initSingleton();
+    }
+
     static int width, height;
     static long durationPerTest = 800;
     static long waitReparent = 0;
@@ -124,13 +128,9 @@ public class TestParenting01cAWT {
         frame1.setVisible(true);
         Assert.assertEquals(newtCanvasAWT.getNativeWindow(),glWindow1.getParentNativeWindow());
 
-        Animator animator1 = new Animator(glWindow1);
-        animator1.start();
-        while(animator1.isAnimating() && animator1.getDuration()<durationPerTest) {
+        while(glWindow1.getDuration()<durationPerTest) {
             Thread.sleep(100);
         }
-        animator1.stop();
-        Assert.assertEquals(false, animator1.isAnimating());
 
         frame1.setVisible(false);
         Assert.assertEquals(false, glWindow1.isDestroyed());
@@ -149,6 +149,64 @@ public class TestParenting01cAWT {
         //Assert.assertEquals(true, glWindow1.isDestroyed());
     }
 
+    @Test
+    public void testWindowParenting05ReparentAWTWinHopFrame2Frame() throws InterruptedException {
+        int x = 0;
+        int y = 0;
+
+        NEWTEventFiFo eventFifo = new NEWTEventFiFo();
+
+        GLWindow glWindow1 = GLWindow.create(glCaps, true);
+        GLEventListener demo1 = new RedSquare();
+        setDemoFields(demo1, glWindow1, false);
+        glWindow1.addGLEventListener(demo1);
+
+        NewtCanvasAWT newtCanvasAWT = new NewtCanvasAWT(glWindow1);
+
+        Frame frame1 = new Frame("AWT Parent Frame");
+        frame1.setLayout(new BorderLayout());
+        frame1.add(new Button("North"), BorderLayout.NORTH);
+        frame1.add(new Button("South"), BorderLayout.SOUTH);
+        frame1.add(new Button("East"), BorderLayout.EAST);
+        frame1.add(new Button("West"), BorderLayout.WEST);
+        frame1.setSize(width, height);
+        frame1.setLocation(0, 0);
+        frame1.setVisible(true);
+
+        Frame frame2 = new Frame("AWT Parent Frame");
+        frame2.setLayout(new BorderLayout());
+        frame2.add(new Button("North"), BorderLayout.NORTH);
+        frame2.add(new Button("South"), BorderLayout.SOUTH);
+        frame2.add(new Button("East"), BorderLayout.EAST);
+        frame2.add(new Button("West"), BorderLayout.WEST);
+        frame2.setSize(width, height);
+        frame2.setLocation(640, 480);
+        frame2.setVisible(true);
+
+        frame1.add(newtCanvasAWT, BorderLayout.CENTER);
+        Assert.assertEquals(newtCanvasAWT.getNativeWindow(),glWindow1.getParentNativeWindow());
+
+        int state = 0;
+        while(glWindow1.getDuration()<3*durationPerTest) {
+            Thread.sleep(durationPerTest);
+            switch(state) {
+                case 0:
+                    frame1.remove(newtCanvasAWT);
+                    frame2.add(newtCanvasAWT, BorderLayout.CENTER);
+                    break;
+                case 1:
+                    frame2.remove(newtCanvasAWT);
+                    frame1.add(newtCanvasAWT, BorderLayout.CENTER);
+                    break;
+            }
+            state++;
+        }
+
+        frame1.dispose();
+        frame2.dispose();
+        glWindow1.destroy(true);
+    }
+
     public static void setDemoFields(GLEventListener demo, GLWindow glWindow, boolean debug) {
         Assert.assertNotNull(demo);
         Assert.assertNotNull(glWindow);
@@ -30,7 +30,7 @@
  * SVEN GOTHEL HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
  */
 
-package com.jogamp.test.junit.newt;
+package com.jogamp.test.junit.newt.parenting;
 
 import java.lang.reflect.*;
 import java.util.ArrayList;
@@ -70,6 +70,10 @@ import com.jogamp.test.junit.jogl.demos.es1.RedSquare;
 import com.jogamp.test.junit.jogl.demos.gl2.gears.Gears;
 
 public class TestParenting01cSwingAWT {
+    static {
+        GLProfile.initSingleton();
+    }
+
     static int width, height;
     static long durationPerTest = 800;
     static long waitReparent = 0;
@@ -147,6 +151,7 @@ public class TestParenting01cSwingAWT {
         jFrame1.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); // equivalent to Frame, use windowClosing event!
         jFrame1.setContentPane(jPanel1);
         jFrame1.setSize(width, height);
+        System.out.println("Demos: 1 - Visible");
         jFrame1.setVisible(true); // from here on, we need to run modifications on EDT
 
         final JFrame _jFrame1 = jFrame1;
@@ -159,23 +164,27 @@ public class TestParenting01cSwingAWT {
         while(animator1.isAnimating() && animator1.getDuration()<durationPerTest) {
             Thread.sleep(100);
         }
+        System.out.println("Demos: 2 - StopAnimator");
         animator1.stop();
         Assert.assertEquals(false, animator1.isAnimating());
 
         SwingUtilities.invokeAndWait(new Runnable() {
                 public void run() {
+                   System.out.println("Demos: 3 - !Visible");
                     _jFrame1.setVisible(false);
                 } });
         Assert.assertEquals(false, glWindow1.isDestroyed());
 
         SwingUtilities.invokeAndWait(new Runnable() {
                 public void run() {
+                   System.out.println("Demos: 4 - Visible");
                     _jFrame1.setVisible(true);
                 } });
         Assert.assertEquals(false, glWindow1.isDestroyed());
 
         SwingUtilities.invokeAndWait(new Runnable() {
                 public void run() {
+                   System.out.println("Demos: 5 - X Container");
                     _jPanel1.remove(_container1);
                 } });
         // Assert.assertNull(glWindow1.getParentNativeWindow());
@@ -30,7 +30,7 @@
  * SVEN GOTHEL HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
  */
 
-package com.jogamp.test.junit.newt;
+package com.jogamp.test.junit.newt.parenting;
 
 import java.lang.reflect.*;
 import java.util.ArrayList;
@@ -65,6 +65,10 @@ import com.jogamp.test.junit.jogl.demos.es1.RedSquare;
 import com.jogamp.test.junit.jogl.demos.gl2.gears.Gears;
 
 public class TestParenting02AWT {
+    static {
+        GLProfile.initSingleton();
+    }
+
     static int width, height;
     static long durationPerTest = 500;
     static long waitReparent = 300;
@@ -30,7 +30,7 @@
  * SVEN GOTHEL HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
  */
 
-package com.jogamp.test.junit.newt;
+package com.jogamp.test.junit.newt.parenting;
 
 import java.lang.reflect.*;
 import java.util.ArrayList;
@@ -59,6 +59,10 @@ import com.jogamp.test.junit.jogl.demos.es1.RedSquare;
 import com.jogamp.test.junit.jogl.demos.gl2.gears.Gears;
 
 public class TestParenting02NEWT {
+    static {
+        GLProfile.initSingleton();
+    }
+
     static int width, height;
     static long durationPerTest = 500;
 
@@ -122,6 +126,11 @@ public class TestParenting02NEWT {
         glWindow1.setPosition(x,y);
         glWindow1.addKeyListener(new TraceKeyAdapter(new KeyAction(eventFifo)));
         glWindow1.addWindowListener(new TraceWindowAdapter());
+
+        GLEventListener demo1 = new RedSquare();
+        setDemoFields(demo1, window1, glWindow1, false);
+        // glWindow1.addGLEventListener(demo1);
+
         glWindow1.setVisible(true);
         Capabilities capsChosen = glWindow1.getGraphicsConfiguration().getNativeGraphicsConfiguration().getChosenCapabilities();
         Assert.assertNotNull(capsChosen);
@@ -139,17 +148,17 @@ public class TestParenting02NEWT {
         glWindow2.addKeyListener(new TraceKeyAdapter(new KeyAction(eventFifo)));
         glWindow2.addWindowListener(new TraceWindowAdapter(new WindowAction(eventFifo)));
         // glWindow2.addMouseListener(new TraceMouseAdapter());
+
+        GLEventListener demo2 = new Gears();
+        setDemoFields(demo2, window2, glWindow2, false);
+        // glWindow2.addGLEventListener(demo2);
+
         glWindow2.setVisible(true);
         capsChosen = glWindow2.getGraphicsConfiguration().getNativeGraphicsConfiguration().getChosenCapabilities();
         Assert.assertNotNull(capsChosen);
         Assert.assertTrue(capsChosen.isOnscreen()==true);
 
-        GLEventListener demo1 = new RedSquare();
-        setDemoFields(demo1, window1, glWindow1, false);
         glWindow1.addGLEventListener(demo1);
-
-        GLEventListener demo2 = new Gears();
-        setDemoFields(demo2, window2, glWindow2, false);
         glWindow2.addGLEventListener(demo2);
 
         boolean shouldQuit = false;
@@ -30,7 +30,7 @@
  * SVEN GOTHEL HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
  */
 
-package com.jogamp.test.junit.newt;
+package com.jogamp.test.junit.newt.parenting;
 
 import com.jogamp.newt.event.*;
 
index 236ef07..a3782d1 100644 (file)
@@ -9,7 +9,7 @@ public class RecursiveToolkitLock {
     private Thread owner = null;
     private int recursionCount = 0;
     private Exception lockedStack = null;
-    private static final long timeout = 3000;  // maximum wait 3s
+    private static final long timeout = 30000;  // maximum wait 3s
     private static final boolean TRACE_LOCK = false;
 
     public Exception getLockedStack() {
index 02c4733..deb4c7a 100755 (executable)
@@ -182,10 +182,9 @@ public abstract class Display {
         return true; 
     }
     public EDTUtil getEDTUtil() {
-        if( !edtQueried ) {
+        if( null == edtUtil ) {
             synchronized (this) {
-                if( !edtQueried ) {
-                    edtQueried = true;
+                if( null == edtUtil ) {
                     if(NewtFactory.useEDT()) {
                         final Display f_dpy = this;
                         Thread current = Thread.currentThread();
@@ -203,12 +202,11 @@ public abstract class Display {
         }
         return edtUtil;
     }
-    volatile boolean edtQueried = false;
 
     public void runOnEDTIfAvail(boolean wait, final Runnable task) {
-        EDTUtil edtUtil = getEDTUtil();
-        if(runCreateAndDestroyOnEDT() && null!=edtUtil) {
-            edtUtil.invoke(wait, task);
+        EDTUtil _edtUtil = getEDTUtil();
+        if(runCreateAndDestroyOnEDT() && null!=_edtUtil) {
+            _edtUtil.invoke(wait, task);
         } else {
             task.run();
         }
@@ -238,6 +236,7 @@ public abstract class Display {
             if(null!=edtUtil) { 
                 edtUtil.waitUntilStopped();
                 edtUtil=null;
+                edt=null;
             }
             aDevice = null;
         } else {
@@ -318,11 +317,12 @@ public abstract class Display {
     private LinkedList/*<NEWTEvent>*/ events = new LinkedList();
 
     protected void dispatchMessages() {
-        if(0==refCount) return; // we should not exist ..
+        if(0==refCount) return; // in destruction ..
+
+        LinkedList/*<NEWTEvent>*/ _events = null;
 
         if(!events.isEmpty()) {
             // swap events list to free ASAP
-            LinkedList/*<NEWTEvent>*/ _events = null;
             synchronized(eventsLock) {
                 if(!events.isEmpty()) {
                     _events = events;
@@ -335,10 +335,13 @@ public abstract class Display {
                     NEWTEventTask eventTask = (NEWTEventTask) iter.next();
                     NEWTEvent event = eventTask.get();
                     Object source = event.getSource();
-                    if(source instanceof Window) {
-                        ((Window)source).sendEvent(event);
+                    if(source instanceof NEWTEventConsumer) {
+                        NEWTEventConsumer consumer = (NEWTEventConsumer) source ;
+                        if(!consumer.consumeEvent(event)) {
+                            enqueueEvent(false, event);
+                        }
                     } else {
-                        throw new RuntimeException("Event source not a NEWT Window: "+source.getClass().getName()+", "+source);
+                        throw new RuntimeException("Event source not a NEWT one: "+source.getClass().getName()+", "+source);
                     }
                     eventTask.notifyIssuer();
                 }
index 9bd4bb3..0cd5b31 100755 (executable)
 package com.jogamp.newt;
 
 import com.jogamp.newt.event.*;
+import com.jogamp.newt.util.*;
 import com.jogamp.newt.impl.Debug;
-import com.jogamp.newt.util.EDTUtil;
 
 import com.jogamp.common.util.*;
 import javax.media.nativewindow.*;
+import com.jogamp.nativewindow.util.Rectangle;
 import com.jogamp.nativewindow.impl.RecursiveToolkitLock;
 
 import java.util.ArrayList;
@@ -46,7 +47,7 @@ import java.util.List;
 import java.util.Iterator;
 import java.lang.reflect.Method;
 
-public abstract class Window implements NativeWindow
+public abstract class Window implements NativeWindow, NEWTEventConsumer
 {
     public static final boolean DEBUG_MOUSE_EVENT = Debug.debug("Window.MouseEvent");
     public static final boolean DEBUG_KEY_EVENT = Debug.debug("Window.KeyEvent");
@@ -155,7 +156,7 @@ public abstract class Window implements NativeWindow
             return 0 != windowHandle ;
         }
         if(DEBUG_IMPLEMENTATION) {
-            System.err.println("Window.createNative() START ("+getThreadName()+", "+this+")");
+            System.out.println("Window.createNative() START ("+getThreadName()+", "+this+")");
         }
         if(validateParentWindowHandle()) {
             Display dpy = getScreen().getDisplay();
@@ -163,7 +164,7 @@ public abstract class Window implements NativeWindow
             setVisibleImpl(true);
         }
         if(DEBUG_IMPLEMENTATION) {
-            System.err.println("Window.createNative() END ("+getThreadName()+", "+this+")");
+            System.out.println("Window.createNative() END ("+getThreadName()+", "+this+")");
         }
         return 0 != windowHandle ;
     }
@@ -190,7 +191,7 @@ public abstract class Window implements NativeWindow
                 }
             } catch (NativeWindowException nwe) {
                 if(DEBUG_IMPLEMENTATION) {
-                    System.err.println("Window.getNativeWindowHandle: not successful yet: "+nwe);
+                    System.out.println("Window.getNativeWindowHandle: not successful yet: "+nwe);
                 }
             } finally {
                 if(locked) {
@@ -198,7 +199,7 @@ public abstract class Window implements NativeWindow
                 }
             }
             if(DEBUG_IMPLEMENTATION) {
-                System.err.println("Window.getNativeWindowHandle: locked "+locked+", "+nativeWindow);
+                System.out.println("Window.getNativeWindowHandle: locked "+locked+", "+nativeWindow);
             }
         }
         return handle;
@@ -245,7 +246,8 @@ public abstract class Window implements NativeWindow
                     "\n, Visible "+isVisible()+
                     "\n, Undecorated "+undecorated+
                     "\n, Fullscreen "+fullscreen+
-                    "\n, WrappedWindow "+getWrappedWindow());
+                    "\n, WrappedWindow "+getWrappedWindow()+
+                    "\n, ChildWindows "+childWindows.size());
 
         sb.append(", SurfaceUpdatedListeners num "+surfaceUpdatedListeners.size()+" [");
         for (Iterator iter = surfaceUpdatedListeners.iterator(); iter.hasNext(); ) {
@@ -376,41 +378,38 @@ public abstract class Window implements NativeWindow
         public void run() {
             windowLock();
             try {
-                if(DEBUG_WINDOW_EVENT) {
-                    System.err.println("Window.destroy(deep: "+deep+") START "+getThreadName()+", "+this);
+                if(DEBUG_IMPLEMENTATION) {
+                    System.out.println("Window.destroy(deep: "+deep+") START "+getThreadName()+", "+Window.this);
                 }
 
                 // Childs first ..
-                ArrayList listeners = null;
-                synchronized(childWindows) {
-                    listeners = childWindows;
-                }
-                for(Iterator i = listeners.iterator(); i.hasNext(); ) {
+                synchronized(childWindowsLock) {
+                  for(Iterator i = childWindows.iterator(); i.hasNext(); ) {
                     NativeWindow nw = (NativeWindow) i.next();
+                    System.out.println("Window.destroy(deep: "+deep+") CHILD BEGIN");
                     if(nw instanceof Window) {
-                        ((Window)nw).destroy(deep);
+                        ((Window)nw).sendWindowEvent(WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY);
+                        if(deep) {
+                                ((Window)nw).destroy(deep);
+                        }
                     } else {
                         nw.destroy();
                     }
+                    System.out.println("Window.destroy(deep: "+deep+") CHILD END");
+                  }
                 }
 
                 // Now us ..
                 if(deep) {
-                    synchronized(childWindows) {
+                    synchronized(childWindowsLock) {
                         childWindows = new ArrayList();
                     }
-                    synchronized(surfaceUpdatedListeners) {
+                    synchronized(surfaceUpdatedListenersLock) {
                         surfaceUpdatedListeners = new ArrayList();
                     }
-                    synchronized(windowListeners) {
-                        windowListeners = new ArrayList();
-                    }
-                    synchronized(mouseListeners) {
-                        mouseListeners = new ArrayList();
-                    }
-                    synchronized(keyListeners) {
-                        keyListeners = new ArrayList();
-                    }
+                    windowListeners = new ArrayList();
+                    mouseListeners = new ArrayList();
+                    keyListeners = new ArrayList();
                 }
                 Display dpy = null;
                 Screen scr = null;
@@ -428,8 +427,8 @@ public abstract class Window implements NativeWindow
                         dpy.destroy();
                     }
                 }
-                if(DEBUG_WINDOW_EVENT) {
-                    System.err.println("Window.destroy(deep: "+deep+") END "+getThreadName()+", "+this);
+                if(DEBUG_IMPLEMENTATION) {
+                    System.out.println("Window.destroy(deep: "+deep+") END "+getThreadName()+", "+Window.this);
                 }
             } finally {
                 windowUnlock();
@@ -466,16 +465,16 @@ public abstract class Window implements NativeWindow
         try{
             if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) {
                 String msg = new String("!!! Window Invalidate(deep: "+deep+") "+getThreadName());
-                System.err.println(msg);
-                //Exception e = new Exception(msg);
-                //e.printStackTrace();
+                //System.out.println(msg);
+                Exception e = new Exception(msg);
+                e.printStackTrace();
             }
             windowHandle = 0;
-            visible=false;
-            fullscreen=false;
+            visible = false;
+            fullscreen = false;
 
             if(deep) {
-                screen   = null;
+                screen = null;
                 parentWindowHandle = 0;
                 parentNativeWindow = null;
                 caps = null;
@@ -593,43 +592,6 @@ public abstract class Window implements NativeWindow
         return false;
     }
 
-    /**
-     * If set to true, the default value, this NEWT Window implementation will 
-     * handle the destruction (ie {@link #destroy()} call) within {@link #windowDestroyNotify()} implementation.<br>
-     * If set to false, it's up to the caller/owner to handle destruction within {@link #windowDestroyNotify()}.
-     */
-    public void setHandleDestroyNotify(boolean b) {
-        handleDestroyNotify = b;
-    }
-
-    protected void windowDestroyNotify() {
-        if(DEBUG_WINDOW_EVENT) {
-            System.err.println("Window.windowDestroyNotify START "+getThreadName());
-        }
-
-        enqueueWindowEvent(false, WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY);
-
-        if(handleDestroyNotify && !isDestroyed()) {
-            destroy();
-        }
-
-        if(DEBUG_WINDOW_EVENT) {
-            System.err.println("Window.windowDestroyeNotify END "+getThreadName());
-        }
-    }
-
-    protected void windowDestroyed() {
-        if(DEBUG_WINDOW_EVENT) {
-            System.err.println("Window.windowDestroyed "+getThreadName());
-        }
-        invalidate();
-    }
-
-    protected boolean reparentWindowImpl() {
-        // default implementation, no native reparenting support
-        return false;
-    }
-
     class ReparentAction implements Runnable {
         NativeWindow newParent;
         Screen newScreen;
@@ -652,7 +614,7 @@ public abstract class Window implements NativeWindow
                 }
 
                 if(DEBUG_IMPLEMENTATION) {
-                    System.err.println("reparent: START ("+getThreadName()+") windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle)+" -> "+toHexString(newParentHandle)+", visible "+visible+", parentNativeWindow "+(null!=parentNativeWindow));
+                    System.out.println("reparent: START ("+getThreadName()+") windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle)+" -> "+toHexString(newParentHandle)+", visible "+visible+", parentNativeWindow "+(null!=parentNativeWindow));
                 }
 
                 if(null!=parentNativeWindow && parentNativeWindow instanceof Window) {
@@ -671,8 +633,16 @@ public abstract class Window implements NativeWindow
                         x = 0;
                         y = 0;
                     }
+                    getScreen().getDisplay().dispatchMessages(); // status up2date
+                    boolean wasVisible = isVisible();
+                    if(wasVisible) {
+                        Window.this.visible = false;
+                        setVisibleImpl(false);
+                        getScreen().getDisplay().dispatchMessages(); // status up2date
+                    }
                     boolean reparentRes = false;
                     reparentRes = reparentWindowImpl();
+                    getScreen().getDisplay().dispatchMessages(); // status up2date
                     if(!reparentRes) {
                         parentWindowHandle = 0;
 
@@ -680,11 +650,17 @@ public abstract class Window implements NativeWindow
                         if( 0 != windowHandle ) {
                             destroy(false);
                         }
+                    } else {
+                        if(wasVisible) {
+                            Window.this.visible = true;
+                            setVisibleImpl(true);
+                            getScreen().getDisplay().dispatchMessages(); // status up2date
+                        }
                     }
                 }
 
                 if(DEBUG_IMPLEMENTATION) {
-                    System.err.println("reparentWindow: END ("+getThreadName()+") windowHandle "+toHexString(windowHandle)+", visible: "+visible+", parentWindowHandle "+toHexString(parentWindowHandle)+", parentNativeWindow "+(null!=parentNativeWindow));
+                    System.out.println("reparentWindow: END ("+getThreadName()+") windowHandle "+toHexString(windowHandle)+", visible: "+visible+", parentWindowHandle "+toHexString(parentWindowHandle)+", parentNativeWindow "+(null!=parentNativeWindow));
                 }
             } finally {
                 windowUnlock();
@@ -707,10 +683,10 @@ public abstract class Window implements NativeWindow
     public void reparentWindow(NativeWindow newParent, Screen newScreen) {
         if(!isDestroyed()) {
             runOnEDTIfAvail(true, new ReparentAction(newParent, newScreen)); 
-            // if( isVisible() ) {
-                enqueueWindowEvent(true, WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout to listener
-                // enqueueWindowEvent(true, WindowEvent.EVENT_WINDOW_REPAINT); // trigger a repaint to listener
-            // }
+            if( isVisible() ) {
+                sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout to listener
+                windowRepaint(0, 0, getWidth(), getHeight());
+            }
         }
     }
 
@@ -723,17 +699,15 @@ public abstract class Window implements NativeWindow
             windowLock();
             try{
                 if( !isDestroyed() ) {
-                    ArrayList listeners = null;
-                    synchronized(childWindows) {
-                        listeners = childWindows;
-                    }
-                    if(!visible && listeners.size()>0) {
-                        for(Iterator i = listeners.iterator(); i.hasNext(); ) {
+                    if(!visible && childWindows.size()>0) {
+                      synchronized(childWindowsLock) {
+                        for(Iterator i = childWindows.iterator(); i.hasNext(); ) {
                             NativeWindow nw = (NativeWindow) i.next();
                             if(nw instanceof Window) {
                                 ((Window)nw).setVisible(false);
                             }
                         }
+                      }
                     }
                     if(0==windowHandle && visible) { 
                         Window.this.visible = visible;
@@ -746,18 +720,20 @@ public abstract class Window implements NativeWindow
                             setVisibleImpl(visible);
                         }
                     }
-                    if(0!=windowHandle && visible && listeners.size()>0) {
-                        for(Iterator i = listeners.iterator(); i.hasNext(); ) {
+                    if(0!=windowHandle && visible && childWindows.size()>0) {
+                      synchronized(childWindowsLock) {
+                        for(Iterator i = childWindows.iterator(); i.hasNext(); ) {
                             NativeWindow nw = (NativeWindow) i.next();
                             if(nw instanceof Window) {
                                 ((Window)nw).setVisible(true);
                             }
                         }
+                      }
                     }
                 }
 
                 if(DEBUG_IMPLEMENTATION) {
-                    System.err.println("Window setVisible: END ("+getThreadName()+") "+x+"/"+y+" "+width+"x"+height+", fs "+fullscreen+", windowHandle "+toHexString(windowHandle)+", visible: "+Window.this.visible);
+                    System.out.println("Window setVisible: END ("+getThreadName()+") "+x+"/"+y+" "+width+"x"+height+", fs "+fullscreen+", windowHandle "+toHexString(windowHandle)+", visible: "+Window.this.visible);
                 }
             } finally {
                 windowUnlock();
@@ -793,7 +769,7 @@ public abstract class Window implements NativeWindow
     public void setVisible(boolean visible) {
         if(DEBUG_IMPLEMENTATION) {
             String msg = new String("Window setVisible: START ("+getThreadName()+") "+x+"/"+y+" "+width+"x"+height+", fs "+fullscreen+", windowHandle "+toHexString(windowHandle)+", visible: "+this.visible+" -> "+visible+", parentWindowHandle "+toHexString(parentWindowHandle)+", parentNativeWindow "+(null!=parentNativeWindow));
-            //System.err.println(msg);
+            //System.out.println(msg);
             Exception ee = new Exception(msg);
             ee.printStackTrace();
         }
@@ -830,7 +806,7 @@ public abstract class Window implements NativeWindow
         try{
             if(DEBUG_IMPLEMENTATION) {
                 String msg = new String("Window setSize: START "+this.width+"x"+this.height+" -> "+width+"x"+height+", fs "+fullscreen+", windowHandle "+toHexString(windowHandle)+", visible "+visible);
-                //System.err.println(msg);
+                //System.out.println(msg);
                 Exception e = new Exception(msg);
                 e.printStackTrace();
             }
@@ -847,7 +823,7 @@ public abstract class Window implements NativeWindow
                         this.width = width;
                         this.height = height;
                     } else if ( 0 != windowHandle ) {
-                        // this width/height will be set by windowChanged, called by X11
+                        // this width/height will be set by windowChanged, called by the native implementation
                         setSizeImpl(width, height);
                     } else {
                         this.width = width;
@@ -856,7 +832,7 @@ public abstract class Window implements NativeWindow
                 }
             }
             if(DEBUG_IMPLEMENTATION) {
-                System.err.println("Window setSize: END "+this.width+"x"+this.height+", visibleAction "+visibleAction);
+                System.out.println("Window setSize: END "+this.width+"x"+this.height+", visibleAction "+visibleAction);
             }
         } finally {
             windowUnlock();
@@ -881,7 +857,7 @@ public abstract class Window implements NativeWindow
         windowLock();
         try{
             if(DEBUG_IMPLEMENTATION) {
-                System.err.println("Window setPosition: "+this.x+"/"+this.y+" -> "+x+"/"+y+", fs "+fullscreen+", windowHandle "+toHexString(windowHandle));
+                System.out.println("Window setPosition: "+this.x+"/"+this.y+" -> "+x+"/"+y+", fs "+fullscreen+", windowHandle "+toHexString(windowHandle));
             }
             if ( this.x != x || this.y != y ) {
                 if(!fullscreen) {
@@ -918,7 +894,7 @@ public abstract class Window implements NativeWindow
                     h = nfs_height;
                 }
                 if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) {
-                    System.err.println("X11Window fs: "+fullscreen+" "+x+"/"+y+" "+w+"x"+h+", "+isUndecorated());
+                    System.out.println("X11Window fs: "+fullscreen+" "+x+"/"+y+" "+w+"x"+h+", "+isUndecorated());
                 }
                 this.fullscreen = setFullscreenImpl(fullscreen, x, y, w, h);
             }
@@ -934,12 +910,11 @@ public abstract class Window implements NativeWindow
     // 
 
     private ArrayList childWindows = new ArrayList();
+    private Object childWindowsLock = new Object();
 
     protected void removeChild(NativeWindow win) {
-        synchronized(childWindows) {
-            ArrayList newChildWindows = (ArrayList) childWindows.clone();
-            newChildWindows.remove(win);
-            childWindows = newChildWindows;
+        synchronized(childWindowsLock) {
+            childWindows.remove(win);
         }
     }
 
@@ -947,16 +922,26 @@ public abstract class Window implements NativeWindow
         if (win == null) {
             return;
         }
-        synchronized(childWindows) {
-            ArrayList newChildWindows = (ArrayList) childWindows.clone();
-            newChildWindows.add(win);
-            childWindows = newChildWindows;
+        synchronized(childWindowsLock) {
+            childWindows.add(win);
         }
     }
 
     // 
     // Generic Event Support
     //
+    private void doEvent(boolean enqueue, boolean wait, com.jogamp.newt.event.NEWTEvent event) {
+        boolean done = false;
+
+        if(!enqueue) {
+            done = consumeEvent(event);
+            wait = done; // don't wait if event can't be consumed now
+        }
+
+        if(!done) {
+            enqueueEvent(wait, event);
+        }
+    }
 
     public void enqueueEvent(boolean wait, com.jogamp.newt.event.NEWTEvent event) {
         if(!getInnerWindow().isDestroyed()) {
@@ -964,21 +949,45 @@ public abstract class Window implements NativeWindow
         }
     }
 
-    public void sendEvent(NEWTEvent e) {
+    public boolean consumeEvent(NEWTEvent e) {
+        switch(e.getEventType()) {
+            case WindowEvent.EVENT_WINDOW_REPAINT:
+                if( windowIsLocked() ) {
+                  if(!repaintQueued) {
+                      repaintQueued=true;
+                      return false;
+                  } else {
+                      return true;
+                  }
+                } else {
+                  if(DEBUG_IMPLEMENTATION) {
+                    System.out.println("Window.windowRepaint: "+e);
+                    // Exception ee = new Exception("Window.windowRepaint: "+e);
+                    // ee.printStackTrace();
+                  }
+                  repaintQueued=false;
+                }
+                break;
+            default:
+                break;
+        }
         if(e instanceof WindowEvent) {
-            getInnerWindow().sendWindowEvent((WindowEvent)e);
+            getInnerWindow().consumeWindowEvent((WindowEvent)e);
         } else if(e instanceof KeyEvent) {
-            getInnerWindow().sendKeyEvent((KeyEvent)e);
+            getInnerWindow().consumeKeyEvent((KeyEvent)e);
         } else if(e instanceof MouseEvent) {
-            getInnerWindow().sendMouseEvent((MouseEvent)e);
+            getInnerWindow().consumeMouseEvent((MouseEvent)e);
         }
+        return true;
     }
+    protected boolean repaintQueued = false;
 
     //
     // SurfaceUpdatedListener Support
     //
 
     private ArrayList surfaceUpdatedListeners = new ArrayList();
+    private Object surfaceUpdatedListenersLock = new Object();
 
     /** 
      * Appends the given {@link com.jogamp.newt.event.SurfaceUpdatedListener} to the end of 
@@ -1004,13 +1013,11 @@ public abstract class Window implements NativeWindow
         if(l == null) {
             return;
         }
-        synchronized(surfaceUpdatedListeners) {
+        synchronized(surfaceUpdatedListenersLock) {
             if(0>index) { 
                 index = surfaceUpdatedListeners.size(); 
             }
-            ArrayList newSurfaceUpdatedListeners = (ArrayList) surfaceUpdatedListeners.clone();
-            newSurfaceUpdatedListeners.add(index, l);
-            surfaceUpdatedListeners = newSurfaceUpdatedListeners;
+            surfaceUpdatedListeners.add(index, l);
         }
     }
 
@@ -1018,21 +1025,19 @@ public abstract class Window implements NativeWindow
         if (l == null) {
             return;
         }
-        synchronized(surfaceUpdatedListeners) {
-            ArrayList newSurfaceUpdatedListeners = (ArrayList) surfaceUpdatedListeners.clone();
-            newSurfaceUpdatedListeners.remove(l);
-            surfaceUpdatedListeners = newSurfaceUpdatedListeners;
+        synchronized(surfaceUpdatedListenersLock) {
+            surfaceUpdatedListeners.remove(l);
         }
     }
 
     public void removeAllSurfaceUpdatedListener() {
-        synchronized(surfaceUpdatedListeners) {
+        synchronized(surfaceUpdatedListenersLock) {
             surfaceUpdatedListeners = new ArrayList();
         }
     }
 
     public SurfaceUpdatedListener getSurfaceUpdatedListener(int index) {
-        synchronized(surfaceUpdatedListeners) {
+        synchronized(surfaceUpdatedListenersLock) {
             if(0>index) { 
                 index = surfaceUpdatedListeners.size()-1; 
             }
@@ -1041,19 +1046,17 @@ public abstract class Window implements NativeWindow
     }
 
     public SurfaceUpdatedListener[] getSurfaceUpdatedListeners() {
-        synchronized(surfaceUpdatedListeners) {
+        synchronized(surfaceUpdatedListenersLock) {
             return (SurfaceUpdatedListener[]) surfaceUpdatedListeners.toArray();
         }
     }
 
     public void surfaceUpdated(Object updater, NativeWindow window, long when) { 
-        ArrayList listeners = null;
-        synchronized(surfaceUpdatedListeners) {
-            listeners = surfaceUpdatedListeners;
-        }
-        for(Iterator i = listeners.iterator(); i.hasNext(); ) {
+        synchronized(surfaceUpdatedListenersLock) {
+          for(Iterator i = surfaceUpdatedListeners.iterator(); i.hasNext(); ) {
             SurfaceUpdatedListener l = (SurfaceUpdatedListener) i.next();
             l.surfaceUpdated(updater, window, when);
+          }
         }
     }
 
@@ -1066,13 +1069,21 @@ public abstract class Window implements NativeWindow
     private int  lastMouseClickCount = 0; // last mouse button click count
     public  static final int ClickTimeout = 300;
 
+    public void sendMouseEvent(int eventType, int modifiers,
+                               int x, int y, int button, int rotation) {
+        doMouseEvent(false, false, eventType, modifiers, x, y, button, rotation);
+    }
     public void enqueueMouseEvent(boolean wait, int eventType, int modifiers,
                                   int x, int y, int button, int rotation) {
+        doMouseEvent(true, wait, eventType, modifiers, x, y, button, rotation);
+    }
+    private void doMouseEvent(boolean enqueue, boolean wait, int eventType, int modifiers,
+                              int x, int y, int button, int rotation) {
         if(x<0||y<0||x>=width||y>=height) {
             return; // .. invalid ..
         }
         if(DEBUG_MOUSE_EVENT) {
-            System.err.println("enqueueMouseEvent: "+MouseEvent.getEventTypeString(eventType)+
+            System.out.println("doMouseEvent: enqueue"+enqueue+", wait "+wait+", "+MouseEvent.getEventTypeString(eventType)+
                                ", mod "+modifiers+", pos "+x+"/"+y+", button "+button);
         }
         if(button<0||button>MouseEvent.BUTTON_NUMBER) {
@@ -1116,12 +1127,12 @@ public abstract class Window implements NativeWindow
         } else {
             e = new MouseEvent(eventType, this, when, modifiers, x, y, 0, button, 0);
         }
-        screen.getDisplay().enqueueEvent(wait, e);
+        doEvent(enqueue, wait, e);
         if(null!=eClicked) {
             if(DEBUG_MOUSE_EVENT) {
-                System.err.println("enqueueMouseEvent: synthesized MOUSE_CLICKED event");
+                System.out.println("doMouseEvent: synthesized MOUSE_CLICKED event");
             }
-            screen.getDisplay().enqueueEvent(wait, eClicked);
+            doEvent(enqueue, wait, eClicked);
         }
     }
 
@@ -1148,52 +1159,41 @@ public abstract class Window implements NativeWindow
         if(l == null) {
             return;
         }
-        synchronized(mouseListeners) {
-            if(0>index) { 
-                index = mouseListeners.size(); 
-            }
-            ArrayList newMouseListeners = (ArrayList) mouseListeners.clone();
-            newMouseListeners.add(index, l);
-            mouseListeners = newMouseListeners;
+        ArrayList clonedListeners = (ArrayList) mouseListeners.clone();
+        if(0>index) { 
+            index = clonedListeners.size(); 
         }
+        clonedListeners.add(index, l);
+        mouseListeners = clonedListeners;
     }
 
     public void removeMouseListener(MouseListener l) {
         if (l == null) {
             return;
         }
-        synchronized(mouseListeners) {
-            ArrayList newMouseListeners = (ArrayList) mouseListeners.clone();
-            newMouseListeners.remove(l);
-            mouseListeners = newMouseListeners;
-        }
+        ArrayList clonedListeners = (ArrayList) mouseListeners.clone();
+        clonedListeners.remove(l);
+        mouseListeners = clonedListeners;
     }
 
     public MouseListener getMouseListener(int index) {
-        synchronized(mouseListeners) {
-            if(0>index) { 
-                index = mouseListeners.size()-1; 
-            }
-            return (MouseListener) mouseListeners.get(index);
+        ArrayList clonedListeners = (ArrayList) mouseListeners.clone();
+        if(0>index) { 
+            index = clonedListeners.size()-1; 
         }
+        return (MouseListener) clonedListeners.get(index);
     }
 
     public MouseListener[] getMouseListeners() {
-        synchronized(mouseListeners) {
-            return (MouseListener[]) mouseListeners.toArray();
-        }
+        return (MouseListener[]) mouseListeners.toArray();
     }
 
-    protected void sendMouseEvent(MouseEvent e) {
+    protected void consumeMouseEvent(MouseEvent e) {
         if(DEBUG_MOUSE_EVENT) {
-            System.err.println("sendMouseEvent: event:         "+e);
+            System.out.println("consumeMouseEvent: event:         "+e);
         }
 
-        ArrayList listeners = null;
-        synchronized(mouseListeners) {
-            listeners = mouseListeners;
-        }
-        for(Iterator i = listeners.iterator(); i.hasNext(); ) {
+        for(Iterator i = mouseListeners.iterator(); i.hasNext(); ) {
             MouseListener l = (MouseListener) i.next();
             switch(e.getEventType()) {
                 case MouseEvent.EVENT_MOUSE_CLICKED:
@@ -1230,10 +1230,12 @@ public abstract class Window implements NativeWindow
     // KeyListener/Event Support
     //
 
+    public void sendKeyEvent(int eventType, int modifiers, int keyCode, char keyChar) {
+        consumeKeyEvent(new KeyEvent(eventType, this, System.currentTimeMillis(), modifiers, keyCode, keyChar) );
+    }
+
     public void enqueueKeyEvent(boolean wait, int eventType, int modifiers, int keyCode, char keyChar) {
-        screen.getDisplay().enqueueEvent(wait,
-            new KeyEvent(eventType, this, System.currentTimeMillis(),
-                         modifiers, keyCode, keyChar) );
+        enqueueEvent(wait, new KeyEvent(eventType, this, System.currentTimeMillis(), modifiers, keyCode, keyChar) );
     }
 
     /** 
@@ -1258,53 +1260,42 @@ public abstract class Window implements NativeWindow
         if(l == null) {
             return;
         }
-        synchronized(keyListeners) {
-            if(0>index) { 
-                index = keyListeners.size(); 
-            }
-            ArrayList newKeyListeners = (ArrayList) keyListeners.clone();
-            newKeyListeners.add(index, l);
-            keyListeners = newKeyListeners;
+        ArrayList clonedListeners = (ArrayList) keyListeners.clone();
+        if(0>index) { 
+            index = clonedListeners.size();
         }
+        clonedListeners.add(index, l);
+        keyListeners = clonedListeners;
     }
 
     public void removeKeyListener(KeyListener l) {
         if (l == null) {
             return;
         }
-        synchronized(keyListeners) {
-            ArrayList newKeyListeners = (ArrayList) keyListeners.clone();
-            newKeyListeners.remove(l);
-            keyListeners = newKeyListeners;
-        }
+        ArrayList clonedListeners = (ArrayList) keyListeners.clone();
+        clonedListeners.remove(l);
+        keyListeners = clonedListeners;
     }
 
     public KeyListener getKeyListener(int index) {
-        synchronized(keyListeners) {
-            if(0>index) { 
-                index = keyListeners.size()-1; 
-            }
-            return (KeyListener) keyListeners.get(index);
+        ArrayList clonedListeners = (ArrayList) keyListeners.clone();
+        if(0>index) { 
+            index = clonedListeners.size()-1;
         }
+        return (KeyListener) clonedListeners.get(index);
     }
 
     public KeyListener[] getKeyListeners() {
-        synchronized(keyListeners) {
-            return (KeyListener[]) keyListeners.toArray();
-        }
+        return (KeyListener[]) keyListeners.toArray();
     }
 
     private ArrayList keyListeners = new ArrayList();
 
-    protected void sendKeyEvent(KeyEvent e) {
+    protected void consumeKeyEvent(KeyEvent e) {
         if(DEBUG_KEY_EVENT) {
-            System.err.println("sendKeyEvent: "+e);
-        }
-        ArrayList listeners = null;
-        synchronized(keyListeners) {
-            listeners = keyListeners;
+            System.out.println("consumeKeyEvent: "+e);
         }
-        for(Iterator i = listeners.iterator(); i.hasNext(); ) {
+        for(Iterator i = keyListeners.iterator(); i.hasNext(); ) {
             KeyListener l = (KeyListener) i.next();
             switch(e.getEventType()) {
                 case KeyEvent.EVENT_KEY_PRESSED:
@@ -1325,10 +1316,12 @@ public abstract class Window implements NativeWindow
     //
     // WindowListener/Event Support
     //
+    public void sendWindowEvent(int eventType) {
+        consumeWindowEvent( new WindowEvent(eventType, this, System.currentTimeMillis()) );
+    }
+
     public void enqueueWindowEvent(boolean wait, int eventType) {
-        WindowEvent event = new WindowEvent(eventType, this, System.currentTimeMillis());
-        screen.getDisplay().enqueueEvent( wait, event );
-        // sendWindowEvent ( event ); // FIXME: Think about performance/lag .. ?
+        enqueueEvent( wait, new WindowEvent(eventType, this, System.currentTimeMillis()) );
     }
 
     private ArrayList windowListeners = new ArrayList();
@@ -1357,55 +1350,40 @@ public abstract class Window implements NativeWindow
         if(l == null) {
             return;
         }
-        synchronized(windowListeners) {
-            if(0>index) { 
-                index = windowListeners.size(); 
-            }
-            ArrayList newWindowListeners = (ArrayList) windowListeners.clone();
-            newWindowListeners.add(index, l);
-            windowListeners = newWindowListeners;
+        ArrayList clonedListeners = (ArrayList) windowListeners.clone();
+        if(0>index) { 
+            index = clonedListeners.size(); 
         }
+        clonedListeners.add(index, l);
+        windowListeners = clonedListeners;
     }
 
     public void removeWindowListener(WindowListener l) {
         if (l == null) {
             return;
         }
-        synchronized(windowListeners) {
-            ArrayList newWindowListeners = (ArrayList) windowListeners.clone();
-            newWindowListeners.remove(l);
-            windowListeners = newWindowListeners;
-        }
+        ArrayList clonedListeners = (ArrayList) windowListeners.clone();
+        clonedListeners.remove(l);
+        windowListeners = clonedListeners;
     }
 
     public WindowListener getWindowListener(int index) {
-        synchronized(windowListeners) {
-            if(0>index) { 
-                index = windowListeners.size()-1; 
-            }
-            return (WindowListener) windowListeners.get(index);
+        ArrayList clonedListeners = (ArrayList) windowListeners.clone();
+        if(0>index) { 
+            index = clonedListeners.size()-1; 
         }
+        return (WindowListener) clonedListeners.get(index);
     }
 
     public WindowListener[] getWindowListeners() {
-        synchronized(windowListeners) {
-            return (WindowListener[]) windowListeners.toArray();
-        }
-    }
-
-    protected void sendWindowEvent(WindowEvent e) {
-        getInnerWindow().sendWindowEvent(e, 0, 0, 0, 0);
+        return (WindowListener[]) windowListeners.toArray();
     }
 
-    protected void sendWindowEvent(WindowEvent e, int p1, int p2, int p3, int p4) {
+    protected void consumeWindowEvent(WindowEvent e) {
         if(DEBUG_WINDOW_EVENT) {
-            System.err.println("sendWindowEvent: "+e+", "+p1+", "+p2+", "+p3+", "+p4);
+            System.out.println("consumeWindowEvent: "+e);
         }
-        ArrayList listeners = null;
-        synchronized(windowListeners) {
-            listeners = windowListeners;
-        }
-        for(Iterator i = listeners.iterator(); i.hasNext(); ) {
+        for(Iterator i = windowListeners.iterator(); i.hasNext(); ) {
             WindowListener l = (WindowListener) i.next();
             switch(e.getEventType()) {
                 case WindowEvent.EVENT_WINDOW_RESIZED:
@@ -1423,9 +1401,9 @@ public abstract class Window implements NativeWindow
                 case WindowEvent.EVENT_WINDOW_LOST_FOCUS:
                     l.windowLostFocus(e);
                     break;
-                //case WindowEvent.EVENT_WINDOW_REPAINT:
-                //    l.windowRepaint(e);
-                //    break;
+                case WindowEvent.EVENT_WINDOW_REPAINT:
+                    l.windowRepaint((WindowUpdateEvent)e);
+                    break;
                 default:
                     throw 
                         new NativeWindowException("Unexpected window event type "
@@ -1434,6 +1412,115 @@ public abstract class Window implements NativeWindow
         }
     }
 
+    /**
+     * @param focusGained
+     */
+    protected void focusChanged(boolean focusGained) {
+        if(DEBUG_IMPLEMENTATION) {
+            System.out.println("Window.focusChanged: "+focusGained);
+        }
+        if (focusGained) {
+            sendWindowEvent(WindowEvent.EVENT_WINDOW_GAINED_FOCUS);
+        } else {
+            sendWindowEvent(WindowEvent.EVENT_WINDOW_LOST_FOCUS);
+        }
+    }
+
+    protected void visibleChanged(boolean visible) {
+        if(DEBUG_IMPLEMENTATION) {
+            System.out.println("Window.visibleChanged: "+this.visible+" -> "+visible);
+        }
+        this.visible = visible ;
+    }
+
+    protected void sizeChanged(int newWidth, int newHeight) {
+        if(DEBUG_IMPLEMENTATION) {
+            System.out.println("Window.sizeChanged: "+width+"x"+height+" -> "+newWidth+"x"+newHeight);
+        }
+        if(width != newWidth || height != newHeight) {
+            width = newWidth;
+            height = newHeight;
+            if(!fullscreen) {
+                nfs_width=width;
+                nfs_height=height;
+            }
+            sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED);
+        }
+    }
+
+    protected void positionChanged(int newX, int newY) {
+        if(DEBUG_IMPLEMENTATION) {
+            System.out.println("Window.positionChanged: "+x+"/"+y+" -> "+newX+"/"+newY);
+        }
+        if( 0==parentWindowHandle && ( x != newX || y != newY ) ) {
+            x = newX;
+            y = newY;
+            if(!fullscreen) {
+                nfs_x=x;
+                nfs_y=y;
+            }
+            sendWindowEvent(WindowEvent.EVENT_WINDOW_MOVED);
+        }
+    }
+
+    /**
+     * If set to true, the default value, this NEWT Window implementation will 
+     * handle the destruction (ie {@link #destroy()} call) within {@link #windowDestroyNotify()} implementation.<br>
+     * If set to false, it's up to the caller/owner to handle destruction within {@link #windowDestroyNotify()}.
+     */
+    public void setHandleDestroyNotify(boolean b) {
+        handleDestroyNotify = b;
+    }
+
+    protected void windowDestroyNotify() {
+        if(DEBUG_IMPLEMENTATION) {
+            System.out.println("Window.windowDestroyNotify START "+getThreadName());
+        }
+
+        enqueueWindowEvent(false, WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY);
+
+        if(handleDestroyNotify && !isDestroyed()) {
+            destroy();
+        }
+
+        if(DEBUG_IMPLEMENTATION) {
+            System.out.println("Window.windowDestroyeNotify END "+getThreadName());
+        }
+    }
+
+    protected void windowDestroyed() {
+        if(DEBUG_IMPLEMENTATION) {
+            System.out.println("Window.windowDestroyed "+getThreadName());
+        }
+        invalidate();
+    }
+
+    public void setPropagateRepaint(boolean v) {
+        propagateRepaint = v;
+    }
+    protected boolean propagateRepaint = true;
+
+    public void windowRepaint(int x, int y, int width, int height) {
+        if(!propagateRepaint) { 
+            return; 
+        }
+        if(0>width) {
+            width=this.width;
+        }
+        if(0>height) {
+            height=this.height;
+        }
+
+        NEWTEvent e = new WindowUpdateEvent(WindowEvent.EVENT_WINDOW_REPAINT, this, System.currentTimeMillis(), 
+                                            new Rectangle(x, y, width, height));
+        doEvent(false, false, e);
+    }
+
+    protected boolean reparentWindowImpl() {
+        // default implementation, no native reparenting support
+        return false;
+    }
+
     //
     // Reflection helper ..
     //
index 8944c03..b2dd719 100644 (file)
@@ -35,13 +35,20 @@ package com.jogamp.newt.awt;
 import java.lang.reflect.*;
 import java.security.*;
 
+import java.awt.Button;
+import java.awt.Frame;
 import java.awt.Canvas;
+import java.awt.Graphics;
+import java.awt.KeyboardFocusManager;
 
 import javax.media.nativewindow.*;
-// import javax.media.nativewindow.awt.*;
 
 import com.jogamp.newt.event.awt.AWTAdapter;
 import com.jogamp.newt.event.awt.AWTParentWindowAdapter;
+import com.jogamp.newt.event.WindowEvent;
+import com.jogamp.newt.event.WindowAdapter;
+import com.jogamp.newt.event.MouseEvent;
+import com.jogamp.newt.event.MouseAdapter;
 import com.jogamp.newt.Screen;
 import com.jogamp.newt.Window;
 import com.jogamp.newt.impl.Debug;
@@ -52,6 +59,7 @@ public class NewtCanvasAWT extends java.awt.Canvas {
     NativeWindow parent = null;
     Window newtChild = null;
     AWTAdapter awtAdapter = null;
+    boolean hasSwingContainer = false;
 
     /**
      * Instantiates a NewtCanvas without a NEWT child.<br>
@@ -67,11 +75,84 @@ public class NewtCanvasAWT extends java.awt.Canvas {
         super();
         setNEWTChild(child);
     }
+    
+    class UnfocusRunnable implements Runnable {
+        boolean focusTraversed = false;
+        public void run() {
+            KeyboardFocusManager focusManager =
+                KeyboardFocusManager.getCurrentKeyboardFocusManager();
+            java.awt.Component comp1 =   focusManager.getPermanentFocusOwner();
+            java.awt.Component comp2 =   focusManager.getFocusOwner();
+            if(DEBUG_IMPLEMENTATION) {
+                   System.out.println("AWT Unfocus: traversed "+focusTraversed+" (1)");
+                   System.out.println("PRE PermenetFocusOwner: "+comp1);
+                   System.out.println("PRE FocusOwner: "+comp2);
+            }
+            if(null!=comp1) {
+                if(!focusTraversed && null==comp2) {
+                    comp1.requestFocus();
+                    focusTraversed=true;
+                    if(DEBUG_IMPLEMENTATION) {
+                        System.out.println("AWT Unfocus: traversed "+focusTraversed+" (*)");
+                    }
+                } else {
+                    focusTraversed=false;
+                }
+                
+                if(DEBUG_IMPLEMENTATION) {
+                    comp1 = focusManager.getPermanentFocusOwner();
+                    comp2 = focusManager.getFocusOwner();
+                    System.out.println("MID PermenetFocusOwner: "+comp1);
+                    System.out.println("MID FocusOwner: "+comp2);
+                }
+
+                focusManager.clearGlobalFocusOwner();
+
+                if(DEBUG_IMPLEMENTATION) {
+                    comp1 = focusManager.getPermanentFocusOwner();
+                    comp2 = focusManager.getFocusOwner();
+                    System.out.println("POST PermenetFocusOwner: "+comp1);
+                    System.out.println("POST FocusOwner: "+comp2);
+                }
+                
+                if(focusTraversed && null!=newtChild) {
+                    newtChild.requestFocus();
+                }
+            }
+        }
+    }
+    UnfocusRunnable unfocusRunnable = new UnfocusRunnable();
+    
+    class FocusListener extends WindowAdapter {
+        public synchronized void windowGainedFocus(WindowEvent e) {
+            if(DEBUG_IMPLEMENTATION) {
+                System.out.println("NewtCanvasAWT focus on: AWT focus "+ NewtCanvasAWT.this.hasFocus()+
+                                   ", focusable "+NewtCanvasAWT.this.isFocusable()+", onEDT "+hasSwingContainer);
+            }
+            if(hasSwingContainer) {
+               java.awt.EventQueue.invokeLater(unfocusRunnable);
+            } else {
+               unfocusRunnable.run();
+            }
+        }
+        public synchronized void windowLostFocus(WindowEvent e) {
+            if(DEBUG_IMPLEMENTATION) {
+                System.out.println("NewtCanvasAWT focus off: AWT focus "+ NewtCanvasAWT.this.hasFocus());
+            }
+        }
+    }
+    FocusListener focusListener = new FocusListener();
 
     /** sets a new NEWT child, provoking reparenting on the NEWT level. */
     public NewtCanvasAWT setNEWTChild(Window child) {
         if(newtChild!=child) {
+            if(null!=newtChild) {
+                newtChild.removeWindowListener(focusListener);
+            }
             newtChild = child;
+            if(null!=newtChild) {
+                newtChild.addWindowListener(focusListener);
+            }
             if(null!=parent) {
                 java.awt.Container cont = getContainer(this);
                 // reparent right away, addNotify has been called already
@@ -100,12 +181,22 @@ public class NewtCanvasAWT extends java.awt.Canvas {
         }
     }
 
-    static java.awt.Container getContainer(java.awt.Component comp) {
-        while( null != comp && !(comp instanceof java.awt.Container) ) {
+    static boolean hasSwingContainer(java.awt.Component comp) {
+        while( null != comp ) {
+               if( comp instanceof javax.swing.JComponent ) {
+                       return true;
+               }
             comp = comp.getParent();
         }
-        if(comp instanceof java.awt.Container) {
-            return (java.awt.Container) comp;
+        return false;
+    }
+
+    static java.awt.Container getContainer(java.awt.Component comp) {
+        while( null != comp ) {
+               if( comp instanceof java.awt.Container ) {
+                       return (java.awt.Container) comp;
+            }
+            comp = comp.getParent();
         }
         return null;
     }
@@ -113,11 +204,13 @@ public class NewtCanvasAWT extends java.awt.Canvas {
     public void addNotify() {
         super.addNotify();
         disableBackgroundErase();
+        hasSwingContainer = hasSwingContainer(this);
         java.awt.Container cont = getContainer(this);
         if(DEBUG_IMPLEMENTATION) {
             // if ( isShowing() == false ) -> Container was not visible yet.
             // if ( isShowing() == true  ) -> Container is already visible.
-            System.err.println("NewtCanvasAWT.addNotify: "+newtChild+", "+this+", visible "+isVisible()+", showing "+isShowing()+", displayable "+isDisplayable()+" -> "+cont);
+            System.err.println("NewtCanvasAWT.addNotify: "+newtChild+", "+this+", visible "+isVisible()+", showing "+isShowing()+
+                                  ", displayable "+isDisplayable()+", swingContainer "+hasSwingContainer+" -> "+cont);
         }  
         reparentWindow(true, cont);
     }
@@ -154,6 +247,8 @@ public class NewtCanvasAWT extends java.awt.Canvas {
               newtChild.reparentWindow(parent, screen);
               newtChild.setVisible(true);
               setWindowAdapter(true);
+              newtChild.sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout to listener
+              newtChild.windowRepaint(0, 0, newtChild.getWidth(), newtChild.getHeight());
           }
       } else {
           setWindowAdapter(false);
@@ -164,9 +259,14 @@ public class NewtCanvasAWT extends java.awt.Canvas {
     }
 
     public void paint(Graphics g) {
-      if(null!=newtChild) {
-          // enqueueWindowEvent(true, WindowEvent.EVENT_WINDOW_REPAINT); // trigger a repaint to listener
-      }
+        if(null!=newtChild) {
+            newtChild.windowRepaint(0, 0, getWidth(), getHeight());
+        }
+    }
+    public void update(Graphics g) {
+        if(null!=newtChild) {
+            newtChild.windowRepaint(0, 0, getWidth(), getHeight());
+        }
     }
 
   // Disables the AWT's erasing of this Canvas's background on Windows
index 476b364..9afcb84 100644 (file)
@@ -123,7 +123,7 @@ public class NEWTEvent extends java.util.EventObject {
 
     /** 
      * Attach the passed object to this event.<br>
-     * If an object was previously attached, it will replaced.<br>
+     * If an object was previously attached, it will be replaced.<br>
      * Attachments to NEWT events allow users to pass on information
      * from one custom listener to another, ie custom listener to listener 
      * communication.
diff --git a/src/newt/classes/com/jogamp/newt/event/NEWTEventConsumer.java b/src/newt/classes/com/jogamp/newt/event/NEWTEventConsumer.java
new file mode 100644 (file)
index 0000000..e37c820
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2010 Sven Gothel. 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 Sven Gothel 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
+ * SVEN GOTHEL HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+package com.jogamp.newt.event;
+
+public interface NEWTEventConsumer {
+
+    /** 
+     * Consume the event 
+     *
+     * @return true if the event can be consumed now,
+     * otherwise propagate it later.
+     */
+    public boolean consumeEvent(NEWTEvent event);
+}
index a6cf0d6..fb9e187 100644 (file)
@@ -65,7 +65,7 @@ public class TraceWindowAdapter implements WindowListener {
         System.out.println(e);
         if(null!=downstream) { downstream.windowLostFocus(e); }
     }
-    public void windowRepaint(WindowEvent e) {
+    public void windowRepaint(WindowUpdateEvent e) {
         System.out.println(e);
         if(null!=downstream) { downstream.windowRepaint(e); }
     }
index 925bc71..587622a 100644 (file)
@@ -45,6 +45,6 @@ public abstract class WindowAdapter implements WindowListener
     }
     public void windowLostFocus(WindowEvent e) {
     }
-    public void windowRepaint(WindowEvent e) {
+    public void windowRepaint(WindowUpdateEvent e) {
     }
 }
diff --git a/src/newt/classes/com/jogamp/newt/event/WindowUpdateEvent.java b/src/newt/classes/com/jogamp/newt/event/WindowUpdateEvent.java
new file mode 100755 (executable)
index 0000000..5a11f0f
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2010 Sven Gothel. 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 Sven Gothel 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
+ * SVEN GOTHEL HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+package com.jogamp.newt.event;
+
+import com.jogamp.newt.*;
+import com.jogamp.nativewindow.util.Rectangle;
+
+public class WindowUpdateEvent extends WindowEvent {
+    Rectangle bounds;
+
+    public WindowUpdateEvent(int eventType, Object source, long when, Rectangle bounds)
+    {
+        super(eventType, source, when);
+        this.bounds = bounds;
+    }
+
+    public Rectangle getBounds() {
+        return bounds;
+    }
+
+    public String toString() {
+        return "WindowUpdateEvent["+super.toString()+", "+bounds+"]";
+    }
+}
index e4e9794..076165c 100644 (file)
@@ -48,8 +48,10 @@ class AWTNewtEventFactory {
         // n/a map.put(java.awt.event.WindowEvent.WINDOW_DEICONIFIED, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_DEICONIFIED);
         map.put(java.awt.event.WindowEvent.WINDOW_ACTIVATED, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_GAINED_FOCUS);
         map.put(java.awt.event.WindowEvent.WINDOW_GAINED_FOCUS, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_GAINED_FOCUS);
+        map.put(java.awt.event.FocusEvent.FOCUS_GAINED, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_GAINED_FOCUS);
         map.put(java.awt.event.WindowEvent.WINDOW_DEACTIVATED, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_LOST_FOCUS);
         map.put(java.awt.event.WindowEvent.WINDOW_LOST_FOCUS, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_LOST_FOCUS);
+        map.put(java.awt.event.FocusEvent.FOCUS_LOST, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_LOST_FOCUS);
         // n/a map.put(java.awt.event.WindowEvent.WINDOW_STATE_CHANGED, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_STATE_CHANGED);
 
         map.put(java.awt.event.ComponentEvent.COMPONENT_MOVED, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_MOVED);
@@ -108,6 +110,14 @@ class AWTNewtEventFactory {
         return null; // no mapping ..
     }
 
+    static final com.jogamp.newt.event.WindowEvent createWindowEvent(java.awt.event.FocusEvent event, com.jogamp.newt.Window newtSource) {
+        int type = eventTypeAWT2NEWT.get(event.getID());
+        if(-1 < type) {
+            return new com.jogamp.newt.event.WindowEvent(type, (null==newtSource)?(Object)event.getComponent():(Object)newtSource, System.currentTimeMillis());
+        }
+        return null; // no mapping ..
+    }
+
     static final com.jogamp.newt.event.MouseEvent createMouseEvent(java.awt.event.MouseEvent event, com.jogamp.newt.Window newtSource) {
         int type = eventTypeAWT2NEWT.get(event.getID());
         if(-1 < type) {
index 7905a72..4308728 100644 (file)
@@ -53,6 +53,19 @@ public class AWTParentWindowAdapter
         return super.removeFrom(awtComponent);
     }
 
+    public void focusGained(java.awt.event.FocusEvent e) {
+        if(DEBUG_IMPLEMENTATION) {
+            System.out.println("AWT: focusGained: START "+ e.getComponent());
+        }
+        newtWindow.requestFocus();
+    }
+
+    public void focusLost(java.awt.event.FocusEvent e) {
+        if(DEBUG_IMPLEMENTATION) {
+            System.out.println("AWT: focusLost: "+ e.getComponent());
+        }
+    }
+
     public void componentResized(java.awt.event.ComponentEvent e) {
         // Need to resize the NEWT child window
         // the resized event will be send via the native window feedback.
index 7bfffba..8754015 100644 (file)
@@ -33,7 +33,7 @@ package com.jogamp.newt.event.awt;
 
 public class AWTWindowAdapter 
     extends AWTAdapter 
-    implements java.awt.event.ComponentListener, java.awt.event.WindowListener
+    implements java.awt.event.ComponentListener, java.awt.event.WindowListener, java.awt.event.FocusListener
 {
     WindowClosingListener windowClosingListener;
 
@@ -52,6 +52,7 @@ public class AWTWindowAdapter
     public AWTAdapter addTo(java.awt.Component awtComponent) {
         java.awt.Window win = getWindow(awtComponent);
         awtComponent.addComponentListener(this);
+        awtComponent.addFocusListener(this);
         if( null == windowClosingListener ) {
             windowClosingListener = new WindowClosingListener();
         }
@@ -65,6 +66,7 @@ public class AWTWindowAdapter
     }
 
     public AWTAdapter removeFrom(java.awt.Component awtComponent) {
+        awtComponent.removeFocusListener(this);
         awtComponent.removeComponentListener(this);
         java.awt.Window win = getWindow(awtComponent);
         if( null != win && null != windowClosingListener ) {
@@ -86,6 +88,24 @@ public class AWTWindowAdapter
         return null;
     }
 
+    public void focusGained(java.awt.event.FocusEvent e) {
+        com.jogamp.newt.event.WindowEvent event = AWTNewtEventFactory.createWindowEvent(e, newtWindow);
+        if(null!=newtListener) {
+            ((com.jogamp.newt.event.WindowListener)newtListener).windowGainedFocus(event);
+        } else {
+            enqueueEvent(false, event);
+        }
+    }
+
+    public void focusLost(java.awt.event.FocusEvent e) {
+        com.jogamp.newt.event.WindowEvent event = AWTNewtEventFactory.createWindowEvent(e, newtWindow);
+        if(null!=newtListener) {
+            ((com.jogamp.newt.event.WindowListener)newtListener).windowLostFocus(event);
+        } else {
+            enqueueEvent(false, event);
+        }
+    }
+
     public void componentResized(java.awt.event.ComponentEvent e) {
         com.jogamp.newt.event.WindowEvent event = AWTNewtEventFactory.createWindowEvent(e, newtWindow);
         if(null!=newtListener) {
index a06b716..6f936d2 100644 (file)
@@ -215,7 +215,7 @@ public class AWTWindow extends Window {
         }
     }
 
-    public com.jogamp.newt.Insets getInsets() {
+    public com.jogamp.newt.util.Insets getInsets() {
         final int insets[] = new int[] { 0, 0, 0, 0 };
         runOnEDT(true, new Runnable() {
                 public void run() {
@@ -226,7 +226,7 @@ public class AWTWindow extends Window {
                     insets[3] = contInsets.right;
                 }
             });
-        return new com.jogamp.newt.
+        return new com.jogamp.newt.util.
             Insets(insets[0],insets[1],insets[2],insets[3]);
     }
 
@@ -264,19 +264,6 @@ public class AWTWindow extends Window {
         return canvas;
     }
 
-    protected void enqueueWindowEvent(int eventType) {
-        super.enqueueWindowEvent(eventType);
-    }
-
-    protected void enqueueKeyEvent(int eventType, int modifiers, int keyCode, char keyChar) {
-        super.enqueueKeyEvent(eventType, modifiers, keyCode, keyChar);
-    }
-
-    protected void enqueueMouseEvent(int eventType, int modifiers,
-                                  int x, int y, int button, int rotation) {
-        super.enqueueMouseEvent(eventType, modifiers, x, y, button, rotation);
-    }
-
     private void runOnEDT(boolean wait, Runnable r) {
         EDTUtil edtUtil = screen.getDisplay().getEDTUtil();
         if ( ( null != edtUtil && edtUtil.isCurrentThreadEDT() ) || EventQueue.isDispatchThread() ) {
index 8a656a5..9f47aa4 100755 (executable)
@@ -39,6 +39,7 @@ import com.jogamp.nativewindow.impl.RecursiveToolkitLock;
 import com.jogamp.newt.*;
 import com.jogamp.newt.event.*;
 import com.jogamp.newt.impl.*;
+import com.jogamp.newt.util.*;
 
 public class MacWindow extends Window {
     
@@ -295,24 +296,6 @@ public class MacWindow extends Window {
         return fullscreen;
     }
     
-    private void sizeChanged(int newWidth, int newHeight) {
-        if(width != newWidth || height != newHeight) {
-            if (DEBUG_IMPLEMENTATION) {
-                System.out.println(Thread.currentThread().getName()+" Size changed to " + newWidth + ", " + newHeight);
-            }
-            width = newWidth;
-            height = newHeight;
-            if(!fullscreen) {
-                nfs_width=width;
-                nfs_height=height;
-            }
-            if (DEBUG_IMPLEMENTATION) {
-                System.out.println("  Posted WINDOW_RESIZED event");
-            }
-            enqueueWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED);
-        }
-    }
-
     private void insetsChanged(int left, int top, int right, int bottom) {
         if (DEBUG_IMPLEMENTATION) {
             System.out.println(Thread.currentThread().getName()+
@@ -326,32 +309,6 @@ public class MacWindow extends Window {
         }
     }
 
-    private void positionChanged(int newX, int newY) {
-        if( 0==parentWindowHandle && ( x != newX || y != newY ) ) {
-            if (DEBUG_IMPLEMENTATION) {
-                System.out.println(Thread.currentThread().getName()+" Position changed to " + newX + ", " + newY);
-            }
-            x = newX;
-            y = newY;
-            if(!fullscreen) {
-                nfs_x=x;
-                nfs_y=y;
-            }
-            if (DEBUG_IMPLEMENTATION) {
-                System.out.println("  Posted WINDOW_MOVED event");
-            }
-            enqueueWindowEvent(WindowEvent.EVENT_WINDOW_MOVED);
-        }
-    }
-
-    private void focusChanged(boolean focusGained) {
-        if (focusGained) {
-            enqueueWindowEvent(WindowEvent.EVENT_WINDOW_GAINED_FOCUS);
-        } else {
-            enqueueWindowEvent(WindowEvent.EVENT_WINDOW_LOST_FOCUS);
-        }
-    }
-
     private char convertKeyChar(char keyChar) {
         if (keyChar == '\r') {
             // Turn these into \n
@@ -435,12 +392,12 @@ public class MacWindow extends Window {
         return keyChar;
     }
 
-    protected void enqueueKeyEvent(int eventType, int modifiers, int keyCode, char keyChar) {
+    public void enqueueKeyEvent(boolean wait, int eventType, int modifiers, int keyCode, char keyChar) {
         int key = convertKeyChar(keyChar);
         if(DEBUG_IMPLEMENTATION) System.out.println("MacWindow.enqueueKeyEvent "+Thread.currentThread().getName());
         // Note that we send the key char for the key code on this
         // platform -- we do not get any useful key codes out of the system
-        super.enqueueKeyEvent(eventType, modifiers, key, keyChar);
+        super.enqueueKeyEvent(wait, eventType, modifiers, key, keyChar);
     }
 
     private void createWindow(final boolean recreate, final int x, final int y, final int width, final int height, final boolean fullscreen) {
@@ -482,9 +439,9 @@ public class MacWindow extends Window {
             ie.printStackTrace();
         }
 
-        enqueueWindowEvent(WindowEvent.EVENT_WINDOW_MOVED);
-        enqueueWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED);
-        enqueueWindowEvent(WindowEvent.EVENT_WINDOW_GAINED_FOCUS);
+        enqueueWindowEvent(false, WindowEvent.EVENT_WINDOW_MOVED);
+        enqueueWindowEvent(false, WindowEvent.EVENT_WINDOW_RESIZED);
+        enqueueWindowEvent(false, WindowEvent.EVENT_WINDOW_GAINED_FOCUS);
     }
     
     protected static native boolean initIDs0();
index 0d12a4a..0c72543 100755 (executable)
@@ -126,16 +126,11 @@ public class KDWindow extends Window {
         windowUserData=userData;
     }
 
-    private void sizeChanged(int newWidth, int newHeight) {
-        width = newWidth;
-        height = newHeight;
-        if(!fullscreen) {
-            nfs_width=width;
-            nfs_height=height;
-        } else {
+    protected void sizeChanged(int newWidth, int newHeight) {
+        if(fullscreen) {
             ((KDScreen)screen).setScreenSize(width, height);
         }
-        enqueueWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED);
+        super.sizeChanged(newWidth, newHeight);
     }
 
     private long   eglWindowHandle;
index aedb4ed..47f79f4 100755 (executable)
@@ -36,6 +36,7 @@ package com.jogamp.newt.impl.windows;
 import javax.media.nativewindow.*;
 import com.jogamp.newt.*;
 import com.jogamp.newt.event.*;
+import com.jogamp.newt.util.*;
 
 public class WindowsWindow extends Window {
 
@@ -216,42 +217,4 @@ public class WindowsWindow extends Window {
             insets.bottom = bottom;
         }
     }
-
-    private void sizeChanged(int newWidth, int newHeight) {
-        if(width != newWidth || height != newHeight) {
-            width = newWidth;
-            height = newHeight;
-            if(!fullscreen) {
-                nfs_width=width;
-                nfs_height=height;
-            }
-            enqueueWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED);
-        }
-    }
-
-    private void positionChanged(int newX, int newY) {
-        if( 0==parentWindowHandle && ( x != newX || y != newY ) ) {
-            x = newX;
-            y = newY;
-            if(!fullscreen) {
-                nfs_x=x;
-                nfs_y=y;
-            }
-            enqueueWindowEvent(WindowEvent.EVENT_WINDOW_MOVED);
-        }
-    }
-
-    /**
-     *
-     * @param focusOwner if focusGained is true, focusOwner is the previous
-     * focus owner, if focusGained is false, focusOwner is the new focus owner
-     * @param focusGained
-     */
-    private void focusChanged(long focusOwner, boolean focusGained) {
-        if (focusGained) {
-            enqueueWindowEvent(WindowEvent.EVENT_WINDOW_GAINED_FOCUS);
-        } else {
-            enqueueWindowEvent(WindowEvent.EVENT_WINDOW_LOST_FOCUS);
-        }
-    }
 }
index e7fc960..6890b29 100755 (executable)
@@ -71,7 +71,8 @@ public class X11Window extends Window {
         if(0!=windowHandleClose && null!=getScreen() ) {
             X11Display display = (X11Display) getScreen().getDisplay();
             try {
-                CloseWindow0(display.getHandle(), windowHandleClose, display.getJavaObjectAtom());
+                CloseWindow0(display.getHandle(), windowHandleClose, 
+                             display.getJavaObjectAtom(), display.getWindowDeleteAtom());
             } catch (Throwable t) {
                 if(DEBUG_IMPLEMENTATION) { 
                     Exception e = new Exception("closeNative failed - "+Thread.currentThread().getName(), t);
@@ -134,7 +135,7 @@ public class X11Window extends Window {
     private        native long CreateWindow0(long parentWindowHandle, long display, int screen_index, 
                                             long visualID, long javaObjectAtom, long windowDeleteAtom, 
                                             int x, int y, int width, int height, boolean undecorated);
-    private        native void CloseWindow0(long display, long windowHandle, long javaObjectAtom);
+    private        native void CloseWindow0(long display, long windowHandle, long javaObjectAtom, long windowDeleteAtom);
     private        native void setVisible0(long display, long windowHandle, boolean visible);
     private        native void setSize0(long display, long windowHandle, int width, int height);
     private        native void setPosSizeDecor0(long parentWindowHandle, long display, int screen_index, long windowHandle, 
@@ -145,51 +146,6 @@ public class X11Window extends Window {
     private        native void reparentWindow0(long parentWindowHandle, long display, int screen_index, long windowHandle, 
                                                int x, int y, boolean undecorated, boolean isVisible);
 
-    private void windowChanged(int newX, int newY, int newWidth, int newHeight) {
-        if(width != newWidth || height != newHeight) {
-            if(DEBUG_IMPLEMENTATION) {
-                System.err.println("X11Window windowChanged size: "+this.width+"x"+this.height+" -> "+newWidth+"x"+newHeight);
-            }
-            width = newWidth;
-            height = newHeight;
-            if(!fullscreen) {
-                nfs_width=width;
-                nfs_height=height;
-            }
-            enqueueWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED);
-        }
-        if( 0==parentWindowHandle && ( x != newX || y != newY ) ) {
-            if(DEBUG_IMPLEMENTATION) {
-                System.err.println("X11Window windowChanged position: "+this.x+"/"+this.y+" -> "+newX+"x"+newY);
-            }
-            x = newX;
-            y = newY;
-            if(!fullscreen) {
-                nfs_x=x;
-                nfs_y=y;
-            }
-            enqueueWindowEvent(WindowEvent.EVENT_WINDOW_MOVED);
-        }
-    }
-
-    /**
-     * @param focusGained
-     */
-    private void focusChanged(boolean focusGained) {
-        if (focusGained) {
-            enqueueWindowEvent(WindowEvent.EVENT_WINDOW_GAINED_FOCUS);
-        } else {
-            enqueueWindowEvent(WindowEvent.EVENT_WINDOW_LOST_FOCUS);
-        }
-    }
-
-    /**
-     * @param focusGained
-     */
-    private void visibleChanged(boolean visible) {
-        // FIXME .. this.visible = visible ;
-    }
-
     private void windowCreated(long windowHandle) {
         this.windowHandle = windowHandle;
     }
index e36e516..e66ed1e 100644 (file)
@@ -35,6 +35,7 @@ package com.jogamp.newt.opengl;
 
 import com.jogamp.newt.*;
 import com.jogamp.newt.event.*;
+import com.jogamp.newt.util.*;
 import com.jogamp.nativewindow.impl.RecursiveToolkitLock;
 import javax.media.nativewindow.*;
 import javax.media.opengl.*;
@@ -55,22 +56,34 @@ import java.util.*;
  */
 public class GLWindow extends Window implements GLAutoDrawable {
     private Window window;
-    private boolean runPumpMessages;
 
     /**
      * Constructor. Do not call this directly -- use {@link #create()} instead.
      */
     protected GLWindow(Window window) {
+        this.startTime = System.currentTimeMillis();
         this.window = window;
         this.window.setHandleDestroyNotify(false);
-        this.runPumpMessages = ( null == getScreen().getDisplay().getEDTUtil() ) ;
         window.addWindowListener(new WindowAdapter() {
+                public void windowRepaint(WindowUpdateEvent e) {
+                    if( !windowIsLocked() && null == getAnimator() ) {
+                        display();
+                    }
+                }
+
                 public void windowResized(WindowEvent e) {
                     sendReshape = true;
+                    if( !windowIsLocked() && null == getAnimator() ) {
+                        display();
+                    }
                 }
 
                 public void windowDestroyNotify(WindowEvent e) {
-                    sendDestroy = true;
+                    if( !windowIsLocked() && null == getAnimator() ) {
+                        destroy();
+                    } else {
+                       sendDestroy = true;
+                   }
                 }
             });
     }
@@ -128,31 +141,6 @@ public class GLWindow extends Window implements GLAutoDrawable {
         return window.getWrappedWindow();
     }
 
-    /** 
-     * EXPERIMENTAL<br> 
-     * Enable or disables running the {@link Display#pumpMessages} in the {@link #display()} call.<br>
-     * The default behavior is to run {@link Display#pumpMessages}.<P>
-     *
-     * The idea was that in a single threaded environment with one {@link Display} and many {@link Window}'s,
-     * a performance benefit was expected while disabling the implicit {@link Display#pumpMessages} and
-     * do it once via {@link GLWindow#runCurrentThreadPumpMessage()} <br>
-     * This could not have been verified. No measurable difference could have been recognized.<P>
-     *
-     * Best performance has been achieved with one GLWindow per thread.<br> 
-     *
-     * Enabling local pump messages while using the EDT, 
-     * {@link com.jogamp.newt.NewtFactory#setUseEDT(boolean)},
-     * will result in an exception.
-     *
-     * @deprecated EXPERIMENTAL, semantic is about to be removed after further verification.
-     */
-    public void setRunPumpMessages(boolean onoff) {
-        if( onoff && null!=getScreen().getDisplay().getEDTUtil() ) {
-            throw new GLException("GLWindow.setRunPumpMessages(true) - Can't do with EDT on");
-        }
-        runPumpMessages = onoff;
-    }
-
     protected void createNativeImpl() {
         shouldNotCallThis();
     }
@@ -178,7 +166,7 @@ public class GLWindow extends Window implements GLAutoDrawable {
             // Lock: Have to cover whole workflow (dispose all, context, drawable and window)
             windowLock();
             try {
-                if(null==window || window.isDestroyed()) {
+               if( isDestroyed() ) {
                     return; // nop
                 }
                 if(Window.DEBUG_WINDOW_EVENT || window.DEBUG_IMPLEMENTATION) {
@@ -186,21 +174,20 @@ public class GLWindow extends Window implements GLAutoDrawable {
                     e1.printStackTrace();
                 }
 
-                if ( null != context && context.isCreated() && null != drawable && drawable.isRealized() ) {
-                    // Catch dispose GLExceptions by GLEventListener, just 'print' them
-                    // so we can continue with the destruction.
-                    try {
-                        helper.invokeGL(drawable, context, disposeAction, null);
-                    } catch (GLException gle) {
-                        gle.printStackTrace();
+                if( window.isNativeWindowValid() && null != drawable && drawable.isRealized() ) {
+                    if( null != context && context.isCreated() ) {
+                        // Catch dispose GLExceptions by GLEventListener, just 'print' them
+                        // so we can continue with the destruction.
+                        try {
+                            helper.invokeGL(drawable, context, disposeAction, null);
+                        } catch (GLException gle) {
+                            gle.printStackTrace();
+                        }
+
+                        context.destroy();
+                        context = null;
                     }
-                }
 
-                if (context != null && null != drawable && drawable.isRealized() ) {
-                    context.destroy();
-                    context = null;
-                }
-                if (drawable != null) {
                     drawable.setRealized(false);
                     drawable = null;
                 }
@@ -228,7 +215,7 @@ public class GLWindow extends Window implements GLAutoDrawable {
      * @see #destroy()
      */
     public void destroy(boolean deep) {
-        if(!isDestroyed()) {
+       if( !isDestroyed() ) {
             runOnEDTIfAvail(true, new DestroyAction(deep));
         }
     }
@@ -369,6 +356,13 @@ public class GLWindow extends Window implements GLAutoDrawable {
         return window.isFullscreen();
     }
 
+    public void enqueueEvent(boolean wait, com.jogamp.newt.event.NEWTEvent event) {
+        window.enqueueEvent(wait, event);
+    }
+    public boolean consumeEvent(NEWTEvent e) {
+        return window.consumeEvent(e);
+    }
+
     public void addSurfaceUpdatedListener(int index, SurfaceUpdatedListener l) {
         window.addSurfaceUpdatedListener(index, l);
     }
@@ -414,6 +408,12 @@ public class GLWindow extends Window implements GLAutoDrawable {
         return window.getKeyListeners();
     }
 
+    public void sendWindowEvent(int eventType) {
+        window.sendWindowEvent(eventType);
+    }
+    public void enqueueWindowEvent(boolean wait, int eventType) {
+        window.enqueueWindowEvent(wait, eventType);
+    }
     public void addWindowListener(int index, WindowListener l) {
         window.addWindowListener(index, l);
     }
@@ -426,6 +426,12 @@ public class GLWindow extends Window implements GLAutoDrawable {
     public WindowListener[] getWindowListeners() {
         return window.getWindowListeners();
     }
+    public void setPropagateRepaint(boolean v) {
+        window.setPropagateRepaint(v);
+    }
+    public void windowRepaint(int x, int y, int width, int height) {
+        window.windowRepaint(x, y, width, height);
+    }
 
     public String toString() {
         return "NEWT-GLWindow[ \n\tHelper: "+helper+", \n\tDrawable: "+drawable + /** ", \n\tWindow: "+window+", \n\tFactory: "+factory+ */ "]";
@@ -483,8 +489,17 @@ public class GLWindow extends Window implements GLAutoDrawable {
         helper.removeGLEventListener(listener);
     }
 
+    public void setAnimator(Thread animator) {
+        helper.setAnimator(animator);
+        window.setPropagateRepaint(null==animator);
+    }
+
+    public Thread getAnimator() {
+        return helper.getAnimator();
+    }
+
     public void invoke(boolean wait, GLRunnable glRunnable) {
-        helper.invoke(wait, glRunnable);
+        helper.invoke(this, wait, glRunnable);
     }
 
     public void display() {
@@ -494,28 +509,26 @@ public class GLWindow extends Window implements GLAutoDrawable {
     public void display(boolean forceReshape) {
         if( null == window ) { return; }
 
+        if(sendDestroy || ( null!=window && window.hasDeviceChanged() && GLAutoDrawable.SCREEN_CHANGE_ACTION_ENABLED ) ) {
+         sendDestroy=false;
+         destroy();
+          return;
+       }
+
         if( null == context && window.isVisible() ) {
             // retry native window and drawable/context creation 
             setVisible(true);
         }
 
-        if( window.isNativeWindowValid() && null != context ) {
-            if(runPumpMessages) {
-                window.getScreen().getDisplay().pumpMessages();
+        if( window.isVisible() && window.isNativeWindowValid() && null != context ) {
+            if(forceReshape) {
+                sendReshape = true;
             }
-            if(sendDestroy || window.hasDeviceChanged() && GLAutoDrawable.SCREEN_CHANGE_ACTION_ENABLED) {
-                destroy();
-                sendDestroy=false;
-            } else if ( window.isVisible() ) {
-                if(forceReshape) {
-                    sendReshape = true;
-                }
-                windowLock();
-                try{
-                    helper.invokeGL(drawable, context, displayAction, initAction);
-                } finally {
-                    windowUnlock();
-                }
+            windowLock();
+            try{
+                helper.invokeGL(drawable, context, displayAction, initAction);
+            } finally {
+                windowUnlock();
             }
         }
     }
@@ -546,7 +559,7 @@ public class GLWindow extends Window implements GLAutoDrawable {
         public void run() {
             // Lock: Locked Surface/Window by MakeCurrent/Release
             helper.init(GLWindow.this);
-            startTime = System.currentTimeMillis();
+            startTime = System.currentTimeMillis(); // overwrite startTime to real init one
             curTime   = startTime;
             if(perfLog) {
                 lastCheck  = startTime;
@@ -560,10 +573,7 @@ public class GLWindow extends Window implements GLAutoDrawable {
         public void run() {
             // Lock: Locked Surface/Window by display _and_ MakeCurrent/Release
             if (sendReshape) {
-                int width = getWidth();
-                int height = getHeight();
-                getGL().glViewport(0, 0, width, height);
-                helper.reshape(GLWindow.this, 0, 0, width, height);
+                helper.reshape(GLWindow.this, 0, 0, getWidth(), getHeight());
                 sendReshape = false;
             }
 
@@ -589,8 +599,8 @@ public class GLWindow extends Window implements GLAutoDrawable {
     private DisplayAction displayAction = new DisplayAction();
 
     public long getStartTime()   { return startTime; }
-    public long getCurrentTime() { return curTime; }
-    public long getDuration()    { return curTime-startTime; }
+    public long getCurrentTime() { curTime = System.currentTimeMillis(); return curTime; }
+    public long getDuration()    { return getCurrentTime()-startTime; }
     public int  getTotalFrames() { return totalFrames; }
 
     private long startTime = 0;
@@ -30,7 +30,7 @@
  * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
  *
  */
-package com.jogamp.newt;
+package com.jogamp.newt.util;
 
 /**
  * Simple class representing insets.
index 5e3311d..a1dab26 100755 (executable)
 
 #define STD_PRINT(...) fprintf(stderr, __VA_ARGS__); fflush(stderr) 
 
-static jmethodID sizeChangedID = NULL;
 static jmethodID insetsChangedID = NULL;
+static jmethodID sizeChangedID = NULL;
 static jmethodID positionChangedID = NULL;
 static jmethodID focusChangedID = NULL;
+static jmethodID visibleChangedID = NULL;
 static jmethodID windowDestroyNotifyID = NULL;
 static jmethodID windowDestroyedID = NULL;
-static jmethodID enqueueMouseEventID = NULL;
-static jmethodID enqueueKeyEventID = NULL;
-static jmethodID sendPaintEventID = NULL;
+static jmethodID windowRepaintID = NULL;
+static jmethodID sendMouseEventID = NULL;
+static jmethodID sendKeyEventID = NULL;
 
 static RECT* UpdateInsets(JNIEnv *env, HWND hwnd, jobject window);
 
@@ -506,7 +507,7 @@ static int WmChar(JNIEnv *env, jobject window, UINT character, UINT repCnt,
     if (character == VK_RETURN) {
         character = J_VK_ENTER;
     }
-    (*env)->CallVoidMethod(env, window, enqueueKeyEventID,
+    (*env)->CallVoidMethod(env, window, sendKeyEventID,
                            (jint) EVENT_KEY_TYPED,
                            GetModifiers(),
                            (jint) -1,
@@ -551,7 +552,7 @@ static int WmKeyDown(JNIEnv *env, jobject window, UINT wkey, UINT repCnt,
     character = WindowsKeyToJavaChar(wkey, modifiers, SAVE);
 */
 
-    (*env)->CallVoidMethod(env, window, enqueueKeyEventID,
+    (*env)->CallVoidMethod(env, window, sendKeyEventID,
                            (jint) EVENT_KEY_PRESSED,
                            modifiers,
                            (jint) jkey,
@@ -562,7 +563,7 @@ static int WmKeyDown(JNIEnv *env, jobject window, UINT wkey, UINT repCnt,
        WM_KEYDOWN.
      */
     if (jkey == J_VK_DELETE) {
-        (*env)->CallVoidMethod(env, window, enqueueKeyEventID,
+        (*env)->CallVoidMethod(env, window, sendKeyEventID,
                                (jint) EVENT_KEY_TYPED,
                                GetModifiers(),
                                (jint) -1,
@@ -586,7 +587,7 @@ static int WmKeyUp(JNIEnv *env, jobject window, UINT wkey, UINT repCnt,
     character = WindowsKeyToJavaChar(wkey, modifiers, SAVE);
 */
 
-    (*env)->CallVoidMethod(env, window, enqueueKeyEventID,
+    (*env)->CallVoidMethod(env, window, sendKeyEventID,
                            (jint) EVENT_KEY_RELEASED,
                            modifiers,
                            (jint) jkey,
@@ -706,6 +707,7 @@ static void WmSize(JNIEnv *env, HWND wnd, jobject window, UINT type)
 static LRESULT CALLBACK wndProc(HWND wnd, UINT message,
                                 WPARAM wParam, LPARAM lParam)
 {
+    LRESULT res = 0;
     int useDefWindowProc = 0;
     JNIEnv *env = NULL;
     jobject window = NULL;
@@ -799,7 +801,7 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message,
 
     case WM_LBUTTONDOWN:
         NewtWindows_requestFocus ( wnd, FALSE, FALSE ); // request focus on this window, if not already ..
-        (*env)->CallVoidMethod(env, window, enqueueMouseEventID,
+        (*env)->CallVoidMethod(env, window, sendMouseEventID,
                                (jint) EVENT_MOUSE_PRESSED,
                                GetModifiers(),
                                (jint) LOWORD(lParam), (jint) HIWORD(lParam),
@@ -808,7 +810,7 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message,
         break;
 
     case WM_LBUTTONUP:
-        (*env)->CallVoidMethod(env, window, enqueueMouseEventID,
+        (*env)->CallVoidMethod(env, window, sendMouseEventID,
                                (jint) EVENT_MOUSE_RELEASED,
                                GetModifiers(),
                                (jint) LOWORD(lParam), (jint) HIWORD(lParam),
@@ -818,7 +820,7 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message,
 
     case WM_MBUTTONDOWN:
         NewtWindows_requestFocus ( wnd, FALSE, FALSE ); // request focus on this window, if not already ..
-        (*env)->CallVoidMethod(env, window, enqueueMouseEventID,
+        (*env)->CallVoidMethod(env, window, sendMouseEventID,
                                (jint) EVENT_MOUSE_PRESSED,
                                GetModifiers(),
                                (jint) LOWORD(lParam), (jint) HIWORD(lParam),
@@ -827,7 +829,7 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message,
         break;
 
     case WM_MBUTTONUP:
-        (*env)->CallVoidMethod(env, window, enqueueMouseEventID,
+        (*env)->CallVoidMethod(env, window, sendMouseEventID,
                                (jint) EVENT_MOUSE_RELEASED,
                                GetModifiers(),
                                (jint) LOWORD(lParam), (jint) HIWORD(lParam),
@@ -837,7 +839,7 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message,
 
     case WM_RBUTTONDOWN:
         NewtWindows_requestFocus ( wnd, FALSE, FALSE ); // request focus on this window, if not already ..
-        (*env)->CallVoidMethod(env, window, enqueueMouseEventID,
+        (*env)->CallVoidMethod(env, window, sendMouseEventID,
                                (jint) EVENT_MOUSE_PRESSED,
                                GetModifiers(),
                                (jint) LOWORD(lParam), (jint) HIWORD(lParam),
@@ -846,7 +848,7 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message,
         break;
 
     case WM_RBUTTONUP:
-        (*env)->CallVoidMethod(env, window, enqueueMouseEventID,
+        (*env)->CallVoidMethod(env, window, sendMouseEventID,
                                (jint) EVENT_MOUSE_RELEASED,
                                GetModifiers(),
                                (jint) LOWORD(lParam), (jint) HIWORD(lParam),
@@ -855,7 +857,7 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message,
         break;
 
     case WM_MOUSEMOVE:
-        (*env)->CallVoidMethod(env, window, enqueueMouseEventID,
+        (*env)->CallVoidMethod(env, window, sendMouseEventID,
                                (jint) EVENT_MOUSE_MOVED,
                                GetModifiers(),
                                (jint) LOWORD(lParam), (jint) HIWORD(lParam),
@@ -871,7 +873,7 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message,
         eventPt.x = x;
         eventPt.y = y;
         ScreenToClient(wnd, &eventPt);
-        (*env)->CallVoidMethod(env, window, enqueueMouseEventID,
+        (*env)->CallVoidMethod(env, window, sendMouseEventID,
                                (jint) EVENT_MOUSE_WHEEL_MOVED,
                                GetModifiers(),
                                (jint) eventPt.x, (jint) eventPt.y,
@@ -881,17 +883,19 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message,
     }
 
     case WM_SETFOCUS:
-        (*env)->CallVoidMethod(env, window, focusChangedID,
-                               (jlong)wParam, JNI_TRUE);
+        (*env)->CallVoidMethod(env, window, focusChangedID, JNI_TRUE);
         useDefWindowProc = 1;
         break;
 
     case WM_KILLFOCUS:
-        (*env)->CallVoidMethod(env, window, focusChangedID,
-                               (jlong)wParam, JNI_FALSE);
+        (*env)->CallVoidMethod(env, window, focusChangedID, JNI_FALSE);
         useDefWindowProc = 1;
         break;
 
+    case WM_SHOWWINDOW:
+        (*env)->CallVoidMethod(env, window, visibleChangedID, wParam==TRUE?JNI_TRUE:JNI_FALSE);
+        break;
+
     case WM_MOVE:
         DBG_PRINT("*** WindowsWindow: WM_MOVE window %p, %d/%d\n", wnd, (int)LOWORD(lParam), (int)HIWORD(lParam));
         (*env)->CallVoidMethod(env, window, positionChangedID,
@@ -901,21 +905,24 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message,
 
     case WM_PAINT: {
         RECT r;
-        if (GetUpdateRect(wnd, &r, FALSE)) {
-            if ((r.right-r.left) > 0 && (r.bottom-r.top) > 0) {
-                (*env)->CallVoidMethod(env, window, sendPaintEventID,
-                                       0, r.left, r.top, r.right-r.left, r.bottom-r.top);
+        useDefWindowProc = 0;
+        if (GetUpdateRect(wnd, &r, TRUE /* erase background */)) {
+               /*
+            jint width = r.right-r.left;
+            jint height = r.bottom-r.top;
+            if (width > 0 && height > 0) {
+                (*env)->CallVoidMethod(env, window, windowRepaintID, r.left, r.top, width, height);
             }
             ValidateRect(wnd, &r);
-            useDefWindowProc = 0;
-        } else {
-            useDefWindowProc = 1;
+            */
         }
         break;
     }
     case WM_ERASEBKGND:
         // ignore erase background
+        (*env)->CallVoidMethod(env, window, windowRepaintID, 0, 0, -1, -1);
         useDefWindowProc = 0;
+        res = 1;
         break;
 
 
@@ -926,7 +933,7 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message,
 
     if (useDefWindowProc)
         return DefWindowProc(wnd, message, wParam, lParam);
-    return 0;
+    return res;
 }
 
 /*
@@ -1052,24 +1059,26 @@ JNIEXPORT jint JNICALL Java_com_jogamp_newt_impl_windows_WindowsScreen_getHeight
 JNIEXPORT jboolean JNICALL Java_com_jogamp_newt_impl_windows_WindowsWindow_initIDs0
   (JNIEnv *env, jclass clazz)
 {
-    sizeChangedID = (*env)->GetMethodID(env, clazz, "sizeChanged", "(II)V");
     insetsChangedID = (*env)->GetMethodID(env, clazz, "insetsChanged", "(IIII)V");
+    sizeChangedID = (*env)->GetMethodID(env, clazz, "sizeChanged", "(II)V");
     positionChangedID = (*env)->GetMethodID(env, clazz, "positionChanged", "(II)V");
-    focusChangedID = (*env)->GetMethodID(env, clazz, "focusChanged", "(JZ)V");
+    focusChangedID = (*env)->GetMethodID(env, clazz, "focusChanged", "(Z)V");
+    visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(Z)V");
     windowDestroyNotifyID    = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "()V");
     windowDestroyedID = (*env)->GetMethodID(env, clazz, "windowDestroyed", "()V");
-    enqueueMouseEventID = (*env)->GetMethodID(env, clazz, "enqueueMouseEvent", "(IIIIII)V");
-    enqueueKeyEventID = (*env)->GetMethodID(env, clazz, "enqueueKeyEvent", "(IIIC)V");
-    sendPaintEventID = (*env)->GetMethodID(env, clazz, "sendPaintEvent", "(IIIII)V");
-    if (sizeChangedID == NULL ||
-        insetsChangedID == NULL ||
+    windowRepaintID = (*env)->GetMethodID(env, clazz, "windowRepaint", "(IIII)V");
+    sendMouseEventID = (*env)->GetMethodID(env, clazz, "sendMouseEvent", "(IIIIII)V");
+    sendKeyEventID = (*env)->GetMethodID(env, clazz, "sendKeyEvent", "(IIIC)V");
+    if (insetsChangedID == NULL ||
+        sizeChangedID == NULL ||
         positionChangedID == NULL ||
         focusChangedID == NULL ||
+        visibleChangedID == NULL ||
         windowDestroyNotifyID == NULL ||
         windowDestroyedID == NULL ||
-        enqueueMouseEventID == NULL ||
-        sendPaintEventID == NULL ||
-        enqueueKeyEventID == NULL)
+        windowRepaintID == NULL ||
+        sendMouseEventID == NULL ||
+        sendKeyEventID == NULL)
     {
         return JNI_FALSE;
     }
index a521d2d..dbf8336 100755 (executable)
@@ -151,14 +151,16 @@ static const char * const ClazzNameNewtWindow =
                             "com/jogamp/newt/Window";
 static jclass    newtWindowClz=NULL;
 
-static jmethodID windowChangedID = NULL;
+static jmethodID sizeChangedID = NULL;
+static jmethodID positionChangedID = NULL;
 static jmethodID focusChangedID = NULL;
 static jmethodID visibleChangedID = NULL;
 static jmethodID windowDestroyNotifyID = NULL;
 static jmethodID windowDestroyedID = NULL;
+static jmethodID windowRepaintID = NULL;
 static jmethodID windowCreatedID = NULL;
-static jmethodID enqueueMouseEventID = NULL;
-static jmethodID enqueueKeyEventID = NULL;
+static jmethodID sendMouseEventID = NULL;
+static jmethodID sendKeyEventID = NULL;
 
 static jmethodID displayCompletedID = NULL;
 
@@ -291,8 +293,7 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Display_CompleteDisplay0
  * Window
  */
 
-// #define WINDOW_EVENT_MASK ( FocusChangeMask | StructureNotifyMask | ExposureMask | VisibilityNotify )
-#define WINDOW_EVENT_MASK ( FocusChangeMask | StructureNotifyMask | VisibilityNotify )
+#define WINDOW_EVENT_MASK ( FocusChangeMask | StructureNotifyMask | ExposureMask )
 
 static int putPtrIn32Long(unsigned long * dst, uintptr_t src) {
     int i=0;
@@ -505,31 +506,37 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Display_DispatchMessages
         switch(evt.type) {
             case ButtonPress:
                 NewtWindows_requestFocus1 ( dpy, evt.xany.window );
-                (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, (jint) EVENT_MOUSE_PRESSED, 
+                (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, 
+                                      (jint) EVENT_MOUSE_PRESSED, 
                                       (jint) evt.xbutton.state, 
                                       (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0 /*rotation*/);
                 break;
             case ButtonRelease:
-                (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, (jint) EVENT_MOUSE_RELEASED, 
+                (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, 
+                                      (jint) EVENT_MOUSE_RELEASED, 
                                       (jint) evt.xbutton.state, 
                                       (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0 /*rotation*/);
                 break;
             case MotionNotify:
-                (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, (jint) EVENT_MOUSE_MOVED, 
+                (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, 
+                                      (jint) EVENT_MOUSE_MOVED, 
                                       (jint) evt.xmotion.state, 
                                       (jint) evt.xmotion.x, (jint) evt.xmotion.y, (jint) 0, 0 /*rotation*/); 
                 break;
             case KeyPress:
-                (*env)->CallVoidMethod(env, jwindow, enqueueKeyEventID, (jint) EVENT_KEY_PRESSED, 
+                (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, 
+                                      (jint) EVENT_KEY_PRESSED, 
                                       (jint) evt.xkey.state, 
                                       X11KeySym2NewtVKey(keySym), (jchar) keyChar);
                 break;
             case KeyRelease:
-                (*env)->CallVoidMethod(env, jwindow, enqueueKeyEventID, (jint) EVENT_KEY_RELEASED, 
+                (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, 
+                                      (jint) EVENT_KEY_RELEASED, 
                                       (jint) evt.xkey.state, 
                                       X11KeySym2NewtVKey(keySym), (jchar) keyChar);
 
-                (*env)->CallVoidMethod(env, jwindow, enqueueKeyEventID, (jint) EVENT_KEY_TYPED, 
+                (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, 
+                                      (jint) EVENT_KEY_TYPED, 
                                       (jint) evt.xkey.state, 
                                       (jint) -1, (jchar) keyChar);
                 break;
@@ -546,9 +553,10 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Display_DispatchMessages
                             (unsigned int)evt.xconfigure.window, (unsigned int)evt.xconfigure.event, (unsigned int)evt.xconfigure.above,
                             evt.xconfigure.x, evt.xconfigure.y, evt.xconfigure.width, evt.xconfigure.height, 
                             evt.xconfigure.override_redirect);
-                (*env)->CallVoidMethod(env, jwindow, windowChangedID, 
-                                        (jint) evt.xconfigure.x, (jint) evt.xconfigure.y,
+                (*env)->CallVoidMethod(env, jwindow, sizeChangedID, 
                                         (jint) evt.xconfigure.width, (jint) evt.xconfigure.height);
+                (*env)->CallVoidMethod(env, jwindow, positionChangedID, 
+                                        (jint) evt.xconfigure.x, (jint) evt.xconfigure.y);
                 break;
             case ClientMessage:
                 if (evt.xclient.send_event==True && evt.xclient.data.l[0]==(Atom)wmDeleteAtom) {
@@ -568,25 +576,28 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Display_DispatchMessages
                 (*env)->CallVoidMethod(env, jwindow, focusChangedID, JNI_FALSE);
                 break;
 
+            case Expose:
+                DBG_PRINT( "X11: event . Expose call 0x%X %d/%d %dx%d\n", (unsigned int)evt.xexpose.window,
+                    evt.xexpose.x, evt.xexpose.y, evt.xexpose.width, evt.xexpose.height);
+
+                if (evt.xexpose.width > 0 && evt.xexpose.height > 0) {
+                    (*env)->CallVoidMethod(env, jwindow, windowRepaintID, 
+                        evt.xexpose.x, evt.xexpose.y, evt.xexpose.width, evt.xexpose.height);
+                }
+                break;
+
             case MapNotify:
                 DBG_PRINT( "X11: event . MapNotify call 0x%X\n", (unsigned int)evt.xunmap.window);
-                // FIXME (*env)->CallVoidMethod(env, jwindow, visibleChangedID, JNI_TRUE);
+                (*env)->CallVoidMethod(env, jwindow, visibleChangedID, JNI_TRUE);
                 break;
 
             case UnmapNotify:
                 DBG_PRINT( "X11: event . UnmapNotify call 0x%X\n", (unsigned int)evt.xunmap.window);
-                // FIXME (*env)->CallVoidMethod(env, jwindow, visibleChangedID, JNI_FALSE);
+                (*env)->CallVoidMethod(env, jwindow, visibleChangedID, JNI_FALSE);
                 break;
 
             // unhandled events .. yet ..
 
-            case VisibilityNotify:
-                DBG_PRINT( "X11: event . VisibilityNotify call 0x%X\n", (unsigned int)evt.xvisibility.window);
-                break;
-            case Expose:
-                DBG_PRINT( "X11: event . Expose call 0x%X\n", (unsigned int)evt.xexpose.window);
-                /* FIXME: Might want to send a repaint event .. */
-                break;
             default:
                 DBG_PRINT("X11: event . unhandled %d 0x%X call 0x%X\n", evt.type, evt.type, (unsigned int)evt.xunmap.window);
         }
@@ -653,23 +664,27 @@ JNIEXPORT jint JNICALL Java_com_jogamp_newt_impl_x11_X11Screen_getHeight0
 JNIEXPORT jboolean JNICALL Java_com_jogamp_newt_impl_x11_X11Window_initIDs0
   (JNIEnv *env, jclass clazz)
 {
-    windowChangedID = (*env)->GetMethodID(env, clazz, "windowChanged", "(IIII)V");
+    sizeChangedID = (*env)->GetMethodID(env, clazz, "sizeChanged", "(II)V");
+    positionChangedID = (*env)->GetMethodID(env, clazz, "positionChanged", "(II)V");
     focusChangedID = (*env)->GetMethodID(env, clazz, "focusChanged", "(Z)V");
     visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(Z)V");
     windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "()V");
     windowDestroyedID = (*env)->GetMethodID(env, clazz, "windowDestroyed", "()V");
+    windowRepaintID = (*env)->GetMethodID(env, clazz, "windowRepaint", "(IIII)V");
     windowCreatedID = (*env)->GetMethodID(env, clazz, "windowCreated", "(J)V");
-    enqueueMouseEventID = (*env)->GetMethodID(env, clazz, "enqueueMouseEvent", "(IIIIII)V");
-    enqueueKeyEventID = (*env)->GetMethodID(env, clazz, "enqueueKeyEvent", "(IIIC)V");
+    sendMouseEventID = (*env)->GetMethodID(env, clazz, "sendMouseEvent", "(IIIIII)V");
+    sendKeyEventID = (*env)->GetMethodID(env, clazz, "sendKeyEvent", "(IIIC)V");
 
-    if (windowChangedID == NULL ||
+    if (sizeChangedID == NULL ||
+        positionChangedID == NULL ||
         focusChangedID == NULL ||
         visibleChangedID == NULL ||
         windowDestroyNotifyID == NULL ||
         windowDestroyedID == NULL ||
+        windowRepaintID == NULL ||
         windowCreatedID == NULL ||
-        enqueueMouseEventID == NULL ||
-        enqueueKeyEventID == NULL) {
+        sendMouseEventID == NULL ||
+        sendKeyEventID == NULL) {
         return JNI_FALSE;
     }
     return JNI_TRUE;
@@ -749,12 +764,17 @@ JNIEXPORT jlong JNICALL Java_com_jogamp_newt_impl_x11_X11Window_CreateWindow0
         pVisualQuery=NULL;
     }
 
-    attrMask  = ( CWBackPixel | CWBorderPixel | CWColormap | CWOverrideRedirect ) ;
+    attrMask  = ( CWBackingStore | CWBackingPlanes | CWBackingPixel | CWBackPixel | 
+                  CWBorderPixel | CWColormap | CWOverrideRedirect ) ;
 
     memset(&xswa, 0, sizeof(xswa));
     xswa.override_redirect = ( 0 != parent ) ? True : False ;
     xswa.border_pixel = 0;
     xswa.background_pixel = 0;
+    xswa.backing_store=NotUseful; /* NotUseful, WhenMapped, Always */
+    xswa.backing_planes=0;        /* planes to be preserved if possible */
+    xswa.backing_pixel=0;         /* value to use in restoring planes */
+
     xswa.colormap = XCreateColormap(dpy,
                                     windowParent, // XRootWindow(dpy, scrn_idx),
                                     visual,
@@ -781,6 +801,7 @@ JNIEXPORT jlong JNICALL Java_com_jogamp_newt_impl_x11_X11Window_CreateWindow0
 
     setJavaWindowProperty(env, dpy, window, javaObjectAtom, (*env)->NewGlobalRef(env, obj));
 
+    // XClearWindow(dpy, window);
     XSync(dpy, False);
 
     {
@@ -806,7 +827,7 @@ JNIEXPORT jlong JNICALL Java_com_jogamp_newt_impl_x11_X11Window_CreateWindow0
  * Signature: (JJ)V
  */
 JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Window_CloseWindow0
-  (JNIEnv *env, jobject obj, jlong display, jlong window, jlong javaObjectAtom)
+  (JNIEnv *env, jobject obj, jlong display, jlong window, jlong javaObjectAtom, jlong wmDeleteAtom)
 {
     Display * dpy = (Display *) (intptr_t) display;
     Window w = (Window)window;
@@ -827,14 +848,19 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Window_CloseWindow0
         _throwNewRuntimeException(dpy, env, "Internal Error .. Window global ref not the same!");
         return;
     }
-    (*env)->DeleteGlobalRef(env, jwindow);
 
     XSync(dpy, False);
     XSelectInput(dpy, w, 0);
     XUnmapWindow(dpy, w);
+
+    // Drain all events related to this window ..
+    JNICALL Java_com_jogamp_newt_impl_x11_X11Display_DispatchMessages0(env, obj, display, javaObjectAtom, wmDeleteAtom);
+
     XDestroyWindow(dpy, w);
     XSync(dpy, False);
 
+    (*env)->DeleteGlobalRef(env, jwindow);
+
     DBG_PRINT( "X11: CloseWindow END\n");
 
     (*env)->CallVoidMethod(env, obj, windowDestroyedID);
@@ -922,6 +948,11 @@ static void NewtWindows_reparentWindow
     DBG_PRINT( "X11: reparentWindow dpy %p, parent %p/%p, win %p, %d/%d undec %d\n", 
         (void*)dpy, (void*) jparent, (void*)parent, (void*)w, x, y, undecorated);
 
+    // don't propagate events during reparenting
+    // long orig_xevent_mask = xwa->your_event_mask ;
+    /* XSelectInput(dpy, w, orig_xevent_mask & ~ ( StructureNotifyMask ) );
+       XSync(dpy, False); */
+
     if(0 != jparent) {
         // move into parent ..
         NewtWindows_setDecorations (dpy, w, False);
@@ -955,6 +986,14 @@ static void NewtWindows_reparentWindow
         XSync(dpy, False);
     }
 
+    /* XSelectInput(dpy, w, orig_xevent_mask);
+       XSync(dpy, False); */
+
+    if(JNI_TRUE == isVisible) {
+        NewtWindows_requestFocus0 ( dpy, w, xwa );
+        XSync(dpy, False);
+    }
+
     DBG_PRINT( "X11: reparentWindow X\n");
 }
 
@@ -993,12 +1032,6 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Window_setPosSizeDecor0
     xwc.width=width;
     xwc.height=height;
     XConfigureWindow(dpy, w, CWX|CWY|CWWidth|CWHeight, &xwc);
-
-    if(JNI_TRUE == isVisible) {
-        XGetWindowAttributes(dpy, w, &xwa);
-        NewtWindows_requestFocus0 ( dpy, w, &xwa );
-        XSync(dpy, False);
-    }
 }
 
 /*
@@ -1039,7 +1072,7 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Window_reparentWindow0
 JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Window_requestFocus0
   (JNIEnv *env, jobject obj, jlong display, jlong window)
 {
-    NewtWindows_requestFocus ( (Display *) (intptr_t) display, (Window)window ) ;
+    NewtWindows_requestFocus1 ( (Display *) (intptr_t) display, (Window)window ) ;
 }
 
 /*
http://JogAmp.org git info: FAQ, tutorial and man pages.