diff options
26 files changed, 1517 insertions, 123 deletions
diff --git a/make/build-newt.xml b/make/build-newt.xml index 2cb848588..27e770611 100644 --- a/make/build-newt.xml +++ b/make/build-newt.xml @@ -87,7 +87,7 @@ <!-- partitioning --> <property name="java.part.core" - value="com/jogamp/newt/*, com/jogamp/newt/event/*, com/jogamp/newt/util/*, com/jogamp/newt/impl/*"/> + value="com/jogamp/newt/*, com/jogamp/newt/event/*, com/jogamp/newt/util/*, com/jogamp/newt/impl/*, com/jogamp/newt/impl/event/*"/> <property name="java.part.awt" value="com/jogamp/newt/impl/awt/*, com/jogamp/newt/awt/*, com/jogamp/newt/event/awt/*"/> diff --git a/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableHelper.java b/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableHelper.java index 8cc12ca89..8fefe149e 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableHelper.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableHelper.java @@ -51,6 +51,7 @@ public class GLDrawableHelper { private static final boolean VERBOSE = Debug.verbose(); private static final boolean NVIDIA_CRASH_WORKAROUND = Debug.isPropertyDefined("jogl.nvidia.crash.workaround", true); private boolean autoSwapBufferMode = true; + private ArrayList glRunnables = new ArrayList(); // one shot GL tasks public GLDrawableHelper() { } @@ -66,8 +67,15 @@ public class GLDrawableHelper { } public synchronized void addGLEventListener(GLEventListener listener) { + addGLEventListener(-1, listener); + } + + public synchronized void addGLEventListener(int index, GLEventListener listener) { + if(0>index) { + index = listeners.size(); + } List newListeners = (List) ((ArrayList) listeners).clone(); - newListeners.add(listener); + newListeners.add(index, listener); listeners = newListeners; } @@ -93,6 +101,7 @@ public class GLDrawableHelper { for (Iterator iter = listeners.iterator(); iter.hasNext(); ) { ((GLEventListener) iter.next()).display(drawable); } + execGLRunnables(drawable); } public void reshape(GLAutoDrawable drawable, @@ -102,6 +111,55 @@ public class GLDrawableHelper { } } + private void execGLRunnables(GLAutoDrawable drawable) { + if(glRunnables.size()>0) { + ArrayList _glRunnables = null; + synchronized(glRunnables) { + if(glRunnables.size()>0) { + _glRunnables = glRunnables; + glRunnables = new ArrayList(); + } + } + if(null!=_glRunnables) { + for (Iterator iter = _glRunnables.iterator(); iter.hasNext(); ) { + ((GLRunnable) iter.next()).run(drawable); + } + } + } + } + + private void invokeLater(GLRunnable glRunnable) { + synchronized(glRunnables) { + glRunnables.add(glRunnable); + glRunnables.notifyAll(); + } + } + + public void invoke(boolean wait, GLRunnable glRunnable) { + if(glRunnable == null) { + return; + } + Object lock = new Object(); + GLRunnableTask rTask = new GLRunnableTask(glRunnable, wait?lock:null/*, true*/); + Throwable throwable = null; + synchronized(lock) { + invokeLater(rTask); + if( wait ) { + try { + lock.wait(); + } catch (InterruptedException ie) { + throwable = ie; + } + } + } + if(null==throwable) { + throwable = rTask.getThrowable(); + } + if(null!=throwable) { + throw new RuntimeException(throwable); + } + } + public void setAutoSwapBufferMode(boolean onOrOff) { autoSwapBufferMode = onOrOff; } diff --git a/src/jogl/classes/com/jogamp/opengl/impl/GLPbufferImpl.java b/src/jogl/classes/com/jogamp/opengl/impl/GLPbufferImpl.java index eb5e09d2f..071ac1378 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/GLPbufferImpl.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/GLPbufferImpl.java @@ -130,10 +130,18 @@ public class GLPbufferImpl implements GLPbuffer { drawableHelper.addGLEventListener(listener); } + public void addGLEventListener(int index, GLEventListener listener) { + drawableHelper.addGLEventListener(index, listener); + } + public void removeGLEventListener(GLEventListener listener) { drawableHelper.removeGLEventListener(listener); } + public void invoke(boolean wait, GLRunnable glRunnable) { + drawableHelper.invoke(wait, glRunnable); + } + public void setContext(GLContext ctx) { context=(GLContextImpl)ctx; } diff --git a/src/jogl/classes/com/jogamp/opengl/impl/GLRunnableTask.java b/src/jogl/classes/com/jogamp/opengl/impl/GLRunnableTask.java new file mode 100644 index 000000000..a6a030c6b --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/GLRunnableTask.java @@ -0,0 +1,62 @@ +/* + * 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: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Sven Gothel nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL Sven Gothel BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.jogamp.opengl.impl; + +import javax.media.opengl.GLRunnable; +import javax.media.opengl.GLAutoDrawable; + +/** + * Helper class to provide a Runnable queue implementation with a Runnable wrapper + * which notifies after execution for the <code>invokeAndWait()</code> semantics. + */ +public class GLRunnableTask implements GLRunnable { + GLRunnable runnable; + Object notifyObject; + + Throwable runnableException; + + public GLRunnableTask(GLRunnable runnable, Object notifyObject) { + this.runnable = runnable ; + this.notifyObject = notifyObject ; + } + + public void run(GLAutoDrawable drawable) { + try { + runnable.run(drawable); + } catch (Throwable t) { + runnableException = t; + } + if(null != notifyObject) { + synchronized (notifyObject) { + notifyObject.notifyAll(); + } + } + } + + public Throwable getThrowable() { return runnableException; } +} + diff --git a/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java b/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java index 7342369d9..7236aa533 100644 --- a/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java +++ b/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java @@ -138,11 +138,22 @@ public interface GLAutoDrawable extends GLDrawable { */ public void setContext(GLContext context); - /** Adds a {@link GLEventListener} to this drawable. If multiple - listeners are added to a given drawable, they are notified of - events in an arbitrary order. */ + /** Adds a {@link GLEventListener} to the end of this drawable queue. + The listeners are notified of events in the order of the queue. */ public void addGLEventListener(GLEventListener listener); + /** + * Adds a {@link GLEventListener} at the given index of this drawable queue. + * The listeners are notified of events in the order of the queue. + * @param index Position where the listener will be inserted. + * Should be within (0 <= index && index <= size()). + * An index value of -1 is interpreted as the end of the list, size(). + * @param listener The GLEventListener object to be inserted + * @throws IndexOutOfBoundsException If the index is not within (0 <= index && index <= size()), or -1 + */ + public void addGLEventListener(int index, GLEventListener listener) + throws IndexOutOfBoundsException; + /** Removes a {@link GLEventListener} from this drawable. Note that if this is done from within a particular drawable's {@link GLEventListener} handler (reshape, display, etc.) that it is not @@ -150,6 +161,19 @@ public interface GLAutoDrawable extends GLDrawable { during this update cycle. */ public void removeGLEventListener(GLEventListener listener); + /** + * 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> + * @see #display() + * @see javax.media.opengl.GLRunnable + */ + public void invoke(boolean wait, GLRunnable glRunnable); + /** FIXME: Returns the current state, {@link #STATE_INVALID}, {@link #STATE_VALID} or {@link #STATE_DESTROYING}. Tool to determine, e.g. if a {@link GLEventListener#dispose dispose(..)} @@ -166,19 +190,28 @@ public interface GLAutoDrawable extends GLDrawable { routine may be called manually. */ public void destroy(); - /** Causes OpenGL rendering to be performed for this GLAutoDrawable - by calling {@link GLEventListener#display display(..)} for all - registered {@link GLEventListener}s. Called automatically by the - window system toolkit upon receiving a repaint() request. this - routine may be called manually for better control over the + /** <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> + 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.*/ + in case this has not been done yet.</p> */ public void display(); /** Enables or disables automatic buffer swapping for this drawable. @@ -211,4 +244,5 @@ public interface GLAutoDrawable extends GLDrawable { demos for examples. @return the set GL pipeline or null if not successful */ public GL setGL(GL gl); + } diff --git a/src/jogl/classes/javax/media/opengl/GLRunnable.java b/src/jogl/classes/javax/media/opengl/GLRunnable.java new file mode 100644 index 000000000..8d619273f --- /dev/null +++ b/src/jogl/classes/javax/media/opengl/GLRunnable.java @@ -0,0 +1,41 @@ +/* + * 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: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Sven Gothel nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL Sven Gothel BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package javax.media.opengl; + +/** <p> Declares one-shot OpenGL commands, which client code can use to manage OpenGL + commands into a {@link GLAutoDrawable}. At the time any of these + methods is called, the drawable has made its associated OpenGL + context current, so it is valid to make OpenGL calls.<br></p> + <p> A GLRunnable maybe used to inject OpenGL commands via I/O event listener, + via {@link GLAutoDrawable#invoke(boolean, GLRunnable)}.</p> + */ +public interface GLRunnable { + /** Called by the drawable to initiate one-shot OpenGL commands by the + client, like {@link GLEventListener#display(GLAutoDrawable)}. */ + public void run(GLAutoDrawable drawable); +} + diff --git a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java index 77b8e45d3..2dafd691a 100644 --- a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java +++ b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java @@ -484,10 +484,18 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable { drawableHelper.addGLEventListener(listener); } + public void addGLEventListener(int index, GLEventListener listener) { + drawableHelper.addGLEventListener(index, listener); + } + public void removeGLEventListener(GLEventListener listener) { drawableHelper.removeGLEventListener(listener); } + public void invoke(boolean wait, GLRunnable glRunnable) { + drawableHelper.invoke(wait, glRunnable); + } + public void setContext(GLContext ctx) { context=(GLContextImpl)ctx; } diff --git a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java index 955949415..73962e979 100644 --- a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java +++ b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java @@ -372,10 +372,18 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable { drawableHelper.addGLEventListener(listener); } + public void addGLEventListener(int index, GLEventListener listener) { + drawableHelper.addGLEventListener(index, listener); + } + public void removeGLEventListener(GLEventListener listener) { drawableHelper.removeGLEventListener(listener); } + public void invoke(boolean wait, GLRunnable glRunnable) { + drawableHelper.invoke(wait, glRunnable); + } + public GLContext createContext(GLContext shareWith) { return backend.createContext(shareWith); } diff --git a/src/junit/com/jogamp/test/junit/newt/GLRunnableDummy.java b/src/junit/com/jogamp/test/junit/newt/GLRunnableDummy.java new file mode 100644 index 000000000..990a0c37d --- /dev/null +++ b/src/junit/com/jogamp/test/junit/newt/GLRunnableDummy.java @@ -0,0 +1,63 @@ +/* + * 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 org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.AfterClass; +import org.junit.Test; + +import javax.media.opengl.*; + +public class GLRunnableDummy implements GLRunnable { + float r=0.0f; + float g=0.0f; + float b=0.0f; + float d=0.001f; + + public void run(GLAutoDrawable drawable) { + // nop .. + GL2ES1 gl = drawable.getGL().getGL2ES1(); + gl.glClearColor(r, g, b, 1f); + r+=d; + if(r>1f) { + r=1f; + d*=-1f; + } else if(r<0f) { + r=0f; + d*=-1f; + } + } + +} diff --git a/src/junit/com/jogamp/test/junit/newt/TestListenerCom01AWT.java b/src/junit/com/jogamp/test/junit/newt/TestListenerCom01AWT.java new file mode 100755 index 000000000..495b8bb3e --- /dev/null +++ b/src/junit/com/jogamp/test/junit/newt/TestListenerCom01AWT.java @@ -0,0 +1,173 @@ +/* + * 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 java.awt.Button; +import java.awt.BorderLayout; +import java.awt.Canvas; +import java.awt.Frame; + +import javax.media.opengl.*; +import javax.media.nativewindow.*; + +import com.jogamp.opengl.util.Animator; +import com.jogamp.newt.*; +import com.jogamp.newt.event.*; +import com.jogamp.newt.opengl.*; +import com.jogamp.newt.awt.NewtCanvasAWT; + +import java.io.IOException; + +import com.jogamp.test.junit.util.*; +import com.jogamp.test.junit.jogl.demos.es1.RedSquare; +import com.jogamp.test.junit.jogl.demos.gl2.gears.Gears; + +public class TestListenerCom01AWT { + static int width, height; + static long durationPerTest = 500; + static long waitReparent = 300; + static boolean verbose = false; + + @BeforeClass + public static void initClass() { + width = 640; + height = 480; + } + + @Test + public void testListenerStringPassingAndOrder() throws InterruptedException { + // setup NEWT GLWindow .. + GLWindow glWindow = GLWindow.create(new GLCapabilities(null)); + Assert.assertNotNull(glWindow); + glWindow.setTitle("NEWT - CHILD"); + + System.out.println("durationPerTest "+durationPerTest); + + GLEventListener demo = new Gears(); + setDemoFields(demo, glWindow, false); + glWindow.addGLEventListener(demo); + + WindowEventCom1 wl1 = new WindowEventCom1(); + WindowEventCom2 wl2 = new WindowEventCom2(); + WindowEventCom3 wl3 = new WindowEventCom3(); + + // TraceWindowAdapter wlT = new TraceWindowAdapter(); + // glWindow.addWindowListener(0, wlT); + // Assert.assertEquals(wlT, glWindow.getWindowListener(0)); + + glWindow.addWindowListener(0, wl3); + glWindow.addWindowListener(0, wl2); + glWindow.addWindowListener(0, wl1); + + Assert.assertEquals(wl1, glWindow.getWindowListener(0)); + Assert.assertEquals(wl2, glWindow.getWindowListener(1)); + Assert.assertEquals(wl3, glWindow.getWindowListener(2)); + + // attach NEWT GLWindow to AWT Canvas + NewtCanvasAWT newtCanvasAWT = new NewtCanvasAWT(glWindow); + Frame frame = new Frame("AWT Parent Frame"); + frame.add(newtCanvasAWT); + frame.setSize(width, height); + frame.setVisible(true); + + Animator animator1 = new Animator(glWindow); + animator1.start(); + while(animator1.isAnimating() && animator1.getDuration()<durationPerTest) { + Thread.sleep(100); + width+=10; height+=10; + frame.setSize(width, height); + } + animator1.stop(); + Assert.assertEquals(false, animator1.isAnimating()); + + frame.dispose(); + glWindow.destroy(true); + } + + public static void setDemoFields(GLEventListener demo, GLWindow glWindow, boolean debug) { + Assert.assertNotNull(demo); + Assert.assertNotNull(glWindow); + Window window = glWindow.getInnerWindow(); + if(debug) { + MiscUtils.setFieldIfExists(demo, "glDebug", true); + MiscUtils.setFieldIfExists(demo, "glTrace", true); + } + if(!MiscUtils.setFieldIfExists(demo, "window", window)) { + 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 { + verbose = true; + 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(); + 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/TestParenting01NEWT.java b/src/junit/com/jogamp/test/junit/newt/TestParenting01NEWT.java index f87ce1111..b1d57e793 100755 --- a/src/junit/com/jogamp/test/junit/newt/TestParenting01NEWT.java +++ b/src/junit/com/jogamp/test/junit/newt/TestParenting01NEWT.java @@ -283,7 +283,7 @@ public class TestParenting01NEWT { static int atoi(String a) { int i=0; try { - durationPerTest = Integer.parseInt(a); + i = Integer.parseInt(a); } catch (Exception ex) { ex.printStackTrace(); } return i; } diff --git a/src/junit/com/jogamp/test/junit/newt/TestParenting01AWT.java b/src/junit/com/jogamp/test/junit/newt/TestParenting01aAWT.java index 2c695f788..d88e7157a 100755 --- a/src/junit/com/jogamp/test/junit/newt/TestParenting01AWT.java +++ b/src/junit/com/jogamp/test/junit/newt/TestParenting01aAWT.java @@ -65,7 +65,7 @@ import com.jogamp.test.junit.util.*; import com.jogamp.test.junit.jogl.demos.es1.RedSquare; import com.jogamp.test.junit.jogl.demos.gl2.gears.Gears; -public class TestParenting01AWT { +public class TestParenting01aAWT { static int width, height; static long durationPerTest = 800; static long waitReparent = 0; @@ -94,7 +94,6 @@ public class TestParenting01AWT { GLEventListener demo1 = new RedSquare(); setDemoFields(demo1, glWindow1, false); glWindow1.addGLEventListener(demo1); - // glWindow1.setSize(600, 300); NewtCanvasAWT newtCanvasAWT = new NewtCanvasAWT(glWindow1); Assert.assertNotNull(newtCanvasAWT); @@ -106,7 +105,6 @@ public class TestParenting01AWT { Assert.assertNotNull(frame); frame.add(newtCanvasAWT); frame.setSize(width, height); - // frame.pack(); // visible test frame.setVisible(true); @@ -152,7 +150,6 @@ public class TestParenting01AWT { GLEventListener demo1 = new RedSquare(); setDemoFields(demo1, glWindow1, false); glWindow1.addGLEventListener(demo1); - // glWindow1.setSize(600, 300); NewtCanvasAWT newtCanvasAWT = new NewtCanvasAWT(glWindow1); Assert.assertNotNull(newtCanvasAWT); @@ -169,7 +166,6 @@ public class TestParenting01AWT { frame.add(newtCanvasAWT); Assert.assertEquals(newtCanvasAWT.getNativeWindow(),glWindow1.getParentNativeWindow()); - // frame.pack(); Animator animator1 = new Animator(glWindow1); animator1.start(); @@ -194,7 +190,6 @@ public class TestParenting01AWT { GLEventListener demo1 = new RedSquare(); setDemoFields(demo1, glWindow1, false); glWindow1.addGLEventListener(demo1); - // glWindow1.setSize(600, 300); NewtCanvasAWT newtCanvasAWT = new NewtCanvasAWT(glWindow1); @@ -206,7 +201,6 @@ public class TestParenting01AWT { frame.setVisible(true); frame.add(newtCanvasAWT); - // frame.pack(); Animator animator1 = new Animator(glWindow1); animator1.start(); @@ -231,7 +225,6 @@ public class TestParenting01AWT { GLEventListener demo1 = new RedSquare(); setDemoFields(demo1, glWindow1, false); glWindow1.addGLEventListener(demo1); - // glWindow1.setSize(600, 300); NewtCanvasAWT newtCanvasAWT = new NewtCanvasAWT(glWindow1); @@ -242,7 +235,6 @@ public class TestParenting01AWT { frame.add(newtCanvasAWT); Assert.assertEquals(newtCanvasAWT.getNativeWindow(),glWindow1.getParentNativeWindow()); - // frame.pack(); Animator animator1 = new Animator(glWindow1); animator1.start(); @@ -283,7 +275,6 @@ public class TestParenting01AWT { GLEventListener demo1 = new RedSquare(); setDemoFields(demo1, glWindow1, false); glWindow1.addGLEventListener(demo1); - // glWindow1.setSize(600, 300); NewtCanvasAWT newtCanvasAWT = new NewtCanvasAWT(glWindow1); @@ -299,7 +290,6 @@ public class TestParenting01AWT { frame.add(newtCanvasAWT, BorderLayout.CENTER); Assert.assertEquals(newtCanvasAWT.getNativeWindow(),glWindow1.getParentNativeWindow()); - // frame.pack(); Animator animator1 = new Animator(glWindow1); animator1.start(); @@ -340,7 +330,6 @@ public class TestParenting01AWT { GLEventListener demo1 = new RedSquare(); setDemoFields(demo1, glWindow1, false); glWindow1.addGLEventListener(demo1); - // glWindow1.setSize(600, 300); NewtCanvasAWT newtCanvasAWT = new NewtCanvasAWT(glWindow1); @@ -366,7 +355,6 @@ public class TestParenting01AWT { frame1.add(newtCanvasAWT, BorderLayout.CENTER); Assert.assertEquals(newtCanvasAWT.getNativeWindow(),glWindow1.getParentNativeWindow()); - // frame1.pack(); Animator animator1 = new Animator(glWindow1); animator1.start(); @@ -378,12 +366,10 @@ public class TestParenting01AWT { case 0: frame1.remove(newtCanvasAWT); frame2.add(newtCanvasAWT, BorderLayout.CENTER); - //frame2.pack(); break; case 1: frame2.remove(newtCanvasAWT); frame1.add(newtCanvasAWT, BorderLayout.CENTER); - //frame1.pack(); break; } state++; @@ -413,7 +399,7 @@ public class TestParenting01AWT { static int atoi(String a) { int i=0; try { - durationPerTest = Integer.parseInt(a); + i = Integer.parseInt(a); } catch (Exception ex) { ex.printStackTrace(); } return i; } @@ -426,7 +412,7 @@ public class TestParenting01AWT { waitReparent = atoi(args[++i]); } } - String tstname = TestParenting01AWT.class.getName(); + String tstname = TestParenting01aAWT.class.getName(); org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(new String[] { tstname, "filtertrace=true", diff --git a/src/junit/com/jogamp/test/junit/newt/TestParentingAWT.java b/src/junit/com/jogamp/test/junit/newt/TestParenting01bAWT.java index c42599810..227744296 100755 --- a/src/junit/com/jogamp/test/junit/newt/TestParentingAWT.java +++ b/src/junit/com/jogamp/test/junit/newt/TestParenting01bAWT.java @@ -65,7 +65,7 @@ import com.jogamp.test.junit.util.*; import com.jogamp.test.junit.jogl.demos.es1.RedSquare; import com.jogamp.test.junit.jogl.demos.gl2.gears.Gears; -public class TestParentingAWT { +public class TestParenting01bAWT { static int width, height; static long durationPerTest = 800; static long waitReparent = 0; @@ -158,7 +158,7 @@ public class TestParentingAWT { static int atoi(String a) { int i=0; try { - durationPerTest = Integer.parseInt(a); + i = Integer.parseInt(a); } catch (Exception ex) { ex.printStackTrace(); } return i; } @@ -171,7 +171,7 @@ public class TestParentingAWT { waitReparent = atoi(args[++i]); } } - String tstname = TestParentingAWT.class.getName(); + String tstname = TestParenting01bAWT.class.getName(); org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(new String[] { tstname, "filtertrace=true", diff --git a/src/junit/com/jogamp/test/junit/newt/TestParenting01cAWT.java b/src/junit/com/jogamp/test/junit/newt/TestParenting01cAWT.java new file mode 100755 index 000000000..7559390fa --- /dev/null +++ b/src/junit/com/jogamp/test/junit/newt/TestParenting01cAWT.java @@ -0,0 +1,195 @@ +/* + * 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 java.awt.Button; +import java.awt.BorderLayout; +import java.awt.Canvas; +import java.awt.Container; +import java.awt.Frame; +import java.awt.Dimension; + +import javax.media.opengl.*; +import javax.media.nativewindow.*; + +import com.jogamp.opengl.util.Animator; +import com.jogamp.newt.*; +import com.jogamp.newt.event.*; +import com.jogamp.newt.opengl.*; +import com.jogamp.newt.awt.NewtCanvasAWT; + +import java.io.IOException; + +import com.jogamp.test.junit.util.*; +import com.jogamp.test.junit.jogl.demos.es1.RedSquare; +import com.jogamp.test.junit.jogl.demos.gl2.gears.Gears; + +public class TestParenting01cAWT { + static int width, height; + static long durationPerTest = 800; + static long waitReparent = 0; + static GLCapabilities glCaps; + + @BeforeClass + public static void initClass() { + width = 640; + height = 480; + glCaps = new GLCapabilities(null); + } + + @Test + public void testWindowParenting01CreateVisibleDestroy1() throws InterruptedException { + int x = 0; + int y = 0; + + NEWTEventFiFo eventFifo = new NEWTEventFiFo(); + + GLWindow glWindow1 = GLWindow.create(glCaps); + Assert.assertNotNull(glWindow1); + Assert.assertEquals(false, glWindow1.isVisible()); + Assert.assertEquals(false, glWindow1.isNativeWindowValid()); + Assert.assertNull(glWindow1.getParentNativeWindow()); + glWindow1.setTitle("testWindowParenting01CreateVisibleDestroy"); + GLEventListener demo1 = new RedSquare(); + setDemoFields(demo1, glWindow1, false); + glWindow1.addGLEventListener(demo1); + + NewtCanvasAWT newtCanvasAWT = new NewtCanvasAWT(glWindow1); + Assert.assertNotNull(newtCanvasAWT); + Assert.assertEquals(false, glWindow1.isVisible()); + Assert.assertEquals(false, glWindow1.isNativeWindowValid()); + Assert.assertNull(glWindow1.getParentNativeWindow()); + + 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 + frame1.setVisible(true); + Assert.assertEquals(newtCanvasAWT.getNativeWindow(),glWindow1.getParentNativeWindow()); + + Animator animator1 = new Animator(glWindow1); + animator1.start(); + while(animator1.isAnimating() && animator1.getDuration()<durationPerTest) { + Thread.sleep(100); + } + animator1.stop(); + Assert.assertEquals(false, animator1.isAnimating()); + + frame1.setVisible(false); + Assert.assertEquals(false, glWindow1.isDestroyed()); + + frame1.setVisible(true); + Assert.assertEquals(false, glWindow1.isDestroyed()); + + frame1.remove(newtCanvasAWT); + // Assert.assertNull(glWindow1.getParentNativeWindow()); + Assert.assertEquals(false, glWindow1.isDestroyed()); + + frame1.dispose(); + Assert.assertEquals(false, glWindow1.isDestroyed()); + + glWindow1.destroy(true); + //Assert.assertEquals(true, glWindow1.isDestroyed()); + } + + public static void setDemoFields(GLEventListener demo, GLWindow glWindow, boolean debug) { + Assert.assertNotNull(demo); + Assert.assertNotNull(glWindow); + Window window = glWindow.getInnerWindow(); + if(debug) { + MiscUtils.setFieldIfExists(demo, "glDebug", true); + MiscUtils.setFieldIfExists(demo, "glTrace", true); + } + if(!MiscUtils.setFieldIfExists(demo, "window", window)) { + 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]); + } else if(args[i].equals("-wait")) { + waitReparent = atoi(args[++i]); + } + } + String tstname = TestParenting01cAWT.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/TestParenting01cSwingAWT.java b/src/junit/com/jogamp/test/junit/newt/TestParenting01cSwingAWT.java new file mode 100755 index 000000000..a3a06aea3 --- /dev/null +++ b/src/junit/com/jogamp/test/junit/newt/TestParenting01cSwingAWT.java @@ -0,0 +1,374 @@ +/* + * 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 java.awt.Button; +import java.awt.BorderLayout; +import java.awt.Canvas; +import java.awt.Container; +import java.awt.Frame; +import java.awt.Dimension; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; + +import javax.media.opengl.*; +import javax.media.nativewindow.*; + +import com.jogamp.opengl.util.Animator; +import com.jogamp.newt.*; +import com.jogamp.newt.event.*; +import com.jogamp.newt.opengl.*; +import com.jogamp.newt.awt.NewtCanvasAWT; + +import java.io.IOException; + +import com.jogamp.test.junit.util.*; +import com.jogamp.test.junit.jogl.demos.es1.RedSquare; +import com.jogamp.test.junit.jogl.demos.gl2.gears.Gears; + +public class TestParenting01cSwingAWT { + static int width, height; + static long durationPerTest = 800; + static long waitReparent = 0; + static GLCapabilities glCaps; + + @BeforeClass + public static void initClass() { + width = 640; + height = 480; + glCaps = new GLCapabilities(null); + } + + @Test + public void testWindowParenting01CreateVisibleDestroy1() throws InterruptedException, InvocationTargetException { + int x = 0; + int y = 0; + + NEWTEventFiFo eventFifo = new NEWTEventFiFo(); + + /** + * JFrame . JPanel . Container . NewtCanvasAWT . GLWindow + */ + GLWindow glWindow1 = GLWindow.create(glCaps); + Assert.assertNotNull(glWindow1); + Assert.assertEquals(false, glWindow1.isVisible()); + Assert.assertEquals(false, glWindow1.isNativeWindowValid()); + Assert.assertNull(glWindow1.getParentNativeWindow()); + glWindow1.setTitle("testWindowParenting01CreateVisibleDestroy"); + GLEventListener demo1 = new RedSquare(); + setDemoFields(demo1, glWindow1, false); + glWindow1.addGLEventListener(demo1); + Animator animator1 = new Animator(glWindow1); + animator1.start(); + final GLWindow _glWindow1 = glWindow1; + final GLRunnable _glRunnable = new GLRunnableDummy(); + Thread disturbanceThread = new Thread(new Runnable() { + public void run() { + System.out.println("$"); + while(true) + { + try { + _glWindow1.invoke(true, _glRunnable); + Thread.yield(); + } catch (Throwable t) {} + } + } + }); + disturbanceThread.start(); + + + NewtCanvasAWT newtCanvasAWT = new NewtCanvasAWT(glWindow1); + Assert.assertNotNull(newtCanvasAWT); + Assert.assertEquals(false, glWindow1.isVisible()); + Assert.assertEquals(false, glWindow1.isNativeWindowValid()); + Assert.assertNull(glWindow1.getParentNativeWindow()); + + 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); + + JPanel jPanel1 = new JPanel(); + jPanel1.setLayout(new BorderLayout()); + jPanel1.add(new Button("north"), BorderLayout.NORTH); + jPanel1.add(new Button("south"), BorderLayout.SOUTH); + jPanel1.add(new Button("east"), BorderLayout.EAST); + jPanel1.add(new Button("west"), BorderLayout.WEST); + jPanel1.add(container1, BorderLayout.CENTER); + + JFrame jFrame1 = new JFrame("Swing Parent JFrame"); + // jFrame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + jFrame1.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); // equivalent to Frame, use windowClosing event! + jFrame1.setContentPane(jPanel1); + jFrame1.setSize(width, height); + jFrame1.setVisible(true); // from here on, we need to run modifications on EDT + + final JFrame _jFrame1 = jFrame1; + final JPanel _jPanel1 = jPanel1; + final Container _container1 = container1; + + // visible test + Assert.assertEquals(newtCanvasAWT.getNativeWindow(),glWindow1.getParentNativeWindow()); + + while(animator1.isAnimating() && animator1.getDuration()<durationPerTest) { + Thread.sleep(100); + } + animator1.stop(); + Assert.assertEquals(false, animator1.isAnimating()); + + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + _jFrame1.setVisible(false); + } }); + Assert.assertEquals(false, glWindow1.isDestroyed()); + + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + _jFrame1.setVisible(true); + } }); + Assert.assertEquals(false, glWindow1.isDestroyed()); + + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + _jPanel1.remove(_container1); + } }); + // Assert.assertNull(glWindow1.getParentNativeWindow()); + Assert.assertEquals(false, glWindow1.isDestroyed()); + + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + _jFrame1.dispose(); + } }); + Assert.assertEquals(false, glWindow1.isDestroyed()); + + glWindow1.destroy(true); + //Assert.assertEquals(true, glWindow1.isDestroyed()); + } + + @Test + public void testWindowParenting05ReparentAWTWinHopFrame2Frame() throws InterruptedException, InvocationTargetException { + int x = 0; + int y = 0; + + NEWTEventFiFo eventFifo = new NEWTEventFiFo(); + + /** + * JFrame . JPanel . Container . NewtCanvasAWT . GLWindow + */ + GLWindow glWindow1 = GLWindow.create(glCaps); + Assert.assertNotNull(glWindow1); + Assert.assertEquals(false, glWindow1.isVisible()); + Assert.assertEquals(false, glWindow1.isNativeWindowValid()); + Assert.assertNull(glWindow1.getParentNativeWindow()); + glWindow1.setTitle("testWindowParenting01CreateVisibleDestroy"); + GLEventListener demo1 = new RedSquare(); + setDemoFields(demo1, glWindow1, false); + glWindow1.addGLEventListener(demo1); + Animator animator1 = new Animator(glWindow1); + animator1.start(); + final GLWindow _glWindow1 = glWindow1; + final GLRunnable _glRunnable = new GLRunnableDummy(); + Thread disturbanceThread = new Thread(new Runnable() { + public void run() { + System.out.println("$"); + while(true) + { + try { + _glWindow1.invoke(true, _glRunnable); + Thread.yield(); + } catch (Throwable t) {} + } + } + }); + disturbanceThread.start(); + + NewtCanvasAWT newtCanvasAWT = new NewtCanvasAWT(glWindow1); + Assert.assertNotNull(newtCanvasAWT); + Assert.assertEquals(false, glWindow1.isVisible()); + Assert.assertEquals(false, glWindow1.isNativeWindowValid()); + Assert.assertNull(glWindow1.getParentNativeWindow()); + + 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); + + JPanel jPanel1 = new JPanel(); + jPanel1.setLayout(new BorderLayout()); + jPanel1.add(new Button("north"), BorderLayout.NORTH); + jPanel1.add(new Button("south"), BorderLayout.SOUTH); + jPanel1.add(new Button("east"), BorderLayout.EAST); + jPanel1.add(new Button("west"), BorderLayout.WEST); + jPanel1.add(container1, BorderLayout.CENTER); + + JFrame jFrame1 = new JFrame("Swing Parent JFrame"); + // jFrame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + jFrame1.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); // equivalent to Frame, use windowClosing event! + jFrame1.setContentPane(jPanel1); + jFrame1.setLocation(0, 0); + jFrame1.setSize(width, height); + jFrame1.setVisible(true); // from here on, we need to run modifications on EDT + + JPanel jPanel2 = new JPanel(); + jPanel2.setLayout(new BorderLayout()); + jPanel2.add(new Button("north"), BorderLayout.NORTH); + jPanel2.add(new Button("south"), BorderLayout.SOUTH); + jPanel2.add(new Button("east"), BorderLayout.EAST); + jPanel2.add(new Button("west"), BorderLayout.WEST); + + JFrame jFrame2 = new JFrame("Swing Parent JFrame"); + // jFrame2.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + jFrame2.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); // equivalent to Frame, use windowClosing event! + jFrame2.setContentPane(jPanel2); + jFrame2.setLocation(640, 480); + jFrame2.setSize(width, height); + jFrame2.setVisible(true); // from here on, we need to run modifications on EDT + + final NewtCanvasAWT _newtCanvasAWT = newtCanvasAWT; + final JFrame _jFrame1 = jFrame1; + final JPanel _jPanel1 = jPanel1; + final Container _container1 = container1; + final JFrame _jFrame2 = jFrame2; + final JPanel _jPanel2 = jPanel2; + + // visible test + Assert.assertEquals(newtCanvasAWT.getNativeWindow(),glWindow1.getParentNativeWindow()); + + int state = 0; + while(animator1.isAnimating() && animator1.getDuration()<3*durationPerTest) { + Thread.sleep(durationPerTest); + switch(state) { + case 0: + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + _container1.remove(_newtCanvasAWT); + _jPanel2.add(_newtCanvasAWT, BorderLayout.CENTER); + } }); + break; + case 1: + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + _jPanel2.remove(_newtCanvasAWT); + _container1.add(_newtCanvasAWT, BorderLayout.CENTER); + } }); + break; + } + state++; + } + + animator1.stop(); + Assert.assertEquals(false, animator1.isAnimating()); + + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + _jFrame1.setVisible(false); + _jFrame2.setVisible(false); + } }); + Assert.assertEquals(false, glWindow1.isDestroyed()); + + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + _jFrame1.dispose(); + _jFrame2.dispose(); + } }); + Assert.assertEquals(false, glWindow1.isDestroyed()); + + glWindow1.destroy(true); + //Assert.assertEquals(true, glWindow1.isDestroyed()); + } + + public static void setDemoFields(GLEventListener demo, GLWindow glWindow, boolean debug) { + Assert.assertNotNull(demo); + Assert.assertNotNull(glWindow); + Window window = glWindow.getInnerWindow(); + if(debug) { + MiscUtils.setFieldIfExists(demo, "glDebug", true); + MiscUtils.setFieldIfExists(demo, "glTrace", true); + } + if(!MiscUtils.setFieldIfExists(demo, "window", window)) { + 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]); + } else if(args[i].equals("-wait")) { + waitReparent = atoi(args[++i]); + } + } + System.out.println("durationPerTest "+durationPerTest); + System.out.println("waitReparent "+waitReparent); + String tstname = TestParenting01cSwingAWT.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/TestParenting02AWT.java b/src/junit/com/jogamp/test/junit/newt/TestParenting02AWT.java index 753da1836..8d9a0f380 100755 --- a/src/junit/com/jogamp/test/junit/newt/TestParenting02AWT.java +++ b/src/junit/com/jogamp/test/junit/newt/TestParenting02AWT.java @@ -239,7 +239,7 @@ public class TestParenting02AWT { static int atoi(String a) { int i=0; try { - durationPerTest = Integer.parseInt(a); + i = Integer.parseInt(a); } catch (Exception ex) { ex.printStackTrace(); } return i; } diff --git a/src/junit/com/jogamp/test/junit/newt/TestParenting02NEWT.java b/src/junit/com/jogamp/test/junit/newt/TestParenting02NEWT.java index 0fa0bef0f..5be04fcc2 100755 --- a/src/junit/com/jogamp/test/junit/newt/TestParenting02NEWT.java +++ b/src/junit/com/jogamp/test/junit/newt/TestParenting02NEWT.java @@ -203,7 +203,7 @@ public class TestParenting02NEWT { static int atoi(String a) { int i=0; try { - durationPerTest = Integer.parseInt(a); + i = Integer.parseInt(a); } catch (Exception ex) { ex.printStackTrace(); } return i; } diff --git a/src/junit/com/jogamp/test/junit/newt/WindowEventCom1.java b/src/junit/com/jogamp/test/junit/newt/WindowEventCom1.java new file mode 100644 index 000000000..fa6ad0e92 --- /dev/null +++ b/src/junit/com/jogamp/test/junit/newt/WindowEventCom1.java @@ -0,0 +1,46 @@ +/* + * 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 com.jogamp.newt.event.*; + +class WindowEventCom1 extends WindowAdapter { + + public void windowResized(WindowEvent e) { + e.setAttachment(new String("WindowEventCom1.windowResized: "+e)); + } + public void windowMoved(WindowEvent e) { + e.setAttachment(new String("WindowEventCom1.windowMoved: "+e)); + } +} + diff --git a/src/junit/com/jogamp/test/junit/newt/WindowEventCom2.java b/src/junit/com/jogamp/test/junit/newt/WindowEventCom2.java new file mode 100644 index 000000000..9c6820831 --- /dev/null +++ b/src/junit/com/jogamp/test/junit/newt/WindowEventCom2.java @@ -0,0 +1,52 @@ +/* + * 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 com.jogamp.newt.event.*; + +class WindowEventCom2 extends WindowAdapter { + + public void windowResized(WindowEvent e) { + String str = (String) e.getAttachment(); + if(null==str) { + e.setAttachment(new String("WindowEventCom2.windowResized: "+e)); + } + } + public void windowMoved(WindowEvent e) { + String str = (String) e.getAttachment(); + if(null==str) { + e.setAttachment(new String("WindowEventCom2.windowMoved: "+e)); + } + } +} + diff --git a/src/junit/com/jogamp/test/junit/newt/WindowEventCom3.java b/src/junit/com/jogamp/test/junit/newt/WindowEventCom3.java new file mode 100644 index 000000000..247393e92 --- /dev/null +++ b/src/junit/com/jogamp/test/junit/newt/WindowEventCom3.java @@ -0,0 +1,48 @@ +/* + * 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 com.jogamp.newt.event.*; + +class WindowEventCom3 extends WindowAdapter { + + public void windowResized(WindowEvent e) { + String str = (String) e.getAttachment(); + System.out.println("WindowEventCom3.windowResized: "+str); + } + public void windowMoved(WindowEvent e) { + String str = (String) e.getAttachment(); + System.out.println("WindowEventCom3.windowMoved: "+str); + } +} + diff --git a/src/newt/classes/com/jogamp/newt/Display.java b/src/newt/classes/com/jogamp/newt/Display.java index c804b3d2d..193bb26dc 100755 --- a/src/newt/classes/com/jogamp/newt/Display.java +++ b/src/newt/classes/com/jogamp/newt/Display.java @@ -36,6 +36,7 @@ package com.jogamp.newt; import javax.media.nativewindow.*; import com.jogamp.nativewindow.impl.RecursiveToolkitLock; import com.jogamp.newt.event.*; +import com.jogamp.newt.impl.event.*; import com.jogamp.newt.impl.Debug; import com.jogamp.newt.util.EDTUtil; import java.util.*; @@ -315,46 +316,31 @@ public abstract class Display { private Object eventsLock = new Object(); private LinkedList/*<NEWTEvent>*/ events = new LinkedList(); - private boolean events2Wait = false; protected void dispatchMessages() { if(0==refCount) return; // we should not exist .. if(!events.isEmpty()) { - if(events2Wait) { - synchronized(eventsLock) { - while (!events.isEmpty()) { - NEWTEvent e = (NEWTEvent) events.removeFirst(); - Object source = e.getSource(); - if(source instanceof Window) { - ((Window)source).sendEvent(e); - } else { - throw new RuntimeException("Event source not a NEWT Window: "+source.getClass().getName()+", "+source); - } - } - events2Wait = false; // clear - eventsLock.notifyAll(); - } - } else { - // swap events list to free ASAP - LinkedList/*<NEWTEvent>*/ _events = null; - synchronized(eventsLock) { - if(!events.isEmpty()) { - _events = events; - events = new LinkedList(); - } - eventsLock.notifyAll(); + // swap events list to free ASAP + LinkedList/*<NEWTEvent>*/ _events = null; + synchronized(eventsLock) { + if(!events.isEmpty()) { + _events = events; + events = new LinkedList(); } - if( null != _events ) { - while (!_events.isEmpty()) { - NEWTEvent e = (NEWTEvent) _events.removeFirst(); - Object source = e.getSource(); - if(source instanceof Window) { - ((Window)source).sendEvent(e); - } else { - throw new RuntimeException("Event source not a NEWT Window: "+source.getClass().getName()+", "+source); - } + eventsLock.notifyAll(); + } + if( null != _events ) { + for (Iterator iter = _events.iterator(); iter.hasNext(); ) { + NEWTEventTask eventTask = (NEWTEventTask) iter.next(); + NEWTEvent event = eventTask.get(); + Object source = event.getSource(); + if(source instanceof Window) { + ((Window)source).sendEvent(event); + } else { + throw new RuntimeException("Event source not a NEWT Window: "+source.getClass().getName()+", "+source); } + eventTask.notifyIssuer(); } } } @@ -372,27 +358,21 @@ public abstract class Display { } public void enqueueEvent(boolean wait, NEWTEvent e) { - synchronized(eventsLock) { - if(DEBUG) { - System.out.println("Display.enqueueEvent: START - wait "+wait+", "+e); - } - events2Wait = wait; - events.addLast(e); - } - if(wait && !events.isEmpty()) { + Object lock = new Object(); + NEWTEventTask eTask = new NEWTEventTask(e, wait?lock:null); + synchronized(lock) { synchronized(eventsLock) { - while(!events.isEmpty()) { - try { - eventsLock.wait(); - } catch (InterruptedException ie) { - ie.printStackTrace(); - } + events.addLast(eTask); + eventsLock.notifyAll(); + } + if( wait ) { + try { + lock.wait(); + } catch (InterruptedException ie) { + throw new RuntimeException(ie); } } } - if(DEBUG) { - System.out.println("Display.enqueueEvent: END - wait "+wait+", "+e); - } } public void lock() { diff --git a/src/newt/classes/com/jogamp/newt/Window.java b/src/newt/classes/com/jogamp/newt/Window.java index 89c1bd146..e9289f5dc 100755 --- a/src/newt/classes/com/jogamp/newt/Window.java +++ b/src/newt/classes/com/jogamp/newt/Window.java @@ -42,6 +42,7 @@ import javax.media.nativewindow.*; import com.jogamp.nativewindow.impl.RecursiveToolkitLock; import java.util.ArrayList; +import java.util.List; import java.util.Iterator; import java.lang.reflect.Method; @@ -706,9 +707,9 @@ public abstract class Window implements NativeWindow public void reparentWindow(NativeWindow newParent, Screen newScreen) { if(!isDestroyed()) { runOnEDTIfAvail(true, new ReparentAction(newParent, newScreen)); - if( isVisible() ) { - enqueueWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout to listener - } + // if( isVisible() ) { + enqueueWindowEvent(true, WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout to listener + // } } } @@ -974,13 +975,36 @@ public abstract class Window implements NativeWindow private ArrayList surfaceUpdatedListeners = new ArrayList(); + /** + * Appends the given {@link com.jogamp.newt.event.SurfaceUpdatedListener} to the end of + * the list. + */ public void addSurfaceUpdatedListener(SurfaceUpdatedListener l) { + getInnerWindow().addSurfaceUpdatedListener(-1, l); + } + + /** + * Inserts the given {@link com.jogamp.newt.event.SurfaceUpdatedListener} at the + * specified position in the list.<br> + + * @param index Position where the listener will be inserted. + * Should be within (0 <= index && index <= size()). + * An index value of -1 is interpreted as the end of the list, size(). + * @param l The listener object to be inserted + * @throws IndexOutOfBoundsException If the index is not within (0 <= index && index <= size()), or -1 + */ + public void addSurfaceUpdatedListener(int index, SurfaceUpdatedListener l) + throws IndexOutOfBoundsException + { if(l == null) { return; } synchronized(surfaceUpdatedListeners) { + if(0>index) { + index = surfaceUpdatedListeners.size(); + } ArrayList newSurfaceUpdatedListeners = (ArrayList) surfaceUpdatedListeners.clone(); - newSurfaceUpdatedListeners.add(l); + newSurfaceUpdatedListeners.add(index, l); surfaceUpdatedListeners = newSurfaceUpdatedListeners; } } @@ -1002,7 +1026,16 @@ public abstract class Window implements NativeWindow } } - public SurfaceUpdatedListener[] getSurfaceUpdatedListener() { + public SurfaceUpdatedListener getSurfaceUpdatedListener(int index) { + synchronized(surfaceUpdatedListeners) { + if(0>index) { + index = surfaceUpdatedListeners.size()-1; + } + return (SurfaceUpdatedListener) surfaceUpdatedListeners.get(index); + } + } + + public SurfaceUpdatedListener[] getSurfaceUpdatedListeners() { synchronized(surfaceUpdatedListeners) { return (SurfaceUpdatedListener[]) surfaceUpdatedListeners.toArray(); } @@ -1088,13 +1121,34 @@ public abstract class Window implements NativeWindow } + /** + * Appends the given {@link com.jogamp.newt.event.MouseListener} to the end of + * the list. + */ public void addMouseListener(MouseListener l) { + getInnerWindow().addMouseListener(-1, l); + } + + /** + * Inserts the given {@link com.jogamp.newt.event.MouseListener} at the + * specified position in the list.<br> + + * @param index Position where the listener will be inserted. + * Should be within (0 <= index && index <= size()). + * An index value of -1 is interpreted as the end of the list, size(). + * @param l The listener object to be inserted + * @throws IndexOutOfBoundsException If the index is not within (0 <= index && index <= size()), or -1 + */ + public void addMouseListener(int index, MouseListener l) { if(l == null) { return; } synchronized(mouseListeners) { + if(0>index) { + index = mouseListeners.size(); + } ArrayList newMouseListeners = (ArrayList) mouseListeners.clone(); - newMouseListeners.add(l); + newMouseListeners.add(index, l); mouseListeners = newMouseListeners; } } @@ -1110,6 +1164,15 @@ public abstract class Window implements NativeWindow } } + public MouseListener getMouseListener(int index) { + synchronized(mouseListeners) { + if(0>index) { + index = mouseListeners.size()-1; + } + return (MouseListener) mouseListeners.get(index); + } + } + public MouseListener[] getMouseListeners() { synchronized(mouseListeners) { return (MouseListener[]) mouseListeners.toArray(); @@ -1168,13 +1231,34 @@ public abstract class Window implements NativeWindow modifiers, keyCode, keyChar) ); } + /** + * Appends the given {@link com.jogamp.newt.event.KeyListener} to the end of + * the list. + */ public void addKeyListener(KeyListener l) { + getInnerWindow().addKeyListener(-1, l); + } + + /** + * Inserts the given {@link com.jogamp.newt.event.KeyListener} at the + * specified position in the list.<br> + + * @param index Position where the listener will be inserted. + * Should be within (0 <= index && index <= size()). + * An index value of -1 is interpreted as the end of the list, size(). + * @param l The listener object to be inserted + * @throws IndexOutOfBoundsException If the index is not within (0 <= index && index <= size()), or -1 + */ + public void addKeyListener(int index, KeyListener l) { if(l == null) { return; } synchronized(keyListeners) { + if(0>index) { + index = keyListeners.size(); + } ArrayList newKeyListeners = (ArrayList) keyListeners.clone(); - newKeyListeners.add(l); + newKeyListeners.add(index, l); keyListeners = newKeyListeners; } } @@ -1190,6 +1274,15 @@ public abstract class Window implements NativeWindow } } + public KeyListener getKeyListener(int index) { + synchronized(keyListeners) { + if(0>index) { + index = keyListeners.size()-1; + } + return (KeyListener) keyListeners.get(index); + } + } + public KeyListener[] getKeyListeners() { synchronized(keyListeners) { return (KeyListener[]) keyListeners.toArray(); @@ -1228,20 +1321,47 @@ public abstract class Window implements NativeWindow // WindowListener/Event Support // protected void enqueueWindowEvent(int eventType) { + enqueueWindowEvent(false, eventType); + } + + protected void enqueueWindowEvent(boolean wait, int eventType) { WindowEvent event = new WindowEvent(eventType, this, System.currentTimeMillis()); - screen.getDisplay().enqueueEvent( event ); + screen.getDisplay().enqueueEvent( wait, event ); // sendWindowEvent ( event ); // FIXME: Think about performance/lag .. ? } private ArrayList windowListeners = new ArrayList(); + /** + * Appends the given {@link com.jogamp.newt.event.WindowListener} to the end of + * the list. + */ public void addWindowListener(WindowListener l) { + getInnerWindow().addWindowListener(-1, l); + } + + /** + * Inserts the given {@link com.jogamp.newt.event.WindowListener} at the + * specified position in the list.<br> + + * @param index Position where the listener will be inserted. + * Should be within (0 <= index && index <= size()). + * An index value of -1 is interpreted as the end of the list, size(). + * @param l The listener object to be inserted + * @throws IndexOutOfBoundsException If the index is not within (0 <= index && index <= size()), or -1 + */ + public void addWindowListener(int index, WindowListener l) + throws IndexOutOfBoundsException + { if(l == null) { return; } synchronized(windowListeners) { + if(0>index) { + index = windowListeners.size(); + } ArrayList newWindowListeners = (ArrayList) windowListeners.clone(); - newWindowListeners.add(l); + newWindowListeners.add(index, l); windowListeners = newWindowListeners; } } @@ -1257,6 +1377,15 @@ public abstract class Window implements NativeWindow } } + public WindowListener getWindowListener(int index) { + synchronized(windowListeners) { + if(0>index) { + index = windowListeners.size()-1; + } + return (WindowListener) windowListeners.get(index); + } + } + public WindowListener[] getWindowListeners() { synchronized(windowListeners) { return (WindowListener[]) windowListeners.toArray(); @@ -1304,13 +1433,34 @@ public abstract class Window implements NativeWindow private ArrayList paintListeners = new ArrayList(); + /** + * Appends the given {@link com.jogamp.newt.event.PaintListener} to the end of + * the list. + */ public void addPaintListener(PaintListener l) { + getInnerWindow().addPaintListener(-1, l); + } + + /** + * Inserts the given {@link com.jogamp.newt.event.PaintListener} at the + * specified position in the list.<br> + + * @param index Position where the listener will be inserted. + * Should be within (0 <= index && index <= size()). + * An index value of -1 is interpreted as the end of the list, size(). + * @param l The listener object to be inserted + * @throws IndexOutOfBoundsException If the index is not within (0 <= index && index <= size()), or -1 + */ + public void addPaintListener(int index, PaintListener l) { if(l == null) { return; } synchronized(paintListeners) { + if(0>index) { + index = paintListeners.size(); + } ArrayList newPaintListeners = (ArrayList) paintListeners.clone(); - newPaintListeners.add(l); + newPaintListeners.add(index, l); paintListeners = newPaintListeners; } } @@ -1326,6 +1476,15 @@ public abstract class Window implements NativeWindow } } + public PaintListener getPaintListener(int index) { + synchronized(paintListeners) { + if(0>index) { + index = paintListeners.size()-1; + } + return (PaintListener) paintListeners.get(index); + } + } + protected void sendPaintEvent(int eventType, int x, int y, int w, int h) { sendPaintEvent( new PaintEvent(eventType, this, System.currentTimeMillis(), x, y, w, h) ); } diff --git a/src/newt/classes/com/jogamp/newt/event/NEWTEvent.java b/src/newt/classes/com/jogamp/newt/event/NEWTEvent.java index 1be3dcb3f..2cb2c5177 100644 --- a/src/newt/classes/com/jogamp/newt/event/NEWTEvent.java +++ b/src/newt/classes/com/jogamp/newt/event/NEWTEvent.java @@ -45,6 +45,7 @@ public class NEWTEvent extends java.util.EventObject { private boolean isSystemEvent; private int eventType; private long when; + private Object attachment; static final boolean DEBUG = false; @@ -105,6 +106,7 @@ public class NEWTEvent extends java.util.EventObject { this.isSystemEvent = evaluateIsSystemEvent(this, new Throwable()); this.eventType = eventType; this.when = when; + this.attachment=null; } /** Indicates whether this event was produced by the system or @@ -123,6 +125,25 @@ public class NEWTEvent extends java.util.EventObject { return when; } + /** + * Attach the passed object to this event.<br> + * If an object was previously attached, it will replaced.<br> + * Attachments to NEWT events allow users to pass on information + * from one custom listener to another, ie custom listener to listener + * communication. + * @param attachment User application specific object + */ + public final void setAttachment(Object attachment) { + this.attachment=attachment; + } + + /** + * @return The user application specific attachment, or null + */ + public final Object getAttachment() { + return attachment; + } + public String toString() { return "NEWTEvent[sys:"+isSystemEvent()+", source:"+getSource().getClass().getName()+", when:"+getWhen()+" d "+(System.currentTimeMillis()-getWhen())+"ms]"; } diff --git a/src/newt/classes/com/jogamp/newt/impl/event/NEWTEventTask.java b/src/newt/classes/com/jogamp/newt/impl/event/NEWTEventTask.java new file mode 100644 index 000000000..479c493b0 --- /dev/null +++ b/src/newt/classes/com/jogamp/newt/impl/event/NEWTEventTask.java @@ -0,0 +1,54 @@ +/* + * 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: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Sven Gothel nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL Sven Gothel BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.jogamp.newt.impl.event; + +import com.jogamp.newt.event.NEWTEvent; + +/** + * Helper class to provide a NEWTEvent queue implementation with a NEWTEvent wrapper + * which notifies after sending the event for the <code>invokeAndWait()</code> semantics. + */ +public class NEWTEventTask { + NEWTEvent event; + Object notifyObject; + + public NEWTEventTask(NEWTEvent event, Object notifyObject) { + this.event = event ; + this.notifyObject = notifyObject ; + } + + public NEWTEvent get() { return event; } + + public void notifyIssuer() { + if(null != notifyObject) { + synchronized (notifyObject) { + notifyObject.notifyAll(); + } + } + } +} + diff --git a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java index 7a223026e..0e93fc0bd 100644 --- a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java +++ b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java @@ -373,8 +373,8 @@ public class GLWindow extends Window implements GLAutoDrawable { window.sendEvent(e); } - public void addSurfaceUpdatedListener(SurfaceUpdatedListener l) { - window.addSurfaceUpdatedListener(l); + public void addSurfaceUpdatedListener(int index, SurfaceUpdatedListener l) { + window.addSurfaceUpdatedListener(index, l); } public void removeSurfaceUpdatedListener(SurfaceUpdatedListener l) { window.removeSurfaceUpdatedListener(l); @@ -382,45 +382,51 @@ public class GLWindow extends Window implements GLAutoDrawable { public void removeAllSurfaceUpdatedListener() { window.removeAllSurfaceUpdatedListener(); } - public SurfaceUpdatedListener[] getSurfaceUpdatedListener() { - return window.getSurfaceUpdatedListener(); + public SurfaceUpdatedListener getSurfaceUpdatedListener(int index) { + return window.getSurfaceUpdatedListener(index); + } + public SurfaceUpdatedListener[] getSurfaceUpdatedListeners() { + return window.getSurfaceUpdatedListeners(); } public void surfaceUpdated(Object updater, NativeWindow window0, long when) { window.surfaceUpdated(updater, window, when); } - public void addMouseListener(MouseListener l) { - window.addMouseListener(l); + public void addMouseListener(int index, MouseListener l) { + window.addMouseListener(index, l); } - public void removeMouseListener(MouseListener l) { window.removeMouseListener(l); } - + public MouseListener getMouseListener(int index) { + return window.getMouseListener(index); + } public MouseListener[] getMouseListeners() { return window.getMouseListeners(); } - public void addKeyListener(KeyListener l) { - window.addKeyListener(l); + public void addKeyListener(int index, KeyListener l) { + window.addKeyListener(index, l); } - public void removeKeyListener(KeyListener l) { window.removeKeyListener(l); } - + public KeyListener getKeyListener(int index) { + return window.getKeyListener(index); + } public KeyListener[] getKeyListeners() { return window.getKeyListeners(); } - public void addWindowListener(WindowListener l) { - window.addWindowListener(l); + public void addWindowListener(int index, WindowListener l) { + window.addWindowListener(index, l); } - public void removeWindowListener(WindowListener l) { window.removeWindowListener(l); } - + public WindowListener getWindowListener(int index) { + return window.getWindowListener(index); + } public WindowListener[] getWindowListeners() { return window.getWindowListeners(); } @@ -473,10 +479,18 @@ public class GLWindow extends Window implements GLAutoDrawable { helper.addGLEventListener(listener); } + public void addGLEventListener(int index, GLEventListener listener) { + helper.addGLEventListener(index, listener); + } + public void removeGLEventListener(GLEventListener listener) { helper.removeGLEventListener(listener); } + public void invoke(boolean wait, GLRunnable glRunnable) { + helper.invoke(wait, glRunnable); + } + public void display() { display(false); } diff --git a/src/newt/classes/com/jogamp/newt/util/EDTUtil.java b/src/newt/classes/com/jogamp/newt/util/EDTUtil.java index 235132460..2e339fd45 100644 --- a/src/newt/classes/com/jogamp/newt/util/EDTUtil.java +++ b/src/newt/classes/com/jogamp/newt/util/EDTUtil.java @@ -36,6 +36,7 @@ package com.jogamp.newt.util; +import com.jogamp.common.util.RunnableTask; import com.jogamp.newt.Display; import com.jogamp.newt.impl.Debug; import java.util.*; @@ -107,10 +108,7 @@ public class EDTUtil { return null!=edt && edt.isRunning() ; } - public void invokeLater(Runnable task) { - if(task == null) { - return; - } + private void invokeLater(Runnable task) { synchronized(edtLock) { if(null!=edt && edt.isRunning() && edt != Thread.currentThread() ) { tasks.add(task); @@ -122,21 +120,33 @@ public class EDTUtil { } } - public void invokeAndWait(Runnable task) { - invoke(true, task); - } - public void invoke(boolean wait, Runnable task) { if(task == null) { return; } - invokeLater(task); - if(wait) { - waitOnWorker(); + boolean doWait = wait && null!=edt && edt.isRunning() && edt != Thread.currentThread(); + Object lock = new Object(); + RunnableTask rTask = new RunnableTask(task, doWait?lock:null, true); + Throwable throwable = null; + synchronized(lock) { + invokeLater(rTask); + if( doWait ) { + try { + lock.wait(); + } catch (InterruptedException ie) { + throwable = ie; + } + } + } + if(null==throwable) { + throwable = rTask.getThrowable(); + } + if(null!=throwable) { + throw new RuntimeException(throwable); } } - public void waitOnWorker() { + public void waitUntilIdle() { synchronized(edtLock) { if(null!=edt && edt.isRunning() && tasks.size()>0 && edt != Thread.currentThread() ) { try { |