diff options
Diffstat (limited to 'src')
78 files changed, 1125 insertions, 575 deletions
diff --git a/src/jogl/classes/com/jogamp/opengl/GLAutoDrawableDelegate.java b/src/jogl/classes/com/jogamp/opengl/GLAutoDrawableDelegate.java index 206331ac0..0f0f03ac4 100644 --- a/src/jogl/classes/com/jogamp/opengl/GLAutoDrawableDelegate.java +++ b/src/jogl/classes/com/jogamp/opengl/GLAutoDrawableDelegate.java @@ -51,12 +51,12 @@ import jogamp.opengl.GLDrawableImpl; * utilizing already created {@link GLDrawable} and {@link GLContext} instances. * <p> * Since no native windowing system events are being processed, it is recommended - * to handle at least: + * to handle at least the {@link com.jogamp.newt.event.WindowEvent window events}: * <ul> * <li>{@link com.jogamp.newt.event.WindowListener#windowRepaint(com.jogamp.newt.event.WindowUpdateEvent) repaint} using {@link #windowRepaintOp()}</li> * <li>{@link com.jogamp.newt.event.WindowListener#windowResized(com.jogamp.newt.event.WindowEvent) resize} using {@link #windowResizedOp()}</li> - * <li>{@link com.jogamp.newt.event.WindowListener#windowDestroyNotify(com.jogamp.newt.event.WindowEvent) destroy-notify} using {@link #windowDestroyNotifyOp()}</li> - * </ul> + * </ul> + * and setup a {@link com.jogamp.newt.Window#setWindowDestroyNotifyAction(Runnable) custom toolkit destruction} issuing {@link #windowDestroyNotifyOp()}. * </p> * <p> * See example {@link com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableDelegateNEWT TestGLAutoDrawableDelegateNEWT}. diff --git a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java index dc4fe955c..ebc25e2ad 100644 --- a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java +++ b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java @@ -86,6 +86,7 @@ import javax.media.opengl.Threading; import com.jogamp.common.GlueGenVersion; import com.jogamp.common.util.VersionUtil; +import com.jogamp.common.util.awt.AWTEDTExecutor; import com.jogamp.common.util.locks.LockFactory; import com.jogamp.common.util.locks.RecursiveLock; import com.jogamp.nativewindow.awt.AWTGraphicsConfiguration; @@ -95,7 +96,6 @@ import com.jogamp.nativewindow.awt.AWTWindowClosingProtocol; import com.jogamp.nativewindow.awt.JAWTWindow; import com.jogamp.opengl.JoglVersion; -import jogamp.common.awt.AWTEDTExecutor; import jogamp.opengl.Debug; import jogamp.opengl.GLContextImpl; import jogamp.opengl.GLDrawableHelper; @@ -176,7 +176,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing public void run() { GLCanvas.this.destroyImpl( true ); } - }); + }, null); /** Creates a new GLCanvas component with a default set of OpenGL capabilities, using the default OpenGL capabilities selection @@ -460,7 +460,6 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing if( isVisible() ) { Threading.invoke(true, displayOnEDTAction, getTreeLock()); } - awtWindowClosingProtocol.addClosingListenerOneShot(); } /** @@ -568,7 +567,8 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing // for all launch flavors (applet/javaws/..) // validateGLDrawable(); } - + awtWindowClosingProtocol.addClosingListener(); + if(DEBUG) { System.err.println(getThreadName()+": Info: addNotify - end: peer: "+getPeer()); } diff --git a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java index 2b99bb570..6c28c75ab 100644 --- a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java +++ b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java @@ -174,7 +174,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing public void run() { GLJPanel.this.destroy(); } - }); + }, null); static { // Force eager initialization of part of the Java2D class since @@ -369,6 +369,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing @Override public void addNotify() { super.addNotify(); + awtWindowClosingProtocol.addClosingListener(); if (DEBUG) { System.err.println(getThreadName()+": GLJPanel.addNotify()"); } @@ -677,8 +678,6 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing if (!isInitialized) { backend.initialize(); } - - awtWindowClosingProtocol.addClosingListenerOneShot(); } @Override diff --git a/src/jogl/classes/jogamp/opengl/awt/AWTThreadingPlugin.java b/src/jogl/classes/jogamp/opengl/awt/AWTThreadingPlugin.java index ae8969d07..56f00b370 100644 --- a/src/jogl/classes/jogamp/opengl/awt/AWTThreadingPlugin.java +++ b/src/jogl/classes/jogamp/opengl/awt/AWTThreadingPlugin.java @@ -44,7 +44,8 @@ import java.awt.EventQueue; import javax.media.opengl.GLException; -import jogamp.common.awt.AWTEDTExecutor; +import com.jogamp.common.util.awt.AWTEDTExecutor; + import jogamp.opengl.GLWorkerThread; import jogamp.opengl.ThreadingImpl; import jogamp.opengl.ToolkitThreadingPlugin; diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLDrawable.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLDrawable.java index 6c7893c3e..b65f5dd2f 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLDrawable.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLDrawable.java @@ -173,7 +173,7 @@ public class WindowsPbufferWGLDrawable extends WindowsWGLDrawable { pformats, nformatsTmp)) { throw new GLException("pbuffer creation error: wglChoosePixelFormat() failed"); } - final int nformats = nformatsTmp.get(0); + final int nformats = Math.min(nformatsTmp.get(0), WindowsWGLGraphicsConfiguration.MAX_PFORMATS); if (nformats <= 0) { throw new GLException("pbuffer creation error: Couldn't find a suitable pixel format"); } diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfiguration.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfiguration.java index 651d981ab..7709e5884 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfiguration.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfiguration.java @@ -361,7 +361,7 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio } return null; } - final int numFormats = numFormatsTmp.get(0); + final int numFormats = Math.min(numFormatsTmp.get(0), WindowsWGLGraphicsConfiguration.MAX_PFORMATS); final int[] pformats; if( 0 < numFormats ) { pformats = new int[numFormats]; diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/awt/AWTWindowClosingProtocol.java b/src/nativewindow/classes/com/jogamp/nativewindow/awt/AWTWindowClosingProtocol.java index d78b4ac15..e499ff705 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/awt/AWTWindowClosingProtocol.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/awt/AWTWindowClosingProtocol.java @@ -33,6 +33,7 @@ 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 jogamp.nativewindow.awt.AWTMisc; @@ -40,15 +41,22 @@ import jogamp.nativewindow.awt.AWTMisc; public class AWTWindowClosingProtocol implements WindowClosingProtocol { private Component comp; - private Runnable closingOperation; - private volatile boolean closingListenerSet = false; + private Runnable closingOperationClose; + private Runnable closingOperationNOP; + private boolean closingListenerSet = false; private Object closingListenerLock = new Object(); private WindowClosingMode defaultCloseOperation = WindowClosingMode.DISPOSE_ON_CLOSE; private boolean defaultCloseOperationSetByUser = false; - public AWTWindowClosingProtocol(Component comp, Runnable closingOperation) { + /** + * @param comp mandatory AWT component which AWT Window is being queried by parent traversal + * @param closingOperationClose mandatory closing operation, triggered if windowClosing and {@link WindowClosingMode#DISPOSE_ON_CLOSE} + * @param closingOperationNOP optional closing operation, triggered if windowClosing and {@link WindowClosingMode#DO_NOTHING_ON_CLOSE} + */ + public AWTWindowClosingProtocol(Component comp, Runnable closingOperationClose, Runnable closingOperationNOP) { this.comp = comp; - this.closingOperation = closingOperation; + this.closingOperationClose = closingOperationClose; + this.closingOperationNOP = closingOperationNOP; } class WindowClosingAdapter extends WindowAdapter { @@ -59,54 +67,50 @@ public class AWTWindowClosingProtocol implements WindowClosingProtocol { if( WindowClosingMode.DISPOSE_ON_CLOSE == op ) { // we have to issue this call right away, // otherwise the window gets destroyed - closingOperation.run(); + closingOperationClose.run(); + } else if( null != closingOperationNOP ){ + closingOperationNOP.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. + * Adds this closing listener to the components Window if exist and only one time. + * <p> + * If the closing listener is already added, and {@link IllegalStateException} is thrown. + * </p> * - * @return + * @return true if added, otherwise false. + * @throws IllegalStateException */ - public final boolean addClosingListenerOneShot() { - if(!closingListenerSet) { // volatile: ok + public final boolean addClosingListener() throws IllegalStateException { synchronized(closingListenerLock) { - if(!closingListenerSet) { - closingListenerSet=addClosingListenerImpl(); - return closingListenerSet; - } + if(closingListenerSet) { + throw new IllegalStateException("WindowClosingListener already set"); + } + final Window w = AWTMisc.getWindow(comp); + if(null!=w) { + w.addWindowListener(windowClosingAdapter); + closingListenerSet = true; + return true; + } } - } - return false; + return false; } public final boolean removeClosingListener() { - if(closingListenerSet) { // volatile: ok synchronized(closingListenerLock) { - if(closingListenerSet) { - Window w = AWTMisc.getWindow(comp); - if(null!=w) { - w.removeWindowListener(windowClosingAdapter); - closingListenerSet = false; - return true; - } - } + if(closingListenerSet) { + final Window w = AWTMisc.getWindow(comp); + if(null!=w) { + w.removeWindowListener(windowClosingAdapter); + closingListenerSet = false; + return true; + } + } } - } - return false; + return false; } /** diff --git a/src/nativewindow/classes/javax/media/nativewindow/NativeWindow.java b/src/nativewindow/classes/javax/media/nativewindow/NativeWindow.java index 12e202975..a740ebbe0 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/NativeWindow.java +++ b/src/nativewindow/classes/javax/media/nativewindow/NativeWindow.java @@ -54,8 +54,7 @@ import javax.media.nativewindow.util.Point; public interface NativeWindow extends NativeSurface { /** - * destroys the window and releases - * windowing related resources. + * Destroys this window incl. releasing all related resources. */ public void destroy(); diff --git a/src/nativewindow/classes/javax/media/nativewindow/WindowClosingProtocol.java b/src/nativewindow/classes/javax/media/nativewindow/WindowClosingProtocol.java index 884c916e4..02f68f442 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/WindowClosingProtocol.java +++ b/src/nativewindow/classes/javax/media/nativewindow/WindowClosingProtocol.java @@ -37,6 +37,10 @@ package javax.media.nativewindow; * this protocol default behavior {@link WindowClosingMode#DISPOSE_ON_CLOSE DISPOSE_ON_CLOSE} shall be used.</p> */ public interface WindowClosingProtocol { + + /** + * Window closing mode if triggered by toolkit close operation. + */ public enum WindowClosingMode { /** * Do nothing on native window close operation.<br> diff --git a/src/newt/classes/com/jogamp/newt/Window.java b/src/newt/classes/com/jogamp/newt/Window.java index cc42465f1..ab1eef308 100644 --- a/src/newt/classes/com/jogamp/newt/Window.java +++ b/src/newt/classes/com/jogamp/newt/Window.java @@ -28,12 +28,15 @@ package com.jogamp.newt; +import com.jogamp.newt.event.WindowEvent; import com.jogamp.newt.event.WindowListener; import com.jogamp.newt.event.KeyListener; import com.jogamp.newt.event.KeyEvent; import com.jogamp.newt.event.InputEvent; import com.jogamp.newt.event.MouseListener; import jogamp.newt.Debug; +import jogamp.newt.WindowImpl; + import javax.media.nativewindow.CapabilitiesChooser; import javax.media.nativewindow.CapabilitiesImmutable; import javax.media.nativewindow.NativeWindow; @@ -104,14 +107,26 @@ public interface Window extends NativeWindow, WindowClosingProtocol { CapabilitiesImmutable getChosenCapabilities(); /** - * Destroy the Window and it's children, incl. native destruction.<br> - * The Window can be recreate via {@link #setVisible(boolean) setVisible(true)}. - * <p>Visibility is set to false.</p> + * {@inheritDoc} + * <p> + * Also iterates through this window's children and destroys them. + * </p> + * <p> + * Visibility is set to false. + * </p> + * <p> + * Method sends out {@link WindowEvent#EVENT_WINDOW_DESTROY_NOTIFY pre-} and + * {@link WindowEvent#EVENT_WINDOW_DESTROYED post-} destruction events + * to all of it's {@link WindowListener}. + * </p> * <p> * This method invokes {@link Screen#removeReference()} after it's own destruction,<br> * which will issue {@link Screen#destroy()} if the reference count becomes 0.<br> * This destruction sequence shall end up in {@link Display#destroy()}, if all reference counts become 0. * </p> + * <p> + * The Window can be recreate via {@link #setVisible(boolean) setVisible(true)}. + * </p> * @see #destroy() * @see #setVisible(boolean) */ @@ -119,6 +134,16 @@ public interface Window extends NativeWindow, WindowClosingProtocol { void destroy(); /** + * Set a custom action handling destruction issued by a {@link WindowImpl#windowDestroyNotify(boolean) toolkit triggered window destroy} + * replacing the default {@link #destroy()} action. + * <p> + * The custom action shall call {@link #destroy()} + * but may perform further tasks before and after. + * </p> + */ + void setWindowDestroyNotifyAction(Runnable r); + + /** * <code>setVisible</code> makes the window and children visible if <code>visible</code> is true, * otherwise the window and children becomes invisible. * <p> @@ -383,10 +408,13 @@ public interface Window extends NativeWindow, WindowClosingProtocol { // WindowListener // + /** + * Send a {@link WindowEvent} to all {@link WindowListener}. + * @param eventType a {@link WindowEvent} type, e.g. {@link WindowEvent#EVENT_WINDOW_REPAINT}. + */ public void sendWindowEvent(int eventType); /** - * * Appends the given {@link com.jogamp.newt.event.WindowListener} to the end of * the list. */ diff --git a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java index 3503dabd5..3c10859bf 100644 --- a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java +++ b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java @@ -51,6 +51,7 @@ import javax.swing.MenuSelectionManager; import jogamp.nativewindow.awt.AWTMisc; import jogamp.newt.Debug; +import jogamp.newt.WindowImpl; import jogamp.newt.awt.NewtFactoryAWT; import jogamp.newt.awt.event.AWTParentWindowAdapter; import jogamp.newt.driver.DriverClearFocus; @@ -59,9 +60,9 @@ import com.jogamp.nativewindow.awt.AWTWindowClosingProtocol; import com.jogamp.nativewindow.awt.JAWTWindow; import com.jogamp.newt.Display; import com.jogamp.newt.Window; -import com.jogamp.newt.event.InputEvent; import com.jogamp.newt.event.KeyEvent; import com.jogamp.newt.event.KeyListener; +import com.jogamp.newt.event.NEWTEvent; import com.jogamp.newt.event.WindowAdapter; import com.jogamp.newt.event.WindowEvent; import com.jogamp.newt.event.WindowListener; @@ -88,16 +89,22 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto private boolean newtChildAttached = false; private boolean isOnscreen = true; private WindowClosingMode newtChildCloseOp; - private AWTAdapter awtAdapter = null; + private AWTParentWindowAdapter awtAdapter = null; private AWTAdapter awtMouseAdapter = null; private AWTAdapter awtKeyAdapter = null; private AWTWindowClosingProtocol awtWindowClosingProtocol = new AWTWindowClosingProtocol(this, new Runnable() { public void run() { - NewtCanvasAWT.this.destroy(); + NewtCanvasAWT.this.destroyImpl(false /* removeNotify */, true /* windowClosing */); } - }); + }, new Runnable() { + public void run() { + if( newtChild != null ) { + newtChild.sendWindowEvent(WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY); + } + } + } ); /** * Instantiates a NewtCanvas without a NEWT child.<br> @@ -209,7 +216,7 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto } public void keyTyped(KeyEvent e) { if(suppress) { - e.setAttachment(InputEvent.consumedTag); + e.setAttachment(NEWTEvent.consumedTag); suppress = false; // reset } } @@ -239,7 +246,7 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto } } if(suppress) { - evt.setAttachment(InputEvent.consumedTag); + evt.setAttachment(NEWTEvent.consumedTag); } if(DEBUG) { System.err.println("NewtCanvasAWT.focusKey: XXX: "+ks); @@ -361,27 +368,17 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto ", displayable "+isDisplayable()+", cont "+AWTMisc.getContainer(this)); } } + awtWindowClosingProtocol.addClosingListener(); } @Override public void removeNotify() { + awtWindowClosingProtocol.removeClosingListener(); + if( Beans.isDesignTime() ) { super.removeNotify(); } else { - java.awt.Container cont = AWTMisc.getContainer(this); - if(DEBUG) { - System.err.println("NewtCanvasAWT.removeNotify: "+newtChild+", from "+cont); - } - // Detach OLS early.. - final OffscreenLayerSurface ols = NativeWindowFactory.getOffscreenLayerSurface(newtChild, true); - if(null != ols && ols.isSurfaceLayerAttached()) { - ols.detachSurfaceLayer(); - } - detachNewtChild(cont); // will destroy context (offscreen -> onscreen) and implicit detachSurfaceLayer (if still attached) - - NewtFactoryAWT.destroyNativeWindow(jawtWindow); - jawtWindow=null; - + destroyImpl(true /* removeNotify */, false /* windowClosing */); super.removeNotify(); } } @@ -397,20 +394,32 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto * @see Window#destroy() */ public final void destroy() { + destroyImpl(false /* removeNotify */, false /* windowClosing */); + } + + private final void destroyImpl(boolean removeNotify, boolean windowClosing) { if( null !=newtChild ) { java.awt.Container cont = AWTMisc.getContainer(this); if(DEBUG) { - System.err.println("NewtCanvasAWT.destroy(): "+newtChild+", from "+cont); + System.err.println("NewtCanvasAWT.destroy(removeNotify "+removeNotify+", windowClosing "+windowClosing+"): nw "+newtWinHandleToHexString(newtChild)+", from "+cont); } - // Detach OLS early.. - final OffscreenLayerSurface ols = NativeWindowFactory.getOffscreenLayerSurface(newtChild, true); - if(null != ols && ols.isSurfaceLayerAttached()) { - ols.detachSurfaceLayer(); - } - detachNewtChild(cont); // will destroy context (offscreen -> onscreen) and implicit detachSurfaceLayer (if still attached) - newtChild.destroy(); - newtChild=null; + detachNewtChild(cont); + + if( !removeNotify ) { + final Window cWin = newtChild; + final Window dWin = cWin.getDelegatedWindow(); + newtChild=null; + if( windowClosing && dWin instanceof WindowImpl ) { + ((WindowImpl)dWin).windowDestroyNotify(true); + } else { + cWin.destroy(); + } + } } + if( ( removeNotify || windowClosing ) && null!=jawtWindow) { + NewtFactoryAWT.destroyNativeWindow(jawtWindow); + jawtWindow=null; + } } @Override @@ -501,8 +510,6 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto return false; } - awtWindowClosingProtocol.addClosingListenerOneShot(); - if( attachNewtChild && !newtChildAttached && null != newtChild ) { attachNewtChild(cont); } @@ -535,11 +542,11 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto throw new InternalError("XXX"); } isOnscreen = jawtWindow.getGraphicsConfiguration().getChosenCapabilities().isOnscreen(); - awtAdapter = new AWTParentWindowAdapter(jawtWindow, newtChild).addTo(this); + awtAdapter = (AWTParentWindowAdapter) new AWTParentWindowAdapter(jawtWindow, newtChild).addTo(this); + awtAdapter.removeWindowClosingFrom(this); // we utilize AWTWindowClosingProtocol triggered destruction! newtChild.addWindowListener(clearAWTMenusOnNewtFocus); newtChild.setFocusAction(focusAction); // enable AWT focus traversal newtChildCloseOp = newtChild.setDefaultCloseOperation(WindowClosingMode.DO_NOTHING_ON_CLOSE); - awtWindowClosingProtocol.addClosingListenerOneShot(); keyboardFocusManager = KeyboardFocusManager.getCurrentKeyboardFocusManager(); keyboardFocusManager.addPropertyChangeListener("focusOwner", focusPropertyChangeListener); if(isOnscreen) { @@ -554,7 +561,6 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto newtChild.removeWindowListener(clearAWTMenusOnNewtFocus); newtChild.setFocusAction(null); newtChild.setDefaultCloseOperation(newtChildCloseOp); - awtWindowClosingProtocol.removeClosingListener(); } } } @@ -611,7 +617,14 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto newtChild.setFocusAction(null); // no AWT focus traversal .. configureNewtChild(false); newtChild.setVisible(false); - newtChild.reparentWindow(null); + + // Detach OLS early.. + final OffscreenLayerSurface ols = NativeWindowFactory.getOffscreenLayerSurface(newtChild, true); + if(null != ols && ols.isSurfaceLayerAttached()) { + ols.detachSurfaceLayer(); + } + newtChild.reparentWindow(null); // will destroy context (offscreen -> onscreen) and implicit detachSurfaceLayer (if still attached) + if(DEBUG) { System.err.println("NewtCanvasAWT.detachNewtChild.X: win "+newtWinHandleToHexString(newtChild)+", EDTUtil: cur "+newtChild.getScreen().getDisplay().getEDTUtil()+", comp "+this); } diff --git a/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtAppletBase.java b/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtAppletBase.java index 07004503e..c3ad51c96 100755 --- a/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtAppletBase.java +++ b/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtAppletBase.java @@ -300,9 +300,7 @@ public class JOGLNewtAppletBase implements KeyListener, GLEventListener { glWindow.reparentWindow(awtParent); } else { glWindow.reparentWindow(null); - if(glClosable) { - glWindow.setDefaultCloseOperation(WindowClosingMode.DISPOSE_ON_CLOSE); - } + glWindow.setDefaultCloseOperation( glClosable ? WindowClosingMode.DISPOSE_ON_CLOSE : WindowClosingMode.DO_NOTHING_ON_CLOSE ); } } } diff --git a/src/newt/classes/com/jogamp/newt/event/InputEvent.java b/src/newt/classes/com/jogamp/newt/event/InputEvent.java index 9ef4de2b6..4920b59ea 100644 --- a/src/newt/classes/com/jogamp/newt/event/InputEvent.java +++ b/src/newt/classes/com/jogamp/newt/event/InputEvent.java @@ -81,11 +81,6 @@ public abstract class InputEvent extends NEWTEvent return 0; } - /** Object when attached via {@link #setAttachment(Object)} marks the event consumed, - * ie. stops propagating the event any further to the event listener. - */ - public static final Object consumedTag = new Object(); - protected InputEvent(short eventType, Object source, long when, int modifiers) { super(eventType, source, when); this.modifiers=modifiers; diff --git a/src/newt/classes/com/jogamp/newt/event/KeyEvent.java b/src/newt/classes/com/jogamp/newt/event/KeyEvent.java index f626fec38..5117ffe29 100644 --- a/src/newt/classes/com/jogamp/newt/event/KeyEvent.java +++ b/src/newt/classes/com/jogamp/newt/event/KeyEvent.java @@ -872,6 +872,11 @@ public class KeyEvent extends InputEvent public static final short VK_BEGIN = (short) 0xFF58; /** + * Constant for Keyboard became invisible, e.g. Android's soft keyboard Back button hit while keyboard is visible. + */ + public static final short VK_KEYBOARD_INVISIBLE = (short) 0xDEAD; + + /** * This value is used to indicate that the keyCode is unknown. * KEY_TYPED events do not have a keyCode value; this value * is used instead. diff --git a/src/newt/classes/com/jogamp/newt/event/MouseEvent.java b/src/newt/classes/com/jogamp/newt/event/MouseEvent.java index 23549533e..8ad1f3f24 100644 --- a/src/newt/classes/com/jogamp/newt/event/MouseEvent.java +++ b/src/newt/classes/com/jogamp/newt/event/MouseEvent.java @@ -70,7 +70,8 @@ public class MouseEvent extends InputEvent super(eventType, source, when, modifiers); this.x = new int[]{x}; this.y = new int[]{y}; - this.pressure = new float[]{0}; + this.pressure = new float[]{0f}; + this.maxPressure= 1.0f; this.pointerids = new short[]{-1}; this.clickCount=clickCount; this.button=button; @@ -78,8 +79,8 @@ public class MouseEvent extends InputEvent } public MouseEvent(short eventType, Object source, long when, - int modifiers, int[] x, int[] y, float[] pressure, short[] pointerids, short clickCount, short button, - float rotation) + int modifiers, int[] x, int[] y, float[] pressure, float maxPressure, short[] pointerids, short clickCount, + short button, float rotation) { super(eventType, source, when, modifiers); this.x = x; @@ -89,7 +90,11 @@ public class MouseEvent extends InputEvent pointerids.length != y.length) { throw new IllegalArgumentException("All multiple pointer arrays must be of same size"); } + if( 0.0f >= maxPressure ) { + throw new IllegalArgumentException("maxPressure must be > 0.0f"); + } this.pressure = pressure; + this.maxPressure= maxPressure; this.pointerids = pointerids; this.clickCount=clickCount; this.button=button; @@ -129,28 +134,59 @@ public class MouseEvent extends InputEvent } /** - * @return x-coord at index where index refers to the - * data coming from a pointer. + * @param index pointer-index within [0 .. {@link #getPointerCount()}-1] + * @return X-Coord associated with the pointer-index. * @see getPointerId(index) */ public int getX(int index) { return x[index]; } + /** + * @param index pointer-index within [0 .. {@link #getPointerCount()}-1] + * @return Y-Coord associated with the pointer-index. + * @see getPointerId(index) + */ public int getY(int index) { return y[index]; } - public float getPressure(){ - return pressure[0]; + /** + * @param normalized if true, method returns the normalized pressure, i.e. <code>pressure / maxPressure</code> + * @return The pressure associated with the pointer-index 0. + * The value of zero is return if not available. + * @see #getMaxPressure() + */ + public float getPressure(boolean normalized){ + return normalized ? pressure[0] / maxPressure : pressure[0]; + } + + /** + * Returns the maximum pressure known for the input device generating this event. + * <p> + * This value may be self calibrating on devices/OS, where no known maximum pressure is known. + * Hence subsequent events may return a higher value. + * </p> + * <p> + * Self calibrating maximum pressure is performed on: + * <ul> + * <li>Android</li> + * </ul> + * </p> + */ + public float getMaxPressure() { + return maxPressure; } /** - * @return the pressure associated with the pointer at index. - * the value of zero is return if not available. + * @param index pointer-index within [0 .. {@link #getPointerCount()}-1] + * @param normalized if true, method returns the normalized pressure, i.e. <code>pressure / maxPressure</code> + * @return The pressure associated with the pointer-index. + * The value of zero is return if not available. + * @see #getMaxPressure() */ - public float getPressure(int index){ - return pressure[index]; + public float getPressure(int index, boolean normalized){ + return normalized ? pressure[index] / maxPressure : pressure[index]; } /** @@ -199,8 +235,8 @@ public class MouseEvent extends InputEvent sb.append(", "); } sb.append(pointerids[i]).append(": ") - .append(x[i]).append(" / ").append(y[i]).append(" ") - .append(pressure[i]).append("p"); + .append(x[i]).append("/").append(y[i]).append(", ") + .append("p[").append(pressure[i]).append("/").append(maxPressure).append("=").append(pressure[i]/maxPressure).append("]"); } sb.append("]"); } @@ -225,6 +261,7 @@ public class MouseEvent extends InputEvent private final short clickCount, button; private final float wheelRotation; private final float pressure[]; + private final float maxPressure; private final short pointerids[]; public static final short EVENT_MOUSE_CLICKED = 200; diff --git a/src/newt/classes/com/jogamp/newt/event/NEWTEvent.java b/src/newt/classes/com/jogamp/newt/event/NEWTEvent.java index b8de6eb18..17210cef8 100644 --- a/src/newt/classes/com/jogamp/newt/event/NEWTEvent.java +++ b/src/newt/classes/com/jogamp/newt/event/NEWTEvent.java @@ -48,6 +48,12 @@ package com.jogamp.newt.event; */ @SuppressWarnings("serial") public class NEWTEvent extends java.util.EventObject { + /** + * Object when attached via {@link #setAttachment(Object)} marks the event consumed, + * ie. stops propagating the event any further to the <i>other</i> event listener. + */ + public static final Object consumedTag = new Object(); + private final short eventType; private final long when; private Object attachment; @@ -101,7 +107,7 @@ public class NEWTEvent extends java.util.EventObject { return sb.append("NEWTEvent[source:").append(getSource().getClass().getName()).append(", when:").append(getWhen()).append(" d ").append((System.currentTimeMillis()-getWhen())).append("ms]"); } - static String toHexString(short hex) { + public static String toHexString(short hex) { return "0x" + Integer.toHexString( (int)hex & 0x0000FFFF ); } } diff --git a/src/newt/classes/com/jogamp/newt/event/WindowListener.java b/src/newt/classes/com/jogamp/newt/event/WindowListener.java index 011e1f654..dde182510 100644 --- a/src/newt/classes/com/jogamp/newt/event/WindowListener.java +++ b/src/newt/classes/com/jogamp/newt/event/WindowListener.java @@ -36,6 +36,7 @@ package com.jogamp.newt.event; import javax.media.nativewindow.WindowClosingProtocol; +/** NEWT {@link WindowEvent} listener. */ public interface WindowListener extends NEWTEventListener { /** Window is resized, your application shall respect the new window dimension. A repaint is recommended. */ public void windowResized(WindowEvent e); @@ -53,7 +54,9 @@ public interface WindowListener extends NEWTEventListener { **/ public void windowDestroyNotify(WindowEvent e); - /** Window has been destroyed.*/ + /** + * Window has been destroyed. + */ public void windowDestroyed(WindowEvent e); /** Window gained focus. */ diff --git a/src/newt/classes/com/jogamp/newt/event/awt/AWTAdapter.java b/src/newt/classes/com/jogamp/newt/event/awt/AWTAdapter.java index 8991203d5..6de2eee45 100644 --- a/src/newt/classes/com/jogamp/newt/event/awt/AWTAdapter.java +++ b/src/newt/classes/com/jogamp/newt/event/awt/AWTAdapter.java @@ -181,8 +181,13 @@ public abstract class AWTAdapter implements java.util.EventListener /** @see #addTo(java.awt.Component) */ public abstract AWTAdapter removeFrom(java.awt.Component awtComponent); + /** + * Enqueues the event to the {@link #getNewtWindow()} is not null. + */ void enqueueEvent(boolean wait, com.jogamp.newt.event.NEWTEvent event) { - newtWindow.enqueueEvent(wait, event); + if( null != newtWindow ) { + newtWindow.enqueueEvent(wait, event); + } } } diff --git a/src/newt/classes/com/jogamp/newt/event/awt/AWTWindowAdapter.java b/src/newt/classes/com/jogamp/newt/event/awt/AWTWindowAdapter.java index 2d63ca455..e91bb2f82 100644 --- a/src/newt/classes/com/jogamp/newt/event/awt/AWTWindowAdapter.java +++ b/src/newt/classes/com/jogamp/newt/event/awt/AWTWindowAdapter.java @@ -66,13 +66,18 @@ public class AWTWindowAdapter return this; } - public AWTAdapter removeFrom(java.awt.Component awtComponent) { - awtComponent.removeFocusListener(this); - awtComponent.removeComponentListener(this); + public AWTAdapter removeWindowClosingFrom(java.awt.Component awtComponent) { java.awt.Window win = getWindow(awtComponent); if( null != win && null != windowClosingListener ) { win.removeWindowListener(windowClosingListener); } + return this; + } + + public AWTAdapter removeFrom(java.awt.Component awtComponent) { + awtComponent.removeFocusListener(this); + awtComponent.removeComponentListener(this); + removeWindowClosingFrom(awtComponent); if(awtComponent instanceof java.awt.Window) { ((java.awt.Window)awtComponent).removeWindowListener(this); } @@ -220,9 +225,16 @@ public class AWTWindowAdapter enqueueEvent(true, event); } } + public void windowClosed(java.awt.event.WindowEvent e) { + com.jogamp.newt.event.WindowEvent event = AWTNewtEventFactory.createWindowEvent(e, newtWindow); + if(null!=newtListener) { + ((com.jogamp.newt.event.WindowListener)newtListener).windowDestroyed(event); + } else { + enqueueEvent(true, event); + } + } public void windowActivated(java.awt.event.WindowEvent e) { } - public void windowClosed(java.awt.event.WindowEvent e) { } public void windowDeactivated(java.awt.event.WindowEvent e) { } public void windowDeiconified(java.awt.event.WindowEvent e) { } public void windowIconified(java.awt.event.WindowEvent e) { } diff --git a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java index 7fccb6622..ce50d95dd 100644 --- a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java +++ b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java @@ -100,7 +100,10 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind protected GLWindow(Window window) { super(null, null, false /* always handle device lifecycle ourselves */); this.window = (WindowImpl) window; - this.window.setHandleDestroyNotify(false); + this.window.setWindowDestroyNotifyAction( new Runnable() { + public void run() { + defaultWindowDestroyNotifyOp(); + } } ); window.addWindowListener(new WindowAdapter() { @Override public void windowRepaint(WindowUpdateEvent e) { @@ -112,10 +115,6 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind defaultWindowResizedOp(getWidth(), getHeight()); } - @Override - public void windowDestroyNotify(WindowEvent e) { - defaultWindowDestroyNotifyOp(); - } }); this.window.setLifecycleHook(new GLLifecycleHook()); } @@ -390,6 +389,11 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind } @Override + public void setWindowDestroyNotifyAction(Runnable r) { + window.setWindowDestroyNotifyAction(r); + } + + @Override public final void setVisible(boolean visible) { window.setVisible(visible); } diff --git a/src/newt/classes/jogamp/newt/DisplayImpl.java b/src/newt/classes/jogamp/newt/DisplayImpl.java index 20b915cae..d4842ba2f 100644 --- a/src/newt/classes/jogamp/newt/DisplayImpl.java +++ b/src/newt/classes/jogamp/newt/DisplayImpl.java @@ -370,15 +370,8 @@ public abstract class DisplayImpl extends Display { DisplayImpl.this.dispatchMessages(); } }; - final void dispatchMessage(final NEWTEventTask eventTask) { - final NEWTEvent event = eventTask.get(); + final void dispatchMessage(final NEWTEvent event) { try { - if(null == event) { - // Ooops ? - System.err.println("Warning: event of eventTask is NULL"); - Thread.dumpStack(); - return; - } final Object source = event.getSource(); if(source instanceof NEWTEventConsumer) { final NEWTEventConsumer consumer = (NEWTEventConsumer) source ; @@ -396,6 +389,21 @@ public abstract class DisplayImpl extends Display { } else { re = new RuntimeException(t); } + throw re; + } + } + + final void dispatchMessage(final NEWTEventTask eventTask) { + final NEWTEvent event = eventTask.get(); + try { + if(null == event) { + // Ooops ? + System.err.println("Warning: event of eventTask is NULL"); + Thread.dumpStack(); + return; + } + dispatchMessage(event); + } catch (RuntimeException re) { if( eventTask.isCallerWaiting() ) { // propagate exception to caller eventTask.setException(re); @@ -451,7 +459,7 @@ public abstract class DisplayImpl extends Display { // can't wait if we are on EDT or NEDT -> consume right away if(wait && edtUtil.isCurrentThreadEDTorNEDT() ) { - dispatchMessage(new NEWTEventTask(e, null)); + dispatchMessage(e); return; } diff --git a/src/newt/classes/jogamp/newt/WindowImpl.java b/src/newt/classes/jogamp/newt/WindowImpl.java index 222a1173c..af0bde179 100644 --- a/src/newt/classes/jogamp/newt/WindowImpl.java +++ b/src/newt/classes/jogamp/newt/WindowImpl.java @@ -110,7 +110,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer private boolean pointerConfined = false; private LifecycleHook lifecycleHook = null; - private boolean handleDestroyNotify = true; + private Runnable windowDestroyNotifyAction = null; private FocusRunnable focusAction = null; private KeyListener keyboardFocusHandler = null; @@ -864,8 +864,12 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer _lock.lock(); try { if(DEBUG_IMPLEMENTATION) { - System.err.println("Window DestroyAction() "+getThreadName()); + System.err.println("Window DestroyAction() hasScreen "+(null != screen)+", isNativeValid "+isNativeValid()+" - "+getThreadName()); } + + // send synced destroy-notify notification + sendWindowEvent(WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY); + // Childs first .. synchronized(childWindowsLock) { if(childWindows.size()>0) { @@ -875,8 +879,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer while( clonedChildWindows.size() > 0 ) { NativeWindow nw = clonedChildWindows.remove(0); if(nw instanceof WindowImpl) { - ((WindowImpl)nw).sendWindowEvent(WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY); - ((WindowImpl)nw).destroy(); + ((WindowImpl)nw).windowDestroyNotify(true); } else { nw.destroy(); } @@ -889,21 +892,19 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer lifecycleHook.destroyActionInLock(); } - if( null != screen ) { - if( isNativeValid() ) { - screen.removeScreenModeListener(screenModeListenerImpl); - closeNativeImpl(); - final AbstractGraphicsDevice cfgADevice = config.getScreen().getDevice(); - if( cfgADevice != screen.getDisplay().getGraphicsDevice() ) { // don't pull display's device - cfgADevice.close(); // ensure a cfg's device is closed - } - setGraphicsConfiguration(null); - removeScreenReference(); - } - Display dpy = screen.getDisplay(); - if(null != dpy) { - dpy.validateEDT(); + if( isNativeValid() ) { + screen.removeScreenModeListener(screenModeListenerImpl); + closeNativeImpl(); + final AbstractGraphicsDevice cfgADevice = config.getScreen().getDevice(); + if( cfgADevice != screen.getDisplay().getGraphicsDevice() ) { // don't pull display's device + cfgADevice.close(); // ensure a cfg's device is closed } + setGraphicsConfiguration(null); + } + removeScreenReference(); + Display dpy = screen.getDisplay(); + if(null != dpy) { + dpy.validateEDT(); } // send synced destroyed notification @@ -1549,14 +1550,10 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer public Object getWrappedWindow() { return null; } - - /** - * If set to true, the default value, this NEWT Window implementation will - * handle the destruction (ie {@link #destroy()} call) within {@link #windowDestroyNotify(boolean)} implementation.<br> - * If set to false, it's up to the caller/owner to handle destruction within {@link #windowDestroyNotify(boolean)}. - */ - public void setHandleDestroyNotify(boolean b) { - handleDestroyNotify = b; + + @Override + public void setWindowDestroyNotifyAction(Runnable r) { + windowDestroyNotifyAction = r; } /** @@ -2211,7 +2208,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer default: throw new NativeWindowException("Unexpected mouse event type " + e.getEventType()); } - consumed = InputEvent.consumedTag == e.getAttachment(); + consumed = NEWTEvent.consumedTag == e.getAttachment(); } } @@ -2340,7 +2337,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer default: throw new NativeWindowException("Unexpected key event type " + e.getEventType()); } - return InputEvent.consumedTag == e.getAttachment(); + return NEWTEvent.consumedTag == e.getAttachment(); } @SuppressWarnings("deprecation") @@ -2446,7 +2443,8 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer if(DEBUG_IMPLEMENTATION) { System.err.println("consumeWindowEvent: "+e+", visible "+isVisible()+" "+getX()+"/"+getY()+" "+getWidth()+"x"+getHeight()); } - for(int i = 0; i < windowListeners.size(); i++ ) { + boolean consumed = false; + for(int i = 0; !consumed && i < windowListeners.size(); i++ ) { WindowListener l = windowListeners.get(i); switch(e.getEventType()) { case WindowEvent.EVENT_WINDOW_RESIZED: @@ -2475,6 +2473,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer new NativeWindowException("Unexpected window event type " + e.getEventType()); } + consumed = NEWTEvent.consumedTag == e.getAttachment(); } } @@ -2615,32 +2614,52 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } /** - * Triggered by implementation's WM events or programmatically + * Triggered by implementation's WM events or programmatic while respecting {@link #getDefaultCloseOperation()}. * * @param force if true, overrides {@link #setDefaultCloseOperation(WindowClosingMode)} with {@link WindowClosingProtocol#DISPOSE_ON_CLOSE} * and hence force destruction. Otherwise is follows the user settings. * @return true if this window is no more valid and hence has been destroyed, otherwise false. */ - protected boolean windowDestroyNotify(boolean force) { + public boolean windowDestroyNotify(boolean force) { + final WindowClosingMode defMode = getDefaultCloseOperation(); + final WindowClosingMode mode = force ? WindowClosingMode.DISPOSE_ON_CLOSE : defMode; if(DEBUG_IMPLEMENTATION) { - System.err.println("Window.windowDestroyNotify(force: "+force+") START "+getThreadName()+": "+this); - } - if(force) { - setDefaultCloseOperation(WindowClosingMode.DISPOSE_ON_CLOSE); - } - - // send synced destroy notifications - enqueueWindowEvent(true, WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY); - - if(handleDestroyNotify && WindowClosingMode.DISPOSE_ON_CLOSE == getDefaultCloseOperation()) { - destroy(); + System.err.println("Window.windowDestroyNotify(isNativeValid: "+isNativeValid()+", force: "+force+", mode "+defMode+" -> "+mode+") "+getThreadName()+": "+this); + // Thread.dumpStack(); } - final boolean destroyed = !isNativeValid(); + final boolean destroyed; + + if( isNativeValid() ) { + if( WindowClosingMode.DISPOSE_ON_CLOSE == mode ) { + if(force) { + setDefaultCloseOperation(mode); + } + try { + if( null == windowDestroyNotifyAction ) { + destroy(); + } else { + windowDestroyNotifyAction.run(); + } + } finally { + if(force) { + setDefaultCloseOperation(defMode); + } + } + } else { + // send synced destroy notifications + sendWindowEvent(WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY); + } + + destroyed = !isNativeValid(); + } else { + destroyed = true; + } if(DEBUG_IMPLEMENTATION) { - System.err.println("Window.windowDestroyNotify(force: "+force+") END "+getThreadName()+": destroyed "+destroyed+", "+this); - } + System.err.println("Window.windowDestroyNotify(isNativeValid: "+isNativeValid()+", force: "+force+", mode "+mode+") END "+getThreadName()+": destroyed "+destroyed+", "+this); + } + return destroyed; } diff --git a/src/newt/classes/jogamp/newt/awt/event/AWTParentWindowAdapter.java b/src/newt/classes/jogamp/newt/awt/event/AWTParentWindowAdapter.java index 701d9d60a..b348220d6 100644 --- a/src/newt/classes/jogamp/newt/awt/event/AWTParentWindowAdapter.java +++ b/src/newt/classes/jogamp/newt/awt/event/AWTParentWindowAdapter.java @@ -42,9 +42,7 @@ import com.jogamp.newt.event.awt.AWTWindowAdapter; * Specialized parent/client adapter, * where the NEWT child window really gets resized, * and the parent move window event gets discarded. */ -public class AWTParentWindowAdapter - extends AWTWindowAdapter - implements java.awt.event.HierarchyListener +public class AWTParentWindowAdapter extends AWTWindowAdapter implements java.awt.event.HierarchyListener { NativeWindow downstreamParent; diff --git a/src/newt/classes/jogamp/newt/driver/android/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/android/WindowDriver.java index a85febca0..c5371ae9c 100644 --- a/src/newt/classes/jogamp/newt/driver/android/WindowDriver.java +++ b/src/newt/classes/jogamp/newt/driver/android/WindowDriver.java @@ -30,6 +30,7 @@ package jogamp.newt.driver.android; import jogamp.common.os.android.StaticContext; import jogamp.newt.WindowImpl; +import jogamp.newt.driver.android.event.AndroidNewtEventFactory; import jogamp.newt.driver.android.event.AndroidNewtEventTranslator; import javax.media.nativewindow.Capabilities; @@ -65,6 +66,8 @@ import android.view.SurfaceHolder.Callback2; import android.view.ViewGroup; import android.view.inputmethod.InputMethodManager; import android.view.SurfaceView; +import android.view.KeyEvent; + public class WindowDriver extends jogamp.newt.WindowImpl implements Callback2 { static { @@ -573,10 +576,8 @@ public class WindowDriver extends jogamp.newt.WindowImpl implements Callback2 { @Override public final void surfaceDestroyed(SurfaceHolder holder) { Log.d(MD.TAG, "surfaceDestroyed - on thread "+Thread.currentThread().getName()); - if(WindowImpl.DEBUG_IMPLEMENTATION) { - Thread.dumpStack(); - } windowDestroyNotify(true); // actually too late .. however .. + Thread.dumpStack(); } @Override @@ -585,6 +586,27 @@ public class WindowDriver extends jogamp.newt.WindowImpl implements Callback2 { windowRepaint(0, 0, getWidth(), getHeight()); } + protected boolean handleKeyCodeBack(KeyEvent.DispatcherState state, android.view.KeyEvent event) { + if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) { + state.startTracking(event, this); + } else if (event.getAction() == KeyEvent.ACTION_UP && !event.isCanceled() && state.isTracking(event)) { + if( isKeyboardVisible() ) { + keyboardVisibilityChanged(false); + enqueueAKey2NKeyUpDown(event); + } else { + Log.d(MD.TAG, "handleKeyCodeBack : "+event); + windowDestroyNotify(true); + } + } + return false; // cont. processing + } + private void enqueueAKey2NKeyUpDown(android.view.KeyEvent aEvent) { + final com.jogamp.newt.event.KeyEvent eDown = AndroidNewtEventFactory.createKeyEvent(aEvent, com.jogamp.newt.event.KeyEvent.EVENT_KEY_PRESSED, this, true); + final com.jogamp.newt.event.KeyEvent eUp = AndroidNewtEventFactory.createKeyEvent(aEvent, com.jogamp.newt.event.KeyEvent.EVENT_KEY_RELEASED, this, true); + enqueueEvent(false, eDown); + enqueueEvent(false, eUp); + } + private boolean added2StaticViewGroup; private MSurfaceView androidView; private int nativeFormat; // chosen current native PixelFormat (suitable for EGL) @@ -600,6 +622,17 @@ public class WindowDriver extends jogamp.newt.WindowImpl implements Callback2 { setBackgroundDrawable(null); // setBackgroundColor(Color.TRANSPARENT); } + + @Override + public boolean onKeyPreIme(int keyCode, KeyEvent event) { + if ( event.getKeyCode() == KeyEvent.KEYCODE_BACK ) { + final KeyEvent.DispatcherState state = getKeyDispatcherState(); + if (state != null) { + return handleKeyCodeBack(state, event); + } + } + return false; // cont. processing + } } //---------------------------------------------------------------------- // Internals only diff --git a/src/newt/classes/jogamp/newt/driver/android/event/AndroidNewtEventFactory.java b/src/newt/classes/jogamp/newt/driver/android/event/AndroidNewtEventFactory.java index 22e2cbc51..1f78bd578 100644 --- a/src/newt/classes/jogamp/newt/driver/android/event/AndroidNewtEventFactory.java +++ b/src/newt/classes/jogamp/newt/driver/android/event/AndroidNewtEventFactory.java @@ -31,6 +31,7 @@ package jogamp.newt.driver.android.event; import com.jogamp.common.os.AndroidVersion; import com.jogamp.newt.Window; import com.jogamp.newt.event.InputEvent; +import com.jogamp.newt.event.NEWTEvent; public class AndroidNewtEventFactory { @@ -86,7 +87,7 @@ public class AndroidNewtEventFactory { return (short)0; } - private static final short aKeyCode2NewtKeyCode(int androidKeyCode) { + private static final short aKeyCode2NewtKeyCode(int androidKeyCode, boolean inclSysKeys) { if(android.view.KeyEvent.KEYCODE_0 <= androidKeyCode && androidKeyCode <= android.view.KeyEvent.KEYCODE_9) { return (short) ( com.jogamp.newt.event.KeyEvent.VK_0 + ( androidKeyCode - android.view.KeyEvent.KEYCODE_0 ) ); } @@ -122,11 +123,19 @@ public class AndroidNewtEventFactory { // case android.view.KeyEvent.KEYCODE_MUTE: ?? case android.view.KeyEvent.KEYCODE_PAGE_UP: return com.jogamp.newt.event.KeyEvent.VK_PAGE_UP; case android.view.KeyEvent.KEYCODE_PAGE_DOWN: return com.jogamp.newt.event.KeyEvent.VK_PAGE_DOWN; - // case android.view.KeyEvent.KEYCODE_HOME: return com.jogamp.newt.event.KeyEvent.VK_HOME; - // case android.view.KeyEvent.KEYCODE_BACK: return com.jogamp.newt.event.KeyEvent.VK_BACK_SPACE; case android.view.KeyEvent.KEYCODE_ESCAPE: return com.jogamp.newt.event.KeyEvent.VK_ESCAPE; case android.view.KeyEvent.KEYCODE_CTRL_LEFT: return com.jogamp.newt.event.KeyEvent.VK_CONTROL; case android.view.KeyEvent.KEYCODE_CTRL_RIGHT: return com.jogamp.newt.event.KeyEvent.VK_CONTROL; // ?? + case android.view.KeyEvent.KEYCODE_BACK: + if( inclSysKeys ) { + return com.jogamp.newt.event.KeyEvent.VK_KEYBOARD_INVISIBLE; + } + break; + case android.view.KeyEvent.KEYCODE_HOME: + if( inclSysKeys ) { + return com.jogamp.newt.event.KeyEvent.VK_HOME; + } + break; } return (short)0; } @@ -140,19 +149,7 @@ public class AndroidNewtEventFactory { return newtMods; } - private final NewtGestureListener gestureListener; - private final android.view.GestureDetector gestureDetector; - private final float touchSlop; - - public AndroidNewtEventFactory(android.content.Context context, android.os.Handler handler) { - gestureListener = new NewtGestureListener(); - gestureDetector = new android.view.GestureDetector(context, gestureListener, handler, false /* ignoreMultitouch */); - gestureDetector.setIsLongpressEnabled(false); // favor scroll event! - final android.view.ViewConfiguration configuration = android.view.ViewConfiguration.get(context); - touchSlop = configuration.getScaledTouchSlop(); - } - - public com.jogamp.newt.event.WindowEvent createWindowEvent(android.view.accessibility.AccessibilityEvent event, com.jogamp.newt.Window newtSource) { + public static com.jogamp.newt.event.WindowEvent createWindowEvent(android.view.accessibility.AccessibilityEvent event, com.jogamp.newt.Window newtSource) { final int aType = event.getEventType(); final short nType = aAccessibilityEventType2Newt(aType); @@ -163,33 +160,88 @@ public class AndroidNewtEventFactory { } - public com.jogamp.newt.event.KeyEvent createKeyEvent(int keyCode, android.view.KeyEvent event, com.jogamp.newt.Window newtSource) { - final short type = aKeyEventType2NewtEventType(event.getAction()); - if(Window.DEBUG_MOUSE_EVENT) { - System.err.println("createKeyEvent: type 0x"+Integer.toHexString(type)+", keyCode 0x"+Integer.toHexString(keyCode)+", "+event); + public static com.jogamp.newt.event.KeyEvent createKeyEvent(android.view.KeyEvent aEvent, com.jogamp.newt.Window newtSource, boolean inclSysKeys) { + final com.jogamp.newt.event.KeyEvent res; + final short newtType = aKeyEventType2NewtEventType(aEvent.getAction()); + if( (short)0 != newtType) { + final short newtKeyCode = aKeyCode2NewtKeyCode(aEvent.getKeyCode(), inclSysKeys); + res = createKeyEventImpl(aEvent, newtType, newtKeyCode, newtSource); + } else { + res = null; } - if( (short)0 != type) { - final short newtKeyCode = aKeyCode2NewtKeyCode(keyCode); - if( (short)0 != newtKeyCode ) { - final Object src = (null==newtSource)?null:(Object)newtSource; - final long unixTime = System.currentTimeMillis() + ( event.getEventTime() - android.os.SystemClock.uptimeMillis() ); - final int newtMods = aKeyModifiers2Newt(event.getMetaState()); - - return new com.jogamp.newt.event.KeyEvent( - type, src, unixTime, newtMods, newtKeyCode, newtKeyCode, event.getDisplayLabel()); - } + if(Window.DEBUG_KEY_EVENT) { + System.err.println("createKeyEvent0: "+aEvent+" -> "+res); } - return null; + return res; } - private int gestureScrollPointerDown = 0; + public static com.jogamp.newt.event.KeyEvent createKeyEvent(android.view.KeyEvent aEvent, short newtType, com.jogamp.newt.Window newtSource, boolean inclSysKeys) { + final short newtKeyCode = aKeyCode2NewtKeyCode(aEvent.getKeyCode(), inclSysKeys); + final com.jogamp.newt.event.KeyEvent res = createKeyEventImpl(aEvent, newtType, newtKeyCode, newtSource); + if(Window.DEBUG_KEY_EVENT) { + System.err.println("createKeyEvent1: newtType "+NEWTEvent.toHexString(newtType)+", "+aEvent+" -> "+res); + } + return res; + } + private static com.jogamp.newt.event.KeyEvent createKeyEventImpl(android.view.KeyEvent aEvent, short newtType, short newtKeyCode, com.jogamp.newt.Window newtSource) { + if( (short)0 != newtType && (short)0 != newtKeyCode ) { + final Object src = null==newtSource ? null : newtSource; + final long unixTime = System.currentTimeMillis() + ( aEvent.getEventTime() - android.os.SystemClock.uptimeMillis() ); + final int newtMods = aKeyModifiers2Newt(aEvent.getMetaState()); + + return new com.jogamp.newt.event.KeyEvent( + newtType, src, unixTime, newtMods, newtKeyCode, newtKeyCode, (char) aEvent.getUnicodeChar()); + } + return null; + } + + private static float maxPressure = 0.7f; // experienced maximum value (Amazon HD = 0.8f) + + /** + * Dynamic calibration of maximum MotionEvent pressure, starting from 0.7f + * <p> + * Specification says no pressure is 0.0f and + * normal pressure is 1.0f, where > 1.0f denominates very high pressure. + * </p> + * <p> + * Some devices exceed this spec, or better, most devices do. + * <ul> + * <li>Asus TF2*: Pressure always > 1.0f</li> + * <li>Amazon HD: Pressure always ≤ 0.8f</li> + * </ul> + * </p> + * + * @return + */ + public static float getMaxPressure() { + return maxPressure; + } + + private final NewtGestureListener gestureListener; + private final android.view.GestureDetector gestureDetector; + private final float touchSlop; + + public AndroidNewtEventFactory(android.content.Context context, android.os.Handler handler) { + gestureListener = new NewtGestureListener(); + gestureDetector = new android.view.GestureDetector(context, gestureListener, handler, false /* ignoreMultitouch */); + gestureDetector.setIsLongpressEnabled(false); // favor scroll event! + final android.view.ViewConfiguration configuration = android.view.ViewConfiguration.get(context); + touchSlop = configuration.getScaledTouchSlop(); + } + + private int gestureScrollPointerDown = 0; + public com.jogamp.newt.event.MouseEvent[] createMouseEvents(boolean isOnTouchEvent, android.view.MotionEvent event, com.jogamp.newt.Window newtSource) { if(Window.DEBUG_MOUSE_EVENT) { System.err.println("createMouseEvent: "+toString(event)); } + if( event.getPressure() > maxPressure ) { + maxPressure = event.getPressure(); + } + // // Prefilter Android Event (Gesture, ..) and determine final type // @@ -314,6 +366,9 @@ public class AndroidNewtEventFactory { y[j] = (int)event.getY(i); pressure[j] = event.getPressure(i); pointerIds[j] = (short)event.getPointerId(i); + if( pressure[j] > maxPressure ) { + maxPressure = pressure[j]; + } if(Window.DEBUG_MOUSE_EVENT) { System.err.println("createMouseEvent: ptr-data["+i+" -> "+j+"] "+x[j]+"/"+y[j]+", pressure "+pressure[j]+", id "+pointerIds[j]); } @@ -336,15 +391,15 @@ public class AndroidNewtEventFactory { final com.jogamp.newt.event.MouseEvent me1 = new com.jogamp.newt.event.MouseEvent( nType, src, unixTime, - modifiers, x, y, pressure, pointerIds, clickCount, - button, rotation); + modifiers, x, y, pressure, maxPressure, pointerIds, + clickCount, button, rotation); if( com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_RELEASED == nType ) { return new com.jogamp.newt.event.MouseEvent[] { me1, new com.jogamp.newt.event.MouseEvent( com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_CLICKED, - src, unixTime, modifiers, x, y, pressure, pointerIds, clickCount, - button, rotation) }; + src, unixTime, modifiers, x, y, pressure, maxPressure, pointerIds, + clickCount, button, rotation) }; } else { return new com.jogamp.newt.event.MouseEvent[] { me1 }; } diff --git a/src/newt/classes/jogamp/newt/driver/android/event/AndroidNewtEventTranslator.java b/src/newt/classes/jogamp/newt/driver/android/event/AndroidNewtEventTranslator.java index 2d972f752..93735863e 100644 --- a/src/newt/classes/jogamp/newt/driver/android/event/AndroidNewtEventTranslator.java +++ b/src/newt/classes/jogamp/newt/driver/android/event/AndroidNewtEventTranslator.java @@ -38,7 +38,7 @@ public class AndroidNewtEventTranslator implements View.OnKeyListener, View.OnTo @Override public boolean onKey(View v, int keyCode, android.view.KeyEvent event) { - final com.jogamp.newt.event.KeyEvent newtEvent = factory.createKeyEvent(keyCode, event, newtWindow); + final com.jogamp.newt.event.KeyEvent newtEvent = AndroidNewtEventFactory.createKeyEvent(event, newtWindow, false /* no system keys */); if(null != newtEvent) { newtWindow.enqueueEvent(false, newtEvent); return true; diff --git a/src/newt/classes/jogamp/newt/driver/awt/AWTEDTUtil.java b/src/newt/classes/jogamp/newt/driver/awt/AWTEDTUtil.java index 27d0f3506..cecb1dd7e 100644 --- a/src/newt/classes/jogamp/newt/driver/awt/AWTEDTUtil.java +++ b/src/newt/classes/jogamp/newt/driver/awt/AWTEDTUtil.java @@ -33,9 +33,9 @@ import java.awt.EventQueue; import javax.media.nativewindow.NativeWindowException; import com.jogamp.common.util.RunnableTask; +import com.jogamp.common.util.awt.AWTEDTExecutor; import com.jogamp.newt.util.EDTUtil; -import jogamp.common.awt.AWTEDTExecutor; import jogamp.newt.Debug; public class AWTEDTUtil implements EDTUtil { diff --git a/src/newt/classes/jogamp/newt/driver/awt/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/awt/WindowDriver.java index bee43a95e..0172309fb 100644 --- a/src/newt/classes/jogamp/newt/driver/awt/WindowDriver.java +++ b/src/newt/classes/jogamp/newt/driver/awt/WindowDriver.java @@ -256,10 +256,7 @@ public class WindowDriver extends WindowImpl { } @Override public void windowDestroyed(WindowEvent e) { - if(isNativeValid()) { - WindowDriver.this.windowDestroyNotify(true); - } - + // Not fwd by AWTWindowAdapter, synthesized by NEWT } @Override public void windowGainedFocus(WindowEvent e) { diff --git a/src/test/com/jogamp/opengl/test/android/MovieCubeActivity0.java b/src/test/com/jogamp/opengl/test/android/MovieCubeActivity0.java index a30262ee3..b1ab90a88 100644 --- a/src/test/com/jogamp/opengl/test/android/MovieCubeActivity0.java +++ b/src/test/com/jogamp/opengl/test/android/MovieCubeActivity0.java @@ -54,7 +54,7 @@ public class MovieCubeActivity0 extends NewtBaseActivity { MouseAdapter showKeyboardMouseListener = new MouseAdapter() { @Override public void mousePressed(MouseEvent e) { - if(e.getPressure()>2f) { + if(e.getPressure(true)>0.8f) { ((com.jogamp.newt.Window) e.getSource()).setKeyboardVisible(true); } } diff --git a/src/test/com/jogamp/opengl/test/android/NEWTGearsES2Activity.java b/src/test/com/jogamp/opengl/test/android/NEWTGearsES2Activity.java index e782ac75f..931ffdbb2 100644 --- a/src/test/com/jogamp/opengl/test/android/NEWTGearsES2Activity.java +++ b/src/test/com/jogamp/opengl/test/android/NEWTGearsES2Activity.java @@ -66,14 +66,6 @@ public class NEWTGearsES2Activity extends NewtBaseActivity { GLWindow glWindow = GLWindow.create(caps); glWindow.setFullscreen(true); setContentView(getWindow(), glWindow); - glWindow.addMouseListener(new MouseAdapter() { - @Override - public void mousePressed(MouseEvent e) { - if(e.getPressure()>2f) { // show Keyboard - ((com.jogamp.newt.Window) e.getSource()).setKeyboardVisible(true); - } - } - }); GearsES2 demo = new GearsES2(-1); // demo.enableAndroidTrace(true); diff --git a/src/test/com/jogamp/opengl/test/bugs/Bug427GLJPanelTest1.java b/src/test/com/jogamp/opengl/test/bugs/Bug427GLJPanelTest1.java index 9bf492e0f..66889e9ed 100644 --- a/src/test/com/jogamp/opengl/test/bugs/Bug427GLJPanelTest1.java +++ b/src/test/com/jogamp/opengl/test/bugs/Bug427GLJPanelTest1.java @@ -13,9 +13,16 @@ public class Bug427GLJPanelTest1 extends JFrame implements GLEventListener { setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setLayout(new BorderLayout()); - setSize(600, 600); - setLocation(40, 40); - setVisible(true); + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + setSize(600, 600); + setLocation(40, 40); + setVisible(true); + } } ); + } catch(Exception ex) { + throw new RuntimeException(ex); + } GLProfile glp = GLProfile.get(GLProfile.GL2); GLCapabilities caps = new GLCapabilities(glp); @@ -29,8 +36,15 @@ public class Bug427GLJPanelTest1 extends JFrame implements GLEventListener { } public static void main(String[] args) { - Bug427GLJPanelTest1 demo = new Bug427GLJPanelTest1(); - demo.setVisible(true); + final Bug427GLJPanelTest1 demo = new Bug427GLJPanelTest1(); + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + demo.setVisible(true); + } } ); + } catch(Exception ex) { + throw new RuntimeException(ex); + } } public void display(GLAutoDrawable drawable) { diff --git a/src/test/com/jogamp/opengl/test/bugs/Issue344Base.java b/src/test/com/jogamp/opengl/test/bugs/Issue344Base.java index 9b0a4c6a0..2a7afabff 100644 --- a/src/test/com/jogamp/opengl/test/bugs/Issue344Base.java +++ b/src/test/com/jogamp/opengl/test/bugs/Issue344Base.java @@ -36,7 +36,7 @@ public abstract class Issue344Base implements GLEventListener protected abstract String getText(); protected void run(String[] args) { - Frame frame = new Frame(getClass().getName()); + final Frame frame = new Frame(getClass().getName()); frame.setLayout(new BorderLayout()); GLCanvas canvas = new GLCanvas(); @@ -53,7 +53,14 @@ public abstract class Issue344Base implements GLEventListener }).start(); } }); - frame.setVisible(true); + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setVisible(true); + } } ); + } catch(Exception ex) { + throw new RuntimeException(ex); + } } public void init(GLAutoDrawable drawable) diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestAWTCloseX11DisplayBug565.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestAWTCloseX11DisplayBug565.java index 8df54988f..89de086bb 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestAWTCloseX11DisplayBug565.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestAWTCloseX11DisplayBug565.java @@ -29,19 +29,16 @@ public class TestAWTCloseX11DisplayBug565 { } GLCapabilitiesImmutable caps = new GLCapabilities( GLProfile.getDefault( ) ); - Frame frame = new Frame( "AWT Resource X11 Leak - #" + j ); + final Frame frame = new Frame( "AWT Resource X11 Leak - #" + j ); - GLCanvas glCanvas = new GLCanvas( caps ); + final GLCanvas glCanvas = new GLCanvas( caps ); frame.add( glCanvas ); - frame.setSize( 128, 128 ); - - final Frame _frame = frame; - final GLCanvas _glCanvas = glCanvas; try { javax.swing.SwingUtilities.invokeAndWait( new Runnable() { public void run() { - _frame.setVisible( true ); + frame.setSize( 128, 128 ); + frame.setVisible( true ); } } ); } @@ -53,9 +50,9 @@ public class TestAWTCloseX11DisplayBug565 { try { javax.swing.SwingUtilities.invokeAndWait( new Runnable() { public void run() { - _frame.setVisible( false ); - _frame.remove( _glCanvas ); - _frame.dispose(); + frame.setVisible( false ); + frame.remove( glCanvas ); + frame.dispose(); } } ); } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableDelegateNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableDelegateNEWT.java new file mode 100644 index 000000000..2729d6a5d --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableDelegateNEWT.java @@ -0,0 +1,160 @@ +/** + * Copyright 2013 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.jogl.acore; + +import java.io.IOException; + +import javax.media.opengl.GLCapabilities; +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.GLProfile; + +import org.junit.Assert; +import org.junit.Test; + +import com.jogamp.newt.NewtFactory; +import com.jogamp.newt.Window; +import com.jogamp.newt.event.WindowAdapter; +import com.jogamp.newt.event.WindowEvent; +import com.jogamp.newt.event.WindowUpdateEvent; +import com.jogamp.opengl.GLAutoDrawableDelegate; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.QuitAdapter; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.util.Animator; + +/** + * Test using a NEWT {@link Window} for onscreen case. + * <p> + * Creates a {@link GLDrawable} using the + * {@link GLDrawableFactory#createGLDrawable(javax.media.nativewindow.NativeSurface) factory model}. + * The {@link GLContext} is derived {@link GLDrawable#createContext(GLContext) from the drawable}. + * </p> + * <p> + * Finally a {@link GLAutoDrawableDelegate} is created with the just created {@link GLDrawable} and {@link GLContext}. + * It is being used to run the {@link GLEventListener}. + * </p> + */ +public class TestGLAutoDrawableDelegateNEWT extends UITestCase { + static long duration = 500; // ms + + void doTest(GLCapabilitiesImmutable reqGLCaps, GLEventListener demo) throws InterruptedException { + final GLDrawableFactory factory = GLDrawableFactory.getFactory(reqGLCaps.getGLProfile()); + + // + // Create native windowing resources .. X11/Win/OSX + // + final Window window = NewtFactory.createWindow(reqGLCaps); + Assert.assertNotNull(window); + window.setSize(640, 400); + window.setVisible(true); + Assert.assertTrue(AWTRobotUtil.waitForVisible(window, true)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(window, true)); + System.out.println("Window: "+window.getClass().getName()); + + final GLDrawable drawable = factory.createGLDrawable(window); + Assert.assertNotNull(drawable); + drawable.setRealized(true); + + final GLAutoDrawableDelegate glad = new GLAutoDrawableDelegate(drawable, drawable.createContext(null), window, false, null) { + @Override + protected void destroyImplInLock() { + super.destroyImplInLock(); // destroys drawable/context + window.destroy(); // destroys the actual window, incl. the device + } + }; + + window.setWindowDestroyNotifyAction( new Runnable() { + public void run() { + glad.windowDestroyNotifyOp(); + } } ); + + window.addWindowListener(new WindowAdapter() { + @Override + public void windowRepaint(WindowUpdateEvent e) { + glad.windowRepaintOp(); + } + + @Override + public void windowResized(WindowEvent e) { + glad.windowResizedOp(window.getWidth(), window.getHeight()); + } + }); + + glad.addGLEventListener(demo); + + QuitAdapter quitAdapter = new QuitAdapter(); + //glWindow.addKeyListener(new TraceKeyAdapter(quitAdapter)); + //glWindow.addWindowListener(new TraceWindowAdapter(quitAdapter)); + window.addKeyListener(quitAdapter); + window.addWindowListener(quitAdapter); + + Animator animator = new Animator(); + animator.setUpdateFPSFrames(60, System.err); + animator.setModeBits(false, Animator.MODE_EXPECT_AWT_RENDERING_THREAD); + animator.add(glad); + animator.start(); + Assert.assertTrue(animator.isStarted()); + Assert.assertTrue(animator.isAnimating()); + + while(!quitAdapter.shouldQuit() && animator.isAnimating() && animator.getTotalFPSDuration()<duration) { + Thread.sleep(100); + } + System.out.println("Fin start ..."); + + animator.stop(); + Assert.assertFalse(animator.isAnimating()); + Assert.assertFalse(animator.isStarted()); + glad.destroy(); + System.out.println("Fin Drawable: "+drawable); + System.out.println("Fin Window: "+window); + } + + @Test + public void testOnScreenDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = new GLCapabilities( GLProfile.getGL2ES2() ); + doTest(reqGLCaps, new GearsES2(1)); + } + + public static void main(String args[]) throws IOException { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + duration = MiscUtils.atol(args[i], duration); + } + } + org.junit.runner.JUnitCore.main(TestGLAutoDrawableDelegateNEWT.class.getName()); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableDelegateOnOffscrnCapsNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableDelegateOnOffscrnCapsNEWT.java index c5b4227c2..050e596cf 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableDelegateOnOffscrnCapsNEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableDelegateOnOffscrnCapsNEWT.java @@ -55,6 +55,7 @@ import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; import com.jogamp.opengl.test.junit.jogl.demos.gl2.Gears; import com.jogamp.opengl.test.junit.util.AWTRobotUtil; import com.jogamp.opengl.test.junit.util.UITestCase; +import jogamp.newt.WindowImpl; /** * Tests using a NEWT {@link Window} for on- and offscreen cases. @@ -169,6 +170,11 @@ public class TestGLAutoDrawableDelegateOnOffscrnCapsNEWT extends UITestCase { } }; + window.setWindowDestroyNotifyAction( new Runnable() { + public void run() { + glad.windowDestroyNotifyOp(); + } } ); + window.addWindowListener(new WindowAdapter() { @Override public void windowRepaint(WindowUpdateEvent e) { @@ -179,11 +185,6 @@ public class TestGLAutoDrawableDelegateOnOffscrnCapsNEWT extends UITestCase { public void windowResized(WindowEvent e) { glad.windowResizedOp(window.getWidth(), window.getHeight()); } - - @Override - public void windowDestroyNotify(WindowEvent e) { - glad.windowDestroyNotifyOp(); - } }); glad.addGLEventListener(demo); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextDrawableSwitch01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextDrawableSwitch01NEWT.java index 8b1449493..cce4149ba 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextDrawableSwitch01NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextDrawableSwitch01NEWT.java @@ -107,6 +107,11 @@ public class TestGLContextDrawableSwitch01NEWT extends UITestCase { } }; + window.setWindowDestroyNotifyAction( new Runnable() { + public void run() { + glad.windowDestroyNotifyOp(); + } } ); + // add basic window interaction window.addWindowListener(new WindowAdapter() { @Override @@ -117,10 +122,6 @@ public class TestGLContextDrawableSwitch01NEWT extends UITestCase { public void windowResized(WindowEvent e) { glad.windowResizedOp(window.getWidth(), window.getHeight()); } - @Override - public void windowDestroyNotify(WindowEvent e) { - glad.windowDestroyNotifyOp(); - } }); window.addWindowListener(wl); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextDrawableSwitch11NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextDrawableSwitch11NEWT.java index 4af9a3932..2ef797fba 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextDrawableSwitch11NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextDrawableSwitch11NEWT.java @@ -109,6 +109,11 @@ public class TestGLContextDrawableSwitch11NEWT extends UITestCase { } }; + window.setWindowDestroyNotifyAction( new Runnable() { + public void run() { + glad.windowDestroyNotifyOp(); + } } ); + // add basic window interaction window.addWindowListener(new WindowAdapter() { @Override @@ -119,10 +124,6 @@ public class TestGLContextDrawableSwitch11NEWT extends UITestCase { public void windowResized(WindowEvent e) { glad.windowResizedOp(window.getWidth(), window.getHeight()); } - @Override - public void windowDestroyNotify(WindowEvent e) { - glad.windowDestroyNotifyOp(); - } }); window.addWindowListener(wl); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextNewtAWTBug523.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextNewtAWTBug523.java index 7894f3e86..fbea81a54 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextNewtAWTBug523.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextNewtAWTBug523.java @@ -68,6 +68,7 @@ import com.jogamp.newt.awt.NewtCanvasAWT; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.test.junit.util.AWTRobotUtil; import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil.WindowClosingListener; import com.jogamp.opengl.util.Animator; import com.jogamp.opengl.util.GLBuffers; @@ -507,6 +508,8 @@ public class TestSharedContextNewtAWTBug523 extends UITestCase { */ public void testContextSharingCreateVisibleDestroy(final boolean useNewt, final boolean shareContext) throws InterruptedException, InvocationTargetException { final JFrame frame = new JFrame("Simple JOGL App for testing context sharing"); + final WindowClosingListener awtClosingListener = AWTRobotUtil.addClosingListener(frame); + // // GLDrawableFactory factory = GLDrawableFactory.getFactory(GLProfile.get(GLProfile.GL2)); // GLContext sharedContext = factory.getOrCreateSharedContext(factory.getDefaultDevice()); @@ -699,7 +702,7 @@ public class TestSharedContextNewtAWTBug523 extends UITestCase { while(animator.isAnimating() && animator.getTotalFPSDuration() < durationPerTest) { Thread.sleep(100); } - AWTRobotUtil.closeWindow(frame, true); + AWTRobotUtil.closeWindow(frame, true, awtClosingListener); boolean windowClosed = closingSemaphore.tryAcquire(5000, TimeUnit.MILLISECONDS); Assert.assertEquals(true, windowClosed); } catch (InterruptedException e) { diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestShutdownCompleteAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestShutdownCompleteAWT.java index 976885de4..afcf51e08 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestShutdownCompleteAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestShutdownCompleteAWT.java @@ -54,7 +54,6 @@ public class TestShutdownCompleteAWT extends UITestCase { final GLCanvas glCanvas = new GLCanvas(new GLCapabilities(GLProfile.getGL2ES2())); Assert.assertNotNull(glCanvas); frame.add(glCanvas); - frame.setSize(256, 256); glCanvas.addGLEventListener(new GearsES2(1)); @@ -62,6 +61,7 @@ public class TestShutdownCompleteAWT extends UITestCase { javax.swing.SwingUtilities.invokeAndWait(new Runnable() { public void run() { + frame.setSize(256, 256); frame.setVisible(true); }}); @@ -78,7 +78,10 @@ public class TestShutdownCompleteAWT extends UITestCase { animator.stop(); Assert.assertEquals(false, animator.isAnimating()); - frame.setVisible(false); + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setVisible(false); + }}); Assert.assertEquals(false, frame.isVisible()); javax.swing.SwingUtilities.invokeAndWait(new Runnable() { public void run() { diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWT01GLn.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWT01GLn.java index e1048c2f8..d444f02f7 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWT01GLn.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWT01GLn.java @@ -60,15 +60,15 @@ public class TestAWT01GLn extends UITestCase { glCanvas.addGLEventListener(new GearsES2()); frame.add(glCanvas); - // Revalidate size/layout. - // Always validate if component added/removed. - // Ensure 1st paint of GLCanvas will have a valid size, hence drawable gets created. - frame.setSize(512, 512); - frame.validate(); - try { javax.swing.SwingUtilities.invokeAndWait(new Runnable() { public void run() { + // Revalidate size/layout. + // Always validate if component added/removed. + // Ensure 1st paint of GLCanvas will have a valid size, hence drawable gets created. + frame.setSize(512, 512); + frame.validate(); + frame.setVisible(true); }}); } catch (Throwable t) { diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWT02WindowClosing.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWT02WindowClosing.java index f83c8c03d..6c0bc7701 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWT02WindowClosing.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWT02WindowClosing.java @@ -29,16 +29,12 @@ package com.jogamp.opengl.test.junit.jogl.awt; import com.jogamp.opengl.test.junit.util.UITestCase; -import javax.media.opengl.GLProfile; import java.awt.*; import java.awt.event.*; import org.junit.Assert; import org.junit.Assume; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.After; import org.junit.Test; public class TestAWT02WindowClosing extends UITestCase { @@ -47,15 +43,14 @@ public class TestAWT02WindowClosing extends UITestCase { @Test public void test01WindowClosing() throws InterruptedException { - Frame frame = new Frame(); - frame.setSize(500, 500); + final Frame frame = new Frame(); ClosingWindowAdapter closingWindowAdapter = new ClosingWindowAdapter(frame); frame.addWindowListener(closingWindowAdapter); - final Frame _frame = frame; try { javax.swing.SwingUtilities.invokeAndWait(new Runnable() { public void run() { - _frame.setVisible(true); + frame.setSize(500, 500); + frame.setVisible(true); }}); } catch (Throwable t) { t.printStackTrace(); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWT03GLCanvasRecreate01.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWT03GLCanvasRecreate01.java index aa7b4e06b..49ad1c9ba 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWT03GLCanvasRecreate01.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWT03GLCanvasRecreate01.java @@ -139,7 +139,7 @@ public class TestAWT03GLCanvasRecreate01 extends UITestCase { } private void setVisible(final Frame frame, final boolean v) { - try { + try { javax.swing.SwingUtilities.invokeAndWait(new Runnable() { public void run() { frame.setVisible(v); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWTCardLayoutAnimatorStartStopBug532.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWTCardLayoutAnimatorStartStopBug532.java index 3f6935588..1237fc9d4 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWTCardLayoutAnimatorStartStopBug532.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWTCardLayoutAnimatorStartStopBug532.java @@ -167,11 +167,10 @@ public class TestAWTCardLayoutAnimatorStartStopBug532 extends UITestCase { frame.add(comboBoxPanel, BorderLayout.PAGE_START); frame.add(cards, BorderLayout.CENTER); - - frame.pack(); - + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { public void run() { + frame.pack(); frame.setVisible(true); }}); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug461FBOSupersamplingSwingAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug461FBOSupersamplingSwingAWT.java index 42949afef..089520658 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug461FBOSupersamplingSwingAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug461FBOSupersamplingSwingAWT.java @@ -57,7 +57,6 @@ import com.jogamp.opengl.test.junit.util.UITestCase; * * @author Wade Walker (from code sample provided by Owen Dimond) */ -@SuppressWarnings("deprecation") public class TestBug461FBOSupersamplingSwingAWT extends UITestCase implements GLEventListener { JFrame jframe; GLOffscreenAutoDrawable offScreenBuffer; @@ -92,8 +91,15 @@ public class TestBug461FBOSupersamplingSwingAWT extends UITestCase implements GL BufferedImage outputImage = com.jogamp.opengl.util.awt.Screenshot.readToBufferedImage(200, 200, false); Assert.assertNotNull(outputImage); ImageIcon imageIcon = new ImageIcon(outputImage); - JLabel imageLabel = new JLabel(imageIcon); - jframe.getContentPane().add(imageLabel); + final JLabel imageLabel = new JLabel(imageIcon); + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + jframe.getContentPane().add(imageLabel); + }}); + } catch (Exception e) { + e.printStackTrace(); + } } /* @Override */ @@ -113,7 +119,6 @@ public class TestBug461FBOSupersamplingSwingAWT extends UITestCase implements GL public void testOffscreenSupersampling() throws InterruptedException, InvocationTargetException { jframe = new JFrame("Offscreen Supersampling"); Assert.assertNotNull(jframe); - jframe.setSize( 300, 300); jframe.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); @@ -147,6 +152,7 @@ public class TestBug461FBOSupersamplingSwingAWT extends UITestCase implements GL offScreenBuffer.display(); javax.swing.SwingUtilities.invokeAndWait(new Runnable() { public void run() { + jframe.setSize( 300, 300); jframe.setVisible(true); }}); offScreenBuffer.destroy(); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug572AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug572AWT.java index 80f0e93b6..ea8fe070d 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug572AWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug572AWT.java @@ -28,6 +28,7 @@ package com.jogamp.opengl.test.junit.jogl.awt; +import java.awt.Dimension; import java.awt.Window; import java.lang.reflect.InvocationTargetException; @@ -47,9 +48,11 @@ import com.jogamp.opengl.test.junit.util.AWTRobotUtil; import com.jogamp.opengl.test.junit.util.UITestCase; /** - * Tests context creation + display on various kinds of Window implementations. + * Test realize GLCanvas and setVisible(true) AWT-Frames on AWT-EDT and on current thread (non AWT-EDT) */ public class TestBug572AWT extends UITestCase { + static long durationPerTest = 150; // ms + static class Cleanup implements Runnable { Window window; @@ -69,9 +72,8 @@ public class TestBug572AWT extends UITestCase { window.dispose(); } } - - @Test - public void test01RealizeGLCanvasOnAWTEDT() throws InterruptedException, InvocationTargetException { + + private void testRealizeGLCanvas(final boolean onAWTEDT, final boolean setFrameSize) throws InterruptedException, InvocationTargetException { final Window window = new JFrame(this.getSimpleTestName(" - ")); final GLCapabilities caps = new GLCapabilities(GLProfile.getGL2ES2()); final GLCanvas glCanvas = new GLCanvas(caps); @@ -81,22 +83,37 @@ public class TestBug572AWT extends UITestCase { glCanvas.addGLEventListener(snapshooter); window.add(glCanvas); - // Revalidate size/layout. - // Always validate if component added/removed. - // Ensure 1st paint of GLCanvas will have a valid size, hence drawable gets created. - window.setSize(512, 512); - window.validate(); - - // trigger realization on AWT-EDT, otherwise it won't immediatly .. - SwingUtilities.invokeAndWait(new Runnable() { + final Runnable realizeAction = new Runnable() { @Override public void run() { + // Revalidate size/layout. + // Always validate if component added/removed. + // Ensure 1st paint of GLCanvas will have a valid size, hence drawable gets created. + if( setFrameSize ) { + window.setSize(512, 512); + window.validate(); + } else { + Dimension size = new Dimension(512, 512); + glCanvas.setPreferredSize(size); + glCanvas.setMinimumSize(size); + window.pack(); + } window.setVisible(true); - } - } ); + } }; + if( onAWTEDT ) { + // trigger realization on AWT-EDT, otherwise it won't immediatly .. + SwingUtilities.invokeAndWait( realizeAction ); + } else { + // trigger realization on non AWT-EDT, realization will happen at a later time .. + realizeAction.run(); + + // Wait until it's displayable after issuing initial setVisible(true) on current thread (non AWT-EDT)! + Assert.assertTrue("GLCanvas didn't become visible", AWTRobotUtil.waitForVisible(glCanvas, true)); + Assert.assertTrue("GLCanvas didn't become realized", AWTRobotUtil.waitForRealized(glCanvas, true)); // implies displayable + } + System.err.println("XXXX-0 "+glCanvas.getDelegatedDrawable().isRealized()+", "+glCanvas); - // Immediately displayable after issuing initial setVisible(true) on AWT-EDT! Assert.assertTrue("GLCanvas didn't become displayable", glCanvas.isDisplayable()); Assert.assertTrue("GLCanvas didn't become realized", glCanvas.isRealized()); @@ -116,59 +133,33 @@ public class TestBug572AWT extends UITestCase { Assert.assertTrue("GLCanvas didn't reshape", snapshooter.getReshapeCount()>0); Assert.assertTrue("GLCanvas didn't display", snapshooter.getDisplayCount()>0); + Thread.sleep(durationPerTest); + // After initial 'setVisible(true)' all AWT manipulation needs to be done // via the AWT EDT, according to the AWT spec. // AWT / Swing on EDT.. SwingUtilities.invokeAndWait(new Cleanup(window)); } + + @Test(timeout = 10000) // 10s timeout + public void test01RealizeGLCanvasOnAWTEDTUseFrameSize() throws InterruptedException, InvocationTargetException { + testRealizeGLCanvas(true, true); + } - @Test - public void test02RealizeGLCanvasOnCurrentThread() throws InterruptedException, InvocationTargetException { - final Window window = new JFrame(this.getSimpleTestName(" - ")); - final GLCapabilities caps = new GLCapabilities(GLProfile.getGL2ES2()); - final GLCanvas glCanvas = new GLCanvas(caps); - final SnapshotGLEventListener snapshooter = new SnapshotGLEventListener(); - snapshooter.setMakeSnapshotAlways(true); - glCanvas.addGLEventListener(new GearsES2()); - glCanvas.addGLEventListener(snapshooter); - window.add(glCanvas); - - // Revalidate size/layout. - // Always validate if component added/removed. - // Ensure 1st paint of GLCanvas will have a valid size, hence drawable gets created. - window.setSize(512, 512); - window.validate(); - - // trigger realization on non AWT-EDT, realization will happen at a later time .. - window.setVisible(true); - System.err.println("XXXX-0 "+glCanvas.getDelegatedDrawable().isRealized()+", "+glCanvas); - - // Wait until it's displayable after issuing initial setVisible(true) on current thread (non AWT-EDT)! - Assert.assertTrue("GLCanvas didn't become visible", AWTRobotUtil.waitForVisible(glCanvas, true)); - Assert.assertTrue("GLCanvas didn't become realized", AWTRobotUtil.waitForRealized(glCanvas, true)); // implies displayable - - // The AWT-EDT reshape/repaint events happen offthread later .. - System.err.println("XXXX-1 reshapeCount "+snapshooter.getReshapeCount()); - System.err.println("XXXX-1 displayCount "+snapshooter.getDisplayCount()); - - // Wait unitl AWT-EDT has issued reshape/repaint - for (int wait=0; wait<AWTRobotUtil.POLL_DIVIDER && - ( 0 == snapshooter.getReshapeCount() || 0 == snapshooter.getDisplayCount() ); - wait++) { - Thread.sleep(AWTRobotUtil.TIME_SLICE); - } - System.err.println("XXXX-2 reshapeCount "+snapshooter.getReshapeCount()); - System.err.println("XXXX-2 displayCount "+snapshooter.getDisplayCount()); - - Assert.assertTrue("GLCanvas didn't reshape", snapshooter.getReshapeCount()>0); - Assert.assertTrue("GLCanvas didn't display", snapshooter.getDisplayCount()>0); - - // After initial 'setVisible(true)' all AWT manipulation needs to be done - // via the AWT EDT, according to the AWT spec. + @Test(timeout = 10000) // 10s timeout + public void test02RealizeGLCanvasOnAWTEDTUseGLCanvasSize() throws InterruptedException, InvocationTargetException { + testRealizeGLCanvas(true, false); + } + + @Test(timeout = 10000) // 10s timeout + public void test11RealizeGLCanvasOnMainTUseFrameSize() throws InterruptedException, InvocationTargetException { + testRealizeGLCanvas(false, true); + } - // AWT / Swing on EDT.. - SwingUtilities.invokeAndWait(new Cleanup(window)); + @Test(timeout = 10000) // 10s timeout + public void test12RealizeGLCanvasOnMainTUseGLCanvasSize() throws InterruptedException, InvocationTargetException { + testRealizeGLCanvas(false, false); } public static void main(String args[]) { diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLCanvasAWTActionDeadlock01AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLCanvasAWTActionDeadlock01AWT.java index c51972c39..0bcde2b35 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLCanvasAWTActionDeadlock01AWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLCanvasAWTActionDeadlock01AWT.java @@ -36,6 +36,7 @@ import javax.media.opengl.awt.GLCanvas; import com.jogamp.common.os.Platform; import com.jogamp.common.util.VersionNumber; +import com.jogamp.common.util.awt.AWTEDTExecutor; import com.jogamp.opengl.util.Animator; import com.jogamp.opengl.util.AnimatorBase; import com.jogamp.opengl.util.FPSAnimator; @@ -51,6 +52,7 @@ import java.awt.Frame; import java.awt.Insets; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; +import java.lang.reflect.InvocationTargetException; import org.junit.Assert; import org.junit.Assume; @@ -70,6 +72,9 @@ import org.junit.Test; * Similar deadlock has been experienced w/ other mutable operation on an AWT Container owning a GLCanvas child, * e.g. setResizable*(). * </p> + * <p> + * Users shall make sure all mutable AWT calls are performed on the EDT, even before 1st setVisible(true) ! + * </p> */ public class TestGLCanvasAWTActionDeadlock01AWT extends UITestCase { static long durationPerTest = 1000; // ms @@ -80,40 +85,45 @@ public class TestGLCanvasAWTActionDeadlock01AWT extends UITestCase { GLEventListener gle2 = null; @Test - public void test00NoAnimator() throws InterruptedException { + public void test00NoAnimator() throws InterruptedException, InvocationTargetException { testImpl(null, 0, false); } @Test - public void test01Animator() throws InterruptedException { + public void test01Animator() throws InterruptedException, InvocationTargetException { testImpl(new Animator(), 0, false); } @Test - public void test02FPSAnimator() throws InterruptedException { + public void test02FPSAnimator() throws InterruptedException, InvocationTargetException { testImpl(new FPSAnimator(30), 0, false); } @Test - public void test02FPSAnimator_RestartOnAWTEDT() throws InterruptedException { + public void test02FPSAnimator_RestartOnAWTEDT() throws InterruptedException, InvocationTargetException { testImpl(new FPSAnimator(30), 200, false); } /** May crash due to invalid thread usage, i.e. non AWT-EDT + * @throws InvocationTargetException + * @throws InterruptedException @Test public void test02FPSAnimator_RestartOnCurrentThread() throws InterruptedException { testImpl(new FPSAnimator(30), 200, true); } */ - private static void setFrameTitle(Frame frame, String msg) { + private static void setFrameTitle(final Frame frame, final String msg) { System.err.println("About to setTitle: <"+msg+"> CT "+Thread.currentThread().getName()+", "+ frame+", displayable "+frame.isDisplayable()+ ", valid "+frame.isValid()+", visible "+frame.isVisible()); // Thread.dumpStack(); - frame.setTitle(msg); + AWTEDTExecutor.singleton.invoke(true, new Runnable() { + public void run() { + frame.setTitle(msg); + } } ); } - void testImpl(final AnimatorBase animator, int restartPeriod, boolean restartOnCurrentThread) throws InterruptedException { + void testImpl(final AnimatorBase animator, int restartPeriod, boolean restartOnCurrentThread) throws InterruptedException, InvocationTargetException { final Frame frame1 = new Frame("Frame 1"); final Applet applet1 = new Applet() { private static final long serialVersionUID = 1L; @@ -127,20 +137,23 @@ public class TestGLCanvasAWTActionDeadlock01AWT extends UITestCase { System.err.println("Java Version "+Platform.getJavaVersionNumber()); Assert.assertNotNull(frame1); - frame1.setLayout(null); - frame1.pack(); - { - Insets insets = frame1.getInsets(); - int w = width + insets.left + insets.right; - int h = height + insets.top + insets.bottom; - frame1.setSize(w, h); - - int usableH = h - insets.top - insets.bottom; - applet1.setBounds((w - width)/2, insets.top + (usableH - height)/2, width, height); - } - frame1.setLocation(0, 0); - frame1.setTitle("Generic Title"); - frame1.add(applet1); + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame1.setLayout(null); + frame1.pack(); + { + Insets insets = frame1.getInsets(); + int w = width + insets.left + insets.right; + int h = height + insets.top + insets.bottom; + frame1.setSize(w, h); + + int usableH = h - insets.top - insets.bottom; + applet1.setBounds((w - width)/2, insets.top + (usableH - height)/2, width, height); + } + frame1.setLocation(0, 0); + frame1.setTitle("Generic Title"); + frame1.add(applet1); + }}); frame1.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLCanvasAWTActionDeadlock02AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLCanvasAWTActionDeadlock02AWT.java index d8f25868b..289c62423 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLCanvasAWTActionDeadlock02AWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLCanvasAWTActionDeadlock02AWT.java @@ -55,6 +55,7 @@ import org.junit.Test; import com.jogamp.common.os.Platform; import com.jogamp.common.util.VersionNumber; +import com.jogamp.common.util.awt.AWTEDTExecutor; import com.jogamp.opengl.util.AnimatorBase; import com.jogamp.opengl.test.junit.util.MiscUtils; import com.jogamp.opengl.test.junit.util.UITestCase; @@ -77,6 +78,9 @@ import com.jogamp.opengl.test.junit.util.UITestCase; * Similar deadlock has been experienced w/ other mutable operation on an AWT Container owning a GLCanvas child, * e.g. setResizable*(). * </p> + * <p> + * Users shall make sure all mutable AWT calls are performed on the EDT, even before 1st setVisible(true) ! + * </p> */ public class TestGLCanvasAWTActionDeadlock02AWT extends UITestCase { static int framesPerTest = 240; // frames @@ -193,53 +197,77 @@ public class TestGLCanvasAWTActionDeadlock02AWT extends UITestCase { width = 300; height = 300; - MiniPApplet applet = this; - Rectangle fullScreenRect = null; + final MiniPApplet applet = this; GraphicsEnvironment environment = GraphicsEnvironment.getLocalGraphicsEnvironment(); GraphicsDevice displayDevice = environment.getDefaultScreenDevice(); frame = new Frame(displayDevice.getDefaultConfiguration()); - frame.setTitle("MiniPApplet"); + final Rectangle fullScreenRect; if (fullScreen) { - frame.setUndecorated(true); - frame.setBackground(Color.GRAY); DisplayMode mode = displayDevice.getDisplayMode(); fullScreenRect = new Rectangle(0, 0, mode.getWidth(), mode.getHeight()); - frame.setBounds(fullScreenRect); - frame.setVisible(true); - } - frame.setLayout(null); - frame.add(applet); - if (fullScreen) { - frame.invalidate(); } else { - frame.pack(); + fullScreenRect = null; } - frame.setResizable(resizeableFrame); - + // All AWT Mods on AWT-EDT, especially due to the follow-up complicated code! + AWTEDTExecutor.singleton.invoke(true, new Runnable() { + public void run() { + frame.setTitle("MiniPApplet"); + } } ); if (fullScreen) { - // After the pack(), the screen bounds are gonna be 0s - frame.setBounds(fullScreenRect); - applet.setBounds((fullScreenRect.width - applet.width) / 2, - (fullScreenRect.height - applet.height) / 2, - applet.width, applet.height); - } else { - Insets insets = frame.getInsets(); - - int windowW = applet.width + insets.left + insets.right; - int windowH = applet.height + insets.top + insets.bottom; - int locationX = 100; - int locationY = 100; - - frame.setSize(windowW, windowH); - frame.setLocation(locationX, locationY); - - int usableWindowH = windowH - insets.top - insets.bottom; - applet.setBounds((windowW - width)/2, insets.top + (usableWindowH - height)/2, width, height); + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setUndecorated(true); + frame.setBackground(Color.GRAY); + frame.setBounds(fullScreenRect); + frame.setVisible(true); + }}); + } catch (Throwable t) { + t.printStackTrace(); + Assume.assumeNoException(t); + } + } + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setLayout(null); + frame.add(applet); + if (fullScreen) { + frame.invalidate(); + } else { + frame.pack(); + } + frame.setResizable(resizeableFrame); + if (fullScreen) { + // After the pack(), the screen bounds are gonna be 0s + frame.setBounds(fullScreenRect); + applet.setBounds((fullScreenRect.width - applet.width) / 2, + (fullScreenRect.height - applet.height) / 2, + applet.width, applet.height); + } else { + Insets insets = frame.getInsets(); + + int windowW = applet.width + insets.left + insets.right; + int windowH = applet.height + insets.top + insets.bottom; + int locationX = 100; + int locationY = 100; + + frame.setSize(windowW, windowH); + frame.setLocation(locationX, locationY); + + int usableWindowH = windowH - insets.top - insets.bottom; + applet.setBounds((windowW - width)/2, insets.top + (usableWindowH - height)/2, width, height); + } + }}); + } catch (Throwable t) { + t.printStackTrace(); + Assume.assumeNoException(t); } + frame.add(this); frame.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { @@ -253,7 +281,7 @@ public class TestGLCanvasAWTActionDeadlock02AWT extends UITestCase { javax.swing.SwingUtilities.invokeAndWait(new Runnable() { public void run() { - frame.setVisible(true); // from here on all AWT mods must be done on AWT-EDT ! + frame.setVisible(true); } } ); // Canvas setup ---------------------------------------------------------- @@ -359,7 +387,10 @@ public class TestGLCanvasAWTActionDeadlock02AWT extends UITestCase { void draw(GL2 gl) { if( !osxCALayerAWTModBug || !justInitialized ) { - frame.setTitle("frame " + frameCount); + AWTEDTExecutor.singleton.invoke(true, new Runnable() { + public void run() { + frame.setTitle("frame " + frameCount); + } } ); } if (printThreadInfo) System.out.println("Current thread at draw(): " + Thread.currentThread()); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestJScrollPaneMixHwLw01AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestJScrollPaneMixHwLw01AWT.java index 8868d255d..991f4acf8 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestJScrollPaneMixHwLw01AWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestJScrollPaneMixHwLw01AWT.java @@ -106,13 +106,13 @@ public class TestJScrollPaneMixHwLw01AWT extends UITestCase { panel.add(textArea, BorderLayout.NORTH); frame.add(panel); - frame.setLocationRelativeTo(null); - frame.setTitle("GLCanvas in JScrollPane example"); frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); try { javax.swing.SwingUtilities.invokeAndWait(new Runnable() { public void run() { + frame.setLocationRelativeTo(null); + frame.setTitle("GLCanvas in JScrollPane example"); frame.setSize(f_sz); frame.setVisible(true); }}); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/text/TestAWTTextRendererUseVertexArrayBug464.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/text/TestAWTTextRendererUseVertexArrayBug464.java index ab369a959..ffe3bb3a6 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/awt/text/TestAWTTextRendererUseVertexArrayBug464.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/text/TestAWTTextRendererUseVertexArrayBug464.java @@ -37,7 +37,6 @@ import com.jogamp.opengl.test.junit.util.UITestCase; import java.awt.Frame; import java.io.IOException; -import java.lang.reflect.InvocationTargetException; import org.junit.Assert; import org.junit.Assume; @@ -84,9 +83,16 @@ public class TestAWTTextRendererUseVertexArrayBug464 extends UITestCase { frame = new Frame("TextRenderer Test"); Assert.assertNotNull(frame); frame.add(glCanvas); - frame.setSize(512, 512); - frame.setVisible(true); - + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setSize(512, 512); + frame.setVisible(true); + }}); + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } } @After diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestMultisampleES1AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestMultisampleES1AWT.java index c5bdfb5f3..208367102 100755 --- a/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestMultisampleES1AWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestMultisampleES1AWT.java @@ -116,11 +116,11 @@ public class TestMultisampleES1AWT extends UITestCase { final Frame frame = new Frame("Multi Samples "+reqSamples); frame.setLayout(new BorderLayout()); canvas.setSize(512, 512); - frame.add(canvas, BorderLayout.CENTER); - frame.pack(); javax.swing.SwingUtilities.invokeAndWait(new Runnable() { public void run() { + frame.add(canvas, BorderLayout.CENTER); + frame.pack(); frame.setVisible(true); canvas.requestFocus(); canvas.display(); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestTranslucencyAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestTranslucencyAWT.java index 7cce5d1e4..6d8270aaf 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestTranslucencyAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestTranslucencyAWT.java @@ -119,18 +119,21 @@ public class TestTranslucencyAWT extends UITestCase { GLAnimatorControl animator1 = new Animator(glCanvas); animator1.start(); - Container cont1 = new Container(); + final Container cont1 = new Container(); cont1.setLayout(new BorderLayout()); cont1.add(glCanvas, BorderLayout.CENTER); - cont1.setVisible(true); + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + cont1.setVisible(true); + }}); frame1.setLayout(new BorderLayout()); frame1.add(cont1, BorderLayout.EAST); frame1.add(new Label("center"), BorderLayout.CENTER); - frame1.setLocation(0, 0); - frame1.setSize((int)size.getWidth(), (int)size.getHeight()); javax.swing.SwingUtilities.invokeAndWait(new Runnable() { public void run() { + frame1.setLocation(0, 0); + frame1.setSize((int)size.getWidth(), (int)size.getHeight()); frame1.pack(); frame1.setVisible(true); }}); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java index 74377a5f8..99df7c102 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java @@ -366,6 +366,10 @@ public class GearsES2 implements GLEventListener { public void mousePressed(MouseEvent e) { prevMouseX = e.getX(); prevMouseY = e.getY(); + Object src = e.getSource(); + if(e.getPressure(true)>0.8f && src instanceof Window) { // show Keyboard + ((Window) src).setKeyboardVisible(true); + } } public void mouseReleased(MouseEvent e) { diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2AWT.java index aca2b675c..d59b81ff1 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2AWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2AWT.java @@ -211,7 +211,10 @@ public class TestGearsES2AWT extends UITestCase { Assert.assertFalse(animator.isAnimating()); Assert.assertFalse(animator.isStarted()); Assert.assertEquals(null, glCanvas.getExclusiveContextThread()); - frame.setVisible(false); + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setVisible(false); + }}); Assert.assertEquals(false, frame.isVisible()); javax.swing.SwingUtilities.invokeAndWait(new Runnable() { public void run() { diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGLJPanelAWTBug450.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGLJPanelAWTBug450.java index bd9b7cae7..aaf995e6c 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGLJPanelAWTBug450.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGLJPanelAWTBug450.java @@ -87,10 +87,10 @@ public class TestGLJPanelAWTBug450 extends UITestCase { throws AWTException, InterruptedException, InvocationTargetException { final GLReadBufferUtil screenshot = new GLReadBufferUtil(true, false); - JFrame frame = new JFrame("Swing GLJPanel"); + final JFrame frame = new JFrame("Swing GLJPanel"); Assert.assertNotNull(frame); - GLJPanel glJPanel = new GLJPanel(caps); + final GLJPanel glJPanel = new GLJPanel(caps); Assert.assertNotNull(glJPanel); RedSquareES2 demo = new RedSquareES2(); demo.setAspect((float)width/(float)height); @@ -129,13 +129,11 @@ public class TestGLJPanelAWTBug450 extends UITestCase { FPSAnimator animator = new FPSAnimator(glJPanel, 60); - final JFrame _frame = frame; - final GLJPanel _glJPanel = glJPanel; SwingUtilities.invokeAndWait(new Runnable() { public void run() { - _frame.getContentPane().add(_glJPanel, BorderLayout.CENTER); - _frame.setSize(width, height); - _frame.setVisible(true); + frame.getContentPane().add(glJPanel, BorderLayout.CENTER); + frame.setSize(width, height); + frame.setVisible(true); } } ) ; animator.setUpdateFPSFrames(1, null); @@ -154,11 +152,11 @@ public class TestGLJPanelAWTBug450 extends UITestCase { Assert.assertEquals(false, animator.isAnimating()); SwingUtilities.invokeAndWait(new Runnable() { public void run() { - _frame.setVisible(false); - _frame.getContentPane().remove(_glJPanel); - _frame.remove(_glJPanel); - _glJPanel.destroy(); - _frame.dispose(); + frame.setVisible(false); + frame.getContentPane().remove(glJPanel); + frame.remove(glJPanel); + glJPanel.destroy(); + frame.dispose(); } } ); Assert.assertFalse( failed ); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGearsAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGearsAWT.java index 498a3285a..528762a9c 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGearsAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGearsAWT.java @@ -114,7 +114,10 @@ public class TestGearsAWT extends UITestCase { animator.stop(); Assert.assertEquals(false, animator.isAnimating()); - frame.setVisible(false); + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setVisible(false); + }}); Assert.assertEquals(false, frame.isVisible()); javax.swing.SwingUtilities.invokeAndWait(new Runnable() { public void run() { diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGearsAWTAnalyzeBug455.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGearsAWTAnalyzeBug455.java index 4807e5d25..22df3313b 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGearsAWTAnalyzeBug455.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGearsAWTAnalyzeBug455.java @@ -105,7 +105,6 @@ public class TestGearsAWTAnalyzeBug455 extends UITestCase { Assert.assertNotNull(glCanvas); glCanvas.setAutoSwapBufferMode(!altSwap); frame.add(glCanvas); - frame.setSize(512, 512); glCanvas.addGLEventListener(new Gears(0)); glCanvas.addGLEventListener(new Swapper()); @@ -118,6 +117,7 @@ public class TestGearsAWTAnalyzeBug455 extends UITestCase { javax.swing.SwingUtilities.invokeAndWait(new Runnable() { public void run() { + frame.setSize(512, 512); frame.setVisible(true); }}); animator.setUpdateFPSFrames(60, System.err); @@ -133,7 +133,10 @@ public class TestGearsAWTAnalyzeBug455 extends UITestCase { animator.stop(); Assert.assertEquals(false, animator.isAnimating()); - frame.setVisible(false); + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setVisible(false); + }}); Assert.assertEquals(false, frame.isVisible()); javax.swing.SwingUtilities.invokeAndWait(new Runnable() { public void run() { diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGearsGLJPanelAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGearsGLJPanelAWT.java index cb54c26bd..d27f3dcf8 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGearsGLJPanelAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGearsGLJPanelAWT.java @@ -70,10 +70,10 @@ public class TestGearsGLJPanelAWT extends UITestCase { protected void runTestGL(GLCapabilities caps) throws AWTException, InterruptedException, InvocationTargetException { - JFrame frame = new JFrame("Swing GLJPanel"); + final JFrame frame = new JFrame("Swing GLJPanel"); Assert.assertNotNull(frame); - GLJPanel glJPanel = new GLJPanel(caps); + final GLJPanel glJPanel = new GLJPanel(caps); Assert.assertNotNull(glJPanel); Dimension glc_sz = new Dimension(width, height); glJPanel.setMinimumSize(glc_sz); @@ -83,14 +83,12 @@ public class TestGearsGLJPanelAWT extends UITestCase { FPSAnimator animator = new FPSAnimator(glJPanel, 60); - final JFrame _frame = frame; - final GLJPanel _glJPanel = glJPanel; SwingUtilities.invokeAndWait(new Runnable() { public void run() { - _frame.getContentPane().add(_glJPanel, BorderLayout.CENTER); - _frame.getContentPane().validate(); - _frame.pack(); - _frame.setVisible(true); + frame.getContentPane().add(glJPanel, BorderLayout.CENTER); + frame.getContentPane().validate(); + frame.pack(); + frame.setVisible(true); } } ) ; animator.setUpdateFPSFrames(1, null); @@ -109,11 +107,11 @@ public class TestGearsGLJPanelAWT extends UITestCase { Assert.assertEquals(false, animator.isAnimating()); SwingUtilities.invokeAndWait(new Runnable() { public void run() { - _frame.setVisible(false); - _frame.getContentPane().remove(_glJPanel); - _frame.remove(_glJPanel); - _glJPanel.destroy(); - _frame.dispose(); + frame.setVisible(false); + frame.getContentPane().remove(glJPanel); + frame.remove(glJPanel); + glJPanel.destroy(); + frame.dispose(); } } ); } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestShaderCompilationBug459AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestShaderCompilationBug459AWT.java index d133ebde5..4d878432f 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestShaderCompilationBug459AWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestShaderCompilationBug459AWT.java @@ -81,7 +81,6 @@ public class TestShaderCompilationBug459AWT extends UITestCase { final GLCanvas glCanvas = new GLCanvas(caps); Assert.assertNotNull(glCanvas); frame.add(glCanvas); - frame.setSize(512, 512); glCanvas.addGLEventListener(new GLEventListener() { /* @Override */ @@ -131,7 +130,15 @@ public class TestShaderCompilationBug459AWT extends UITestCase { }); Animator animator = new Animator(glCanvas); - frame.setVisible(true); + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setSize(512, 512); + frame.setVisible(true); + } } ); + } catch(Exception ex) { + throw new RuntimeException(ex); + } animator.setUpdateFPSFrames(1, null); animator.start(); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/newt/TestSwingAWTRobotUsageBeforeJOGLInitBug411.java b/src/test/com/jogamp/opengl/test/junit/jogl/newt/TestSwingAWTRobotUsageBeforeJOGLInitBug411.java index 0e9b6cd88..a6b3eb85d 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/newt/TestSwingAWTRobotUsageBeforeJOGLInitBug411.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/newt/TestSwingAWTRobotUsageBeforeJOGLInitBug411.java @@ -142,15 +142,15 @@ public class TestSwingAWTRobotUsageBeforeJOGLInitBug411 extends UITestCase { } }); frame.setContentPane(panel); - frame.setSize(512, 512); - frame.setLocation(0, 0); - frame.pack(); // AWT/Swing: From here on (post setVisible(true) // you need to use AWT/Swing's invokeAndWait() javax.swing.SwingUtilities.invokeAndWait(new Runnable() { public void run() { + frame.setSize(512, 512); + frame.setLocation(0, 0); + frame.pack(); frame.setVisible(true); colorPanel.setBackground(Color.white); colorPanel.repaint(); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTAccessor03AWTGLn.java b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTAccessor03AWTGLn.java index 91902a896..5803a1675 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTAccessor03AWTGLn.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTAccessor03AWTGLn.java @@ -83,10 +83,17 @@ public class TestSWTAccessor03AWTGLn extends UITestCase { return; } System.out.println( "GLProfile " + GLProfile.glAvailabilityToString() ); - Frame f0 = new Frame("Test - AWT 1st"); + final Frame f0 = new Frame("Test - AWT 1st"); f0.add(new java.awt.Label("AWT was here 1st")); - f0.pack(); - f0.setVisible(true); + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + f0.pack(); + f0.setVisible(true); + }}); + } catch (Exception e) { + throw new RuntimeException(e); + } if(!GLProfile.isAvailable(GLProfile.GL2)) { setTestSupported(false); } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTexture01AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTexture01AWT.java index 2d7b3b080..8baba68ec 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTexture01AWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTexture01AWT.java @@ -111,14 +111,22 @@ public class TestTexture01AWT extends UITestCase { final Frame frame = new Frame("Texture Test"); Assert.assertNotNull(frame); frame.add(glCanvas); - frame.setSize(512, 512); // create texture TextureData textureData = AWTTextureIO.newTextureData(caps.getGLProfile(), textureImage, false); glCanvas.addGLEventListener(new TextureDraw01GL2Listener(textureData)); Animator animator = new Animator(glCanvas); - frame.setVisible(true); + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setSize(512, 512); + frame.setVisible(true); + }}); + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } animator.start(); Thread.sleep(500); // 500 ms diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTextureSequence01AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTextureSequence01AWT.java index 36dad45e6..7bad83781 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTextureSequence01AWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTextureSequence01AWT.java @@ -42,7 +42,6 @@ public class TestTextureSequence01AWT extends UITestCase { final Frame frame = new Frame("TestTextureSequence01AWT"); Assert.assertNotNull(frame); frame.add(glc); - frame.setSize(width, height); final TextureSequenceDemo01 texSource = new TextureSequenceDemo01(useBuildInTexLookup); glc.addGLEventListener(new GLEventListener() { @@ -63,7 +62,16 @@ public class TestTextureSequence01AWT extends UITestCase { QuitAdapter quitAdapter = new QuitAdapter(); new com.jogamp.newt.event.awt.AWTKeyAdapter(quitAdapter).addTo(glc); new com.jogamp.newt.event.awt.AWTWindowAdapter(quitAdapter).addTo(glc); - frame.setVisible(true); + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setSize(width, height); + frame.setVisible(true); + }}); + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } animator.start(); while(!quitAdapter.shouldQuit() && animator.isAnimating() && animator.getTotalFPSDuration()<duration) { 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 4ebb7dddd..d63193445 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.opengl.GLWindow; import com.jogamp.opengl.test.junit.util.AWTRobotUtil; import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil.WindowClosingListener; public class TestCloseNewtAWT extends UITestCase { @@ -107,9 +108,11 @@ public class TestCloseNewtAWT extends UITestCase { frame.setVisible(true); } }); - Thread.sleep(500); + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(newtWindow, true)); + final WindowClosingListener closingListener = AWTRobotUtil.addClosingListener(frame); - Assert.assertEquals(true, AWTRobotUtil.closeWindow(frame, true)); + Assert.assertEquals(true, AWTRobotUtil.closeWindow(frame, true, closingListener)); } public static void main(String[] args) { diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestFocus02SwingAWTRobot.java b/src/test/com/jogamp/opengl/test/junit/newt/TestFocus02SwingAWTRobot.java index 0e87144da..978bc1c0a 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/TestFocus02SwingAWTRobot.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/TestFocus02SwingAWTRobot.java @@ -72,15 +72,20 @@ public class TestFocus02SwingAWTRobot extends UITestCase { static GLCapabilities glCaps; @BeforeClass - public static void initClass() throws AWTException { + public static void initClass() throws AWTException, InterruptedException, InvocationTargetException { width = 640; height = 480; - JFrame f = new JFrame(); - f.setSize(100,100); - f.setVisible(true); - f.dispose(); - f=null; + final JFrame f = new JFrame(); + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + f.setSize(100,100); + f.setVisible(true); + } } ); + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + f.dispose(); + } } ); glCaps = new GLCapabilities(null); } @@ -126,7 +131,7 @@ public class TestFocus02SwingAWTRobot extends UITestCase { AWTMouseAdapter buttonNorthInnerMA = new AWTMouseAdapter("ButtonNorthInner"); buttonNorthInner.addMouseListener(buttonNorthInnerMA); eventCountAdapters.add(buttonNorthInnerMA); - Container container1 = new Container(); + final Container container1 = new Container(); container1.setLayout(new BorderLayout()); container1.add(buttonNorthInner, BorderLayout.NORTH); container1.add(new Button("south"), BorderLayout.SOUTH); @@ -143,7 +148,7 @@ public class TestFocus02SwingAWTRobot extends UITestCase { AWTMouseAdapter buttonNorthOuterMA = new AWTMouseAdapter("ButtonNorthOuter"); buttonNorthOuter.addMouseListener(buttonNorthOuterMA); eventCountAdapters.add(buttonNorthOuterMA); - JPanel jPanel1 = new JPanel(); + final JPanel jPanel1 = new JPanel(); jPanel1.setLayout(new BorderLayout()); jPanel1.add(buttonNorthOuter, BorderLayout.NORTH); jPanel1.add(new Button("south"), BorderLayout.SOUTH); @@ -249,14 +254,11 @@ public class TestFocus02SwingAWTRobot extends UITestCase { animator1.stop(); Assert.assertEquals(false, animator1.isAnimating()); - final JFrame _jFrame1 = jFrame1; - final JPanel _jPanel1 = jPanel1; - final Container _container1 = container1; SwingUtilities.invokeAndWait(new Runnable() { public void run() { - _jFrame1.setVisible(false); - _jPanel1.remove(_container1); - _jFrame1.dispose(); + jFrame1.setVisible(false); + jPanel1.remove(container1); + jFrame1.dispose(); } }); glWindow1.destroy(); diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestWindowClosingProtocol01AWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestWindowClosingProtocol01AWT.java index 6aedb8433..acaa279fe 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/TestWindowClosingProtocol01AWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/TestWindowClosingProtocol01AWT.java @@ -46,13 +46,14 @@ import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; import com.jogamp.opengl.test.junit.util.AWTRobotUtil; import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil.WindowClosingListener; public class TestWindowClosingProtocol01AWT extends UITestCase { @Test public void testCloseFrameGLCanvas() throws InterruptedException, InvocationTargetException { final Frame frame = new Frame("testCloseFrameGLCanvas AWT"); - + final WindowClosingListener closingListener = AWTRobotUtil.addClosingListener(frame); GLProfile glp = GLProfile.getGL2ES2(); GLCapabilities caps = new GLCapabilities(glp); final GLCanvas glCanvas = new GLCanvas(caps); @@ -74,12 +75,14 @@ public class TestWindowClosingProtocol01AWT extends UITestCase { WindowClosingMode op = glCanvas.getDefaultCloseOperation(); Assert.assertEquals(WindowClosingMode.DO_NOTHING_ON_CLOSE, op); - Assert.assertEquals(true, AWTRobotUtil.closeWindow(frame, false)); // nop + Assert.assertEquals(true, AWTRobotUtil.closeWindow(frame, false, closingListener)); // nop Thread.sleep(100); - Assert.assertEquals(true, frame.isDisplayable()); + Assert.assertEquals(true, frame.isDisplayable()); Assert.assertEquals(true, frame.isVisible()); - Assert.assertEquals(true, glCanvas.isValid()); - Assert.assertEquals(true, glCanvas.isDisplayable()); + Assert.assertEquals(true, glCanvas.isValid()); + Assert.assertEquals(true, glCanvas.isDisplayable()); + Assert.assertEquals(true, closingListener.isWindowClosing()); + Assert.assertEquals(false, closingListener.isWindowClosed()); // // close with op (GLCanvas): DISPOSE_ON_CLOSE -> dispose @@ -90,10 +93,12 @@ public class TestWindowClosingProtocol01AWT extends UITestCase { Thread.sleep(300); - Assert.assertEquals(true, AWTRobotUtil.closeWindow(frame, false)); // no frame close, but GLCanvas's GL resources will be destroyed + Assert.assertEquals(true, AWTRobotUtil.closeWindow(frame, false, closingListener)); // no frame close, but GLCanvas's GL resources will be destroyed Thread.sleep(100); Assert.assertEquals(true, frame.isDisplayable()); Assert.assertEquals(true, frame.isVisible()); + Assert.assertEquals(true, closingListener.isWindowClosing()); + Assert.assertEquals(false, closingListener.isWindowClosed()); for (int wait=0; wait<AWTRobotUtil.POLL_DIVIDER && glCanvas.isRealized(); wait++) { Thread.sleep(AWTRobotUtil.TIME_SLICE); } @@ -108,17 +113,18 @@ public class TestWindowClosingProtocol01AWT extends UITestCase { @Test public void testCloseJFrameGLCanvas() throws InterruptedException, InvocationTargetException { final JFrame frame = new JFrame("testCloseJFrameGLCanvas AWT"); - + final WindowClosingListener closingListener = AWTRobotUtil.addClosingListener(frame); + GLProfile glp = GLProfile.getGL2ES2(); GLCapabilities caps = new GLCapabilities(glp); - GLCanvas glCanvas = new GLCanvas(caps); + final GLCanvas glCanvas = new GLCanvas(caps); glCanvas.addGLEventListener(new GearsES2()); - frame.getContentPane().add(glCanvas); - frame.pack(); - frame.setSize(512, 512); - frame.validate(); SwingUtilities.invokeAndWait(new Runnable() { public void run() { + frame.getContentPane().add(glCanvas); + frame.pack(); + frame.setSize(512, 512); + frame.validate(); frame.setVisible(true); } }); Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true)); @@ -133,9 +139,10 @@ public class TestWindowClosingProtocol01AWT extends UITestCase { Thread.sleep(300); - Assert.assertEquals(true, AWTRobotUtil.closeWindow(frame, false)); // nop - Thread.sleep(100); + Assert.assertEquals(true, AWTRobotUtil.closeWindow(frame, false, closingListener)); // hide + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, false)); // hide -> invisible Assert.assertEquals(true, frame.isDisplayable()); + Assert.assertEquals(false, frame.isVisible()); Assert.assertEquals(true, glCanvas.isValid()); Assert.assertEquals(true, glCanvas.isDisplayable()); @@ -145,6 +152,8 @@ public class TestWindowClosingProtocol01AWT extends UITestCase { } }); Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true)); Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas, true)); + Assert.assertEquals(true, frame.isDisplayable()); + Assert.assertEquals(true, frame.isVisible()); // // close with op (JFrame): DISPOSE_ON_CLOSE -- GLCanvas --> dispose @@ -154,7 +163,7 @@ public class TestWindowClosingProtocol01AWT extends UITestCase { op = glCanvas.getDefaultCloseOperation(); Assert.assertEquals(WindowClosingMode.DISPOSE_ON_CLOSE, op); - Assert.assertEquals(true, AWTRobotUtil.closeWindow(frame, true)); + Assert.assertEquals(true, AWTRobotUtil.closeWindow(frame, true, closingListener)); Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas, false)); Assert.assertEquals(false, frame.isDisplayable()); Assert.assertEquals(false, glCanvas.isValid()); diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestWindowClosingProtocol02NEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestWindowClosingProtocol02NEWT.java index 8cd44b82c..8d32beea3 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/TestWindowClosingProtocol02NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/TestWindowClosingProtocol02NEWT.java @@ -52,7 +52,7 @@ public class TestWindowClosingProtocol02NEWT extends UITestCase { GLProfile glp = GLProfile.getGL2ES2(); GLCapabilities caps = new GLCapabilities(glp); final GLWindow glWindow = GLWindow.create(caps); - final AWTRobotUtil.WindowClosingListener windowClosingListener = AWTRobotUtil.addClosingListener(glWindow); + final AWTRobotUtil.WindowClosingListener closingListener = AWTRobotUtil.addClosingListener(glWindow); glWindow.addGLEventListener(new GearsES2()); glWindow.setSize(512, 512); @@ -72,10 +72,10 @@ public class TestWindowClosingProtocol02NEWT extends UITestCase { Thread.sleep(300); - Assert.assertEquals(true, AWTRobotUtil.closeWindow(glWindow, false)); // nop + Assert.assertEquals(true, AWTRobotUtil.closeWindow(glWindow, false, closingListener)); // nop Assert.assertEquals(true, glWindow.isNativeValid()); - Assert.assertEquals(true, windowClosingListener.isWindowClosing()); - windowClosingListener.reset(); + Assert.assertEquals(true, closingListener.isWindowClosing()); + closingListener.reset(); // // close with op (GLCanvas): DISPOSE_ON_CLOSE -> dispose @@ -84,9 +84,9 @@ public class TestWindowClosingProtocol02NEWT extends UITestCase { op = glWindow.getDefaultCloseOperation(); Assert.assertEquals(WindowClosingMode.DISPOSE_ON_CLOSE, op); - Assert.assertEquals(true, AWTRobotUtil.closeWindow(glWindow, true)); + Assert.assertEquals(true, AWTRobotUtil.closeWindow(glWindow, true, closingListener)); Assert.assertEquals(false, glWindow.isNativeValid()); - Assert.assertEquals(true, windowClosingListener.isWindowClosing()); + Assert.assertEquals(true, closingListener.isWindowClosing()); } public static void main(String[] args) { diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestWindowClosingProtocol03NewtAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestWindowClosingProtocol03NewtAWT.java index be3c48fb6..45b41219a 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/TestWindowClosingProtocol03NewtAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/TestWindowClosingProtocol03NewtAWT.java @@ -46,17 +46,19 @@ import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; import com.jogamp.opengl.test.junit.util.AWTRobotUtil; import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil.WindowClosingListener; public class TestWindowClosingProtocol03NewtAWT extends UITestCase { @Test public void testCloseJFrameNewtCanvasAWT() throws InterruptedException, InvocationTargetException { final JFrame frame = new JFrame("testCloseJFrameNewtCanvasAWT"); - + final WindowClosingListener awtClosingListener = AWTRobotUtil.addClosingListener(frame); + GLProfile glp = GLProfile.getGL2ES2(); GLCapabilities caps = new GLCapabilities(glp); final GLWindow glWindow = GLWindow.create(caps); - final AWTRobotUtil.WindowClosingListener windowClosingListener = AWTRobotUtil.addClosingListener(glWindow); + final AWTRobotUtil.WindowClosingListener newtClosingListener = AWTRobotUtil.addClosingListener(glWindow); glWindow.addGLEventListener(new GearsES2()); @@ -81,46 +83,60 @@ public class TestWindowClosingProtocol03NewtAWT extends UITestCase { // // close with op: DO_NOTHING_ON_CLOSE -> NOP / HIDE (default) // - Assert.assertEquals(JFrame.HIDE_ON_CLOSE, frame.getDefaultCloseOperation()); - WindowClosingMode op = newtCanvas.getDefaultCloseOperation(); - Assert.assertEquals(WindowClosingMode.DO_NOTHING_ON_CLOSE, op); + { + Assert.assertEquals(JFrame.HIDE_ON_CLOSE, frame.getDefaultCloseOperation()); + WindowClosingMode op = newtCanvas.getDefaultCloseOperation(); + Assert.assertEquals(WindowClosingMode.DO_NOTHING_ON_CLOSE, op); + } Thread.sleep(300); - Assert.assertEquals(true, AWTRobotUtil.closeWindow(frame, false)); + Assert.assertEquals(true, AWTRobotUtil.closeWindow(frame, false, awtClosingListener)); // hide + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, false)); // hide -> invisible Assert.assertEquals(true, frame.isDisplayable()); Assert.assertEquals(false, frame.isVisible()); Assert.assertEquals(true, newtCanvas.isValid()); Assert.assertEquals(true, newtCanvas.isDisplayable()); Assert.assertEquals(true, glWindow.isNativeValid()); - Assert.assertEquals(true, windowClosingListener.isWindowClosing()); - windowClosingListener.reset(); + Assert.assertEquals(true, awtClosingListener.isWindowClosing()); + Assert.assertEquals(false, awtClosingListener.isWindowClosed()); + Assert.assertEquals(true, newtClosingListener.isWindowClosing()); + Assert.assertEquals(false, newtClosingListener.isWindowClosed()); + awtClosingListener.reset(); + newtClosingListener.reset(); SwingUtilities.invokeAndWait(new Runnable() { public void run() { frame.setVisible(true); } }); Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow, true)); Assert.assertEquals(true, frame.isDisplayable()); Assert.assertEquals(true, frame.isVisible()); // // 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(WindowClosingMode.DISPOSE_ON_CLOSE, op); + { + frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + Assert.assertEquals(JFrame.DISPOSE_ON_CLOSE, frame.getDefaultCloseOperation()); + WindowClosingMode op = newtCanvas.getDefaultCloseOperation(); + Assert.assertEquals(WindowClosingMode.DISPOSE_ON_CLOSE, op); + } Thread.sleep(300); - Assert.assertEquals(true, AWTRobotUtil.closeWindow(frame, true)); + Assert.assertEquals(true, AWTRobotUtil.closeWindow(frame, true, awtClosingListener)); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow, false)); Assert.assertEquals(false, frame.isDisplayable()); Assert.assertEquals(false, frame.isVisible()); Assert.assertEquals(false, newtCanvas.isValid()); Assert.assertEquals(false, newtCanvas.isDisplayable()); Assert.assertEquals(false, glWindow.isNativeValid()); - Assert.assertEquals(true, windowClosingListener.isWindowClosing()); + Assert.assertEquals(true, awtClosingListener.isWindowClosing()); + Assert.assertEquals(true, awtClosingListener.isWindowClosed()); + Assert.assertEquals(true, newtClosingListener.isWindowClosing()); + Assert.assertEquals(true, newtClosingListener.isWindowClosed()); } public static void main(String[] args) { diff --git a/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyCodesAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyCodesAWT.java index b3ba71795..277924477 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyCodesAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyCodesAWT.java @@ -114,9 +114,9 @@ public class TestNewtKeyCodesAWT extends UITestCase { // Add the canvas to a frame, and make it all visible. final JFrame frame1 = new JFrame("Swing AWT Parent Frame: "+ glWindow.getTitle()); frame1.getContentPane().add(newtCanvasAWT, BorderLayout.CENTER); - frame1.setSize(width, height); javax.swing.SwingUtilities.invokeAndWait(new Runnable() { public void run() { + frame1.setSize(width, height); frame1.setVisible(true); } } ); diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01aAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01aAWT.java index de29db417..21c737d8f 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01aAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01aAWT.java @@ -98,11 +98,11 @@ public class TestParenting01aAWT extends UITestCase { container1.add(newtCanvasAWT, BorderLayout.CENTER); frame1.add(container1, BorderLayout.CENTER); - frame1.setSize(width, height); // visible test SwingUtilities.invokeAndWait(new Runnable() { public void run() { + frame1.setSize(width, height); frame1.setVisible(true); } }); @@ -168,11 +168,11 @@ public class TestParenting01aAWT extends UITestCase { final Frame frame = new Frame("AWT Parent Frame"); Assert.assertNotNull(frame); - frame.setSize(width, height); // visible test SwingUtilities.invokeAndWait(new Runnable() { public void run() { + frame.setSize(width, height); frame.setVisible(true); } }); @@ -212,11 +212,11 @@ public class TestParenting01aAWT extends UITestCase { final Frame frame = new Frame("AWT Parent Frame"); Assert.assertNotNull(frame); - frame.setSize(width, height); // visible test SwingUtilities.invokeAndWait(new Runnable() { public void run() { + frame.setSize(width, height); frame.setVisible(true); } }); @@ -256,10 +256,10 @@ public class TestParenting01aAWT extends UITestCase { final NewtCanvasAWT newtCanvasAWT = new NewtCanvasAWT(glWindow1); final Frame frame = new Frame("AWT Parent Frame"); - frame.setSize(width, height); - frame.setLocation(640, 480); SwingUtilities.invokeAndWait(new Runnable() { public void run() { + frame.setSize(width, height); + frame.setLocation(640, 480); frame.setVisible(true); } }); @@ -320,11 +320,11 @@ public class TestParenting01aAWT extends UITestCase { frame.add(new Button("South"), BorderLayout.SOUTH); frame.add(new Button("East"), BorderLayout.EAST); frame.add(new Button("West"), BorderLayout.WEST); - frame.setSize(width, height); - frame.setLocation(640, 480); SwingUtilities.invokeAndWait(new Runnable() { public void run() { + frame.setSize(width, height); + frame.setLocation(640, 480); frame.setVisible(true); } }); @@ -386,10 +386,10 @@ public class TestParenting01aAWT extends UITestCase { frame1.add(new Button("South"), BorderLayout.SOUTH); frame1.add(new Button("East"), BorderLayout.EAST); frame1.add(new Button("West"), BorderLayout.WEST); - frame1.setSize(width, height); - frame1.setLocation(0, 0); SwingUtilities.invokeAndWait(new Runnable() { public void run() { + frame1.setSize(width, height); + frame1.setLocation(0, 0); frame1.setVisible(true); } }); @@ -400,10 +400,10 @@ public class TestParenting01aAWT extends UITestCase { frame2.add(new Button("South"), BorderLayout.SOUTH); frame2.add(new Button("East"), BorderLayout.EAST); frame2.add(new Button("West"), BorderLayout.WEST); - frame2.setSize(width, height); - frame2.setLocation(640, 480); SwingUtilities.invokeAndWait(new Runnable() { public void run() { + frame2.setSize(width, height); + frame2.setLocation(640, 480); frame2.setVisible(true); } }); diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01bAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01bAWT.java index d98a540ec..906aeee45 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01bAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01bAWT.java @@ -89,10 +89,10 @@ public class TestParenting01bAWT extends UITestCase { frame1.add(new Button("South"), BorderLayout.SOUTH); frame1.add(new Button("East"), BorderLayout.EAST); frame1.add(new Button("West"), BorderLayout.WEST); - frame1.setSize(width, height); - frame1.setLocation(0, 0); SwingUtilities.invokeAndWait(new Runnable() { public void run() { + frame1.setSize(width, height); + frame1.setLocation(0, 0); frame1.setVisible(true); } }); @@ -103,10 +103,10 @@ public class TestParenting01bAWT extends UITestCase { frame2.add(new Button("South"), BorderLayout.SOUTH); frame2.add(new Button("East"), BorderLayout.EAST); frame2.add(new Button("West"), BorderLayout.WEST); - frame2.setSize(width, height); - frame2.setLocation(640, 480); SwingUtilities.invokeAndWait(new Runnable() { public void run() { + frame2.setSize(width, height); + frame2.setLocation(640, 480); frame2.setVisible(true); } }); diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01cAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01cAWT.java index dfd0787e7..aade7f93a 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01cAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01cAWT.java @@ -98,11 +98,11 @@ public class TestParenting01cAWT extends UITestCase { container1.add(newtCanvasAWT, BorderLayout.CENTER); frame1.add(container1, BorderLayout.CENTER); - frame1.setSize(width, height); // visible test SwingUtilities.invokeAndWait(new Runnable() { public void run() { + frame1.setSize(width, height); frame1.setVisible(true); } }); @@ -160,10 +160,10 @@ public class TestParenting01cAWT extends UITestCase { frame1.add(new Button("South"), BorderLayout.SOUTH); frame1.add(new Button("East"), BorderLayout.EAST); frame1.add(new Button("West"), BorderLayout.WEST); - frame1.setSize(width, height); - frame1.setLocation(0, 0); SwingUtilities.invokeAndWait(new Runnable() { public void run() { + frame1.setSize(width, height); + frame1.setLocation(0, 0); frame1.setVisible(true); } }); @@ -174,10 +174,10 @@ public class TestParenting01cAWT extends UITestCase { frame2.add(new Button("South"), BorderLayout.SOUTH); frame2.add(new Button("East"), BorderLayout.EAST); frame2.add(new Button("West"), BorderLayout.WEST); - frame2.setSize(width, height); - frame2.setLocation(640, 480); SwingUtilities.invokeAndWait(new Runnable() { public void run() { + frame2.setSize(width, height); + frame2.setLocation(640, 480); frame2.setVisible(true); } }); diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01cSwingAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01cSwingAWT.java index 4b02be873..c84823a04 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01cSwingAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01cSwingAWT.java @@ -165,10 +165,10 @@ public class TestParenting01cSwingAWT extends UITestCase { // jFrame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); jFrame1.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); // equivalent to Frame, use windowClosing event! jFrame1.setContentPane(jPanel1); - jFrame1.setSize(width, height); System.err.println("Demos: 1 - Visible"); SwingUtilities.invokeAndWait(new Runnable() { public void run() { + jFrame1.setSize(width, height); jFrame1.setVisible(true); } }); @@ -292,10 +292,10 @@ public class TestParenting01cSwingAWT extends UITestCase { // jFrame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); jFrame1.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); // equivalent to Frame, use windowClosing event! jFrame1.setContentPane(jPanel1); - jFrame1.setLocation(0, 0); - jFrame1.setSize(width, height); SwingUtilities.invokeAndWait(new Runnable() { public void run() { + jFrame1.setLocation(0, 0); + jFrame1.setSize(width, height); jFrame1.setVisible(true); } }); @@ -311,10 +311,10 @@ public class TestParenting01cSwingAWT extends UITestCase { // jFrame2.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); jFrame2.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); // equivalent to Frame, use windowClosing event! jFrame2.setContentPane(jPanel2); - jFrame2.setLocation(640, 480); - jFrame2.setSize(width, height); SwingUtilities.invokeAndWait(new Runnable() { public void run() { + jFrame2.setLocation(640, 480); + jFrame2.setSize(width, height); jFrame2.setVisible(true); } }); diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting02AWT.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting02AWT.java index da689cea6..dc1c0ba57 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting02AWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting02AWT.java @@ -118,11 +118,10 @@ public class TestParenting02AWT extends UITestCase { } } - // frame.setSize(width, height); - frame.setBounds(100, 100, width, height); - javax.swing.SwingUtilities.invokeAndWait(new Runnable() { public void run() { + // frame.setSize(width, height); + frame.setBounds(100, 100, width, height); frame.setVisible(true); }}); // X11: true, Windows: false - Assert.assertEquals(true, glWindow.isVisible()); diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting03AWT.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting03AWT.java index b33a40fae..4f880347a 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting03AWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting03AWT.java @@ -133,11 +133,11 @@ public class TestParenting03AWT extends UITestCase { frame1.add(new Button("CENTER"), BorderLayout.CENTER); frame1.add(new Button("SOUTH"), BorderLayout.SOUTH); frame1.add(cont1, BorderLayout.EAST); - frame1.setLocation(0, 0); - frame1.setSize(fSize); javax.swing.SwingUtilities.invokeAndWait(new Runnable() { public void run() { System.err.println("******* Frame setVisible"); + frame1.setLocation(0, 0); + frame1.setSize(fSize); frame1.validate(); frame1.setVisible(true); }}); diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting04AWT.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting04AWT.java index 09b6d048c..b0e58b5ec 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting04AWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting04AWT.java @@ -100,10 +100,10 @@ public class TestParenting04AWT extends UITestCase { frame1.add(new Button("South"), BorderLayout.SOUTH); frame1.add(new Button("East"), BorderLayout.EAST); frame1.add(new Button("West"), BorderLayout.WEST); - frame1.setSize(width, height); - frame1.setLocation(0, 0); SwingUtilities.invokeAndWait(new Runnable() { public void run() { + frame1.setSize(width, height); + frame1.setLocation(0, 0); frame1.setVisible(true); frame1.validate(); } @@ -123,10 +123,10 @@ public class TestParenting04AWT extends UITestCase { frame2.add(new Button("South"), BorderLayout.SOUTH); frame2.add(new Button("East"), BorderLayout.EAST); frame2.add(new Button("West"), BorderLayout.WEST); - frame2.setSize(width, height); - frame2.setLocation(width+50, 0); SwingUtilities.invokeAndWait(new Runnable() { public void run() { + frame2.setSize(width, height); + frame2.setLocation(width+50, 0); frame2.setVisible(true); frame2.validate(); } diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParentingFocusTraversal01AWT.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParentingFocusTraversal01AWT.java index 122138f6d..a1f07bda6 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParentingFocusTraversal01AWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParentingFocusTraversal01AWT.java @@ -183,10 +183,10 @@ public class TestParentingFocusTraversal01AWT extends UITestCase { frame1.add(newtCanvasAWT1, BorderLayout.CENTER); frame1.add(cEast, BorderLayout.EAST); - frame1.setLocation(0, 0); - frame1.setSize(fSize); javax.swing.SwingUtilities.invokeAndWait(new Runnable() { public void run() { + frame1.setLocation(0, 0); + frame1.setSize(fSize); frame1.validate(); frame1.setVisible(true); }}); diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestTranslucentParentingAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestTranslucentParentingAWT.java index 280cc7495..2d668c224 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestTranslucentParentingAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestTranslucentParentingAWT.java @@ -137,10 +137,10 @@ public class TestTranslucentParentingAWT extends UITestCase { frame1.setLayout(new BorderLayout()); frame1.add(cont1, BorderLayout.EAST); frame1.add(new Label("center"), BorderLayout.CENTER); - frame1.setLocation(0, 0); - frame1.setSize((int)size.getWidth(), (int)size.getHeight()); javax.swing.SwingUtilities.invokeAndWait(new Runnable() { public void run() { + frame1.setLocation(0, 0); + frame1.setSize((int)size.getWidth(), (int)size.getHeight()); frame1.pack(); frame1.setVisible(true); }}); @@ -157,7 +157,10 @@ public class TestTranslucentParentingAWT extends UITestCase { Assert.assertEquals(false, animator1.isPaused()); Assert.assertEquals(null, animator1.getThread()); - frame1.dispose(); + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame1.dispose(); + } } ); glWindow1.destroy(); } 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 ffc42e318..960145e78 100644 --- a/src/test/com/jogamp/opengl/test/junit/util/AWTRobotUtil.java +++ b/src/test/com/jogamp/opengl/test/junit/util/AWTRobotUtil.java @@ -41,6 +41,9 @@ import javax.media.opengl.awt.GLCanvas; import org.junit.Assert; +import com.jogamp.common.util.awt.AWTEDTExecutor; +import com.jogamp.newt.event.WindowEvent; + public class AWTRobotUtil { static final boolean DEBUG = false; @@ -646,16 +649,19 @@ public class AWTRobotUtil { * * @param obj either an AWT Window (Frame, JFrame) or NEWT Window * @param willClose indicating that the window will close, hence this method waits for the window to be closed + * @param wcl the WindowClosingListener to determine whether the AWT or NEWT widget has been closed. It should be attached + * to the widget ASAP before any other listener, e.g. via {@link #addClosingListener(Object)}. + * The WindowClosingListener will be reset before attempting to close the widget. * @return True if the Window is closing and closed (if willClose is true), each within TIME_OUT * @throws InterruptedException */ - public static boolean closeWindow(Object obj, boolean willClose) throws InterruptedException, InvocationTargetException { - WindowClosingListener closingListener = addClosingListener(obj); + public static boolean closeWindow(Object obj, boolean willClose, WindowClosingListener closingListener) throws InterruptedException { + closingListener.reset(); if(obj instanceof java.awt.Window) { final java.awt.Window win = (java.awt.Window) obj; java.awt.Toolkit tk = java.awt.Toolkit.getDefaultToolkit(); final java.awt.EventQueue evtQ = tk.getSystemEventQueue(); - java.awt.EventQueue.invokeAndWait(new Runnable() { + AWTEDTExecutor.singleton.invoke(true, new Runnable() { public void run() { evtQ.postEvent(new java.awt.event.WindowEvent(win, java.awt.event.WindowEvent.WINDOW_CLOSING)); } }); @@ -675,12 +681,15 @@ public class AWTRobotUtil { return wait<POLL_DIVIDER; } - public static WindowClosingListener addClosingListener(Object obj) throws InterruptedException { + public static WindowClosingListener addClosingListener(Object obj) { WindowClosingListener cl = null; if(obj instanceof java.awt.Window) { - java.awt.Window win = (java.awt.Window) obj; - AWTWindowClosingAdapter acl = new AWTWindowClosingAdapter(); - win.addWindowListener(acl); + final java.awt.Window win = (java.awt.Window) obj; + final AWTWindowClosingAdapter acl = new AWTWindowClosingAdapter(); + AWTEDTExecutor.singleton.invoke(true, new Runnable() { + public void run() { + win.addWindowListener(acl); + } } ); cl = acl; } else if(obj instanceof com.jogamp.newt.Window) { com.jogamp.newt.Window win = (com.jogamp.newt.Window) obj; @@ -694,53 +703,77 @@ public class AWTRobotUtil { } public static interface WindowClosingListener { void reset(); + public int getWindowClosingCount(); + public int getWindowClosedCount(); public boolean isWindowClosing(); public boolean isWindowClosed(); } static class AWTWindowClosingAdapter extends java.awt.event.WindowAdapter implements WindowClosingListener { - volatile boolean closing = false; - volatile boolean closed = false; + volatile int closing = 0; + volatile int closed = 0; public void reset() { - closing = false; - closed = false; + closing = 0; + closed = 0; } - public boolean isWindowClosing() { + public int getWindowClosingCount() { return closing; } - public boolean isWindowClosed() { + public int getWindowClosedCount() { return closed; } + public boolean isWindowClosing() { + return 0 < closing; + } + public boolean isWindowClosed() { + return 0 < closed; + } public void windowClosing(java.awt.event.WindowEvent e) { - closing = true; + closing++; + System.err.println("AWTWindowClosingAdapter.windowClosing: "+this); } public void windowClosed(java.awt.event.WindowEvent e) { - closed = true; + closed++; + System.err.println("AWTWindowClosingAdapter.windowClosed: "+this); + } + public String toString() { + return "AWTWindowClosingAdapter[closing "+closing+", closed "+closed+"]"; } } static class NEWTWindowClosingAdapter extends com.jogamp.newt.event.WindowAdapter implements WindowClosingListener { - volatile boolean closing = false; - volatile boolean closed = false; + volatile int closing = 0; + volatile int closed = 0; public void reset() { - closing = false; - closed = false; + closing = 0; + closed = 0; } - public boolean isWindowClosing() { + public int getWindowClosingCount() { return closing; } - public boolean isWindowClosed() { + public int getWindowClosedCount() { return closed; } - public void windowDestroyNotify(com.jogamp.newt.event.WindowEvent e) { - closing = true; + public boolean isWindowClosing() { + return 0 < closing; + } + public boolean isWindowClosed() { + return 0 < closed; + } + public void windowDestroyNotify(WindowEvent e) { + closing++; + System.err.println("NEWTWindowClosingAdapter.windowDestroyNotify: "+this); + } + public void windowDestroyed(WindowEvent e) { + closed++; + System.err.println("NEWTWindowClosingAdapter.windowDestroyed: "+this); } - public void windowDestroyed(com.jogamp.newt.event.WindowEvent e) { - closed = true; + public String toString() { + return "NEWTWindowClosingAdapter[closing "+closing+", closed "+closed+"]"; } } |