diff options
author | Sven Gothel <[email protected]> | 2010-06-26 06:59:48 +0300 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2010-06-26 06:59:48 +0300 |
commit | 969e427642d3b9be376cefaada9febd489b7b3d7 (patch) | |
tree | d2b4af8b500c0f561fc9d77807f318959ef41b4b /src | |
parent | ce8c373576fe58fa5c71811fa376321e5379f71d (diff) |
GLAutoDrawable: setAnimator/getAnimator/invoke/display changes; NEWT: Adding native repaint; NewtCanvasAWT focus fix
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.
Diffstat (limited to 'src')
51 files changed, 1526 insertions, 706 deletions
diff --git a/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableHelper.java b/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableHelper.java index 8fefe149e..1e954af1d 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableHelper.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableHelper.java @@ -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) { diff --git a/src/jogl/classes/com/jogamp/opengl/impl/GLPbufferImpl.java b/src/jogl/classes/com/jogamp/opengl/impl/GLPbufferImpl.java index 071ac1378..c2efb3f4e 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/GLPbufferImpl.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/GLPbufferImpl.java @@ -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) { diff --git a/src/jogl/classes/com/jogamp/opengl/util/Animator.java b/src/jogl/classes/com/jogamp/opengl/util/Animator.java index 15b9d5eb9..66d3d5b88 100755 --- a/src/jogl/classes/com/jogamp/opengl/util/Animator.java +++ b/src/jogl/classes/com/jogamp/opengl/util/Animator.java @@ -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); + } } } diff --git a/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java b/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java index 7236aa533..1b5c56c95 100644 --- a/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java +++ b/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java @@ -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. diff --git a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java index 2dafd691a..f150b2507 100644 --- a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java +++ b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java @@ -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; } diff --git a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java index 73962e979..d0d97fe31 100644 --- a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java +++ b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java @@ -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; } diff --git a/src/junit/com/jogamp/test/junit/jogl/awt/TestAWT01GLn.java b/src/junit/com/jogamp/test/junit/jogl/awt/TestAWT01GLn.java index 1652acd82..f10218509 100755 --- a/src/junit/com/jogamp/test/junit/jogl/awt/TestAWT01GLn.java +++ b/src/junit/com/jogamp/test/junit/jogl/awt/TestAWT01GLn.java @@ -48,6 +48,10 @@ import org.junit.After; import org.junit.Test; public class TestAWT01GLn { + static { + GLProfile.initSingleton(); + } + Frame frame=null; GLCanvas glCanvas=null; diff --git a/src/junit/com/jogamp/test/junit/jogl/awt/TestSwingAWT01GLn.java b/src/junit/com/jogamp/test/junit/jogl/awt/TestSwingAWT01GLn.java index ed8a5dd0f..6144a6308 100755 --- a/src/junit/com/jogamp/test/junit/jogl/awt/TestSwingAWT01GLn.java +++ b/src/junit/com/jogamp/test/junit/jogl/awt/TestSwingAWT01GLn.java @@ -56,6 +56,10 @@ import static javax.swing.SwingUtilities.*; * @author Michael Bien */ public class TestSwingAWT01GLn { + static { + GLProfile.initSingleton(); + } + private Window[] windows; diff --git a/src/junit/com/jogamp/test/junit/jogl/demos/es1/RedSquare.java b/src/junit/com/jogamp/test/junit/jogl/demos/es1/RedSquare.java index 9b8982ed4..be416f01d 100755 --- a/src/junit/com/jogamp/test/junit/jogl/demos/es1/RedSquare.java +++ b/src/junit/com/jogamp/test/junit/jogl/demos/es1/RedSquare.java @@ -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) { - } - } diff --git a/src/junit/com/jogamp/test/junit/jogl/demos/gl2/gears/Gears.java b/src/junit/com/jogamp/test/junit/jogl/demos/gl2/gears/Gears.java index 1fa49be8c..ef5cf134a 100644 --- a/src/junit/com/jogamp/test/junit/jogl/demos/gl2/gears/Gears.java +++ b/src/junit/com/jogamp/test/junit/jogl/demos/gl2/gears/Gears.java @@ -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, diff --git a/src/junit/com/jogamp/test/junit/jogl/demos/gl2/gears/TestGearsAWT.java b/src/junit/com/jogamp/test/junit/jogl/demos/gl2/gears/TestGearsAWT.java index 2df3f0de9..b191dbbaf 100755 --- a/src/junit/com/jogamp/test/junit/jogl/demos/gl2/gears/TestGearsAWT.java +++ b/src/junit/com/jogamp/test/junit/jogl/demos/gl2/gears/TestGearsAWT.java @@ -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; diff --git a/src/junit/com/jogamp/test/junit/jogl/demos/gl2/gears/TestGearsNEWT.java b/src/junit/com/jogamp/test/junit/jogl/demos/gl2/gears/TestGearsNEWT.java index e50ffbde9..bafa8a1fb 100755 --- a/src/junit/com/jogamp/test/junit/jogl/demos/gl2/gears/TestGearsNEWT.java +++ b/src/junit/com/jogamp/test/junit/jogl/demos/gl2/gears/TestGearsNEWT.java @@ -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; diff --git a/src/junit/com/jogamp/test/junit/jogl/demos/gl2/gears/TestGearsNewtAWTWrapper.java b/src/junit/com/jogamp/test/junit/jogl/demos/gl2/gears/TestGearsNewtAWTWrapper.java index 51977d6d3..316c9edb4 100755 --- a/src/junit/com/jogamp/test/junit/jogl/demos/gl2/gears/TestGearsNewtAWTWrapper.java +++ b/src/junit/com/jogamp/test/junit/jogl/demos/gl2/gears/TestGearsNewtAWTWrapper.java @@ -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; diff --git a/src/junit/com/jogamp/test/junit/jogl/drawable/TestDrawable01NEWT.java b/src/junit/com/jogamp/test/junit/jogl/drawable/TestDrawable01NEWT.java index cd0c7c0e0..8a9c960c1 100755 --- a/src/junit/com/jogamp/test/junit/jogl/drawable/TestDrawable01NEWT.java +++ b/src/junit/com/jogamp/test/junit/jogl/drawable/TestDrawable01NEWT.java @@ -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; diff --git a/src/junit/com/jogamp/test/junit/jogl/offscreen/TestOffscreen01NEWT.java b/src/junit/com/jogamp/test/junit/jogl/offscreen/TestOffscreen01NEWT.java index bae727019..ad198fca8 100755 --- a/src/junit/com/jogamp/test/junit/jogl/offscreen/TestOffscreen01NEWT.java +++ b/src/junit/com/jogamp/test/junit/jogl/offscreen/TestOffscreen01NEWT.java @@ -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; diff --git a/src/junit/com/jogamp/test/junit/jogl/texture/TestTexture01AWT.java b/src/junit/com/jogamp/test/junit/jogl/texture/TestTexture01AWT.java index 7fdbd59c8..b34023bee 100755 --- a/src/junit/com/jogamp/test/junit/jogl/texture/TestTexture01AWT.java +++ b/src/junit/com/jogamp/test/junit/jogl/texture/TestTexture01AWT.java @@ -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; diff --git a/src/junit/com/jogamp/test/junit/newt/TestGLWindows01NEWT.java b/src/junit/com/jogamp/test/junit/newt/TestGLWindows01NEWT.java index 4fd7744db..3a36a1132 100755 --- a/src/junit/com/jogamp/test/junit/newt/TestGLWindows01NEWT.java +++ b/src/junit/com/jogamp/test/junit/newt/TestGLWindows01NEWT.java @@ -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 index 000000000..0677bc82c --- /dev/null +++ b/src/junit/com/jogamp/test/junit/newt/TestGLWindows02NEWTAnimated.java @@ -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" } ); + } + +} diff --git a/src/junit/com/jogamp/test/junit/newt/TestListenerCom01AWT.java b/src/junit/com/jogamp/test/junit/newt/TestListenerCom01AWT.java index 495b8bb3e..5a67bbc15 100755 --- a/src/junit/com/jogamp/test/junit/newt/TestListenerCom01AWT.java +++ b/src/junit/com/jogamp/test/junit/newt/TestListenerCom01AWT.java @@ -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(); diff --git a/src/junit/com/jogamp/test/junit/newt/TestWindows01NEWT.java b/src/junit/com/jogamp/test/junit/newt/TestWindows01NEWT.java index 58ea235df..89d9c1ca2 100755 --- a/src/junit/com/jogamp/test/junit/newt/TestWindows01NEWT.java +++ b/src/junit/com/jogamp/test/junit/newt/TestWindows01NEWT.java @@ -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); diff --git a/src/junit/com/jogamp/test/junit/newt/GLRunnableDummy.java b/src/junit/com/jogamp/test/junit/newt/parenting/GLRunnableDummy.java index 990a0c37d..53dd960f8 100644 --- a/src/junit/com/jogamp/test/junit/newt/GLRunnableDummy.java +++ b/src/junit/com/jogamp/test/junit/newt/parenting/GLRunnableDummy.java @@ -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; diff --git a/src/junit/com/jogamp/test/junit/newt/KeyAction.java b/src/junit/com/jogamp/test/junit/newt/parenting/KeyAction.java index 3ca12a840..c9e1db074 100644 --- a/src/junit/com/jogamp/test/junit/newt/KeyAction.java +++ b/src/junit/com/jogamp/test/junit/newt/parenting/KeyAction.java @@ -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.*; diff --git a/src/junit/com/jogamp/test/junit/newt/TestParenting01NEWT.java b/src/junit/com/jogamp/test/junit/newt/parenting/TestParenting01NEWT.java index b1d57e793..421f74aa4 100755 --- a/src/junit/com/jogamp/test/junit/newt/TestParenting01NEWT.java +++ b/src/junit/com/jogamp/test/junit/newt/parenting/TestParenting01NEWT.java @@ -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; diff --git a/src/junit/com/jogamp/test/junit/newt/TestParenting01aAWT.java b/src/junit/com/jogamp/test/junit/newt/parenting/TestParenting01aAWT.java index d88e7157a..28b95884d 100755 --- a/src/junit/com/jogamp/test/junit/newt/TestParenting01aAWT.java +++ b/src/junit/com/jogamp/test/junit/newt/parenting/TestParenting01aAWT.java @@ -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); diff --git a/src/junit/com/jogamp/test/junit/newt/TestParenting01bAWT.java b/src/junit/com/jogamp/test/junit/newt/parenting/TestParenting01bAWT.java index 227744296..f95ad1c14 100755 --- a/src/junit/com/jogamp/test/junit/newt/TestParenting01bAWT.java +++ b/src/junit/com/jogamp/test/junit/newt/parenting/TestParenting01bAWT.java @@ -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; diff --git a/src/junit/com/jogamp/test/junit/newt/TestParenting01cAWT.java b/src/junit/com/jogamp/test/junit/newt/parenting/TestParenting01cAWT.java index 7559390fa..0233a6aad 100755 --- a/src/junit/com/jogamp/test/junit/newt/TestParenting01cAWT.java +++ b/src/junit/com/jogamp/test/junit/newt/parenting/TestParenting01cAWT.java @@ -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); diff --git a/src/junit/com/jogamp/test/junit/newt/TestParenting01cSwingAWT.java b/src/junit/com/jogamp/test/junit/newt/parenting/TestParenting01cSwingAWT.java index a3a06aea3..07e60ed1c 100755 --- a/src/junit/com/jogamp/test/junit/newt/TestParenting01cSwingAWT.java +++ b/src/junit/com/jogamp/test/junit/newt/parenting/TestParenting01cSwingAWT.java @@ -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()); diff --git a/src/junit/com/jogamp/test/junit/newt/TestParenting02AWT.java b/src/junit/com/jogamp/test/junit/newt/parenting/TestParenting02AWT.java index 8d9a0f380..08a3dc425 100755 --- a/src/junit/com/jogamp/test/junit/newt/TestParenting02AWT.java +++ b/src/junit/com/jogamp/test/junit/newt/parenting/TestParenting02AWT.java @@ -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; diff --git a/src/junit/com/jogamp/test/junit/newt/TestParenting02NEWT.java b/src/junit/com/jogamp/test/junit/newt/parenting/TestParenting02NEWT.java index 5be04fcc2..0f25d2275 100755 --- a/src/junit/com/jogamp/test/junit/newt/TestParenting02NEWT.java +++ b/src/junit/com/jogamp/test/junit/newt/parenting/TestParenting02NEWT.java @@ -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; diff --git a/src/junit/com/jogamp/test/junit/newt/WindowAction.java b/src/junit/com/jogamp/test/junit/newt/parenting/WindowAction.java index c52b895e6..387a06006 100644 --- a/src/junit/com/jogamp/test/junit/newt/WindowAction.java +++ b/src/junit/com/jogamp/test/junit/newt/parenting/WindowAction.java @@ -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.*; diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/impl/RecursiveToolkitLock.java b/src/nativewindow/classes/com/jogamp/nativewindow/impl/RecursiveToolkitLock.java index 236ef0754..a3782d1e6 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/impl/RecursiveToolkitLock.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/impl/RecursiveToolkitLock.java @@ -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() { diff --git a/src/newt/classes/com/jogamp/newt/Display.java b/src/newt/classes/com/jogamp/newt/Display.java index 02c4733e7..deb4c7abe 100755 --- a/src/newt/classes/com/jogamp/newt/Display.java +++ b/src/newt/classes/com/jogamp/newt/Display.java @@ -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(); } diff --git a/src/newt/classes/com/jogamp/newt/Window.java b/src/newt/classes/com/jogamp/newt/Window.java index 9bd4bb377..0cd5b31bc 100755 --- a/src/newt/classes/com/jogamp/newt/Window.java +++ b/src/newt/classes/com/jogamp/newt/Window.java @@ -34,11 +34,12 @@ 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 .. // diff --git a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java index 8944c03bb..b2dd719bc 100644 --- a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java +++ b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java @@ -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 diff --git a/src/newt/classes/com/jogamp/newt/event/NEWTEvent.java b/src/newt/classes/com/jogamp/newt/event/NEWTEvent.java index 476b3640e..9afcb840c 100644 --- a/src/newt/classes/com/jogamp/newt/event/NEWTEvent.java +++ b/src/newt/classes/com/jogamp/newt/event/NEWTEvent.java @@ -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 index 000000000..e37c820a1 --- /dev/null +++ b/src/newt/classes/com/jogamp/newt/event/NEWTEventConsumer.java @@ -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); +} diff --git a/src/newt/classes/com/jogamp/newt/event/TraceWindowAdapter.java b/src/newt/classes/com/jogamp/newt/event/TraceWindowAdapter.java index a6cf0d6ed..fb9e1877a 100644 --- a/src/newt/classes/com/jogamp/newt/event/TraceWindowAdapter.java +++ b/src/newt/classes/com/jogamp/newt/event/TraceWindowAdapter.java @@ -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); } } diff --git a/src/newt/classes/com/jogamp/newt/event/WindowAdapter.java b/src/newt/classes/com/jogamp/newt/event/WindowAdapter.java index 925bc7113..587622a81 100644 --- a/src/newt/classes/com/jogamp/newt/event/WindowAdapter.java +++ b/src/newt/classes/com/jogamp/newt/event/WindowAdapter.java @@ -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 index 000000000..5a11f0f77 --- /dev/null +++ b/src/newt/classes/com/jogamp/newt/event/WindowUpdateEvent.java @@ -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+"]"; + } +} diff --git a/src/newt/classes/com/jogamp/newt/event/awt/AWTNewtEventFactory.java b/src/newt/classes/com/jogamp/newt/event/awt/AWTNewtEventFactory.java index e4e97946a..076165c73 100644 --- a/src/newt/classes/com/jogamp/newt/event/awt/AWTNewtEventFactory.java +++ b/src/newt/classes/com/jogamp/newt/event/awt/AWTNewtEventFactory.java @@ -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) { diff --git a/src/newt/classes/com/jogamp/newt/event/awt/AWTParentWindowAdapter.java b/src/newt/classes/com/jogamp/newt/event/awt/AWTParentWindowAdapter.java index 7905a728c..43087289a 100644 --- a/src/newt/classes/com/jogamp/newt/event/awt/AWTParentWindowAdapter.java +++ b/src/newt/classes/com/jogamp/newt/event/awt/AWTParentWindowAdapter.java @@ -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. diff --git a/src/newt/classes/com/jogamp/newt/event/awt/AWTWindowAdapter.java b/src/newt/classes/com/jogamp/newt/event/awt/AWTWindowAdapter.java index 7bfffbafc..875401544 100644 --- a/src/newt/classes/com/jogamp/newt/event/awt/AWTWindowAdapter.java +++ b/src/newt/classes/com/jogamp/newt/event/awt/AWTWindowAdapter.java @@ -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) { diff --git a/src/newt/classes/com/jogamp/newt/impl/awt/AWTWindow.java b/src/newt/classes/com/jogamp/newt/impl/awt/AWTWindow.java index a06b7160c..6f936d2c6 100644 --- a/src/newt/classes/com/jogamp/newt/impl/awt/AWTWindow.java +++ b/src/newt/classes/com/jogamp/newt/impl/awt/AWTWindow.java @@ -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() ) { diff --git a/src/newt/classes/com/jogamp/newt/impl/macosx/MacWindow.java b/src/newt/classes/com/jogamp/newt/impl/macosx/MacWindow.java index 8a656a5a8..9f47aa49f 100755 --- a/src/newt/classes/com/jogamp/newt/impl/macosx/MacWindow.java +++ b/src/newt/classes/com/jogamp/newt/impl/macosx/MacWindow.java @@ -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(); diff --git a/src/newt/classes/com/jogamp/newt/impl/opengl/kd/KDWindow.java b/src/newt/classes/com/jogamp/newt/impl/opengl/kd/KDWindow.java index 0d12a4a0a..0c7254376 100755 --- a/src/newt/classes/com/jogamp/newt/impl/opengl/kd/KDWindow.java +++ b/src/newt/classes/com/jogamp/newt/impl/opengl/kd/KDWindow.java @@ -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; diff --git a/src/newt/classes/com/jogamp/newt/impl/windows/WindowsWindow.java b/src/newt/classes/com/jogamp/newt/impl/windows/WindowsWindow.java index aedb4ed7d..47f79f46a 100755 --- a/src/newt/classes/com/jogamp/newt/impl/windows/WindowsWindow.java +++ b/src/newt/classes/com/jogamp/newt/impl/windows/WindowsWindow.java @@ -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); - } - } } diff --git a/src/newt/classes/com/jogamp/newt/impl/x11/X11Window.java b/src/newt/classes/com/jogamp/newt/impl/x11/X11Window.java index e7fc96019..6890b29fa 100755 --- a/src/newt/classes/com/jogamp/newt/impl/x11/X11Window.java +++ b/src/newt/classes/com/jogamp/newt/impl/x11/X11Window.java @@ -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; } diff --git a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java index e36e516df..e66ed1e34 100644 --- a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java +++ b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java @@ -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; diff --git a/src/newt/classes/com/jogamp/newt/Insets.java b/src/newt/classes/com/jogamp/newt/util/Insets.java index e440892f0..068cc1dfb 100644 --- a/src/newt/classes/com/jogamp/newt/Insets.java +++ b/src/newt/classes/com/jogamp/newt/util/Insets.java @@ -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. diff --git a/src/newt/native/WindowsWindow.c b/src/newt/native/WindowsWindow.c index 5e3311d3b..a1dab2678 100755 --- a/src/newt/native/WindowsWindow.c +++ b/src/newt/native/WindowsWindow.c @@ -109,15 +109,16 @@ #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; } diff --git a/src/newt/native/X11Window.c b/src/newt/native/X11Window.c index a521d2dbd..dbf833633 100755 --- a/src/newt/native/X11Window.c +++ b/src/newt/native/X11Window.c @@ -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 ) ; } /* |