diff options
author | Sven Gothel <[email protected]> | 2013-11-23 17:01:09 +0100 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2013-11-23 17:01:09 +0100 |
commit | 0c3709ba4ba2dd4ba7bb2e7f0783fba346e090e1 (patch) | |
tree | b44e3850f157c6cd56d42aca0f601ab9f4f72e02 | |
parent | fa1d211c9658ce209f411e559333da0e2fccd402 (diff) |
Workaround Bug 910 (IcedTea-Web): NewtCanvasAWT shall postpone JAWTWindow destruction if removeNotify() is called from non AWT-EDT
-rw-r--r-- | src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java | 117 |
1 files changed, 88 insertions, 29 deletions
diff --git a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java index 749002b0f..9c66daf1c 100644 --- a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java +++ b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java @@ -29,6 +29,7 @@ package com.jogamp.newt.awt; +import java.applet.Applet; import java.awt.AWTKeyStroke; import java.awt.Canvas; import java.awt.Component; @@ -97,6 +98,7 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto private final Object sync = new Object(); private JAWTWindow jawtWindow = null; + private boolean isApplet = false; private boolean shallUseOffscreenLayer = false; private Window newtChild = null; private boolean newtChildAttached = false; @@ -106,16 +108,26 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto private final AWTAdapter awtMouseAdapter; private final AWTAdapter awtKeyAdapter; + /** Mitigates Bug 910 (IcedTea-Web), i.e. crash via removeNotify() from 'other' AWT-EDT. */ + private boolean addedOnAWTEDT = false; + /** Mitigates Bug 910 (IcedTea-Web), i.e. crash via removeNotify() from 'other' AWT-EDT. */ + private boolean destroyJAWTPending = false; + + /** Safeguard for AWTWindowClosingProtocol and 'removeNotify()' on other thread than AWT-EDT. */ + private volatile boolean componentAdded = false; + private final AWTWindowClosingProtocol awtWindowClosingProtocol = new AWTWindowClosingProtocol(this, new Runnable() { @Override public void run() { - NewtCanvasAWT.this.destroyImpl(false /* removeNotify */, true /* windowClosing */); + if( componentAdded ) { + NewtCanvasAWT.this.destroyImpl(false /* removeNotify */, true /* windowClosing */); + } } }, new Runnable() { @Override public void run() { - if( newtChild != null ) { + if( componentAdded && newtChild != null ) { newtChild.sendWindowEvent(WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY); } } @@ -185,20 +197,20 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto /** * Returns true if the AWT component is parented to an {@link java.applet.Applet}, - * otherwise false. This information is valid only after {@link #addNotify()} is issued, - * ie. before adding the component to the AWT tree and make it visible. + * otherwise false. This information is valid only after {@link #addNotify()} is issued. */ - public boolean isApplet() { - final JAWTWindow w = jawtWindow; - return null != w && w.isApplet(); + public final boolean isApplet() { + return isApplet; } - boolean isParent() { - return null!=newtChild && jawtWindow == newtChild.getParent(); + private final boolean isParent() { + final Window nw = newtChild; + return null!=nw && jawtWindow == nw.getParent(); } - boolean isFullscreen() { - return null != newtChild && newtChild.isFullscreen(); + private final boolean isFullscreen() { + final Window nw = newtChild; + return null != nw && nw.isFullscreen(); } class FocusAction implements Window.FocusRunnable { @@ -413,6 +425,15 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto return awtWindowClosingProtocol.setDefaultCloseOperation(op); } + private final void determineIfApplet() { + isApplet = false; + Component c = this; + while(!isApplet && null != c) { + isApplet = c instanceof Applet; + c = c.getParent(); + } + } + @Override public void addNotify() { if( Beans.isDesignTime() ) { @@ -428,30 +449,43 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto disableBackgroundErase(); synchronized(sync) { - jawtWindow = NewtFactoryAWT.getNativeWindow(this, null != newtChild ? newtChild.getRequestedCapabilities() : null); + determineIfApplet(); + addedOnAWTEDT = EventQueue.isDispatchThread(); + if(DEBUG) { + System.err.println("NewtCanvasAWT.addNotify.0 - isApplet "+isApplet+", addedOnAWTEDT "+addedOnAWTEDT+" @ "+currentThreadName()); + Thread.dumpStack(); + } + jawtWindow = NewtFactoryAWT.getNativeWindow(NewtCanvasAWT.this, null != newtChild ? newtChild.getRequestedCapabilities() : null); jawtWindow.setShallUseOffscreenLayer(shallUseOffscreenLayer); - + awtWindowClosingProtocol.addClosingListener(); + componentAdded = true; // Bug 910 if(DEBUG) { // if ( isShowing() == false ) -> Container was not visible yet. // if ( isShowing() == true ) -> Container is already visible. - System.err.println("NewtCanvasAWT.addNotify: win "+newtWinHandleToHexString(newtChild)+ + System.err.println("NewtCanvasAWT.addNotify.X: twin "+newtWinHandleToHexString(newtChild)+ ", comp "+this+", visible "+isVisible()+", showing "+isShowing()+ ", displayable "+isDisplayable()+", cont "+AWTMisc.getContainer(this)); } } } - awtWindowClosingProtocol.addClosingListener(); } @Override public void removeNotify() { - awtWindowClosingProtocol.removeClosingListener(); - if( Beans.isDesignTime() ) { super.removeNotify(); } else { + if(DEBUG) { + System.err.println("NewtCanvasAWT.removeNotify.0 - isApplet "+isApplet+" @ "+currentThreadName()); + Thread.dumpStack(); + } + componentAdded = false; // Bug 910 + awtWindowClosingProtocol.removeClosingListener(); destroyImpl(true /* removeNotify */, false /* windowClosing */); super.removeNotify(); + if(DEBUG) { + System.err.println("NewtCanvasAWT.removeNotify.X @ "+currentThreadName()); + } } } @@ -466,6 +500,10 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto * @see Window#destroy() */ public final void destroy() { + if(DEBUG) { + System.err.println("NewtCanvasAWT.destroy() @ "+currentThreadName()); + Thread.dumpStack(); + } AWTEDTExecutor.singleton.invoke(true, new Runnable() { @Override public void run() { @@ -475,11 +513,24 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto private final void destroyImpl(boolean removeNotify, boolean windowClosing) { synchronized(sync) { + final java.awt.Container cont = AWTMisc.getContainer(this); + /** + * Mitigates Bug 910 (IcedTea-Web), i.e. crash via removeNotify() from 'other' AWT-EDT. + * + * 'destroyJAWT' defaults to 'true' - however, IcedTea-Web (Applet) issues removeNotify() from + * a different AWT-EDT thread, which is not recognized as an AWT-EDT thread! + * This 'different AWT-EDT thread' maybe caused due to a AppContext issue in IcedTea-Web. + */ + final boolean isOnAWTEDT = EventQueue.isDispatchThread(); + final boolean destroyJAWTOK = !isApplet || !addedOnAWTEDT || isOnAWTEDT; + if(DEBUG) { + System.err.println("NewtCanvasAWT.destroyImpl @ "+currentThreadName()); + System.err.println("NewtCanvasAWT.destroyImpl.0 - isApplet "+isApplet+", addedOnAWTEDT "+addedOnAWTEDT+", isOnAWTEDT "+isOnAWTEDT+" -> destroyJAWTOK "+destroyJAWTOK+ + "; removeNotify "+removeNotify+", windowClosing "+windowClosing+", destroyJAWTPending "+destroyJAWTPending+ + ", hasJAWT "+(null!=jawtWindow)+", hasNEWT "+(null!=newtChild)+ + "): nw "+newtWinHandleToHexString(newtChild)+", from "+cont); + } if( null !=newtChild ) { - java.awt.Container cont = AWTMisc.getContainer(this); - if(DEBUG) { - System.err.println("NewtCanvasAWT.destroy(removeNotify "+removeNotify+", windowClosing "+windowClosing+"): nw "+newtWinHandleToHexString(newtChild)+", from "+cont); - } detachNewtChild(cont); if( !removeNotify ) { @@ -493,9 +544,16 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto } } } - if( ( removeNotify || windowClosing ) && null!=jawtWindow ) { - NewtFactoryAWT.destroyNativeWindow(jawtWindow); - jawtWindow=null; + if( ( destroyJAWTPending || removeNotify || windowClosing ) && null!=jawtWindow ) { + if( destroyJAWTOK ) { + NewtFactoryAWT.destroyNativeWindow(jawtWindow); + jawtWindow=null; + destroyJAWTPending = false; + } else { + // Bug 910 - See above FIXME + destroyJAWTPending = true; + System.err.println("Info: JAWT destruction pending due to: isApplet "+isApplet+", addedOnAWTEDT "+addedOnAWTEDT+", isOnAWTEDT "+isOnAWTEDT+" -> destroyJAWTOK "+destroyJAWTOK); + } } } } @@ -555,14 +613,14 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto synchronized(sync) { if( !validateComponent(true) ) { if(DEBUG) { - System.err.println(getThreadName()+": Info: NewtCanvasAWT setupPrint - skipped GL render, drawable not valid yet"); + System.err.println(currentThreadName()+": Info: NewtCanvasAWT setupPrint - skipped GL render, drawable not valid yet"); } printActive = false; return; // not yet available .. } if( !isVisible() ) { if(DEBUG) { - System.err.println(getThreadName()+": Info: NewtCanvasAWT setupPrint - skipped GL render, drawable visible"); + System.err.println(currentThreadName()+": Info: NewtCanvasAWT setupPrint - skipped GL render, drawable visible"); } printActive = false; return; // not yet available .. @@ -665,7 +723,7 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto throw new IllegalStateException("setupPrint() not called"); } if(DEBUG && !EventQueue.isDispatchThread()) { - System.err.println(getThreadName()+": Warning: GLCanvas print - not called from AWT-EDT"); + System.err.println(currentThreadName()+": Warning: GLCanvas print - not called from AWT-EDT"); // we cannot dispatch print on AWT-EDT due to printing internal locking .. } @@ -787,7 +845,8 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto if(DEBUG) { // if ( isShowing() == false ) -> Container was not visible yet. // if ( isShowing() == true ) -> Container is already visible. - System.err.println("NewtCanvasAWT.attachNewtChild.0 @ "+Thread.currentThread().getName()+": win "+newtWinHandleToHexString(newtChild)+ + System.err.println("NewtCanvasAWT.attachNewtChild.0 @ "+currentThreadName()); + System.err.println("\twin "+newtWinHandleToHexString(newtChild)+ ", EDTUtil: cur "+newtChild.getScreen().getDisplay().getEDTUtil()+ ", comp "+this+", visible "+isVisible()+", showing "+isShowing()+", displayable "+isDisplayable()+ ", cont "+AWTMisc.getContainer(this)); @@ -913,7 +972,7 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto } } - protected static String getThreadName() { return Thread.currentThread().getName(); } + protected static String currentThreadName() { return "["+Thread.currentThread().getName()+", isAWT-EDT "+EventQueue.isDispatchThread()+"]"; } static String newtWinHandleToHexString(Window w) { return null != w ? toHexString(w.getWindowHandle()) : "nil"; |