diff options
author | Sven Gothel <[email protected]> | 2010-12-19 14:54:08 +0100 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2010-12-19 14:54:08 +0100 |
commit | 2cbab63bd6c230d31b8ae6f1d794ad49bf23bb53 (patch) | |
tree | 9da105f466b81424ae089e59e4bd67fce7c32d54 /src | |
parent | 2323c30c23b6f9eb7d7ccf94e6cdcbcb3d2f34a6 (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')
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); + } } |