diff options
Diffstat (limited to 'src/newt')
-rw-r--r-- | src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java | 137 | ||||
-rw-r--r-- | src/newt/classes/jogamp/newt/awt/NewtFactoryAWT.java | 50 |
2 files changed, 175 insertions, 12 deletions
diff --git a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java index 5920d6de8..0a27f7f22 100644 --- a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java +++ b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java @@ -37,6 +37,7 @@ import java.awt.EventQueue; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.GraphicsConfiguration; +import java.awt.GraphicsDevice; import java.awt.KeyboardFocusManager; import java.awt.geom.NoninvertibleTransformException; import java.beans.Beans; @@ -47,6 +48,7 @@ import java.security.AccessController; import java.security.PrivilegedAction; import java.util.Set; +import com.jogamp.nativewindow.CapabilitiesImmutable; import com.jogamp.nativewindow.NativeWindow; import com.jogamp.nativewindow.OffscreenLayerOption; import com.jogamp.nativewindow.WindowClosingProtocol; @@ -71,6 +73,7 @@ import jogamp.opengl.awt.AWTTilePainter; import com.jogamp.common.ExceptionUtils; import com.jogamp.common.util.awt.AWTEDTExecutor; +import com.jogamp.nativewindow.awt.AWTGraphicsConfiguration; import com.jogamp.nativewindow.awt.AWTPrintLifecycle; import com.jogamp.nativewindow.awt.AWTWindowClosingProtocol; import com.jogamp.nativewindow.awt.JAWTWindow; @@ -101,7 +104,7 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto public static final boolean DEBUG = Debug.debug("Window"); private final Object sync = new Object(); - private JAWTWindow jawtWindow = null; + private volatile JAWTWindow jawtWindow = null; // the JAWTWindow presentation of this AWT Canvas, bound to the 'drawable' lifecycle private boolean isApplet = false; private boolean shallUseOffscreenLayer = false; private Window newtChild = null; @@ -112,6 +115,8 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto private final AWTAdapter awtMouseAdapter; private final AWTAdapter awtKeyAdapter; + private volatile AWTGraphicsConfiguration awtConfig; + /** Mitigates Bug 910 (IcedTea-Web), i.e. crash via removeNotify() invoked before Applet.destroy(). */ private boolean destroyJAWTPending = false; /** Mitigates Bug 910 (IcedTea-Web), i.e. crash via removeNotify() invoked before Applet.destroy(). */ @@ -452,14 +457,142 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto } } + private void setAWTGraphicsConfiguration(final AWTGraphicsConfiguration config) { + // Cache awtConfig + awtConfig = config; + if( null != jawtWindow ) { + // Notify JAWTWindow .. + jawtWindow.setAWTGraphicsConfiguration(config); + } + } + + /** + * {@inheritDoc} + * <p> + * Overridden to choose a {@link GraphicsConfiguration} from a parent container's + * {@link GraphicsDevice}. + * </p> + * <p> + * Method also intercepts {@link GraphicsConfiguration} changes regarding to + * its capabilities and its {@link GraphicsDevice}. This may happen in case + * the display changes its configuration or the component is moved to another screen. + * </p> + */ + @Override + public GraphicsConfiguration getGraphicsConfiguration() { + /** + * parentGC will be null unless: + * - A native peer has assigned it. This means we have a native + * peer, and are already committed to a graphics configuration. + * - This canvas has been added to a component hierarchy and has + * an ancestor with a non-null GC, but the native peer has not + * yet been created. This means we can still choose the GC on + * all platforms since the peer hasn't been created. + */ + final GraphicsConfiguration parentGC = super.getGraphicsConfiguration(); + + if( Beans.isDesignTime() ) { + return parentGC; + } + final GraphicsConfiguration oldGC = null != awtConfig ? awtConfig.getAWTGraphicsConfiguration() : null; + + if ( null != parentGC && null != oldGC && !oldGC.equals(parentGC) ) { + // Previous oldGC != parentGC of native peer + + if ( !oldGC.getDevice().getIDstring().equals(parentGC.getDevice().getIDstring()) ) { + // Previous oldGC's GraphicsDevice != parentGC's GraphicsDevice of native peer + + /** + * Here we select a GraphicsConfiguration on the alternate device. + * In case the new configuration differs (-> !equalCaps), + * we might need a reconfiguration, + */ + final AWTGraphicsConfiguration newConfig = AWTGraphicsConfiguration.create(parentGC, + awtConfig.getChosenCapabilities(), + awtConfig.getRequestedCapabilities()); + final GraphicsConfiguration newGC = newConfig.getAWTGraphicsConfiguration(); + final boolean equalCaps = newConfig.getChosenCapabilities().equals(awtConfig.getChosenCapabilities()); + if(DEBUG) { + System.err.println(getThreadName()+": getGraphicsConfiguration() Info: Changed GC and GD"); + System.err.println("Created Config (n): Old GC "+oldGC); + System.err.println("Created Config (n): Old GD "+oldGC.getDevice().getIDstring()); + System.err.println("Created Config (n): Parent GC "+parentGC); + System.err.println("Created Config (n): Parent GD "+parentGC.getDevice().getIDstring()); + System.err.println("Created Config (n): New GC "+newGC); + System.err.println("Created Config (n): Old CF "+awtConfig); + System.err.println("Created Config (n): New CF "+newConfig); + System.err.println("Created Config (n): EQUALS CAPS "+equalCaps); + // Thread.dumpStack(); + } + if ( null != newGC ) { + setAWTGraphicsConfiguration(newConfig); + /** + * Return the newGC, which covers the desired capabilities and is compatible + * with the available GC's of its devices. + */ + if(DEBUG) { + System.err.println(getThreadName()+": Info: getGraphicsConfiguration - end.01: newGC "+newGC); + } + return newGC; + } else { + if(DEBUG) { + System.err.println(getThreadName()+": Info: getGraphicsConfiguration - end.00: oldGC "+oldGC); + } + } + } + /** + * If a new GC was _not_ found/defined above, + * method returns oldGC as selected in the constructor or first addNotify(). + * This may cause an exception in Component.checkGD when adding to a + * container, and is the desired behavior. + */ + return oldGC; + } else if (null == parentGC) { + /** + * The parentGC is null, which means we have no native peer, and are not + * part of a (realized) component hierarchy. So we return the + * desired visual that was selected in the constructor (possibly + * null). + */ + return oldGC; + } else { + /** + * Otherwise we have not explicitly selected a GC in the constructor, so + * just return what Canvas would have. + */ + return parentGC; + } + } + private static String getThreadName() { return Thread.currentThread().getName(); } + @Override public void addNotify() { if( Beans.isDesignTime() ) { super.addNotify(); } else { + /** + * 'super.addNotify()' determines the GraphicsConfiguration, + * while calling this class's overridden 'getGraphicsConfiguration()' method + * after which it creates the native peer. + * Hence we have to set the 'awtConfig' before since it's GraphicsConfiguration + * is being used in getGraphicsConfiguration(). + * This code order also allows recreation, ie re-adding the GLCanvas. + */ // before native peer is valid: X11 disableBackgroundErase(); + // Query AWT GraphicsDevice from parent tree, default + final GraphicsConfiguration gc = super.getGraphicsConfiguration(); + if(null==gc) { + throw new GLException("Error: NULL AWT GraphicsConfiguration"); + } + final CapabilitiesImmutable capsReq = null != newtChild ? newtChild.getRequestedCapabilities() : null; + final AWTGraphicsConfiguration awtConfig = AWTGraphicsConfiguration.create(gc, null, capsReq); + if(null==awtConfig) { + throw new GLException("Error: NULL AWTGraphicsConfiguration"); + } + setAWTGraphicsConfiguration(awtConfig); + // creates the native peer super.addNotify(); @@ -472,7 +605,7 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto System.err.println("NewtCanvasAWT.addNotify.0 - isApplet "+isApplet+", addedOnAWTEDT "+EventQueue.isDispatchThread()+" @ "+currentThreadName()); ExceptionUtils.dumpStack(System.err); } - jawtWindow = NewtFactoryAWT.getNativeWindow(NewtCanvasAWT.this, null != newtChild ? newtChild.getRequestedCapabilities() : null); + jawtWindow = NewtFactoryAWT.getNativeWindow(NewtCanvasAWT.this, awtConfig); jawtWindow.setShallUseOffscreenLayer(shallUseOffscreenLayer); // enforce initial lock on AWT-EDT, allowing acquisition of pixel-scale jawtWindow.lockSurface(); diff --git a/src/newt/classes/jogamp/newt/awt/NewtFactoryAWT.java b/src/newt/classes/jogamp/newt/awt/NewtFactoryAWT.java index 8eaca7c0e..cc71fb559 100644 --- a/src/newt/classes/jogamp/newt/awt/NewtFactoryAWT.java +++ b/src/newt/classes/jogamp/newt/awt/NewtFactoryAWT.java @@ -28,8 +28,6 @@ package jogamp.newt.awt; -import java.awt.GraphicsDevice; - import com.jogamp.nativewindow.AbstractGraphicsConfiguration; import com.jogamp.nativewindow.CapabilitiesImmutable; import com.jogamp.nativewindow.NativeWindow; @@ -57,6 +55,8 @@ public class NewtFactoryAWT extends NewtFactory { public static final boolean DEBUG_IMPLEMENTATION = Debug.debug("Window"); /** + * @deprecated Use {@link #getNativeWindow(java.awt.Component, AWTGraphicsConfiguration)} + * * Wraps an AWT component into a {@link com.jogamp.nativewindow.NativeWindow} utilizing the {@link com.jogamp.nativewindow.NativeWindowFactory},<br> * using a configuration agnostic dummy {@link com.jogamp.nativewindow.DefaultGraphicsConfiguration}.<br> * <p> @@ -78,9 +78,37 @@ public class NewtFactoryAWT extends NewtFactory { return getNativeWindow( (java.awt.Component) awtCompObject, capsRequested ); } + /** + * @deprecated Use {@link #getNativeWindow(java.awt.Component, AWTGraphicsConfiguration)} + * @param awtComp + * @param capsRequested + * @return + */ public static JAWTWindow getNativeWindow(final java.awt.Component awtComp, final CapabilitiesImmutable capsRequested) { - final AWTGraphicsConfiguration config = AWTGraphicsConfiguration.create(awtComp, null, capsRequested); - final NativeWindow nw = NativeWindowFactory.getNativeWindow(awtComp, config); // a JAWTWindow + final AWTGraphicsConfiguration awtConfig = AWTGraphicsConfiguration.create(awtComp, null, capsRequested); + return getNativeWindow(awtComp, awtConfig); + } + + /** + * Wraps an AWT component into a {@link com.jogamp.nativewindow.NativeWindow} utilizing the {@link com.jogamp.nativewindow.NativeWindowFactory},<br> + * using the given {@link AWTGraphicsConfiguration}. + * <p> + * The actual wrapping implementation is {@link com.jogamp.nativewindow.awt.JAWTWindow}. + * </p> + * <p> + * The required {@link AWTGraphicsConfiguration} may be constructed via + * {@link AWTGraphicsConfiguration#create(java.awt.GraphicsConfiguration, CapabilitiesImmutable, CapabilitiesImmutable)} + * </p> + * <p> + * Purpose of this wrapping is to access the AWT window handle,<br> + * not to actually render into it. + * </p> + * + * @param awtComp {@link java.awt.Component} + * @param awtConfig {@link AWTGraphicsConfiguration} reflecting the used {@link java.awt.GraphicsConfiguration} + */ + public static JAWTWindow getNativeWindow(final java.awt.Component awtComp, final AWTGraphicsConfiguration awtConfig) { + final NativeWindow nw = NativeWindowFactory.getNativeWindow(awtComp, awtConfig); // a JAWTWindow if(! ( nw instanceof JAWTWindow ) ) { throw new NativeWindowException("Not an AWT NativeWindow: "+nw); } @@ -101,13 +129,15 @@ public class NewtFactoryAWT extends NewtFactory { * @throws IllegalArgumentException if {@code awtComp} is not {@link java.awt.Component#isDisplayable() displayable} * or has {@code null} {@link java.awt.Component#getGraphicsConfiguration() GraphicsConfiguration}. */ - private static void checkComponentValid(final java.awt.Component awtComp) throws IllegalArgumentException { + private static java.awt.GraphicsConfiguration checkComponentValid(final java.awt.Component awtComp) throws IllegalArgumentException { if( !awtComp.isDisplayable() ) { throw new IllegalArgumentException("Given AWT-Component is not displayable: "+awtComp); } - if( null == awtComp.getGraphicsConfiguration() ) { + final java.awt.GraphicsConfiguration gc = awtComp.getGraphicsConfiguration(); + if( null == gc ) { throw new IllegalArgumentException("Given AWT-Component has no GraphicsConfiguration set: "+awtComp); } + return gc; } /** @@ -120,8 +150,8 @@ public class NewtFactoryAWT extends NewtFactory { * @see #getAbstractGraphicsScreen(java.awt.Component) */ public static Display createDisplay(final java.awt.Component awtComp, final boolean reuse) throws IllegalArgumentException { - checkComponentValid(awtComp); - final GraphicsDevice device = awtComp.getGraphicsConfiguration().getDevice(); + final java.awt.GraphicsConfiguration gc = checkComponentValid(awtComp); + final java.awt.GraphicsDevice device = gc.getDevice(); final String displayConnection; final String nwt = NativeWindowFactory.getNativeWindowType(true); @@ -174,13 +204,13 @@ public class NewtFactoryAWT extends NewtFactory { * @see #createScreen(java.awt.Component, boolean) */ public static MonitorDevice getMonitorDevice(final Screen screen, final java.awt.Component awtComp) throws IllegalArgumentException { - checkComponentValid(awtComp); + final java.awt.GraphicsConfiguration gc = checkComponentValid(awtComp); final String nwt = NativeWindowFactory.getNativeWindowType(true); MonitorDevice res = null; screen.addReference(); try { if( NativeWindowFactory.TYPE_MACOSX == nwt ) { - res = screen.getMonitor( JAWTUtil.getMonitorDisplayID( awtComp.getGraphicsConfiguration().getDevice() ) ); + res = screen.getMonitor( JAWTUtil.getMonitorDisplayID( gc.getDevice() ) ); } if( null == res ) { // Fallback, use AWT component coverage |