summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2010-12-19 14:54:08 +0100
committerSven Gothel <[email protected]>2010-12-19 14:54:08 +0100
commit2cbab63bd6c230d31b8ae6f1d794ad49bf23bb53 (patch)
tree9da105f466b81424ae089e59e4bd67fce7c32d54 /src
parent2323c30c23b6f9eb7d7ccf94e6cdcbcb3d2f34a6 (diff)
JOGL/NEWT: Introduce WindowClosingProtocol (solves Bug/Request 444)
Similar to JFrame's closing behavior, the following components window closing follow the new WindowClosingProtocol: - GLCanvas - GLJPanel - NEWT Window, GLWindow - NEWT NewtCanvasAWT The implementation obeys either 1) the user value set by this interface, 2) an underlying toolkit set user value (JFrame, ..) 3) or it's default, eg. {@link #DO_NOTHING_ON_CLOSE DO_NOTHING_ON_CLOSE} within an AWT environment. If none of the above determines the operation, this protocol default behavior {@link #DISPOSE_ON_CLOSE DISPOSE_ON_CLOSE} shall be used.
Diffstat (limited to 'src')
-rw-r--r--src/jogl/classes/com/jogamp/opengl/impl/awt/AWTUtil.java3
-rw-r--r--src/jogl/classes/javax/media/opengl/awt/GLCanvas.java123
-rw-r--r--src/jogl/classes/javax/media/opengl/awt/GLJPanel.java99
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/impl/awt/AWTMisc.java96
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/impl/jawt/JAWTUtil.java2
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/WindowClosingProtocol.java66
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/awt/AWTWindowClosingProtocol.java138
-rw-r--r--src/newt/classes/com/jogamp/newt/Window.java3
-rw-r--r--src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java78
-rw-r--r--src/newt/classes/com/jogamp/newt/impl/WindowImpl.java22
-rw-r--r--src/newt/classes/com/jogamp/newt/opengl/GLWindow.java47
-rw-r--r--src/test/com/jogamp/newt/impl/WindowImplAccess.java52
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/TestCloseNewtAWT.java7
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/TestRemoteGLWindows01NEWT.java44
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/TestRemoteWindow01NEWT.java20
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/TestWindowClosingProtocol01AWT.java155
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/TestWindowClosingProtocol02NEWT.java116
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/TestWindowClosingProtocol03NewtAWT.java140
-rw-r--r--src/test/com/jogamp/opengl/test/junit/util/AWTRobotUtil.java63
19 files changed, 1104 insertions, 170 deletions
diff --git a/src/jogl/classes/com/jogamp/opengl/impl/awt/AWTUtil.java b/src/jogl/classes/com/jogamp/opengl/impl/awt/AWTUtil.java
index 36c0a3250..081d1f9b3 100644
--- a/src/jogl/classes/com/jogamp/opengl/impl/awt/AWTUtil.java
+++ b/src/jogl/classes/com/jogamp/opengl/impl/awt/AWTUtil.java
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright (c) 2010 JogAmp Community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -38,8 +39,6 @@ package com.jogamp.opengl.impl.awt;
import com.jogamp.nativewindow.impl.jawt.*;
-import com.jogamp.opengl.impl.*;
-
import javax.media.opengl.*;
import java.lang.reflect.*;
diff --git a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
index 1329977b2..9578ce291 100644
--- a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
+++ b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
@@ -40,32 +40,56 @@
package javax.media.opengl.awt;
-import com.jogamp.common.GlueGenVersion;
-import com.jogamp.common.util.VersionUtil;
-import com.jogamp.common.util.locks.RecursiveLock;
-import com.jogamp.nativewindow.NativeWindowVersion;
-import javax.media.opengl.*;
-import javax.media.nativewindow.*;
-import javax.media.nativewindow.awt.*;
-
-import com.jogamp.opengl.impl.*;
-import com.jogamp.opengl.JoglVersion;
+import java.beans.Beans;
+import java.lang.reflect.Method;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
import java.awt.Canvas;
import java.awt.Color;
-import java.awt.Component;
import java.awt.FontMetrics;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
-import java.awt.Window;
-import java.awt.event.WindowEvent;
-import java.awt.event.WindowAdapter;
-import java.awt.geom.*;
-import java.beans.*;
-import java.lang.reflect.*;
-import java.security.*;
+import java.awt.geom.Rectangle2D;
+
+import com.jogamp.common.GlueGenVersion;
+import com.jogamp.common.util.VersionUtil;
+import com.jogamp.common.util.locks.RecursiveLock;
+
+import javax.media.nativewindow.WindowClosingProtocol;
+import javax.media.nativewindow.AbstractGraphicsConfiguration;
+import javax.media.nativewindow.AbstractGraphicsDevice;
+import javax.media.nativewindow.AbstractGraphicsScreen;
+import javax.media.nativewindow.GraphicsConfigurationFactory;
+import javax.media.nativewindow.NativeSurface;
+import javax.media.nativewindow.NativeWindowFactory;
+import javax.media.nativewindow.awt.AWTGraphicsConfiguration;
+import javax.media.nativewindow.awt.AWTGraphicsDevice;
+import javax.media.nativewindow.awt.AWTGraphicsScreen;
+import javax.media.nativewindow.awt.AWTWindowClosingProtocol;
+import com.jogamp.nativewindow.NativeWindowVersion;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GLAnimatorControl;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLCapabilitiesChooser;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLDrawable;
+import javax.media.opengl.GLDrawableFactory;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLException;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.GLRunnable;
+import javax.media.opengl.Threading;
+import com.jogamp.opengl.JoglVersion;
+import com.jogamp.opengl.impl.Debug;
+import com.jogamp.opengl.impl.GLContextImpl;
+import com.jogamp.opengl.impl.GLDrawableHelper;
+import com.jogamp.opengl.impl.ThreadingImpl;
// FIXME: Subclasses need to call resetGLFunctionAvailability() on their
// context whenever the displayChanged() function is called on our
@@ -105,7 +129,7 @@ import java.security.*;
* </ul>
*/
-public class GLCanvas extends Canvas implements AWTGLAutoDrawable {
+public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosingProtocol {
private static final boolean DEBUG;
private static final GLProfile defaultGLProfile;
@@ -127,6 +151,13 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable {
private GLContext shareWith;
private GraphicsDevice device;
+ private AWTWindowClosingProtocol awtWindowClosingProtocol =
+ new AWTWindowClosingProtocol(this, new Runnable() {
+ public void run() {
+ GLCanvas.this.destroy();
+ }
+ });
+
/** Creates a new GLCanvas component with a default set of OpenGL
capabilities, using the default OpenGL capabilities selection
mechanism, on the default screen device. */
@@ -203,33 +234,6 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable {
this.device = device;
}
- protected interface DestroyMethod {
- public void destroyMethod();
- }
-
- /* package private */ final static Object addClosingListener(Component c, final DestroyMethod d) {
- WindowAdapter cl = null;
- Window w = getWindow(c);
- if(null!=w) {
- cl = new WindowAdapter() {
- public void windowClosing(WindowEvent e) {
- // we have to issue this call rigth away,
- // otherwise the window gets destroyed
- d.destroyMethod();
- }
- };
- w.addWindowListener(cl);
- }
- return cl;
- }
-
- private final static Window getWindow(Component c) {
- while ( c!=null && ! ( c instanceof Window ) ) {
- c = c.getParent();
- }
- return (Window)c;
- }
-
/**
* Overridden to choose a GraphicsConfiguration on a parent container's
* GraphicsDevice because both devices
@@ -351,8 +355,13 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable {
return ( null != drawable ) ? drawable.isRealized() : false;
}
- private Object closingListener = null;
- private Object closingListenerLock = new Object();
+ public int getDefaultCloseOperation() {
+ return awtWindowClosingProtocol.getDefaultCloseOperation();
+ }
+
+ public int setDefaultCloseOperation(int op) {
+ return awtWindowClosingProtocol.setDefaultCloseOperation(op);
+ }
public void display() {
if( !validateGLDrawable() ) {
@@ -360,14 +369,8 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable {
}
maybeDoSingleThreadedWorkaround(displayOnEventDispatchThreadAction,
displayAction);
- if(null==closingListener) {
- synchronized(closingListenerLock) {
- if(null==closingListener) {
- closingListener=addClosingListener(this, new DestroyMethod() {
- public void destroyMethod() { destroy(); } });
- }
- }
- }
+
+ awtWindowClosingProtocol.addClosingListenerOneShot();
}
private void dispose(boolean regenerate) {
@@ -564,6 +567,8 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable {
ex1.printStackTrace();
}
+ awtWindowClosingProtocol.removeClosingListener();
+
if (Beans.isDesignTime()) {
super.removeNotify();
} else {
@@ -685,15 +690,15 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable {
}
public NativeSurface getNativeSurface() {
- return drawable.getNativeSurface();
+ return (null != drawable) ? drawable.getNativeSurface() : null;
}
public long getHandle() {
- return drawable.getHandle();
+ return (null != drawable) ? drawable.getHandle() : 0;
}
public GLDrawableFactory getFactory() {
- return drawable.getFactory();
+ return (null != drawable) ? drawable.getFactory() : null;
}
public String toString() {
diff --git a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
index 18ebcd129..46c799d71 100644
--- a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
+++ b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
@@ -40,19 +40,57 @@
package javax.media.opengl.awt;
-import javax.media.opengl.*;
-import javax.media.nativewindow.*;
-
-import java.awt.*;
-import java.awt.geom.*;
-import java.awt.image.*;
-import java.beans.*;
-import java.nio.*;
-import java.security.*;
+import java.nio.ByteBuffer;
+import java.nio.IntBuffer;
+import java.beans.Beans;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+
+import java.awt.Color;
+import java.awt.EventQueue;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.GraphicsConfiguration;
+import java.awt.GraphicsEnvironment;
+import java.awt.Rectangle;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.BufferedImage;
+import java.awt.image.DataBufferByte;
+import java.awt.image.DataBufferInt;
import javax.swing.JPanel;
+
+import javax.media.nativewindow.WindowClosingProtocol;
+import javax.media.nativewindow.AbstractGraphicsDevice;
+import javax.media.nativewindow.NativeSurface;
+import javax.media.nativewindow.awt.AWTWindowClosingProtocol;
+
+import javax.media.opengl.DefaultGLCapabilitiesChooser;
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2;
+import javax.media.opengl.GL2GL3;
+import javax.media.opengl.GLAnimatorControl;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLCapabilitiesChooser;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLDrawable;
+import javax.media.opengl.GLDrawableFactory;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLException;
+import javax.media.opengl.GLPbuffer;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.GLRunnable;
+import javax.media.opengl.Threading;
import com.jogamp.opengl.util.FBObject;
-import com.jogamp.opengl.impl.*;
-import com.jogamp.opengl.impl.awt.*;
+import com.jogamp.opengl.impl.Debug;
+import com.jogamp.opengl.impl.GLContextImpl;
+import com.jogamp.opengl.impl.GLDrawableFactoryImpl;
+import com.jogamp.opengl.impl.GLDrawableHelper;
+import com.jogamp.opengl.impl.GLDrawableImpl;
+import com.jogamp.opengl.impl.ThreadingImpl;
+import com.jogamp.opengl.impl.awt.Java2D;
+import com.jogamp.opengl.impl.awt.Java2DGLContext;
// FIXME: Subclasses need to call resetGLFunctionAvailability() on their
// context whenever the displayChanged() function is called on their
@@ -85,7 +123,7 @@ import com.jogamp.opengl.impl.awt.*;
* </P>
*/
-public class GLJPanel extends JPanel implements AWTGLAutoDrawable {
+public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosingProtocol {
private static final boolean DEBUG = Debug.debug("GLJPanel");
private static final boolean VERBOSE = Debug.verbose();
@@ -129,8 +167,8 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable {
!Debug.isPropertyDefined("jogl.gljpanel.noogl", true, localACC);
// For handling reshape events lazily
- private int reshapeX;
- private int reshapeY;
+ // private int reshapeX;
+ // private int reshapeY;
private int reshapeWidth;
private int reshapeHeight;
@@ -139,6 +177,13 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable {
private int viewportX;
private int viewportY;
+ private AWTWindowClosingProtocol awtWindowClosingProtocol =
+ new AWTWindowClosingProtocol(this, new Runnable() {
+ public void run() {
+ GLJPanel.this.destroy();
+ }
+ });
+
static {
// Force eager initialization of part of the Java2D class since
// otherwise it's likely it will try to be initialized while on
@@ -365,6 +410,9 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable {
Exception ex1 = new Exception("Info: removeNotify - start");
ex1.printStackTrace();
}
+
+ awtWindowClosingProtocol.removeClosingListener();
+
dispose(false);
if (backend != null) {
backend.destroy();
@@ -387,8 +435,8 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable {
public void reshape(int x, int y, int width, int height) {
super.reshape(x, y, width, height);
- reshapeX = x;
- reshapeY = y;
+ // reshapeX = x;
+ // reshapeY = y;
reshapeWidth = width;
reshapeHeight = height;
handleReshape = true;
@@ -573,17 +621,16 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable {
// a different implementation -- try again
} while (backend == null);
- if(null==closingListener) {
- synchronized(closingListenerLock) {
- if(null==closingListener) {
- closingListener=GLCanvas.addClosingListener(this, new GLCanvas.DestroyMethod() {
- public void destroyMethod() { destroy(); } });
- }
- }
- }
+ awtWindowClosingProtocol.addClosingListenerOneShot();
+ }
+
+ public int getDefaultCloseOperation() {
+ return awtWindowClosingProtocol.getDefaultCloseOperation();
+ }
+
+ public int setDefaultCloseOperation(int op) {
+ return awtWindowClosingProtocol.setDefaultCloseOperation(op);
}
- private Object closingListener = null;
- private Object closingListenerLock = new Object();
private void handleReshape() {
panelWidth = reshapeWidth;
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/impl/awt/AWTMisc.java b/src/nativewindow/classes/com/jogamp/nativewindow/impl/awt/AWTMisc.java
new file mode 100644
index 000000000..c61ae5531
--- /dev/null
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/impl/awt/AWTMisc.java
@@ -0,0 +1,96 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``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 JogAmp Community OR
+ * CONTRIBUTORS 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.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.nativewindow.impl.awt;
+
+import java.awt.Window;
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Frame;
+import javax.swing.JFrame;
+import javax.swing.WindowConstants;
+
+import javax.media.nativewindow.NativeWindowException;
+import javax.media.nativewindow.WindowClosingProtocol;
+import javax.swing.MenuSelectionManager;
+
+public class AWTMisc {
+
+ public static final JFrame getJFrame(Component c) {
+ while (c != null && !(c instanceof JFrame)) {
+ c = c.getParent();
+ }
+ return (JFrame) c;
+ }
+
+ public static final Frame getFrame(Component c) {
+ while (c != null && !(c instanceof Frame)) {
+ c = c.getParent();
+ }
+ return (Frame) c;
+ }
+
+ public static final Window getWindow(Component c) {
+ while (c != null && !(c instanceof Window)) {
+ c = c.getParent();
+ }
+ return (Window) c;
+ }
+
+ public static final Container getContainer(Component c) {
+ while (c != null && !(c instanceof Container)) {
+ c = c.getParent();
+ }
+ return (Container) c;
+ }
+
+ /**
+ * Issue this when your non AWT toolkit gains focus to clear AWT menu path
+ */
+ public static final void clearAWTMenus() {
+ MenuSelectionManager.defaultManager().clearSelectedPath();
+ }
+
+ public final static int AWT2NWClosingOperation(int awtClosingOperation) {
+ switch (awtClosingOperation) {
+ case WindowConstants.DISPOSE_ON_CLOSE:
+ case WindowConstants.EXIT_ON_CLOSE:
+ return WindowClosingProtocol.DISPOSE_ON_CLOSE;
+ case WindowConstants.DO_NOTHING_ON_CLOSE:
+ case WindowConstants.HIDE_ON_CLOSE:
+ return WindowClosingProtocol.DO_NOTHING_ON_CLOSE;
+ default:
+ throw new NativeWindowException("Unhandled AWT Closing Operation: " + awtClosingOperation);
+ }
+ }
+
+ public final static int getNWClosingOperation(Component c) {
+ JFrame jf = getJFrame(c);
+ int op = (null != jf) ? jf.getDefaultCloseOperation() : WindowConstants.DO_NOTHING_ON_CLOSE ;
+ return AWT2NWClosingOperation(op);
+ }
+}
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/impl/jawt/JAWTUtil.java b/src/nativewindow/classes/com/jogamp/nativewindow/impl/jawt/JAWTUtil.java
index 68d6dc2a8..39816ff6a 100644
--- a/src/nativewindow/classes/com/jogamp/nativewindow/impl/jawt/JAWTUtil.java
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/impl/jawt/JAWTUtil.java
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright (c) 2010 JogAmp Community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -38,7 +39,6 @@ package com.jogamp.nativewindow.impl.jawt;
import com.jogamp.nativewindow.impl.*;
import java.awt.EventQueue;
-import java.awt.Frame;
import javax.media.nativewindow.*;
diff --git a/src/nativewindow/classes/javax/media/nativewindow/WindowClosingProtocol.java b/src/nativewindow/classes/javax/media/nativewindow/WindowClosingProtocol.java
new file mode 100644
index 000000000..949aee79c
--- /dev/null
+++ b/src/nativewindow/classes/javax/media/nativewindow/WindowClosingProtocol.java
@@ -0,0 +1,66 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``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 JogAmp Community OR
+ * CONTRIBUTORS 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.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package javax.media.nativewindow;
+
+/**
+ * Protocol for handling window closing events.
+ * <p>
+ * The implementation shall obey either the user value set by this interface,<br>
+ * an underlying toolkit set user value or it's default, eg. {@link #DO_NOTHING_ON_CLOSE DO_NOTHING_ON_CLOSE} within an AWT environment.<br>
+ * If none of the above determines the operation,
+ * this protocol default behavior {@link #DISPOSE_ON_CLOSE DISPOSE_ON_CLOSE} shall be used.</p>
+ */
+public interface WindowClosingProtocol {
+ /**
+ * Dispose resources on native window close operation.<br>
+ * This is the default behavior in case no underlying toolkit defines otherwise.
+ */
+ int DISPOSE_ON_CLOSE = 1;
+
+ /**
+ * Do nothing on native window close operation.<br>
+ * This is the default behavior within an AWT environment.
+ */
+ int DO_NOTHING_ON_CLOSE = 0;
+
+ /**
+ * @return the current close operation value
+ * @see #DISPOSE_ON_CLOSE
+ * @see #DO_NOTHING_ON_CLOSE
+ */
+ int getDefaultCloseOperation();
+
+ /**
+ * @param op the new close operation value
+ * @return the previous close operation value
+ * @see #DISPOSE_ON_CLOSE
+ * @see #DO_NOTHING_ON_CLOSE
+ */
+ int setDefaultCloseOperation(int op);
+}
diff --git a/src/nativewindow/classes/javax/media/nativewindow/awt/AWTWindowClosingProtocol.java b/src/nativewindow/classes/javax/media/nativewindow/awt/AWTWindowClosingProtocol.java
new file mode 100644
index 000000000..a0e9efa49
--- /dev/null
+++ b/src/nativewindow/classes/javax/media/nativewindow/awt/AWTWindowClosingProtocol.java
@@ -0,0 +1,138 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``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 JogAmp Community OR
+ * CONTRIBUTORS 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.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package javax.media.nativewindow.awt;
+
+import java.awt.Component;
+import java.awt.Window;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.awt.event.WindowListener;
+import javax.media.nativewindow.WindowClosingProtocol;
+import com.jogamp.nativewindow.impl.awt.AWTMisc;
+
+public class AWTWindowClosingProtocol implements WindowClosingProtocol {
+
+ private Component comp;
+ private Runnable closingOperation;
+ private volatile boolean closingListenerSet = false;
+ private Object closingListenerLock = new Object();
+ private int defaultCloseOperation = DISPOSE_ON_CLOSE;
+ private boolean defaultCloseOperationSetByUser = false;
+
+ public AWTWindowClosingProtocol(Component comp, Runnable closingOperation) {
+ this.comp = comp;
+ this.closingOperation = closingOperation;
+ }
+
+ class WindowClosingAdapter extends WindowAdapter {
+ public void windowClosing(WindowEvent e) {
+ int op = AWTWindowClosingProtocol.this.getDefaultCloseOperation();
+
+ if( DISPOSE_ON_CLOSE == op ) {
+ // we have to issue this call right away,
+ // otherwise the window gets destroyed
+ closingOperation.run();
+ }
+ }
+ }
+ WindowListener windowClosingAdapter = new WindowClosingAdapter();
+
+ final boolean addClosingListenerImpl() {
+ Window w = AWTMisc.getWindow(comp);
+ if(null!=w) {
+ w.addWindowListener(windowClosingAdapter);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Adds this closing listener to the components Window if exist and only one time.<br>
+ * Hence you may call this method every time to ensure it has been set,
+ * ie in case the Window parent is not available yet.
+ *
+ * @return
+ */
+ public final boolean addClosingListenerOneShot() {
+ if(!closingListenerSet) {
+ synchronized(closingListenerLock) {
+ if(!closingListenerSet) {
+ closingListenerSet=addClosingListenerImpl();
+ return closingListenerSet;
+ }
+ }
+ }
+ return false;
+ }
+
+ public final boolean removeClosingListener() {
+ if(closingListenerSet) {
+ synchronized(closingListenerLock) {
+ if(closingListenerSet) {
+ Window w = AWTMisc.getWindow(comp);
+ if(null!=w) {
+ w.removeWindowListener(windowClosingAdapter);
+ closingListenerSet = false;
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ *
+ * @return the user set close operation if set by {@link #setDefaultCloseOperation(int) setDefaultCloseOperation(int)},
+ * otherwise return the AWT/Swing close operation value translated to
+ * a {@link WindowClosingProtocol} value .
+ */
+ public final int getDefaultCloseOperation() {
+ int op = -1;
+ synchronized(closingListenerLock) {
+ if(defaultCloseOperationSetByUser) {
+ op = defaultCloseOperation;
+ }
+ }
+ if(0 <= op) {
+ return op;
+ }
+ // User didn't determine the behavior, use underlying AWT behavior
+ return AWTMisc.getNWClosingOperation(comp);
+ }
+
+ public final int setDefaultCloseOperation(int op) {
+ synchronized(closingListenerLock) {
+ int _op = defaultCloseOperation;
+ defaultCloseOperation = op;
+ defaultCloseOperationSetByUser = true;
+ return _op;
+ }
+ }
+}
diff --git a/src/newt/classes/com/jogamp/newt/Window.java b/src/newt/classes/com/jogamp/newt/Window.java
index 99db47168..9fe5089be 100644
--- a/src/newt/classes/com/jogamp/newt/Window.java
+++ b/src/newt/classes/com/jogamp/newt/Window.java
@@ -36,13 +36,14 @@ import javax.media.nativewindow.CapabilitiesChooser;
import javax.media.nativewindow.CapabilitiesImmutable;
import javax.media.nativewindow.NativeWindow;
import javax.media.nativewindow.SurfaceUpdatedListener;
+import javax.media.nativewindow.WindowClosingProtocol;
import javax.media.nativewindow.util.Insets;
/**
* Specifying the public Window functionality for the
* using a Window and for shadowing one like {@link com.jogamp.newt.opengl.GLWindow}.
*/
-public interface Window extends NativeWindow {
+public interface Window extends NativeWindow, WindowClosingProtocol {
public static final boolean DEBUG_MOUSE_EVENT = Debug.debug("Window.MouseEvent");
public static final boolean DEBUG_KEY_EVENT = Debug.debug("Window.KeyEvent");
public static final boolean DEBUG_WINDOW_EVENT = Debug.debug("Window.WindowEvent");
diff --git a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java
index bee81624a..18213f94f 100644
--- a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java
+++ b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java
@@ -38,21 +38,36 @@ import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.KeyboardFocusManager;
-import javax.media.nativewindow.*;
+import javax.media.nativewindow.NativeWindow;
+import javax.media.nativewindow.NativeWindowException;
+import javax.media.nativewindow.WindowClosingProtocol;
+import javax.media.nativewindow.awt.AWTWindowClosingProtocol;
+import com.jogamp.nativewindow.impl.awt.AWTMisc;
import com.jogamp.newt.event.awt.AWTAdapter;
import com.jogamp.newt.event.awt.AWTParentWindowAdapter;
import com.jogamp.newt.event.WindowEvent;
import com.jogamp.newt.Window;
+import com.jogamp.newt.event.WindowAdapter;
+import com.jogamp.newt.event.WindowListener;
import com.jogamp.newt.impl.Debug;
+import javax.swing.MenuSelectionManager;
-public class NewtCanvasAWT extends java.awt.Canvas {
+public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProtocol {
public static final boolean DEBUG = Debug.debug("Window");
NativeWindow nativeWindow = null;
Window newtChild = null;
+ int newtChildCloseOp;
AWTAdapter awtAdapter = null;
+ private AWTWindowClosingProtocol awtWindowClosingProtocol =
+ new AWTWindowClosingProtocol(this, new Runnable() {
+ public void run() {
+ NewtCanvasAWT.this.destroy();
+ }
+ });
+
/**
* Instantiates a NewtCanvas without a NEWT child.<br>
*/
@@ -97,12 +112,18 @@ public class NewtCanvasAWT extends java.awt.Canvas {
}
FocusAction focusAction = new FocusAction();
+ WindowListener clearAWTMenusOnNewtFocus = new WindowAdapter() {
+ public void windowGainedFocus(WindowEvent arg0) {
+ MenuSelectionManager.defaultManager().clearSelectedPath();
+ }
+ };
+
/** sets a new NEWT child, provoking reparenting on the NEWT level. */
public NewtCanvasAWT setNEWTChild(Window child) {
if(newtChild!=child) {
newtChild = child;
if(null!=nativeWindow) {
- java.awt.Container cont = getContainer(this);
+ java.awt.Container cont = AWTMisc.getContainer(this);
// reparent right away, addNotify has been called already
reparentWindow( (null!=newtChild) ? true : false, cont );
}
@@ -119,24 +140,37 @@ public class NewtCanvasAWT extends java.awt.Canvas {
* or {@link #addNotify()} hasn't been called yet.*/
public NativeWindow getNativeWindow() { return nativeWindow; }
- void setWindowAdapter(boolean attach) {
+ public int getDefaultCloseOperation() {
+ return awtWindowClosingProtocol.getDefaultCloseOperation();
+ }
+
+ public int setDefaultCloseOperation(int op) {
+ return awtWindowClosingProtocol.setDefaultCloseOperation(op);
+ }
+
+ void configureNewtChild(boolean attach) {
if(null!=awtAdapter) {
awtAdapter.removeFrom(this);
awtAdapter=null;
}
- if(attach && null!=newtChild) {
- awtAdapter = new AWTParentWindowAdapter(newtChild).addTo(this);
- }
- }
-
- static java.awt.Container getContainer(java.awt.Component comp) {
- while( null != comp ) {
- if( comp instanceof java.awt.Container ) {
- return (java.awt.Container) comp;
+ if( null != newtChild ) {
+ if(attach) {
+ awtAdapter = new AWTParentWindowAdapter(newtChild).addTo(this);
+ if(newtChild.isValid()) {
+ newtChild.addWindowListener(clearAWTMenusOnNewtFocus);
+ }
+ newtChild.setFocusAction(focusAction); // enable AWT focus traversal
+ newtChildCloseOp = newtChild.setDefaultCloseOperation(WindowClosingProtocol.DO_NOTHING_ON_CLOSE);
+ awtWindowClosingProtocol.addClosingListenerOneShot();
+ } else {
+ if(newtChild.isValid()) {
+ newtChild.removeWindowListener(clearAWTMenusOnNewtFocus);
+ }
+ newtChild.setFocusAction(null);
+ newtChild.setDefaultCloseOperation(newtChildCloseOp);
+ awtWindowClosingProtocol.removeClosingListener();
}
- comp = comp.getParent();
}
- return null;
}
public void addNotify() {
@@ -150,7 +184,7 @@ public class NewtCanvasAWT extends java.awt.Canvas {
// after native peer is valid: Windows
disableBackgroundErase();
- java.awt.Container cont = getContainer(this);
+ java.awt.Container cont = AWTMisc.getContainer(this);
if(DEBUG) {
// if ( isShowing() == false ) -> Container was not visible yet.
// if ( isShowing() == true ) -> Container is already visible.
@@ -161,7 +195,7 @@ public class NewtCanvasAWT extends java.awt.Canvas {
}
public void removeNotify() {
- java.awt.Container cont = getContainer(this);
+ java.awt.Container cont = AWTMisc.getContainer(this);
if(DEBUG) {
System.err.println("NewtCanvasAWT.removeNotify: "+newtChild+", from "+cont);
}
@@ -187,13 +221,12 @@ public class NewtCanvasAWT extends java.awt.Canvas {
newtChild.setSize(w, h);
newtChild.reparentWindow(nativeWindow);
newtChild.setVisible(true);
- setWindowAdapter(true);
+ configureNewtChild(true);
newtChild.sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout to listener
newtChild.windowRepaint(0, 0, w, h);
- newtChild.setFocusAction(focusAction); // enable AWT focus traversal
}
} else {
- setWindowAdapter(false);
+ configureNewtChild(false);
nativeWindow = null;
newtChild.setVisible(false);
newtChild.reparentWindow(null);
@@ -213,10 +246,11 @@ public class NewtCanvasAWT extends java.awt.Canvas {
*/
public final void destroy() {
if(null!=newtChild) {
- java.awt.Container cont = getContainer(this);
+ java.awt.Container cont = AWTMisc.getContainer(this);
if(DEBUG) {
System.err.println("NewtCanvasAWT.destroy(): "+newtChild+", from "+cont);
}
+ configureNewtChild(false);
nativeWindow = null;
newtChild.setVisible(false);
newtChild.reparentWindow(null);
@@ -229,11 +263,13 @@ public class NewtCanvasAWT extends java.awt.Canvas {
}
public void paint(Graphics g) {
+ awtWindowClosingProtocol.addClosingListenerOneShot();
if(null!=newtChild) {
newtChild.windowRepaint(0, 0, getWidth(), getHeight());
}
}
public void update(Graphics g) {
+ awtWindowClosingProtocol.addClosingListenerOneShot();
if(null!=newtChild) {
newtChild.windowRepaint(0, 0, getWidth(), getHeight());
}
diff --git a/src/newt/classes/com/jogamp/newt/impl/WindowImpl.java b/src/newt/classes/com/jogamp/newt/impl/WindowImpl.java
index ad11d8ab9..e04bd1208 100644
--- a/src/newt/classes/com/jogamp/newt/impl/WindowImpl.java
+++ b/src/newt/classes/com/jogamp/newt/impl/WindowImpl.java
@@ -372,6 +372,26 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
protected void unlockSurfaceImpl() { }
//----------------------------------------------------------------------
+ // WindowClosingProtocol implementation
+ //
+ private Object closingListenerLock = new Object();
+ private int defaultCloseOperation = DISPOSE_ON_CLOSE;
+
+ public int getDefaultCloseOperation() {
+ synchronized (closingListenerLock) {
+ return defaultCloseOperation;
+ }
+ }
+
+ public int setDefaultCloseOperation(int op) {
+ synchronized (closingListenerLock) {
+ int _op = defaultCloseOperation;
+ defaultCloseOperation = op;
+ return _op;
+ }
+ }
+
+ //----------------------------------------------------------------------
// Window: Native implementation
//
@@ -2101,7 +2121,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
enqueueWindowEvent(false, WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY);
- if(handleDestroyNotify && isValid()) {
+ if(handleDestroyNotify && DISPOSE_ON_CLOSE == defaultCloseOperation && isValid()) {
destroy();
}
diff --git a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java
index 358a3d4ce..4a1855d05 100644
--- a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java
+++ b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java
@@ -85,24 +85,26 @@ public class GLWindow implements GLAutoDrawable, Window, NEWTEventConsumer {
}
public void windowDestroyNotify(WindowEvent e) {
- // Is an animator thread perform rendering?
- if (GLWindow.this.helper.isExternalAnimatorRunning()) {
- // Pause animations before initiating safe destroy.
- GLAnimatorControl ctrl = GLWindow.this.helper.getAnimator();
- boolean isPaused = ctrl.pause();
- destroy();
- if(isPaused) {
- ctrl.resume();
+ if( DISPOSE_ON_CLOSE == GLWindow.this.getDefaultCloseOperation() ) {
+ // Is an animator thread perform rendering?
+ if (GLWindow.this.helper.isExternalAnimatorRunning()) {
+ // Pause animations before initiating safe destroy.
+ GLAnimatorControl ctrl = GLWindow.this.helper.getAnimator();
+ boolean isPaused = ctrl.pause();
+ destroy();
+ if(isPaused) {
+ ctrl.resume();
+ }
+ } else if (GLWindow.this.window.isSurfaceLockedByOtherThread()) {
+ // Surface is locked by another thread
+ // Flag that destroy should be performed on the next
+ // attempt to display.
+ sendDestroy = true;
+ } else {
+ // Without an external thread animating or locking the
+ // surface, we are safe.
+ destroy ();
}
- } else if (GLWindow.this.window.isSurfaceLockedByOtherThread()) {
- // Surface is locked by another thread
- // Flag that destroy should be performed on the next
- // attempt to display.
- sendDestroy = true;
- } else {
- // Without an external thread animating or locking the
- // surface, we are safe.
- destroy ();
}
}
});
@@ -152,6 +154,17 @@ public class GLWindow implements GLAutoDrawable, Window, NEWTEventConsumer {
}
//----------------------------------------------------------------------
+ // WindowClosingProtocol implementation
+ //
+ public int getDefaultCloseOperation() {
+ return window.getDefaultCloseOperation();
+ }
+
+ public int setDefaultCloseOperation(int op) {
+ return window.setDefaultCloseOperation(op);
+ }
+
+ //----------------------------------------------------------------------
// Window Access
//
diff --git a/src/test/com/jogamp/newt/impl/WindowImplAccess.java b/src/test/com/jogamp/newt/impl/WindowImplAccess.java
new file mode 100644
index 000000000..5a90c8094
--- /dev/null
+++ b/src/test/com/jogamp/newt/impl/WindowImplAccess.java
@@ -0,0 +1,52 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``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 JogAmp Community OR
+ * CONTRIBUTORS 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.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.newt.impl;
+
+import com.jogamp.newt.Window;
+import com.jogamp.newt.opengl.GLWindow;
+
+/**
+ * Allows access to protected methods of WindowImpl
+ */
+public class WindowImplAccess {
+ public static final void windowDestroyNotify(Window win) {
+ WindowImpl winImpl = null;
+ if(win instanceof GLWindow) {
+ GLWindow glwin = (GLWindow) win;
+ winImpl = (WindowImpl) glwin.getWindow();
+ } else if(win instanceof WindowImpl) {
+ winImpl = (WindowImpl) win;
+ } else {
+ throw new RuntimeException("Given Window not a GLWindow, not WindowImpl, but "+win.getClass());
+ }
+ winImpl.windowDestroyNotify();
+ }
+}
+
+
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestCloseNewtAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestCloseNewtAWT.java
index 8cad4f0ed..509a0af15 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/TestCloseNewtAWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/TestCloseNewtAWT.java
@@ -45,6 +45,7 @@ import com.jogamp.newt.awt.NewtCanvasAWT;
import com.jogamp.newt.event.WindowAdapter;
import com.jogamp.newt.event.WindowEvent;
import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
import com.jogamp.opengl.test.junit.util.UITestCase;
public class TestCloseNewtAWT extends UITestCase {
@@ -124,11 +125,7 @@ public class TestCloseNewtAWT extends UITestCase {
});
Thread.sleep(1000);
- // programatically issue windowClosing
- Toolkit tk = Toolkit.getDefaultToolkit();
- EventQueue evtQ = tk.getSystemEventQueue();
- evtQ.postEvent(new java.awt.event.WindowEvent(frame, java.awt.event.WindowEvent.WINDOW_CLOSING));
- Thread.sleep(200);
+ AWTRobotUtil.closeWindow(frame);
GLProfile.shutdown();
}
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestRemoteGLWindows01NEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestRemoteGLWindows01NEWT.java
index 96ea861a7..6b501e31d 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/TestRemoteGLWindows01NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/TestRemoteGLWindows01NEWT.java
@@ -49,6 +49,7 @@ public class TestRemoteGLWindows01NEWT extends UITestCase {
static GLProfile glp;
static int width, height;
static long durationPerTest = 100; // ms
+ static String remoteDisplay = "nowhere:0.0";
@BeforeClass
public static void initClass() {
@@ -59,7 +60,7 @@ public class TestRemoteGLWindows01NEWT extends UITestCase {
glp = GLProfile.getDefault();
}
- static GLWindow createWindow(Screen screen, GLCapabilities caps)
+ static GLWindow createWindow(Screen screen, GLCapabilities caps, GLEventListener demo)
throws InterruptedException
{
Assert.assertNotNull(caps);
@@ -74,8 +75,7 @@ public class TestRemoteGLWindows01NEWT extends UITestCase {
glWindow = GLWindow.create(caps);
Assert.assertNotNull(glWindow);
}
-
- GLEventListener demo = new Gears();
+
glWindow.addGLEventListener(demo);
glWindow.setSize(512, 512);
@@ -96,42 +96,49 @@ public class TestRemoteGLWindows01NEWT extends UITestCase {
@Test
public void testRemoteWindow01() throws InterruptedException {
+ Animator animator = new Animator();
GLCapabilities caps = new GLCapabilities(glp);
Assert.assertNotNull(caps);
- GLWindow window1 = createWindow(null, caps); // local
+ GLWindow window1 = createWindow(null, caps, new Gears(1)); // local with vsync
Assert.assertEquals(true,window1.isNativeValid());
Assert.assertEquals(true,window1.isVisible());
AbstractGraphicsDevice device1 = window1.getScreen().getDisplay().getGraphicsDevice();
System.err.println("GLProfiles window1: "+device1.getConnection()+": "+GLProfile.glAvailabilityToString(device1));
- Animator animator1 = new Animator(window1);
- animator1.start();
+ animator.add(window1);
+ // Remote Display/Device/Screen/Window ..
// Eager initialization of NEWT Display -> AbstractGraphicsDevice -> GLProfile (device)
- Display display2 = NewtFactory.createDisplay("charelle:0.0"); // remote display
+ Display display2; // remote display
+ AbstractGraphicsDevice device2;
+ Screen screen2;
+ GLWindow window2;
try {
- display2.createNative();
+ display2 = NewtFactory.createDisplay(remoteDisplay); // remote display
+ display2.createNative();
+ System.err.println(display2);
+ device2 = display2.getGraphicsDevice();
+ System.err.println(device2);
+ GLProfile.initProfiles(device2); // just to make sure
+ System.err.println("");
+ System.err.println("GLProfiles window2: "+device2.getConnection()+": "+GLProfile.glAvailabilityToString(device2));
+ screen2 = NewtFactory.createScreen(display2, 0); // screen 0
+ window2 = createWindow(screen2, caps, new Gears(0)); // remote, no vsync
} catch (NativeWindowException nwe) {
System.err.println(nwe);
Assume.assumeNoException(nwe);
destroyWindow(window1);
return;
}
- AbstractGraphicsDevice device2 = display2.getGraphicsDevice();
- GLProfile.initProfiles(device2); // just to make sure
- System.err.println("");
- System.err.println("GLProfiles window2: "+device2.getConnection()+": "+GLProfile.glAvailabilityToString(device2));
- Screen screen2 = NewtFactory.createScreen(display2, 0); // screen 0
- GLWindow window2 = createWindow(screen2, caps); // remote
Assert.assertEquals(true,window2.isNativeValid());
Assert.assertEquals(true,window2.isVisible());
- Animator animator2 = new Animator(window2);
- animator2.start();
+ animator.add(window2);
+ animator.start();
- for(int state=0; state*100<durationPerTest; state++) {
+ while(animator.getDuration()<durationPerTest) {
Thread.sleep(100);
}
@@ -151,9 +158,12 @@ public class TestRemoteGLWindows01NEWT extends UITestCase {
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
durationPerTest = atoi(args[++i]);
+ } else if(args[i].equals("-display")) {
+ remoteDisplay = args[++i];
}
}
System.out.println("durationPerTest: "+durationPerTest);
+ System.out.println("display: "+remoteDisplay);
String tstname = TestRemoteGLWindows01NEWT.class.getName();
org.junit.runner.JUnitCore.main(tstname);
}
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestRemoteWindow01NEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestRemoteWindow01NEWT.java
index f0cd3b89f..9c44545f2 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/TestRemoteWindow01NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/TestRemoteWindow01NEWT.java
@@ -43,6 +43,7 @@ import com.jogamp.opengl.test.junit.util.UITestCase;
public class TestRemoteWindow01NEWT extends UITestCase {
static int width, height;
+ static String remoteDisplay = "nowhere:0.0";
@BeforeClass
public static void initClass() {
@@ -109,18 +110,23 @@ public class TestRemoteWindow01NEWT extends UITestCase {
Assert.assertEquals(true,window1.isNativeValid());
Assert.assertEquals(true,window1.isVisible());
- Display display2 = NewtFactory.createDisplay("charelle:0.0"); // remote display
+ // Remote Display/Device/Screen/Window ..
+ Display display2;
+ AbstractGraphicsDevice device2;
+ Screen screen2;
+ Window window2;
try {
+ display2 = NewtFactory.createDisplay(remoteDisplay);
display2.createNative();
+ screen2 = NewtFactory.createScreen(display2, 0); // screen 0
+ window2 = createWindow(screen2, caps, width, height, true /* onscreen */, false /* undecorated */);
+ window2.setVisible(true);
} catch (NativeWindowException nwe) {
System.err.println(nwe);
Assume.assumeNoException(nwe);
destroyWindow(display1, screen1, window1);
return;
}
- Screen screen2 = NewtFactory.createScreen(display2, 0); // screen 0
- Window window2 = createWindow(screen2, caps, width, height, true /* onscreen */, false /* undecorated */);
- window2.setVisible(true);
Assert.assertEquals(true,window2.isNativeValid());
Assert.assertEquals(true,window2.isVisible());
@@ -132,6 +138,12 @@ public class TestRemoteWindow01NEWT extends UITestCase {
}
public static void main(String args[]) throws IOException {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-display")) {
+ remoteDisplay = args[++i];
+ }
+ }
+ System.out.println("display: "+remoteDisplay);
String tstname = TestRemoteWindow01NEWT.class.getName();
org.junit.runner.JUnitCore.main(tstname);
}
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestWindowClosingProtocol01AWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestWindowClosingProtocol01AWT.java
new file mode 100644
index 000000000..c7ac00934
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/newt/TestWindowClosingProtocol01AWT.java
@@ -0,0 +1,155 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``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 JogAmp Community OR
+ * CONTRIBUTORS 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.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.newt;
+
+import org.junit.Test;
+import org.junit.Assert;
+
+import java.lang.reflect.InvocationTargetException;
+import java.awt.Frame;
+import javax.swing.JFrame;
+import javax.swing.SwingUtilities;
+
+import javax.media.nativewindow.WindowClosingProtocol;
+
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.awt.GLCanvas;
+
+import com.jogamp.opengl.test.junit.jogl.demos.gl2.gears.Gears;
+import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+
+public class TestWindowClosingProtocol01AWT extends UITestCase {
+
+ @Test
+ public void testCloseFrameGLCanvas() throws InterruptedException, InvocationTargetException {
+ final Frame frame = new Frame("testCloseFrameGLCanvas AWT");
+
+ GLProfile glp = GLProfile.getDefault();
+ GLCapabilities caps = new GLCapabilities(glp);
+ GLCanvas glCanvas = new GLCanvas(caps);
+ glCanvas.addGLEventListener(new Gears());
+ frame.add(glCanvas);
+ frame.pack();
+ frame.setSize(512, 512);
+ frame.validate();
+ frame.setVisible(true);
+ Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true));
+
+ //
+ // close with op: DO_NOTHING_ON_CLOSE -> NOP (default)
+ //
+ int op = glCanvas.getDefaultCloseOperation();
+ Assert.assertEquals(WindowClosingProtocol.DO_NOTHING_ON_CLOSE, op);
+
+ AWTRobotUtil.closeWindow(frame);
+ Assert.assertEquals(true, frame.isVisible());
+ Assert.assertEquals(true, frame.isDisplayable());
+ Assert.assertEquals(true, glCanvas.isValid());
+ Assert.assertEquals(true, glCanvas.isVisible());
+ Assert.assertEquals(true, glCanvas.isDisplayable());
+
+ //
+ // close with op (GLCanvas): DISPOSE_ON_CLOSE -> dispose
+ //
+ glCanvas.setDefaultCloseOperation(WindowClosingProtocol.DISPOSE_ON_CLOSE);
+ op = glCanvas.getDefaultCloseOperation();
+ Assert.assertEquals(WindowClosingProtocol.DISPOSE_ON_CLOSE, op);
+
+ AWTRobotUtil.closeWindow(frame);
+ Assert.assertEquals(true, frame.isVisible());
+ Assert.assertEquals(true, frame.isDisplayable());
+ Assert.assertEquals(false, glCanvas.isValid());
+ Assert.assertEquals(true, glCanvas.isVisible());
+ Assert.assertEquals(false, glCanvas.isDisplayable());
+
+ SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ frame.dispose();
+ } });
+ }
+
+ @Test
+ public void testCloseJFrameGLCanvas() throws InterruptedException, InvocationTargetException {
+ final JFrame frame = new JFrame("testCloseJFrameGLCanvas AWT");
+
+ GLProfile glp = GLProfile.getDefault();
+ GLCapabilities caps = new GLCapabilities(glp);
+ GLCanvas glCanvas = new GLCanvas(caps);
+ glCanvas.addGLEventListener(new Gears());
+ frame.getContentPane().add(glCanvas);
+ frame.pack();
+ frame.setSize(512, 512);
+ frame.validate();
+ frame.setVisible(true);
+ Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true));
+
+ //
+ // close with op: DO_NOTHING_ON_CLOSE -> NOP / HIDE (default)
+ //
+ Assert.assertEquals(JFrame.HIDE_ON_CLOSE, frame.getDefaultCloseOperation());
+ int op = glCanvas.getDefaultCloseOperation();
+ Assert.assertEquals(WindowClosingProtocol.DO_NOTHING_ON_CLOSE, op);
+
+ AWTRobotUtil.closeWindow(frame);
+ Assert.assertEquals(false, frame.isVisible());
+ Assert.assertEquals(true, frame.isDisplayable());
+ Assert.assertEquals(true, glCanvas.isValid());
+ Assert.assertEquals(true, glCanvas.isVisible());
+ Assert.assertEquals(true, glCanvas.isDisplayable());
+
+ SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ frame.setVisible(true);
+ } });
+ Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true));
+
+ //
+ // close with op (JFrame): DISPOSE_ON_CLOSE -- GLCanvas --> dispose
+ //
+ frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
+ Assert.assertEquals(JFrame.DISPOSE_ON_CLOSE, frame.getDefaultCloseOperation());
+ op = glCanvas.getDefaultCloseOperation();
+ Assert.assertEquals(WindowClosingProtocol.DISPOSE_ON_CLOSE, op);
+
+ AWTRobotUtil.closeWindow(frame);
+ Assert.assertEquals(false, frame.isVisible());
+ Assert.assertEquals(false, frame.isDisplayable());
+ Assert.assertEquals(false, glCanvas.isValid());
+ Assert.assertEquals(true, glCanvas.isVisible());
+ Assert.assertEquals(false, glCanvas.isDisplayable());
+ }
+
+ public static void main(String[] args) {
+ String tstname = TestWindowClosingProtocol01AWT.class.getName();
+ org.junit.runner.JUnitCore.main(tstname);
+ }
+
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestWindowClosingProtocol02NEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestWindowClosingProtocol02NEWT.java
new file mode 100644
index 000000000..f9a6003e7
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/newt/TestWindowClosingProtocol02NEWT.java
@@ -0,0 +1,116 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``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 JogAmp Community OR
+ * CONTRIBUTORS 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.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.newt;
+
+import com.jogamp.newt.event.WindowAdapter;
+import com.jogamp.newt.event.WindowEvent;
+import java.lang.reflect.InvocationTargetException;
+
+import org.junit.Test;
+import org.junit.Assert;
+
+import javax.media.nativewindow.WindowClosingProtocol;
+
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLProfile;
+
+import com.jogamp.newt.opengl.GLWindow;
+
+import com.jogamp.opengl.test.junit.jogl.demos.gl2.gears.Gears;
+import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+
+public class TestWindowClosingProtocol02NEWT extends UITestCase {
+
+ static class NEWTWindowClosingAdapter extends WindowAdapter {
+ volatile boolean windowDestroyNotifyReached = false;
+
+ public void reset() {
+ windowDestroyNotifyReached = false;
+ }
+ public boolean windowDestroyNotifyReached() {
+ return windowDestroyNotifyReached;
+ }
+ public void windowDestroyNotify(WindowEvent e) {
+ windowDestroyNotifyReached = true;
+ }
+ }
+
+ @Test
+ public void testCloseGLWindow() throws InterruptedException, InvocationTargetException {
+ GLProfile glp = GLProfile.getDefault();
+ GLCapabilities caps = new GLCapabilities(glp);
+ final GLWindow glWindow = GLWindow.create(caps);
+ final NEWTWindowClosingAdapter newtWindowClosingAdapter = new NEWTWindowClosingAdapter();
+
+ glWindow.addWindowListener(newtWindowClosingAdapter);
+ glWindow.addGLEventListener(new Gears());
+ glWindow.setSize(512, 512);
+ glWindow.setVisible(true);
+ Assert.assertEquals(true, glWindow.isVisible());
+
+ // CHECK DEFAULT ..
+ int op = glWindow.getDefaultCloseOperation();
+ Assert.assertEquals(WindowClosingProtocol.DISPOSE_ON_CLOSE, op);
+
+ //
+ // close with op: DO_NOTHING_ON_CLOSE -> NOP
+ //
+ glWindow.setDefaultCloseOperation(WindowClosingProtocol.DO_NOTHING_ON_CLOSE);
+ op = glWindow.getDefaultCloseOperation();
+ Assert.assertEquals(WindowClosingProtocol.DO_NOTHING_ON_CLOSE, op);
+
+ AWTRobotUtil.closeWindow(glWindow);
+ Assert.assertEquals(true, glWindow.isValid());
+ Assert.assertEquals(true, glWindow.isVisible());
+ Assert.assertEquals(true, glWindow.isNativeValid());
+ Assert.assertEquals(true, newtWindowClosingAdapter.windowDestroyNotifyReached());
+ newtWindowClosingAdapter.reset();
+
+ //
+ // close with op (GLCanvas): DISPOSE_ON_CLOSE -> dispose
+ //
+ glWindow.setDefaultCloseOperation(WindowClosingProtocol.DISPOSE_ON_CLOSE);
+ op = glWindow.getDefaultCloseOperation();
+ Assert.assertEquals(WindowClosingProtocol.DISPOSE_ON_CLOSE, op);
+
+ AWTRobotUtil.closeWindow(glWindow);
+ Assert.assertEquals(true, AWTRobotUtil.waitForVisible(glWindow, false));
+ Assert.assertEquals(true, glWindow.isValid());
+ Assert.assertEquals(false, glWindow.isVisible());
+ Assert.assertEquals(false, glWindow.isNativeValid());
+ Assert.assertEquals(true, newtWindowClosingAdapter.windowDestroyNotifyReached());
+ }
+
+ public static void main(String[] args) {
+ String tstname = TestWindowClosingProtocol02NEWT.class.getName();
+ org.junit.runner.JUnitCore.main(tstname);
+ }
+
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestWindowClosingProtocol03NewtAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestWindowClosingProtocol03NewtAWT.java
new file mode 100644
index 000000000..e69aae992
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/newt/TestWindowClosingProtocol03NewtAWT.java
@@ -0,0 +1,140 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``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 JogAmp Community OR
+ * CONTRIBUTORS 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.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.newt;
+
+import com.jogamp.newt.awt.NewtCanvasAWT;
+import com.jogamp.newt.event.WindowAdapter;
+import com.jogamp.newt.event.WindowEvent;
+import com.jogamp.newt.opengl.GLWindow;
+import org.junit.Test;
+import org.junit.Assert;
+
+import java.lang.reflect.InvocationTargetException;
+import java.awt.Frame;
+import javax.swing.JFrame;
+import javax.swing.SwingUtilities;
+
+import javax.media.nativewindow.WindowClosingProtocol;
+
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.awt.GLCanvas;
+
+import com.jogamp.opengl.test.junit.jogl.demos.gl2.gears.Gears;
+import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+
+public class TestWindowClosingProtocol03NewtAWT extends UITestCase {
+
+ static class NEWTWindowClosingAdapter extends WindowAdapter {
+ volatile boolean windowDestroyNotifyReached = false;
+
+ public void reset() {
+ windowDestroyNotifyReached = false;
+ }
+ public boolean windowDestroyNotifyReached() {
+ return windowDestroyNotifyReached;
+ }
+ public void windowDestroyNotify(WindowEvent e) {
+ windowDestroyNotifyReached = true;
+ }
+ }
+
+ @Test
+ public void testCloseJFrameNewtCanvasAWT() throws InterruptedException, InvocationTargetException {
+ final JFrame frame = new JFrame("testCloseJFrameNewtCanvasAWT");
+
+ GLProfile glp = GLProfile.getDefault();
+ GLCapabilities caps = new GLCapabilities(glp);
+ final GLWindow glWindow = GLWindow.create(caps);
+ final NEWTWindowClosingAdapter newtWindowClosingAdapter = new NEWTWindowClosingAdapter();
+
+ glWindow.addWindowListener(newtWindowClosingAdapter);
+ glWindow.addGLEventListener(new Gears());
+
+ NewtCanvasAWT newtCanvas = new NewtCanvasAWT(glWindow);
+
+ frame.getContentPane().add(newtCanvas);
+ frame.pack();
+ frame.setSize(512, 512);
+ frame.validate();
+ frame.setVisible(true);
+ Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true));
+
+ //
+ // close with op: DO_NOTHING_ON_CLOSE -> NOP / HIDE (default)
+ //
+ Assert.assertEquals(JFrame.HIDE_ON_CLOSE, frame.getDefaultCloseOperation());
+ int op = newtCanvas.getDefaultCloseOperation();
+ Assert.assertEquals(WindowClosingProtocol.DO_NOTHING_ON_CLOSE, op);
+
+ AWTRobotUtil.closeWindow(frame);
+ Assert.assertEquals(false, frame.isVisible());
+ Assert.assertEquals(true, frame.isDisplayable());
+ Assert.assertEquals(true, newtCanvas.isValid());
+ Assert.assertEquals(true, newtCanvas.isVisible());
+ Assert.assertEquals(true, newtCanvas.isDisplayable());
+ Assert.assertEquals(true, glWindow.isValid());
+ Assert.assertEquals(false, glWindow.isVisible());
+ Assert.assertEquals(true, glWindow.isNativeValid());
+ Assert.assertEquals(true, newtWindowClosingAdapter.windowDestroyNotifyReached());
+ newtWindowClosingAdapter.reset();
+
+ SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ frame.setVisible(true);
+ } });
+ Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true));
+
+ //
+ // close with op (JFrame): DISPOSE_ON_CLOSE -- newtCanvas -- glWindow --> dispose
+ //
+ frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
+ Assert.assertEquals(JFrame.DISPOSE_ON_CLOSE, frame.getDefaultCloseOperation());
+ op = newtCanvas.getDefaultCloseOperation();
+ Assert.assertEquals(WindowClosingProtocol.DISPOSE_ON_CLOSE, op);
+
+ AWTRobotUtil.closeWindow(frame);
+ Assert.assertEquals(false, frame.isVisible());
+ Assert.assertEquals(false, frame.isDisplayable());
+ Assert.assertEquals(false, newtCanvas.isValid());
+ Assert.assertEquals(true, newtCanvas.isVisible());
+ Assert.assertEquals(false, newtCanvas.isDisplayable());
+ Assert.assertEquals(true, glWindow.isValid());
+ Assert.assertEquals(false, glWindow.isVisible());
+ Assert.assertEquals(false, glWindow.isNativeValid());
+ Assert.assertEquals(true, newtWindowClosingAdapter.windowDestroyNotifyReached());
+ }
+
+ public static void main(String[] args) {
+ String tstname = TestWindowClosingProtocol03NewtAWT.class.getName();
+ org.junit.runner.JUnitCore.main(tstname);
+ }
+
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/util/AWTRobotUtil.java b/src/test/com/jogamp/opengl/test/junit/util/AWTRobotUtil.java
index 61aa95bf8..9812be5f2 100644
--- a/src/test/com/jogamp/opengl/test/junit/util/AWTRobotUtil.java
+++ b/src/test/com/jogamp/opengl/test/junit/util/AWTRobotUtil.java
@@ -28,15 +28,17 @@
package com.jogamp.opengl.test.junit.util;
+import com.jogamp.newt.impl.WindowImplAccess;
import java.lang.reflect.InvocationTargetException;
import java.awt.AWTException;
import java.awt.Component;
import java.awt.Container;
+import java.awt.EventQueue;
import java.awt.KeyboardFocusManager;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Robot;
-import java.awt.Window;
+import java.awt.Toolkit;
import java.awt.event.InputEvent;
import javax.swing.JFrame;
@@ -92,7 +94,7 @@ public class AWTRobotUtil {
*
* @return True if the Window became the global focused Window within TIME_OUT
*/
- public static boolean toFront(Robot robot, Window window)
+ public static boolean toFront(Robot robot, final java.awt.Window window)
throws AWTException, InterruptedException, InvocationTargetException {
if(null == robot) {
@@ -104,12 +106,11 @@ public class AWTRobotUtil {
robot.mouseMove( (int) p0.getX(), (int) p0.getY() );
robot.delay(ROBOT_DELAY);
- final Window f_window = window;
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
- f_window.setVisible(true);
- f_window.toFront();
- f_window.requestFocus();
+ window.setVisible(true);
+ window.toFront();
+ window.requestFocus();
}});
robot.delay(ROBOT_DELAY);
@@ -126,22 +127,12 @@ public class AWTRobotUtil {
*/
public static void centerMouse(Robot robot, Object obj)
throws AWTException, InterruptedException, InvocationTargetException {
- Component comp = null;
- com.jogamp.newt.Window win = null;
if(null == robot) {
robot = new Robot();
robot.setAutoWaitForIdle(true);
}
- if(obj instanceof com.jogamp.newt.Window) {
- win = (com.jogamp.newt.Window) obj;
- } else if(obj instanceof Component) {
- comp = (Component) obj;
- } else {
- throw new RuntimeException("Neither AWT nor NEWT: "+obj);
- }
-
Point p0 = getCenterLocation(obj, false);
System.err.println("robot pos: "+p0);
@@ -334,5 +325,45 @@ public class AWTRobotUtil {
return false;
}
+ /**
+ *
+ * @return True if the Component becomes <code>visible</code> within TIME_OUT
+ */
+ public static boolean waitForVisible(Object obj, boolean visible) throws InterruptedException {
+ int wait;
+ if(obj instanceof Component) {
+ Component comp = (Component) obj;
+ for (wait=0; wait<POLL_DIVIDER && visible != comp.isVisible(); wait++) {
+ Thread.sleep(TIME_OUT/POLL_DIVIDER);
+ }
+ } else if(obj instanceof com.jogamp.newt.Window) {
+ com.jogamp.newt.Window win = (com.jogamp.newt.Window) obj;
+ for (wait=0; wait<POLL_DIVIDER && visible != win.isVisible(); wait++) {
+ Thread.sleep(TIME_OUT/POLL_DIVIDER);
+ }
+ } else {
+ throw new RuntimeException("Neither AWT nor NEWT: "+obj);
+ }
+ return wait<POLL_DIVIDER;
+ }
+
+ /**
+ * Programmatically issue windowClosing on AWT or NEWT
+ *
+ * @param obj either an AWT Window (Frame, JFrame) or NEWT Window
+ * @throws InterruptedException
+ */
+ public static void closeWindow(Object obj) throws InterruptedException {
+ if(obj instanceof java.awt.Window) {
+ java.awt.Window win = (java.awt.Window) obj;
+ Toolkit tk = Toolkit.getDefaultToolkit();
+ EventQueue evtQ = tk.getSystemEventQueue();
+ evtQ.postEvent(new java.awt.event.WindowEvent(win, java.awt.event.WindowEvent.WINDOW_CLOSING));
+ } else if(obj instanceof com.jogamp.newt.Window) {
+ com.jogamp.newt.Window win = (com.jogamp.newt.Window) obj;
+ WindowImplAccess.windowDestroyNotify(win);
+ }
+ Thread.sleep(200);
+ }
}