diff options
author | Sven Gothel <[email protected]> | 2010-12-19 14:54:08 +0100 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2010-12-19 14:54:08 +0100 |
commit | 2cbab63bd6c230d31b8ae6f1d794ad49bf23bb53 (patch) | |
tree | 9da105f466b81424ae089e59e4bd67fce7c32d54 /src/newt/classes/com | |
parent | 2323c30c23b6f9eb7d7ccf94e6cdcbcb3d2f34a6 (diff) |
JOGL/NEWT: Introduce WindowClosingProtocol (solves Bug/Request 444)
Similar to JFrame's closing behavior,
the following components window closing follow the new WindowClosingProtocol:
- GLCanvas
- GLJPanel
- NEWT Window, GLWindow
- NEWT NewtCanvasAWT
The implementation obeys either
1) the user value set by this interface,
2) an underlying toolkit set user value (JFrame, ..)
3) or it's default, eg. {@link #DO_NOTHING_ON_CLOSE DO_NOTHING_ON_CLOSE} within an AWT environment.
If none of the above determines the operation,
this protocol default behavior {@link #DISPOSE_ON_CLOSE DISPOSE_ON_CLOSE} shall be used.
Diffstat (limited to 'src/newt/classes/com')
4 files changed, 110 insertions, 40 deletions
diff --git a/src/newt/classes/com/jogamp/newt/Window.java b/src/newt/classes/com/jogamp/newt/Window.java index 99db47168..9fe5089be 100644 --- a/src/newt/classes/com/jogamp/newt/Window.java +++ b/src/newt/classes/com/jogamp/newt/Window.java @@ -36,13 +36,14 @@ import javax.media.nativewindow.CapabilitiesChooser; import javax.media.nativewindow.CapabilitiesImmutable; import javax.media.nativewindow.NativeWindow; import javax.media.nativewindow.SurfaceUpdatedListener; +import javax.media.nativewindow.WindowClosingProtocol; import javax.media.nativewindow.util.Insets; /** * Specifying the public Window functionality for the * using a Window and for shadowing one like {@link com.jogamp.newt.opengl.GLWindow}. */ -public interface Window extends NativeWindow { +public interface Window extends NativeWindow, WindowClosingProtocol { public static final boolean DEBUG_MOUSE_EVENT = Debug.debug("Window.MouseEvent"); public static final boolean DEBUG_KEY_EVENT = Debug.debug("Window.KeyEvent"); public static final boolean DEBUG_WINDOW_EVENT = Debug.debug("Window.WindowEvent"); diff --git a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java index bee81624a..18213f94f 100644 --- a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java +++ b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java @@ -38,21 +38,36 @@ import java.awt.EventQueue; import java.awt.Graphics; import java.awt.KeyboardFocusManager; -import javax.media.nativewindow.*; +import javax.media.nativewindow.NativeWindow; +import javax.media.nativewindow.NativeWindowException; +import javax.media.nativewindow.WindowClosingProtocol; +import javax.media.nativewindow.awt.AWTWindowClosingProtocol; +import com.jogamp.nativewindow.impl.awt.AWTMisc; import com.jogamp.newt.event.awt.AWTAdapter; import com.jogamp.newt.event.awt.AWTParentWindowAdapter; import com.jogamp.newt.event.WindowEvent; import com.jogamp.newt.Window; +import com.jogamp.newt.event.WindowAdapter; +import com.jogamp.newt.event.WindowListener; import com.jogamp.newt.impl.Debug; +import javax.swing.MenuSelectionManager; -public class NewtCanvasAWT extends java.awt.Canvas { +public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProtocol { public static final boolean DEBUG = Debug.debug("Window"); NativeWindow nativeWindow = null; Window newtChild = null; + int newtChildCloseOp; AWTAdapter awtAdapter = null; + private AWTWindowClosingProtocol awtWindowClosingProtocol = + new AWTWindowClosingProtocol(this, new Runnable() { + public void run() { + NewtCanvasAWT.this.destroy(); + } + }); + /** * Instantiates a NewtCanvas without a NEWT child.<br> */ @@ -97,12 +112,18 @@ public class NewtCanvasAWT extends java.awt.Canvas { } FocusAction focusAction = new FocusAction(); + WindowListener clearAWTMenusOnNewtFocus = new WindowAdapter() { + public void windowGainedFocus(WindowEvent arg0) { + MenuSelectionManager.defaultManager().clearSelectedPath(); + } + }; + /** sets a new NEWT child, provoking reparenting on the NEWT level. */ public NewtCanvasAWT setNEWTChild(Window child) { if(newtChild!=child) { newtChild = child; if(null!=nativeWindow) { - java.awt.Container cont = getContainer(this); + java.awt.Container cont = AWTMisc.getContainer(this); // reparent right away, addNotify has been called already reparentWindow( (null!=newtChild) ? true : false, cont ); } @@ -119,24 +140,37 @@ public class NewtCanvasAWT extends java.awt.Canvas { * or {@link #addNotify()} hasn't been called yet.*/ public NativeWindow getNativeWindow() { return nativeWindow; } - void setWindowAdapter(boolean attach) { + public int getDefaultCloseOperation() { + return awtWindowClosingProtocol.getDefaultCloseOperation(); + } + + public int setDefaultCloseOperation(int op) { + return awtWindowClosingProtocol.setDefaultCloseOperation(op); + } + + void configureNewtChild(boolean attach) { if(null!=awtAdapter) { awtAdapter.removeFrom(this); awtAdapter=null; } - if(attach && null!=newtChild) { - awtAdapter = new AWTParentWindowAdapter(newtChild).addTo(this); - } - } - - static java.awt.Container getContainer(java.awt.Component comp) { - while( null != comp ) { - if( comp instanceof java.awt.Container ) { - return (java.awt.Container) comp; + if( null != newtChild ) { + if(attach) { + awtAdapter = new AWTParentWindowAdapter(newtChild).addTo(this); + if(newtChild.isValid()) { + newtChild.addWindowListener(clearAWTMenusOnNewtFocus); + } + newtChild.setFocusAction(focusAction); // enable AWT focus traversal + newtChildCloseOp = newtChild.setDefaultCloseOperation(WindowClosingProtocol.DO_NOTHING_ON_CLOSE); + awtWindowClosingProtocol.addClosingListenerOneShot(); + } else { + if(newtChild.isValid()) { + newtChild.removeWindowListener(clearAWTMenusOnNewtFocus); + } + newtChild.setFocusAction(null); + newtChild.setDefaultCloseOperation(newtChildCloseOp); + awtWindowClosingProtocol.removeClosingListener(); } - comp = comp.getParent(); } - return null; } public void addNotify() { @@ -150,7 +184,7 @@ public class NewtCanvasAWT extends java.awt.Canvas { // after native peer is valid: Windows disableBackgroundErase(); - java.awt.Container cont = getContainer(this); + java.awt.Container cont = AWTMisc.getContainer(this); if(DEBUG) { // if ( isShowing() == false ) -> Container was not visible yet. // if ( isShowing() == true ) -> Container is already visible. @@ -161,7 +195,7 @@ public class NewtCanvasAWT extends java.awt.Canvas { } public void removeNotify() { - java.awt.Container cont = getContainer(this); + java.awt.Container cont = AWTMisc.getContainer(this); if(DEBUG) { System.err.println("NewtCanvasAWT.removeNotify: "+newtChild+", from "+cont); } @@ -187,13 +221,12 @@ public class NewtCanvasAWT extends java.awt.Canvas { newtChild.setSize(w, h); newtChild.reparentWindow(nativeWindow); newtChild.setVisible(true); - setWindowAdapter(true); + configureNewtChild(true); newtChild.sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout to listener newtChild.windowRepaint(0, 0, w, h); - newtChild.setFocusAction(focusAction); // enable AWT focus traversal } } else { - setWindowAdapter(false); + configureNewtChild(false); nativeWindow = null; newtChild.setVisible(false); newtChild.reparentWindow(null); @@ -213,10 +246,11 @@ public class NewtCanvasAWT extends java.awt.Canvas { */ public final void destroy() { if(null!=newtChild) { - java.awt.Container cont = getContainer(this); + java.awt.Container cont = AWTMisc.getContainer(this); if(DEBUG) { System.err.println("NewtCanvasAWT.destroy(): "+newtChild+", from "+cont); } + configureNewtChild(false); nativeWindow = null; newtChild.setVisible(false); newtChild.reparentWindow(null); @@ -229,11 +263,13 @@ public class NewtCanvasAWT extends java.awt.Canvas { } public void paint(Graphics g) { + awtWindowClosingProtocol.addClosingListenerOneShot(); if(null!=newtChild) { newtChild.windowRepaint(0, 0, getWidth(), getHeight()); } } public void update(Graphics g) { + awtWindowClosingProtocol.addClosingListenerOneShot(); if(null!=newtChild) { newtChild.windowRepaint(0, 0, getWidth(), getHeight()); } diff --git a/src/newt/classes/com/jogamp/newt/impl/WindowImpl.java b/src/newt/classes/com/jogamp/newt/impl/WindowImpl.java index ad11d8ab9..e04bd1208 100644 --- a/src/newt/classes/com/jogamp/newt/impl/WindowImpl.java +++ b/src/newt/classes/com/jogamp/newt/impl/WindowImpl.java @@ -372,6 +372,26 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer protected void unlockSurfaceImpl() { } //---------------------------------------------------------------------- + // WindowClosingProtocol implementation + // + private Object closingListenerLock = new Object(); + private int defaultCloseOperation = DISPOSE_ON_CLOSE; + + public int getDefaultCloseOperation() { + synchronized (closingListenerLock) { + return defaultCloseOperation; + } + } + + public int setDefaultCloseOperation(int op) { + synchronized (closingListenerLock) { + int _op = defaultCloseOperation; + defaultCloseOperation = op; + return _op; + } + } + + //---------------------------------------------------------------------- // Window: Native implementation // @@ -2101,7 +2121,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer enqueueWindowEvent(false, WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY); - if(handleDestroyNotify && isValid()) { + if(handleDestroyNotify && DISPOSE_ON_CLOSE == defaultCloseOperation && isValid()) { destroy(); } diff --git a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java index 358a3d4ce..4a1855d05 100644 --- a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java +++ b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java @@ -85,24 +85,26 @@ public class GLWindow implements GLAutoDrawable, Window, NEWTEventConsumer { } public void windowDestroyNotify(WindowEvent e) { - // Is an animator thread perform rendering? - if (GLWindow.this.helper.isExternalAnimatorRunning()) { - // Pause animations before initiating safe destroy. - GLAnimatorControl ctrl = GLWindow.this.helper.getAnimator(); - boolean isPaused = ctrl.pause(); - destroy(); - if(isPaused) { - ctrl.resume(); + if( DISPOSE_ON_CLOSE == GLWindow.this.getDefaultCloseOperation() ) { + // Is an animator thread perform rendering? + if (GLWindow.this.helper.isExternalAnimatorRunning()) { + // Pause animations before initiating safe destroy. + GLAnimatorControl ctrl = GLWindow.this.helper.getAnimator(); + boolean isPaused = ctrl.pause(); + destroy(); + if(isPaused) { + ctrl.resume(); + } + } else if (GLWindow.this.window.isSurfaceLockedByOtherThread()) { + // Surface is locked by another thread + // Flag that destroy should be performed on the next + // attempt to display. + sendDestroy = true; + } else { + // Without an external thread animating or locking the + // surface, we are safe. + destroy (); } - } else if (GLWindow.this.window.isSurfaceLockedByOtherThread()) { - // Surface is locked by another thread - // Flag that destroy should be performed on the next - // attempt to display. - sendDestroy = true; - } else { - // Without an external thread animating or locking the - // surface, we are safe. - destroy (); } } }); @@ -152,6 +154,17 @@ public class GLWindow implements GLAutoDrawable, Window, NEWTEventConsumer { } //---------------------------------------------------------------------- + // WindowClosingProtocol implementation + // + public int getDefaultCloseOperation() { + return window.getDefaultCloseOperation(); + } + + public int setDefaultCloseOperation(int op) { + return window.setDefaultCloseOperation(op); + } + + //---------------------------------------------------------------------- // Window Access // |