diff options
Diffstat (limited to 'src/nativewindow')
24 files changed, 1109 insertions, 167 deletions
diff --git a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsConfiguration.java b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsConfiguration.java index ffa8bfae6..3eb7a6c9a 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsConfiguration.java +++ b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsConfiguration.java @@ -84,8 +84,6 @@ public class DefaultGraphicsConfiguration implements Cloneable, AbstractGraphics * The use case for setting the Capabilities at a later time is * a change of the graphics device in a multi-screen environment.<br> * - * The objects reference is being used. - * * @see javax.media.nativewindow.GraphicsConfigurationFactory#chooseGraphicsConfiguration(Capabilities, CapabilitiesChooser, AbstractGraphicsScreen) */ protected void setChosenCapabilities(CapabilitiesImmutable capsChosen) { diff --git a/src/nativewindow/classes/javax/media/nativewindow/GraphicsConfigurationFactory.java b/src/nativewindow/classes/javax/media/nativewindow/GraphicsConfigurationFactory.java index fa3923dcf..e510c0b78 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/GraphicsConfigurationFactory.java +++ b/src/nativewindow/classes/javax/media/nativewindow/GraphicsConfigurationFactory.java @@ -60,9 +60,9 @@ import java.util.Map; public abstract class GraphicsConfigurationFactory { protected static final boolean DEBUG = Debug.debug("GraphicsConfiguration"); - private static Map/*<Class, NativeWindowFactory>*/ registeredFactories = - Collections.synchronizedMap(new HashMap()); - private static Class abstractGraphicsDeviceClass; + private static Map<Class<?>, GraphicsConfigurationFactory> registeredFactories = + Collections.synchronizedMap(new HashMap<Class<?>, GraphicsConfigurationFactory>()); + private static Class<?> abstractGraphicsDeviceClass; static { initialize(); @@ -122,7 +122,7 @@ public abstract class GraphicsConfigurationFactory { * * @throws IllegalArgumentException if the given class does not implement AbstractGraphicsDevice */ - public static GraphicsConfigurationFactory getFactory(Class abstractGraphicsDeviceImplementor) + public static GraphicsConfigurationFactory getFactory(Class<?> abstractGraphicsDeviceImplementor) throws IllegalArgumentException, NativeWindowException { if (!(abstractGraphicsDeviceClass.isAssignableFrom(abstractGraphicsDeviceImplementor))) { @@ -130,10 +130,9 @@ public abstract class GraphicsConfigurationFactory { } GraphicsConfigurationFactory factory = null; - Class clazz = abstractGraphicsDeviceImplementor; + Class<?> clazz = abstractGraphicsDeviceImplementor; while (clazz != null) { - factory = - (GraphicsConfigurationFactory) registeredFactories.get(clazz); + factory = registeredFactories.get(clazz); if (factory != null) { if(DEBUG) { System.err.println("GraphicsConfigurationFactory.getFactory() "+abstractGraphicsDeviceImplementor+" -> "+factory); @@ -143,7 +142,7 @@ public abstract class GraphicsConfigurationFactory { clazz = clazz.getSuperclass(); } // Return the default - factory = (GraphicsConfigurationFactory)registeredFactories.get(abstractGraphicsDeviceClass); + factory = registeredFactories.get(abstractGraphicsDeviceClass); if(DEBUG) { System.err.println("GraphicsConfigurationFactory.getFactory() DEFAULT "+abstractGraphicsDeviceClass+" -> "+factory); } @@ -157,7 +156,7 @@ public abstract class GraphicsConfigurationFactory { * * @throws IllegalArgumentException if the given class does not implement AbstractGraphicsDevice */ - protected static void registerFactory(Class abstractGraphicsDeviceImplementor, GraphicsConfigurationFactory factory) + protected static void registerFactory(Class<?> abstractGraphicsDeviceImplementor, GraphicsConfigurationFactory factory) throws IllegalArgumentException { if (!(abstractGraphicsDeviceClass.isAssignableFrom(abstractGraphicsDeviceImplementor))) { diff --git a/src/nativewindow/classes/javax/media/nativewindow/NativeSurface.java b/src/nativewindow/classes/javax/media/nativewindow/NativeSurface.java index e691ba8e6..b2a2bc4ee 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/NativeSurface.java +++ b/src/nativewindow/classes/javax/media/nativewindow/NativeSurface.java @@ -118,6 +118,24 @@ public interface NativeSurface extends SurfaceUpdatedListener { */ public boolean surfaceSwap(); + /** Appends the given {@link SurfaceUpdatedListener} to the end of the list. */ + public void addSurfaceUpdatedListener(SurfaceUpdatedListener l); + + /** + * Inserts the given {@link SurfaceUpdatedListener} at the + * specified position in the list.<br> + * + * @param index Position where the listener will be inserted. + * Should be within (0 <= index && index <= size()). + * An index value of -1 is interpreted as the end of the list, size(). + * @param l The listener object to be inserted + * @throws IndexOutOfBoundsException If the index is not within (0 <= index && index <= size()), or -1 + */ + public void addSurfaceUpdatedListener(int index, SurfaceUpdatedListener l) throws IndexOutOfBoundsException; + + /** Remove the specified {@link SurfaceUpdatedListener} from the list. */ + public void removeSurfaceUpdatedListener(SurfaceUpdatedListener l); + /** * Returns the handle to the surface for this NativeSurface. <P> * diff --git a/src/nativewindow/classes/javax/media/nativewindow/NativeWindow.java b/src/nativewindow/classes/javax/media/nativewindow/NativeWindow.java index 76ac72953..e3ee85cf4 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/NativeWindow.java +++ b/src/nativewindow/classes/javax/media/nativewindow/NativeWindow.java @@ -126,4 +126,7 @@ public interface NativeWindow extends NativeSurface { */ public Point getLocationOnScreen(Point point); + /** Returns true if this native window owns the focus, otherwise false. */ + boolean hasFocus(); + } diff --git a/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java b/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java index ef8876f50..b6c850098 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java +++ b/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java @@ -33,15 +33,20 @@ package javax.media.nativewindow; -import java.security.*; -import java.util.*; - -import com.jogamp.common.util.*; -import com.jogamp.common.os.Platform; - -import jogamp.nativewindow.*; import java.lang.reflect.Constructor; import java.lang.reflect.Method; +import java.security.AccessControlContext; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import jogamp.nativewindow.Debug; +import jogamp.nativewindow.NativeWindowFactoryImpl; + +import com.jogamp.common.os.Platform; +import com.jogamp.common.util.ReflectionUtil; /** Provides a pluggable mechanism for arbitrary window toolkits to adapt their components to the {@link NativeWindow} interface, @@ -470,4 +475,33 @@ public abstract class NativeWindowFactory { NativeWindow. Implementors of concrete NativeWindowFactory subclasses should override this method. */ protected abstract NativeWindow getNativeWindowImpl(Object winObj, AbstractGraphicsConfiguration config) throws IllegalArgumentException; + + /** + * Returns the {@link OffscreenLayerSurface} instance of this {@link NativeSurface}. + * <p> + * In case this surface is a {@link NativeWindow}, we traverse from the given surface + * up to root until a {@link OffscreenLayerSurface} is found. + * </p> + * + * @param surface The surface to query. + * @param ifEnabled If true, only return the enabled {@link OffscreenLayerSurface}, see {@link OffscreenLayerSurface#isOffscreenLayerSurfaceEnabled()}. + * @return + */ + public static OffscreenLayerSurface getOffscreenLayerSurface(NativeSurface surface, boolean ifEnabled) { + if(surface instanceof OffscreenLayerSurface) { + final OffscreenLayerSurface ols = (OffscreenLayerSurface) surface; + return ( !ifEnabled || ols.isOffscreenLayerSurfaceEnabled() ) ? ols : null; + } + if(surface instanceof NativeWindow) { + NativeWindow nw = ((NativeWindow) surface).getParent(); + while(null != nw) { + if(nw instanceof OffscreenLayerSurface) { + final OffscreenLayerSurface ols = (OffscreenLayerSurface) nw; + return ( !ifEnabled || ols.isOffscreenLayerSurfaceEnabled() ) ? ols : null; + } + nw = nw.getParent(); + } + } + return null; + } } diff --git a/src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerSurface.java b/src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerSurface.java new file mode 100644 index 000000000..82ae0f39e --- /dev/null +++ b/src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerSurface.java @@ -0,0 +1,51 @@ +/** + * Copyright 2011 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package javax.media.nativewindow; + +/** + * Interface specifying the offscreen layer surface protocol. + */ +public interface OffscreenLayerSurface { + /** Returns true if this instance uses an offscreen layer, otherwise false. */ + public boolean isOffscreenLayerSurfaceEnabled(); + + /** + * Attach the offscreen layer to this offscreen layer surface. + * @see #isOffscreenLayerSurfaceEnabled() + * @throws NativeWindowException if {@link #isOffscreenLayerSurfaceEnabled()} == false + */ + public void attachSurfaceLayer(final long layerHandle) throws NativeWindowException; + + /** + * Detaches a previously attached offscreen layer from this offscreen layer surface. + * @see #attachSurfaceLayer(long) + * @see #isOffscreenLayerSurfaceEnabled() + * @throws NativeWindowException if {@link #isOffscreenLayerSurfaceEnabled()} == false + */ + public void detachSurfaceLayer(final long layerHandle) throws NativeWindowException; +} diff --git a/src/nativewindow/classes/javax/media/nativewindow/ProxySurface.java b/src/nativewindow/classes/javax/media/nativewindow/ProxySurface.java index e34476228..7380d19b6 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/ProxySurface.java +++ b/src/nativewindow/classes/javax/media/nativewindow/ProxySurface.java @@ -28,6 +28,8 @@ package javax.media.nativewindow; +import jogamp.nativewindow.SurfaceUpdatedHelper; + import com.jogamp.common.util.locks.LockFactory; import com.jogamp.common.util.locks.RecursiveLock; @@ -38,6 +40,7 @@ public abstract class ProxySurface implements NativeSurface { protected int height; protected int scrnIndex; protected int width; + private SurfaceUpdatedHelper surfaceUpdatedHelper = new SurfaceUpdatedHelper(); public ProxySurface(AbstractGraphicsConfiguration cfg) { invalidate(); @@ -73,7 +76,7 @@ public abstract class ProxySurface implements NativeSurface { return height; } - public void setSize(int width, int height) { + public void surfaceSizeChanged(int width, int height) { this.width = width; this.height = height; } @@ -82,9 +85,22 @@ public abstract class ProxySurface implements NativeSurface { return false; } - public void surfaceUpdated(Object updater, NativeSurface ns, long when) { + public void addSurfaceUpdatedListener(SurfaceUpdatedListener l) { + surfaceUpdatedHelper.addSurfaceUpdatedListener(l); + } + + public void addSurfaceUpdatedListener(int index, SurfaceUpdatedListener l) throws IndexOutOfBoundsException { + surfaceUpdatedHelper.addSurfaceUpdatedListener(index, l); } + public void removeSurfaceUpdatedListener(SurfaceUpdatedListener l) { + surfaceUpdatedHelper.removeSurfaceUpdatedListener(l); + } + + public void surfaceUpdated(Object updater, NativeSurface ns, long when) { + surfaceUpdatedHelper.surfaceUpdated(updater, ns, when); + } + public int lockSurface() throws NativeWindowException { surfaceLock.lock(); int res = surfaceLock.getHoldCount() == 1 ? LOCK_SURFACE_NOT_READY : LOCK_SUCCESS; // new lock ? @@ -143,5 +159,5 @@ public abstract class ProxySurface implements NativeSurface { return surfaceLock.getOwner(); } - public abstract String toString(); + public abstract String toString(); } diff --git a/src/nativewindow/classes/javax/media/nativewindow/SurfaceChangeable.java b/src/nativewindow/classes/javax/media/nativewindow/SurfaceChangeable.java index fc32b57b3..956e68e61 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/SurfaceChangeable.java +++ b/src/nativewindow/classes/javax/media/nativewindow/SurfaceChangeable.java @@ -41,8 +41,14 @@ package javax.media.nativewindow; public interface SurfaceChangeable { + /** Sets the surface handle which is created outside of this implementation */ public void setSurfaceHandle(long surfaceHandle); - public void setSize(int width, int height); + + /** + * The surface's size has been determined or changed. + * Implementation shall update the stored surface size with the given ones. + */ + public void surfaceSizeChanged(int width, int height); } diff --git a/src/nativewindow/classes/javax/media/nativewindow/SurfaceUpdatedListener.java b/src/nativewindow/classes/javax/media/nativewindow/SurfaceUpdatedListener.java index 88e805d14..0912b5afe 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/SurfaceUpdatedListener.java +++ b/src/nativewindow/classes/javax/media/nativewindow/SurfaceUpdatedListener.java @@ -34,8 +34,12 @@ package javax.media.nativewindow; +/** + * Clients may add their SurfaceUpdateListener implementation to a {@link javax.media.nativewindow.NativeSurface} + * allowing to get notified after the surface has been updated, eg. after a swap buffer operation. + */ public interface SurfaceUpdatedListener { - /** Notification of a surface update event. + /** Notification of a surface update event, eg. after a swap buffer operation. * * @param updater is the caller object who updated the surface, * e.g. a JOGL GLDrawable. diff --git a/src/nativewindow/classes/javax/media/nativewindow/awt/AWTGraphicsConfiguration.java b/src/nativewindow/classes/javax/media/nativewindow/awt/AWTGraphicsConfiguration.java index d83a92a5b..38ad2d795 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/awt/AWTGraphicsConfiguration.java +++ b/src/nativewindow/classes/javax/media/nativewindow/awt/AWTGraphicsConfiguration.java @@ -41,6 +41,7 @@ package javax.media.nativewindow.awt; import javax.media.nativewindow.*; + import java.awt.Component; import java.awt.GraphicsConfiguration; import java.awt.GraphicsDevice; @@ -98,12 +99,42 @@ public class AWTGraphicsConfiguration extends DefaultGraphicsConfiguration imple if(null==capsChosen) { GraphicsConfiguration gc = awtGraphicsDevice.getDefaultConfiguration(); - capsChosen = setupCapabilitiesRGBABits(capsChosen, gc); + capsChosen = setupCapabilitiesRGBABits(capsRequested, gc); } return new AWTGraphicsConfiguration(awtScreen, capsChosen, capsRequested, awtGfxConfig); } - @Override + public void updateGraphicsConfiguration(Component awtComp) + { + AWTGraphicsScreen awtScreen = null; + AWTGraphicsDevice awtDevice = null; + GraphicsDevice awtGraphicsDevice = null; + GraphicsConfiguration awtGfxConfig = awtComp.getGraphicsConfiguration(); + if(null!=awtGfxConfig) { + awtGraphicsDevice = awtGfxConfig.getDevice(); + if(null!=awtGraphicsDevice) { + // Create Device/Screen + awtDevice = new AWTGraphicsDevice(awtGraphicsDevice, AbstractGraphicsDevice.DEFAULT_UNIT); + awtScreen = new AWTGraphicsScreen(awtDevice); + } + } + if(null==awtScreen) { + throw new NativeWindowException("native peer n/a: "+awtComp); + } + config = awtGfxConfig; + setScreen(awtScreen); + + CapabilitiesImmutable caps = ( null != getChosenCapabilities() ) ? getChosenCapabilities() : getRequestedCapabilities(); + GraphicsConfiguration gc = awtGraphicsDevice.getDefaultConfiguration(); + setChosenCapabilities(setupCapabilitiesRGBABits(caps, gc)); + } + + // open access to superclass method + public void setChosenCapabilities(CapabilitiesImmutable capsChosen) { + super.setChosenCapabilities(capsChosen); + } + + @Override public Object clone() { return super.clone(); } diff --git a/src/nativewindow/classes/javax/media/nativewindow/x11/X11GraphicsConfiguration.java b/src/nativewindow/classes/javax/media/nativewindow/x11/X11GraphicsConfiguration.java index 100b6b839..9869e1eb3 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/x11/X11GraphicsConfiguration.java +++ b/src/nativewindow/classes/javax/media/nativewindow/x11/X11GraphicsConfiguration.java @@ -32,8 +32,9 @@ package javax.media.nativewindow.x11; -import javax.media.nativewindow.*; +import javax.media.nativewindow.CapabilitiesImmutable; +import jogamp.nativewindow.MutableGraphicsConfiguration; import jogamp.nativewindow.x11.XVisualInfo; /** Encapsulates a graphics configuration, or OpenGL pixel format, on @@ -42,7 +43,7 @@ import jogamp.nativewindow.x11.XVisualInfo; GraphicsConfigurationFactory.chooseGraphicsConfiguration()} on X11 platforms when toolkits other than the AWT are being used. */ -public class X11GraphicsConfiguration extends DefaultGraphicsConfiguration implements Cloneable { +public class X11GraphicsConfiguration extends MutableGraphicsConfiguration implements Cloneable { private XVisualInfo info; public X11GraphicsConfiguration(X11GraphicsScreen screen, diff --git a/src/nativewindow/classes/jogamp/nativewindow/MutableGraphicsConfiguration.java b/src/nativewindow/classes/jogamp/nativewindow/MutableGraphicsConfiguration.java new file mode 100644 index 000000000..ee3ab73ba --- /dev/null +++ b/src/nativewindow/classes/jogamp/nativewindow/MutableGraphicsConfiguration.java @@ -0,0 +1,43 @@ +/** + * Copyright 2011 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 jogamp.nativewindow; + +import javax.media.nativewindow.AbstractGraphicsScreen; +import javax.media.nativewindow.CapabilitiesImmutable; +import javax.media.nativewindow.DefaultGraphicsConfiguration; + +public class MutableGraphicsConfiguration extends DefaultGraphicsConfiguration { + public MutableGraphicsConfiguration(AbstractGraphicsScreen screen, + CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested) { + super(screen, capsChosen, capsRequested); + } + + public void setChosenCapabilities(CapabilitiesImmutable caps) { + super.setChosenCapabilities(caps); + } +} diff --git a/src/nativewindow/classes/jogamp/nativewindow/NativeWindowFactoryImpl.java b/src/nativewindow/classes/jogamp/nativewindow/NativeWindowFactoryImpl.java index d34d4e58f..5cb7d5aca 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/NativeWindowFactoryImpl.java +++ b/src/nativewindow/classes/jogamp/nativewindow/NativeWindowFactoryImpl.java @@ -32,11 +32,16 @@ package jogamp.nativewindow; -import com.jogamp.common.os.Platform; -import com.jogamp.common.util.*; -import java.lang.reflect.*; +import java.lang.reflect.Constructor; + +import javax.media.nativewindow.AbstractGraphicsConfiguration; +import javax.media.nativewindow.NativeSurface; +import javax.media.nativewindow.NativeWindow; +import javax.media.nativewindow.NativeWindowFactory; +import javax.media.nativewindow.ToolkitLock; -import javax.media.nativewindow.*; +import com.jogamp.common.os.Platform; +import com.jogamp.common.util.ReflectionUtil; public class NativeWindowFactoryImpl extends NativeWindowFactory { private static final ToolkitLock nullToolkitLock = new NullToolkitLock(); @@ -44,13 +49,10 @@ public class NativeWindowFactoryImpl extends NativeWindowFactory { public static ToolkitLock getNullToolkitLock() { return nullToolkitLock; } - + // This subclass of NativeWindowFactory handles the case of // NativeWindows being passed in protected NativeWindow getNativeWindowImpl(Object winObj, AbstractGraphicsConfiguration config) throws IllegalArgumentException { - if (null == winObj) { - throw new IllegalArgumentException("winObj is null"); - } if (winObj instanceof NativeWindow) { // Use the NativeWindow directly return (NativeWindow) winObj; @@ -69,7 +71,7 @@ public class NativeWindowFactoryImpl extends NativeWindowFactory { "javax.media.nativewindow.NativeWindow or "+AWTComponentClassName); } - private Constructor nativeWindowConstructor = null; + private Constructor<?> nativeWindowConstructor = null; private NativeWindow getAWTNativeWindow(Object winObj, AbstractGraphicsConfiguration config) { if (nativeWindowConstructor == null) { diff --git a/src/nativewindow/classes/jogamp/nativewindow/SurfaceUpdatedHelper.java b/src/nativewindow/classes/jogamp/nativewindow/SurfaceUpdatedHelper.java new file mode 100644 index 000000000..4877d5c4f --- /dev/null +++ b/src/nativewindow/classes/jogamp/nativewindow/SurfaceUpdatedHelper.java @@ -0,0 +1,85 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package jogamp.nativewindow; + +import java.util.ArrayList; + +import javax.media.nativewindow.NativeSurface; +import javax.media.nativewindow.SurfaceUpdatedListener; + +public class SurfaceUpdatedHelper implements SurfaceUpdatedListener { + private Object surfaceUpdatedListenersLock = new Object(); + private ArrayList<SurfaceUpdatedListener> surfaceUpdatedListeners = new ArrayList<SurfaceUpdatedListener>(); + + // + // Management Utils + // + public int size() { return surfaceUpdatedListeners.size(); } + public SurfaceUpdatedListener get(int i) { return surfaceUpdatedListeners.get(i); } + + // + // Implementation of NativeSurface SurfaceUpdatedListener methods + // + + public void addSurfaceUpdatedListener(SurfaceUpdatedListener l) { + addSurfaceUpdatedListener(-1, l); + } + + public void addSurfaceUpdatedListener(int index, SurfaceUpdatedListener l) + throws IndexOutOfBoundsException + { + if(l == null) { + return; + } + synchronized(surfaceUpdatedListenersLock) { + if(0>index) { + index = surfaceUpdatedListeners.size(); + } + surfaceUpdatedListeners.add(index, l); + } + } + + public void removeSurfaceUpdatedListener(SurfaceUpdatedListener l) { + if (l == null) { + return; + } + synchronized(surfaceUpdatedListenersLock) { + surfaceUpdatedListeners.remove(l); + } + } + + public void surfaceUpdated(Object updater, NativeSurface ns, long when) { + synchronized(surfaceUpdatedListenersLock) { + for(int i = 0; i < surfaceUpdatedListeners.size(); i++ ) { + SurfaceUpdatedListener l = surfaceUpdatedListeners.get(i); + l.surfaceUpdated(updater, ns, when); + } + } + } +} diff --git a/src/nativewindow/classes/jogamp/nativewindow/WrappedSurface.java b/src/nativewindow/classes/jogamp/nativewindow/WrappedSurface.java index 4c2b1c875..65ecc48fe 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/WrappedSurface.java +++ b/src/nativewindow/classes/jogamp/nativewindow/WrappedSurface.java @@ -33,7 +33,7 @@ import javax.media.nativewindow.ProxySurface; import javax.media.nativewindow.SurfaceChangeable; -public class WrappedSurface extends ProxySurface implements SurfaceChangeable { +public class WrappedSurface extends ProxySurface implements SurfaceChangeable { protected long surfaceHandle; public WrappedSurface(AbstractGraphicsConfiguration cfg) { diff --git a/src/nativewindow/classes/jogamp/nativewindow/jawt/JAWTUtil.java b/src/nativewindow/classes/jogamp/nativewindow/jawt/JAWTUtil.java index c1c97eece..ddf453bab 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/jawt/JAWTUtil.java +++ b/src/nativewindow/classes/jogamp/nativewindow/jawt/JAWTUtil.java @@ -42,6 +42,8 @@ import java.awt.EventQueue; import javax.media.nativewindow.*; +import com.jogamp.common.os.Platform; + import java.awt.GraphicsEnvironment; import java.awt.Toolkit; @@ -55,6 +57,7 @@ public class JAWTUtil { // See whether we're running in headless mode private static final boolean headlessMode; + private static final JAWT jawtLockObject; // Java2D magic .. private static final Method isQueueFlusherThread; @@ -75,31 +78,63 @@ public class JAWTUtil { boolean ok; } + /** + * Returns true if this platform's JAWT implementation supports + * or uses offscreen layer. + */ + public static boolean isOffscreenLayerSupported() { + return Platform.OS_TYPE == Platform.OSType.MACOS && + Platform.OS_VERSION_NUMBER.compareTo(JAWT.JAWT_MacOSXCALayerMinVersion) >= 0; + } + + /** + * @param useOffscreenLayerIfAvailable + * @return + */ + public static JAWT getJAWT(boolean useOffscreenLayerIfAvailable) { + int jawt_version_flags = JAWTFactory.JAWT_VERSION_1_4; + if(useOffscreenLayerIfAvailable) { + switch(Platform.OS_TYPE) { + case MACOS: + if(Platform.OS_VERSION_NUMBER.compareTo(JAWT.JAWT_MacOSXCALayerMinVersion) >= 0) { + jawt_version_flags |= JAWT.JAWT_MACOSX_USE_CALAYER; + } + } + } + return JAWT.getJAWT(jawt_version_flags); + } + + public static boolean isJAWTUsingOffscreenLayer(JAWT jawt) { + return 0 != ( jawt.getCachedVersion() & JAWT.JAWT_MACOSX_USE_CALAYER ); + } + static { JAWTJNILibLoader.loadAWTImpl(); JAWTJNILibLoader.loadNativeWindow("awt"); headlessMode = GraphicsEnvironment.isHeadless(); - boolean ok = false; - Class jC = null; + Class<?> jC = null; Method m = null; if (!headlessMode) { + jawtLockObject = getJAWT(false); // don't care for offscreen layer here try { jC = Class.forName("jogamp.opengl.awt.Java2D"); m = jC.getMethod("isQueueFlusherThread", (Class[])null); ok = true; } catch (Exception e) { } + } else { + jawtLockObject = null; // headless ! } isQueueFlusherThread = m; j2dExist = ok; - PrivilegedDataBlob1 pdb1 = (PrivilegedDataBlob1) AccessController.doPrivileged(new PrivilegedAction() { + PrivilegedDataBlob1 pdb1 = (PrivilegedDataBlob1) AccessController.doPrivileged(new PrivilegedAction<Object>() { public Object run() { PrivilegedDataBlob1 d = new PrivilegedDataBlob1(); try { - final Class sunToolkitClass = Class.forName("sun.awt.SunToolkit"); + final Class<?> sunToolkitClass = Class.forName("sun.awt.SunToolkit"); d.sunToolkitAWTLockMethod = sunToolkitClass.getDeclaredMethod("awtLock", new Class[]{}); d.sunToolkitAWTLockMethod.setAccessible(true); d.sunToolkitAWTUnlockMethod = sunToolkitClass.getDeclaredMethod("awtUnlock", new Class[]{}); @@ -129,21 +164,21 @@ public class JAWTUtil { jawtToolkitLock = new JAWTToolkitLock(); // trigger native AWT toolkit / properties initialization - Map desktophints = null; + Map<?,?> desktophints = null; try { if(EventQueue.isDispatchThread()) { - desktophints = (Map)(Toolkit.getDefaultToolkit().getDesktopProperty("awt.font.desktophints")); + desktophints = (Map<?,?>)(Toolkit.getDefaultToolkit().getDesktopProperty("awt.font.desktophints")); } else { - final ArrayList desktophintsBucket = new ArrayList(1); + final ArrayList<Map<?,?>> desktophintsBucket = new ArrayList<Map<?,?>>(1); EventQueue.invokeAndWait(new Runnable() { public void run() { - Map _desktophints = (Map)(Toolkit.getDefaultToolkit().getDesktopProperty("awt.font.desktophints")); + Map<?,?> _desktophints = (Map<?,?>)(Toolkit.getDefaultToolkit().getDesktopProperty("awt.font.desktophints")); if(null!=_desktophints) { desktophintsBucket.add(_desktophints); } } }); - desktophints = ( desktophintsBucket.size() > 0 ) ? (Map)desktophintsBucket.get(0) : null ; + desktophints = ( desktophintsBucket.size() > 0 ) ? desktophintsBucket.get(0) : null ; } } catch (InterruptedException ex) { ex.printStackTrace(); @@ -189,7 +224,7 @@ public class JAWTUtil { * JAWT's native Lock() function calls SunToolkit.awtLock(), * which just uses AWT's global ReentrantLock.<br> */ - public static void awtLock() { + private static void awtLock() { if(hasSunToolkitAWTLock) { try { sunToolkitAWTLockMethod.invoke(null, (Object[])null); @@ -197,7 +232,7 @@ public class JAWTUtil { throw new NativeWindowException("SunToolkit.awtLock failed", e); } } else { - JAWT.getJAWT().Lock(); + jawtLockObject.Lock(); } } @@ -207,7 +242,7 @@ public class JAWTUtil { * JAWT's native Unlock() function calls SunToolkit.awtUnlock(), * which just uses AWT's global ReentrantLock.<br> */ - public static void awtUnlock() { + private static void awtUnlock() { if(hasSunToolkitAWTLock) { try { sunToolkitAWTUnlockMethod.invoke(null, (Object[])null); @@ -215,7 +250,7 @@ public class JAWTUtil { throw new NativeWindowException("SunToolkit.awtUnlock failed", e); } } else { - JAWT.getJAWT().Unlock(); + jawtLockObject.Unlock(); } } diff --git a/src/nativewindow/classes/jogamp/nativewindow/jawt/JAWTWindow.java b/src/nativewindow/classes/jogamp/nativewindow/jawt/JAWTWindow.java index 2c80392ad..0f97b0b9f 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/jawt/JAWTWindow.java +++ b/src/nativewindow/classes/jogamp/nativewindow/jawt/JAWTWindow.java @@ -42,48 +42,101 @@ import com.jogamp.common.util.locks.RecursiveLock; import java.awt.Component; import java.awt.Window; +import java.applet.Applet; import javax.media.nativewindow.AbstractGraphicsConfiguration; import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.NativeSurface; import javax.media.nativewindow.NativeWindow; import javax.media.nativewindow.NativeWindowException; +import javax.media.nativewindow.OffscreenLayerSurface; +import javax.media.nativewindow.SurfaceUpdatedListener; +import javax.media.nativewindow.awt.AWTGraphicsConfiguration; import javax.media.nativewindow.util.Insets; import javax.media.nativewindow.util.InsetsImmutable; import javax.media.nativewindow.util.Point; import javax.media.nativewindow.util.Rectangle; import javax.media.nativewindow.util.RectangleImmutable; -public abstract class JAWTWindow implements NativeWindow { +import jogamp.nativewindow.SurfaceUpdatedHelper; + +public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface { protected static final boolean DEBUG = JAWTUtil.DEBUG; + // user properties + protected boolean shallUseOffscreenLayer = false; + // lifetime: forever protected Component component; - protected AbstractGraphicsConfiguration config; + protected AWTGraphicsConfiguration config; + private SurfaceUpdatedHelper surfaceUpdatedHelper = new SurfaceUpdatedHelper(); - // lifetime: valid after lock, forever until invalidate + // lifetime: valid after lock but may change with each 1st lock, purges after invalidate + private boolean isApplet; + private JAWT jawt; + private boolean isOffscreenLayerSurface; protected long drawable; protected Rectangle bounds; - public JAWTWindow(Object comp, AbstractGraphicsConfiguration config) { + /** + * Constructed by {@link jogamp.nativewindow.NativeWindowFactoryImpl#getNativeWindow(Object, AbstractGraphicsConfiguration)} + * via this platform's specialization (X11, OSX, Windows, ..). + * + * @param comp + * @param config + */ + protected JAWTWindow(Object comp, AbstractGraphicsConfiguration config) { if (config == null) { throw new NativeWindowException("Error: AbstractGraphicsConfiguration is null"); } - this.config = config; + if(! ( config instanceof AWTGraphicsConfiguration ) ) { + throw new NativeWindowException("Error: AbstractGraphicsConfiguration is not an AWTGraphicsConfiguration"); + } + this.config = (AWTGraphicsConfiguration) config; init((Component)comp); } private void init(Component windowObject) throws NativeWindowException { invalidate(); this.component = windowObject; + this.isApplet = false; validateNative(); } + + /** + * Request an JAWT offscreen layer if supported. + * Shall be called before {@link #lockSurface()}. + * + * @see #getShallUseOffscreenLayer() + * @see #isOffscreenLayerSurfaceEnabled() + */ + public void setShallUseOffscreenLayer(boolean v) { + shallUseOffscreenLayer = v; + } + + /** Returns the property set by {@link #setShallUseOffscreenLayer(boolean)}. */ + public final boolean getShallUseOffscreenLayer() { + return shallUseOffscreenLayer; + } + + /** + * Implementors shall ensure that all native handles are valid, eg. the {@link javax.media.nativewindow.awt.AWTGraphicsDevice AWTGraphicsDevice}'s + * subtype via {@link javax.media.nativewindow.awt.AWTGraphicsDevice#setSubType(String, long) awtGraphicsDevice.setSubType(NativeWindowFactory.TYPE_X11, displayHandle)}. + * <p> + * This method may be called several times, + * hence the implementation shall check for valid values 1st and bail out early if satisfied. + * </p> + * @throws NativeWindowException + */ protected abstract void validateNative() throws NativeWindowException; protected synchronized void invalidate() { - component = null; + invalidateNative(); + jawt = null; + isOffscreenLayerSurface = false; drawable= 0; bounds = new Rectangle(); } + protected abstract void invalidateNative(); protected final void updateBounds(JAWT_Rectangle jawtBounds) { bounds.setX(jawtBounds.getX()); @@ -100,14 +153,91 @@ public abstract class JAWTWindow implements NativeWindow { public final Component getAWTComponent() { return component; } + + /** + * Returns true if the AWT component is parented to an {@link java.applet.Applet}, + * otherwise false. This information is valid only after {@link #lockSurface()}. + */ + public final boolean isApplet() { + return isApplet; + } + /** Returns the underlying JAWT instance created @ {@link #lockSurface()}. */ + public final JAWT getJAWT() { + return jawt; + } + + /** + * {@inheritDoc} + * @see #setShallUseOffscreenLayer(boolean) + */ + public final boolean isOffscreenLayerSurfaceEnabled() { + return isOffscreenLayerSurface; + } + + /** + * {@inheritDoc} + */ + public final void attachSurfaceLayer(final long layerHandle) throws NativeWindowException { + if( !isOffscreenLayerSurfaceEnabled() ) { + throw new NativeWindowException("Not an offscreen layer surface"); + } + int lockRes = lockSurface(); + if (NativeSurface.LOCK_SURFACE_NOT_READY >= lockRes) { + throw new NativeWindowException("Could not lock (offscreen layer): "+this); + } + try { + if(DEBUG) { + System.err.println("JAWTWindow.attachSurfaceHandle(): 0x"+Long.toHexString(layerHandle)); + } + attachSurfaceLayerImpl(layerHandle); + } finally { + unlockSurface(); + } + } + protected abstract void attachSurfaceLayerImpl(final long layerHandle); + + /** + * {@inheritDoc} + */ + public final void detachSurfaceLayer(final long layerHandle) throws NativeWindowException { + if( !isOffscreenLayerSurfaceEnabled() ) { + throw new java.lang.UnsupportedOperationException("Not an offscreen layer surface"); + } + int lockRes = lockSurface(); + if (NativeSurface.LOCK_SURFACE_NOT_READY >= lockRes) { + throw new NativeWindowException("Could not lock (offscreen layer): "+this); + } + try { + if(DEBUG) { + System.err.println("JAWTWindow.detachSurfaceHandle(): 0x"+Long.toHexString(layerHandle)); + } + detachSurfaceLayerImpl(layerHandle); + } finally { + unlockSurface(); + } + } + protected abstract void detachSurfaceLayerImpl(final long layerHandle); + // // SurfaceUpdateListener // - public final void surfaceUpdated(Object updater, NativeSurface ns, long when) { - // nop + public void addSurfaceUpdatedListener(SurfaceUpdatedListener l) { + surfaceUpdatedHelper.addSurfaceUpdatedListener(l); } + + public void addSurfaceUpdatedListener(int index, SurfaceUpdatedListener l) throws IndexOutOfBoundsException { + surfaceUpdatedHelper.addSurfaceUpdatedListener(index, l); + } + + public void removeSurfaceUpdatedListener(SurfaceUpdatedListener l) { + surfaceUpdatedHelper.removeSurfaceUpdatedListener(l); + } + + public void surfaceUpdated(Object updater, NativeSurface ns, long when) { + surfaceUpdatedHelper.surfaceUpdated(updater, ns, when); + } // // NativeSurface @@ -115,17 +245,39 @@ public abstract class JAWTWindow implements NativeWindow { private RecursiveLock surfaceLock = LockFactory.createRecursiveLock(); + private void determineIfApplet() { + Component c = component; + while(!isApplet && null != c) { + isApplet = c instanceof Applet; + c = c.getParent(); + } + } + + /** + * If JAWT offscreen layer is supported, + * implementation shall respect {@link #getShallUseOffscreenLayer()} + * and may respect {@link #isApplet()}. + * + * @return The JAWT instance reflecting offscreen layer support, etc. + * + * @throws NativeWindowException + */ + protected abstract JAWT fetchJAWTImpl() throws NativeWindowException; protected abstract int lockSurfaceImpl() throws NativeWindowException; public final int lockSurface() throws NativeWindowException { + validateNative(); surfaceLock.lock(); int res = surfaceLock.getHoldCount() == 1 ? LOCK_SURFACE_NOT_READY : LOCK_SUCCESS; // new lock ? if ( LOCK_SURFACE_NOT_READY == res ) { + determineIfApplet(); try { final AbstractGraphicsDevice adevice = config.getScreen().getDevice(); adevice.lock(); try { + jawt = fetchJAWTImpl(); + isOffscreenLayerSurface = JAWTUtil.isJAWTUsingOffscreenLayer(jawt); res = lockSurfaceImpl(); } finally { if (LOCK_SURFACE_NOT_READY >= res) { @@ -169,15 +321,14 @@ public abstract class JAWTWindow implements NativeWindow { return surfaceLock.getOwner(); } - public final boolean surfaceSwap() { + public boolean surfaceSwap() { return false; } - public final void surfaceUpdated(Object updater, NativeWindow window, long when) { } - - public final long getSurfaceHandle() { + public long getSurfaceHandle() { return drawable; } + public final AbstractGraphicsConfiguration getGraphicsConfiguration() { return config; } @@ -190,15 +341,11 @@ public abstract class JAWTWindow implements NativeWindow { return config.getScreen().getIndex(); } - public final void setSize(int width, int height) { - component.setSize(width, height); - } - - public final int getWidth() { + public int getWidth() { return component.getWidth(); } - public final int getHeight() { + public int getHeight() { return component.getHeight(); } @@ -207,12 +354,13 @@ public abstract class JAWTWindow implements NativeWindow { // public synchronized void destroy() { + invalidate(); if(null!=component) { if(component instanceof Window) { ((Window)component).dispose(); } + component = null; } - invalidate(); } public final NativeWindow getParent() { @@ -222,7 +370,7 @@ public abstract class JAWTWindow implements NativeWindow { public long getWindowHandle() { return drawable; } - + public final int getX() { return component.getX(); } @@ -230,44 +378,85 @@ public abstract class JAWTWindow implements NativeWindow { public final int getY() { return component.getY(); } - + + /** + * {@inheritDoc} + * + * <p> + * This JAWT default implementation is currently still using + * a blocking implementation. It first attempts to retrieve the location + * via a native implementation. If this fails, it tries the blocking AWT implementation. + * If the latter fails due to an external AWT tree-lock, the non block + * implementation {@link #getLocationOnScreenNonBlocking(Point, Component)} is being used. + * The latter simply traverse up to the AWT component tree and sums the rel. position. + * We have to determine whether the latter is good enough for all cases, + * currently only OS X utilizes the non blocking method per default. + * </p> + */ public Point getLocationOnScreen(Point storage) { + Point los = getLocationOnScreenNative(storage); + if(null == los) { + if(!Thread.holdsLock(component.getTreeLock())) { + // avoid deadlock .. + if(DEBUG) { + System.err.println("Warning: JAWT Lock hold, but not the AWT tree lock: "+this); + Thread.dumpStack(); + } + return getLocationOnScreenNonBlocking(storage, component); + } + java.awt.Point awtLOS = component.getLocationOnScreen(); + if(null!=storage) { + los = storage.translate(awtLOS.x, awtLOS.y); + } else { + los = new Point(awtLOS.x, awtLOS.y); + } + } + return los; + } + + protected Point getLocationOnScreenNative(Point storage) { int lockRes = lockSurface(); if(LOCK_SURFACE_NOT_READY == lockRes) { - // FIXME: Shall we deal with already locked or unrealized surfaces ? - System.err.println("Warning: JAWT Lock couldn't be acquired!"); - Thread.dumpStack(); + if(DEBUG) { + System.err.println("Warning: JAWT Lock couldn't be acquired: "+this); + Thread.dumpStack(); + } return null; } try { - Point d = getLocationOnScreenImpl(0, 0); + Point d = getLocationOnScreenNativeImpl(0, 0); if(null!=d) { if(null!=storage) { storage.translate(d.getX(),d.getY()); return storage; } - return d; - } - // fall through intended .. - if(!Thread.holdsLock(component.getTreeLock())) { - // FIXME: Verify if this check is still required! - System.err.println("Warning: JAWT Lock hold, but not the AWT tree lock!"); - Thread.dumpStack(); - return null; // avoid deadlock .. } - java.awt.Point awtLOS = component.getLocationOnScreen(); - int dx = (int) ( awtLOS.getX() + .5 ) ; - int dy = (int) ( awtLOS.getY() + .5 ) ; - if(null!=storage) { - return storage.translate(dx, dy); - } - return new Point(dx, dy); + return d; } finally { unlockSurface(); + } + } + protected abstract Point getLocationOnScreenNativeImpl(int x, int y); + + protected static Point getLocationOnScreenNonBlocking(Point storage, Component comp) { + int x = 0; + int y = 0; + while(null != comp) { + x += comp.getX(); + y += comp.getY(); + comp = comp.getParent(); + } + if(null!=storage) { + storage.translate(x, y); + return storage; } + return new Point(x, y); } - protected abstract Point getLocationOnScreenImpl(int x, int y); - + + public boolean hasFocus() { + return component.hasFocus(); + } + @Override public String toString() { StringBuilder sb = new StringBuilder(); diff --git a/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java b/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java index d4f6a95d4..70fc1d62f 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java +++ b/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java @@ -41,37 +41,96 @@ package jogamp.nativewindow.jawt.macosx; import java.awt.Component; +import java.nio.Buffer; import java.security.AccessController; import java.security.PrivilegedAction; import javax.media.nativewindow.AbstractGraphicsConfiguration; +import javax.media.nativewindow.Capabilities; import javax.media.nativewindow.NativeWindow; import javax.media.nativewindow.NativeWindowException; +import javax.media.nativewindow.SurfaceChangeable; import javax.media.nativewindow.util.Point; import jogamp.nativewindow.jawt.JAWT; import jogamp.nativewindow.jawt.JAWTFactory; +import jogamp.nativewindow.jawt.JAWTUtil; import jogamp.nativewindow.jawt.JAWTWindow; import jogamp.nativewindow.jawt.JAWT_DrawingSurface; import jogamp.nativewindow.jawt.JAWT_DrawingSurfaceInfo; -// import jogamp.nativewindow.macosx.OSXUtil; - -public class MacOSXJAWTWindow extends JAWTWindow { +import jogamp.nativewindow.macosx.OSXUtil; +public class MacOSXJAWTWindow extends JAWTWindow implements SurfaceChangeable { public MacOSXJAWTWindow(Object comp, AbstractGraphicsConfiguration config) { super(comp, config); + if(DEBUG) { + dumpInfo(); + } } protected void validateNative() throws NativeWindowException { + } + + protected void invalidateNative() { + surfaceHandle=0; + if(isOffscreenLayerSurfaceEnabled()) { + if(0 != drawable) { + OSXUtil.DestroyNSWindow(drawable); + drawable = 0; + } + } } + protected void attachSurfaceLayerImpl(final long layerHandle) { + OSXUtil.AddCASublayer(rootSurfaceLayerHandle, layerHandle); + } + + protected void detachSurfaceLayerImpl(final long layerHandle) { + OSXUtil.RemoveCASublayer(rootSurfaceLayerHandle, layerHandle); + } + + public long getSurfaceHandle() { + return isOffscreenLayerSurfaceEnabled() ? surfaceHandle : super.getSurfaceHandle() ; + } + + public void setSurfaceHandle(long surfaceHandle) { + if( !isOffscreenLayerSurfaceEnabled() ) { + throw new java.lang.UnsupportedOperationException("Not using CALAYER"); + } + if(DEBUG) { + System.err.println("MacOSXJAWTWindow.setSurfaceHandle(): 0x"+Long.toHexString(surfaceHandle)); + } + sscSet &= 0 != surfaceHandle; // reset ssc flag if NULL surfaceHandle, ie. back to JAWT + this.surfaceHandle = surfaceHandle; + } + + public void surfaceSizeChanged(int width, int height) { + sscSet = true; + sscWidth = width; + sscHeight = height; + } + + public int getWidth() { + return sscSet ? sscWidth : super.getWidth(); + } + + public int getHeight() { + return sscSet ? sscHeight: super.getHeight(); + } + + protected JAWT fetchJAWTImpl() throws NativeWindowException { + // use offscreen if supported and [ applet or requested ] + return JAWTUtil.getJAWT(getShallUseOffscreenLayer() || isApplet()); + } protected int lockSurfaceImpl() throws NativeWindowException { - int ret = NativeWindow.LOCK_SUCCESS; - ds = JAWT.getJAWT().GetDrawingSurface(component); - if (ds == null) { - // Widget not yet realized - unlockSurfaceImpl(); - return NativeWindow.LOCK_SURFACE_NOT_READY; + int ret = NativeWindow.LOCK_SURFACE_NOT_READY; + if(null == ds) { + ds = getJAWT().GetDrawingSurface(component); + if (ds == null) { + // Widget not yet realized + unlockSurfaceImpl(); + return NativeWindow.LOCK_SURFACE_NOT_READY; + } } int res = ds.Lock(); dsLocked = ( 0 == ( res & JAWTFactory.JAWT_LOCK_ERROR ) ) ; @@ -87,37 +146,83 @@ public class MacOSXJAWTWindow extends JAWTWindow { if ((res & JAWTFactory.JAWT_LOCK_SURFACE_CHANGED) != 0) { ret = NativeWindow.LOCK_SURFACE_CHANGED; } - if (firstLock) { - AccessController.doPrivileged(new PrivilegedAction<Object>() { - public Object run() { - dsi = ds.GetDrawingSurfaceInfo(); - return null; - } - }); - } else { - dsi = ds.GetDrawingSurfaceInfo(); + if(null == dsi) { + if (firstLock) { + AccessController.doPrivileged(new PrivilegedAction<Object>() { + public Object run() { + dsi = ds.GetDrawingSurfaceInfo(); + return null; + } + }); + } else { + dsi = ds.GetDrawingSurfaceInfo(); + } + if (dsi == null) { + unlockSurfaceImpl(); + return NativeWindow.LOCK_SURFACE_NOT_READY; + } } - if (dsi == null) { - unlockSurfaceImpl(); - return NativeWindow.LOCK_SURFACE_NOT_READY; + updateBounds(dsi.getBounds()); + if (DEBUG && firstLock ) { + dumpInfo(); } firstLock = false; - macosxdsi = (JAWT_MacOSXDrawingSurfaceInfo) dsi.platformInfo(); - if (macosxdsi == null) { - unlockSurfaceImpl(); - return NativeWindow.LOCK_SURFACE_NOT_READY; - } - drawable = macosxdsi.getCocoaViewRef(); - - if (drawable == 0) { - unlockSurfaceImpl(); - return NativeWindow.LOCK_SURFACE_NOT_READY; + if( !isOffscreenLayerSurfaceEnabled() ) { + macosxdsi = (JAWT_MacOSXDrawingSurfaceInfo) dsi.platformInfo(getJAWT()); + if (macosxdsi == null) { + unlockSurfaceImpl(); + return NativeWindow.LOCK_SURFACE_NOT_READY; + } + drawable = macosxdsi.getCocoaViewRef(); + + if (drawable == 0) { + unlockSurfaceImpl(); + return NativeWindow.LOCK_SURFACE_NOT_READY; + } else { + ret = NativeWindow.LOCK_SUCCESS; + } } else { - updateBounds(dsi.getBounds()); + /** + * Only create a fake invisible NSWindow for the drawable handle + * to please frameworks requiring such (eg. NEWT). + * + * The actual surface/ca-layer shall be created/attached + * by the upper framework (JOGL) since they require more information. + */ + if(0 == drawable) { + drawable = OSXUtil.CreateNSWindow(0, 0, getBounds().getWidth(), getBounds().getHeight()); + if(0 == drawable) { + unlockSurfaceImpl(); + throw new NativeWindowException("Unable to created dummy NSWindow (layered case)"); + } + // fix caps reflecting offscreen! + Capabilities caps = (Capabilities) config.getChosenCapabilities().cloneMutable(); + caps.setOnscreen(false); + config.setChosenCapabilities(caps); + } + if(0 == rootSurfaceLayerHandle) { + rootSurfaceLayerHandle = OSXUtil.CreateCALayer(); + if(0 == rootSurfaceLayerHandle) { + OSXUtil.DestroyNSWindow(drawable); + drawable = 0; + unlockSurfaceImpl(); + throw new NativeWindowException("Could not create root CALayer: "+this); + } + if(!AttachJAWTSurfaceLayer(dsi, rootSurfaceLayerHandle)) { + OSXUtil.DestroyCALayer(rootSurfaceLayerHandle); + rootSurfaceLayerHandle = 0; + OSXUtil.DestroyNSWindow(drawable); + drawable = 0; + unlockSurfaceImpl(); + throw new NativeWindowException("Could not attach JAWT surfaceLayerHandle: "+this); + } + } + ret = NativeWindow.LOCK_SUCCESS; } + return ret; } - + protected void unlockSurfaceImpl() throws NativeWindowException { if(null!=ds) { if (null!=dsi) { @@ -126,30 +231,65 @@ public class MacOSXJAWTWindow extends JAWTWindow { if (dsLocked) { ds.Unlock(); } - JAWT.getJAWT().FreeDrawingSurface(ds); + getJAWT().FreeDrawingSurface(ds); } ds = null; dsi = null; - macosxdsi = null; } - protected Point getLocationOnScreenImpl(int x, int y) { - Component c = component; - while(null != c) { - x += c.getX(); - y += c.getY(); - c = c.getParent(); + private void dumpInfo() { + System.err.println("MaxOSXJAWTWindow: 0x"+Integer.toHexString(this.hashCode())+" - thread: "+Thread.currentThread().getName()); + if(null != getJAWT()) { + System.err.println("JAWT version: 0x"+Integer.toHexString(getJAWT().getCachedVersion())+ + ", CA_LAYER: "+ JAWTUtil.isJAWTUsingOffscreenLayer(getJAWT())+ + ", isLayeredSurface "+isOffscreenLayerSurfaceEnabled()+", bounds "+bounds); + } else { + System.err.println("JAWT n/a, bounds "+bounds); } - // return OSXUtil.GetLocationOnScreen(getWindowHandle(), x, y); - return new Point(x, y); + // Thread.dumpStack(); } + + /** + * {@inheritDoc} + * <p> + * On OS X locking the surface at this point (ie after creation and for location validation) + * is 'tricky' since the JVM traverses through many threads and crashes at: + * lockSurfaceImpl() { + * .. + * ds = getJAWT().GetDrawingSurface(component); + * due to a SIGSEGV. + * + * Hence we have some threading / sync issues with the native JAWT implementation. + * </p> + */ + @Override + public Point getLocationOnScreen(Point storage) { + return getLocationOnScreenNonBlocking(storage, component); + } + protected Point getLocationOnScreenNativeImpl(final int x0, final int y0) { return null; } + private static boolean AttachJAWTSurfaceLayer(JAWT_DrawingSurfaceInfo dsi, long caLayer) { + if(0==caLayer) { + throw new IllegalArgumentException("caLayer 0x"+Long.toHexString(caLayer)); + } + return AttachJAWTSurfaceLayer0(dsi.getBuffer(), caLayer); + } + + private static native boolean AttachJAWTSurfaceLayer0(Buffer jawtDrawingSurfaceInfoBuffer, long caLayer); + // Variables for lockSurface/unlockSurface private JAWT_DrawingSurface ds; private boolean dsLocked; private JAWT_DrawingSurfaceInfo dsi; + private JAWT_MacOSXDrawingSurfaceInfo macosxdsi; - + + private long rootSurfaceLayerHandle = 0; // is autoreleased, once it is attached to the JAWT_SurfaceLayer + + private long surfaceHandle = 0; + private int sscWidth, sscHeight; + private boolean sscSet = false; + // Workaround for instance of 4796548 private boolean firstLock = true; diff --git a/src/nativewindow/classes/jogamp/nativewindow/jawt/windows/WindowsJAWTWindow.java b/src/nativewindow/classes/jogamp/nativewindow/jawt/windows/WindowsJAWTWindow.java index 982b94888..adb9353ce 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/jawt/windows/WindowsJAWTWindow.java +++ b/src/nativewindow/classes/jogamp/nativewindow/jawt/windows/WindowsJAWTWindow.java @@ -47,6 +47,7 @@ import javax.media.nativewindow.util.Point; import jogamp.nativewindow.jawt.JAWT; import jogamp.nativewindow.jawt.JAWTFactory; +import jogamp.nativewindow.jawt.JAWTUtil; import jogamp.nativewindow.jawt.JAWTWindow; import jogamp.nativewindow.jawt.JAWT_DrawingSurface; import jogamp.nativewindow.jawt.JAWT_DrawingSurfaceInfo; @@ -61,15 +62,24 @@ public class WindowsJAWTWindow extends JAWTWindow { protected void validateNative() throws NativeWindowException { } - @Override - protected synchronized void invalidate() { - super.invalidate(); + protected void invalidateNative() { windowHandle = 0; } + protected void attachSurfaceLayerImpl(final long layerHandle) { + throw new UnsupportedOperationException("offscreen layer not supported"); + } + protected void detachSurfaceLayerImpl(final long layerHandle) { + throw new UnsupportedOperationException("offscreen layer not supported"); + } + + protected JAWT fetchJAWTImpl() throws NativeWindowException { + return JAWTUtil.getJAWT(false); // no offscreen + } + protected int lockSurfaceImpl() throws NativeWindowException { int ret = NativeWindow.LOCK_SUCCESS; - ds = JAWT.getJAWT().GetDrawingSurface(component); + ds = getJAWT().GetDrawingSurface(component); if (ds == null) { // Widget not yet realized unlockSurfaceImpl(); @@ -94,7 +104,8 @@ public class WindowsJAWTWindow extends JAWTWindow { unlockSurfaceImpl(); return LOCK_SURFACE_NOT_READY; } - win32dsi = (JAWT_Win32DrawingSurfaceInfo) dsi.platformInfo(); + updateBounds(dsi.getBounds()); + win32dsi = (JAWT_Win32DrawingSurfaceInfo) dsi.platformInfo(getJAWT()); if (win32dsi == null) { unlockSurfaceImpl(); return LOCK_SURFACE_NOT_READY; @@ -104,14 +115,11 @@ public class WindowsJAWTWindow extends JAWTWindow { if (windowHandle == 0 || drawable == 0) { unlockSurfaceImpl(); return LOCK_SURFACE_NOT_READY; - } else { - updateBounds(dsi.getBounds()); } return ret; } protected void unlockSurfaceImpl() throws NativeWindowException { - long startTime = 0; if(null!=ds) { if (null!=dsi) { ds.FreeDrawingSurfaceInfo(dsi); @@ -119,7 +127,7 @@ public class WindowsJAWTWindow extends JAWTWindow { if (dsLocked) { ds.Unlock(); } - JAWT.getJAWT().FreeDrawingSurface(ds); + getJAWT().FreeDrawingSurface(ds); } ds = null; dsi = null; @@ -131,7 +139,7 @@ public class WindowsJAWTWindow extends JAWTWindow { return windowHandle; } - protected Point getLocationOnScreenImpl(int x, int y) { + protected Point getLocationOnScreenNativeImpl(int x, int y) { return GDI.GetRelativeLocation( getWindowHandle(), 0 /*root win*/, x, y); } diff --git a/src/nativewindow/classes/jogamp/nativewindow/jawt/x11/X11JAWTWindow.java b/src/nativewindow/classes/jogamp/nativewindow/jawt/x11/X11JAWTWindow.java index 2319d6269..236d380d8 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/jawt/x11/X11JAWTWindow.java +++ b/src/nativewindow/classes/jogamp/nativewindow/jawt/x11/X11JAWTWindow.java @@ -48,6 +48,7 @@ import javax.media.nativewindow.util.Point; import jogamp.nativewindow.jawt.JAWT; import jogamp.nativewindow.jawt.JAWTFactory; +import jogamp.nativewindow.jawt.JAWTUtil; import jogamp.nativewindow.jawt.JAWTWindow; import jogamp.nativewindow.jawt.JAWT_DrawingSurface; import jogamp.nativewindow.jawt.JAWT_DrawingSurfaceInfo; @@ -60,7 +61,7 @@ public class X11JAWTWindow extends JAWTWindow { } protected void validateNative() throws NativeWindowException { - AWTGraphicsDevice awtDevice = (AWTGraphicsDevice) config.getScreen().getDevice(); + final AWTGraphicsDevice awtDevice = (AWTGraphicsDevice) config.getScreen().getDevice(); if(awtDevice.getHandle() != 0) { // subtype and handle set already, done @@ -85,10 +86,23 @@ public class X11JAWTWindow extends JAWTWindow { } awtDevice.setSubType(NativeWindowFactory.TYPE_X11, displayHandle); } + + protected void invalidateNative() { } + protected void attachSurfaceLayerImpl(final long layerHandle) { + throw new UnsupportedOperationException("offscreen layer not supported"); + } + protected void detachSurfaceLayerImpl(final long layerHandle) { + throw new UnsupportedOperationException("offscreen layer not supported"); + } + + protected JAWT fetchJAWTImpl() throws NativeWindowException { + return JAWTUtil.getJAWT(false); // no offscreen + } + protected int lockSurfaceImpl() throws NativeWindowException { int ret = NativeWindow.LOCK_SUCCESS; - ds = JAWT.getJAWT().GetDrawingSurface(component); + ds = getJAWT().GetDrawingSurface(component); if (ds == null) { // Widget not yet realized unlockSurfaceImpl(); @@ -113,7 +127,8 @@ public class X11JAWTWindow extends JAWTWindow { unlockSurfaceImpl(); return LOCK_SURFACE_NOT_READY; } - x11dsi = (JAWT_X11DrawingSurfaceInfo) dsi.platformInfo(); + updateBounds(dsi.getBounds()); + x11dsi = (JAWT_X11DrawingSurfaceInfo) dsi.platformInfo(getJAWT()); if (x11dsi == null) { unlockSurfaceImpl(); return LOCK_SURFACE_NOT_READY; @@ -122,8 +137,6 @@ public class X11JAWTWindow extends JAWTWindow { if (drawable == 0) { unlockSurfaceImpl(); return LOCK_SURFACE_NOT_READY; - } else { - updateBounds(dsi.getBounds()); } return ret; } @@ -136,14 +149,14 @@ public class X11JAWTWindow extends JAWTWindow { if (dsLocked) { ds.Unlock(); } - JAWT.getJAWT().FreeDrawingSurface(ds); + getJAWT().FreeDrawingSurface(ds); } ds = null; dsi = null; x11dsi = null; } - protected Point getLocationOnScreenImpl(int x, int y) { + protected Point getLocationOnScreenNativeImpl(int x, int y) { return X11Util.GetRelativeLocation( getDisplayHandle(), getScreenIndex(), getWindowHandle(), 0 /*root win*/, x, y); } diff --git a/src/nativewindow/classes/jogamp/nativewindow/jawt/x11/X11SunJDKReflection.java b/src/nativewindow/classes/jogamp/nativewindow/jawt/x11/X11SunJDKReflection.java index b576b0c6b..6dbf36612 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/jawt/x11/X11SunJDKReflection.java +++ b/src/nativewindow/classes/jogamp/nativewindow/jawt/x11/X11SunJDKReflection.java @@ -55,14 +55,14 @@ import javax.media.nativewindow.awt.AWTGraphicsConfiguration; the purposes of correctly enumerating the available visuals. */ public class X11SunJDKReflection { - private static Class x11GraphicsDeviceClass; - private static Method x11GraphicsDeviceGetDisplayMethod; - private static Class x11GraphicsConfigClass; - private static Method x11GraphicsConfigGetVisualMethod; - private static boolean initted; + private static Class<?> x11GraphicsDeviceClass; + private static Method x11GraphicsDeviceGetDisplayMethod; + private static Class<?> x11GraphicsConfigClass; + private static Method x11GraphicsConfigGetVisualMethod; + private static boolean initialized; static { - AccessController.doPrivileged(new PrivilegedAction() { + AccessController.doPrivileged(new PrivilegedAction<Object>() { public Object run() { try { x11GraphicsDeviceClass = Class.forName("sun.awt.X11GraphicsDevice"); @@ -72,7 +72,7 @@ public class X11SunJDKReflection { x11GraphicsConfigClass = Class.forName("sun.awt.X11GraphicsConfig"); x11GraphicsConfigGetVisualMethod = x11GraphicsConfigClass.getDeclaredMethod("getVisual", new Class[] {}); x11GraphicsConfigGetVisualMethod.setAccessible(true); - initted = true; + initialized = true; } catch (Exception e) { // Either not a Sun JDK or the interfaces have changed since 1.4.2 / 1.5 } @@ -82,7 +82,7 @@ public class X11SunJDKReflection { } public static long graphicsDeviceGetDisplay(GraphicsDevice device) { - if (!initted) { + if (!initialized) { return 0; } @@ -105,7 +105,7 @@ public class X11SunJDKReflection { } public static int graphicsConfigurationGetVisualID(GraphicsConfiguration config) { - if (!initted) { + if (!initialized) { return 0; } diff --git a/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java b/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java index cd558c05d..a93ab2ac1 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java +++ b/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java @@ -1,5 +1,7 @@ package jogamp.nativewindow.macosx; +import java.nio.Buffer; + import javax.media.nativewindow.NativeWindowException; import javax.media.nativewindow.util.Point; @@ -34,6 +36,42 @@ public class OSXUtil { return (Point) GetLocationOnScreen0(windowOrView, src_x, src_y); } + public static long CreateNSView(int x, int y, int width, int height) { + return CreateNSView0(x, y, width, height); + } + public static void DestroyNSView(long nsView) { + DestroyNSView0(nsView); + } + + public static long CreateNSWindow(int x, int y, int width, int height) { + return CreateNSWindow0(x, y, width, height); + } + public static void DestroyNSWindow(long nsWindow) { + DestroyNSWindow0(nsWindow); + } + + public static long CreateCALayer() { + return CreateCALayer0(); + } + public static void AddCASublayer(long rootCALayer, long subCALayer) { + if(0==rootCALayer || 0==subCALayer) { + throw new IllegalArgumentException("rootCALayer 0x"+Long.toHexString(rootCALayer)+", subCALayer 0x"+Long.toHexString(subCALayer)); + } + AddCASublayer0(rootCALayer, subCALayer); + } + public static void RemoveCASublayer(long rootCALayer, long subCALayer) { + if(0==rootCALayer || 0==subCALayer) { + throw new IllegalArgumentException("rootCALayer 0x"+Long.toHexString(rootCALayer)+", subCALayer 0x"+Long.toHexString(subCALayer)); + } + RemoveCASublayer0(rootCALayer, subCALayer); + } + public static void DestroyCALayer(long caLayer) { + if(0==caLayer) { + throw new IllegalArgumentException("caLayer 0x"+Long.toHexString(caLayer)); + } + DestroyCALayer0(caLayer); + } + public static void RunOnMainThread(boolean waitUntilDone, Runnable runnable) { if(IsMainThread0()) { runnable.run(); // don't leave the JVM @@ -48,6 +86,14 @@ public class OSXUtil { private static native boolean initIDs0(); private static native Object GetLocationOnScreen0(long windowOrView, int src_x, int src_y); + private static native long CreateNSView0(int x, int y, int width, int height); + private static native void DestroyNSView0(long nsView); + private static native long CreateNSWindow0(int x, int y, int width, int height); + private static native void DestroyNSWindow0(long nsWindow); + private static native long CreateCALayer0(); + private static native void AddCASublayer0(long rootCALayer, long subCALayer); + private static native void RemoveCASublayer0(long rootCALayer, long subCALayer); + private static native void DestroyCALayer0(long caLayer); private static native void RunOnMainThread0(boolean waitUntilDone, Runnable runnable); private static native boolean IsMainThread0(); } diff --git a/src/nativewindow/classes/jogamp/nativewindow/x11/X11GraphicsConfigurationFactory.java b/src/nativewindow/classes/jogamp/nativewindow/x11/X11GraphicsConfigurationFactory.java index b669bce75..910e564af 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/x11/X11GraphicsConfigurationFactory.java +++ b/src/nativewindow/classes/jogamp/nativewindow/x11/X11GraphicsConfigurationFactory.java @@ -33,8 +33,14 @@ package jogamp.nativewindow.x11; -import javax.media.nativewindow.*; -import javax.media.nativewindow.x11.*; +import javax.media.nativewindow.AbstractGraphicsConfiguration; +import javax.media.nativewindow.AbstractGraphicsScreen; +import javax.media.nativewindow.CapabilitiesChooser; +import javax.media.nativewindow.CapabilitiesImmutable; +import javax.media.nativewindow.GraphicsConfigurationFactory; +import javax.media.nativewindow.NativeWindowException; +import javax.media.nativewindow.x11.X11GraphicsConfiguration; +import javax.media.nativewindow.x11.X11GraphicsScreen; public class X11GraphicsConfigurationFactory extends GraphicsConfigurationFactory { protected AbstractGraphicsConfiguration chooseGraphicsConfigurationImpl( diff --git a/src/nativewindow/native/macosx/OSXmisc.m b/src/nativewindow/native/macosx/OSXmisc.m index e19d5ecf7..d7a2feff3 100644 --- a/src/nativewindow/native/macosx/OSXmisc.m +++ b/src/nativewindow/native/macosx/OSXmisc.m @@ -35,6 +35,19 @@ #include "NativewindowCommon.h" #include "jogamp_nativewindow_macosx_OSXUtil.h" +#include "jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow.h" + +#include <jawt_md.h> +#import <JavaNativeFoundation.h> + +// #define VERBOSE 1 +// +#ifdef VERBOSE + // #define DBG_PRINT(...) NSLog(@ ## __VA_ARGS__) + #define DBG_PRINT(...) fprintf(stderr, __VA_ARGS__); fflush(stderr) +#else + #define DBG_PRINT(...) +#endif static const char * const ClazzNameRunnable = "java/lang/Runnable"; static jmethodID runnableRunID = NULL; @@ -81,7 +94,7 @@ Java_jogamp_nativewindow_macosx_OSXUtil_initIDs0(JNIEnv *env, jclass _unused) { /* * Class: Java_jogamp_nativewindow_macosx_OSXUtil - * Method: getLocationOnScreenImpl0 + * Method: getLocationOnScreen0 * Signature: (JII)Ljavax/media/nativewindow/util/Point; */ JNIEXPORT jobject JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetLocationOnScreen0 @@ -97,7 +110,7 @@ JNIEXPORT jobject JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetLocationOnS int dest_x=-1; int dest_y=-1; - NSObject *nsObj = (NSObject*) ((intptr_t) winOrView); + NSObject *nsObj = (NSObject*) (intptr_t) winOrView; NSWindow* win = NULL; NSView* view = NULL; @@ -135,6 +148,182 @@ JNIEXPORT jobject JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetLocationOnS return res; } +/* + * Class: Java_jogamp_nativewindow_macosx_OSXUtil + * Method: CreateNSView0 + * Signature: (IIIIZ)J + */ +JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_CreateNSView0 + (JNIEnv *env, jclass unused, jint x, jint y, jint width, jint height) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + NSRect rect = NSMakeRect(x, y, width, height); + NSView * view = [[NSView alloc] initWithFrame: rect] ; + [view setCanDrawConcurrently: YES]; + [pool release]; + + return (jlong) (intptr_t) view; +} + +/* + * Class: Java_jogamp_nativewindow_macosx_OSXUtil + * Method: DestroyNSView0 + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_DestroyNSView0 + (JNIEnv *env, jclass unused, jlong nsView) +{ + NSView* view = (NSView*) (intptr_t) nsView; + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + [view release]; + [pool release]; +} + +/* + * Class: Java_jogamp_nativewindow_macosx_OSXUtil + * Method: CreateNSWindow0 + * Signature: (IIIIZ)J + */ +JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_CreateNSWindow0 + (JNIEnv *env, jclass unused, jint x, jint y, jint width, jint height) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + NSRect rect = NSMakeRect(x, y, width, height); + + // Allocate the window + NSWindow* myWindow = [[NSWindow alloc] initWithContentRect: rect + styleMask: NSBorderlessWindowMask + backing: NSBackingStoreBuffered + defer: YES]; + [myWindow setReleasedWhenClosed: YES]; // default + [myWindow setPreservesContentDuringLiveResize: YES]; + + // invisible .. + [myWindow setOpaque: NO]; + [myWindow setBackgroundColor: [NSColor clearColor]]; + + // force surface creation + // [myView lockFocus]; + // [myView unlockFocus]; + + [pool release]; + + return (jlong) ((intptr_t) myWindow); +} + +/* + * Class: Java_jogamp_nativewindow_macosx_OSXUtil + * Method: DestroyNSWindow0 + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_DestroyNSWindow0 + (JNIEnv *env, jclass unused, jlong nsWindow) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + NSWindow* mWin = (NSWindow*) ((intptr_t) nsWindow); + NSView* mView = [mWin contentView]; + + if(NULL!=mView) { + [mWin setContentView: nil]; + [mView release]; + } + [mWin orderOut: mWin]; + [mWin close]; // performs release! + [pool release]; +} + +/* + * Class: Java_jogamp_nativewindow_macosx_OSXUtil + * Method: CreateCALayer0 + * Signature: (V)J + */ +JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_CreateCALayer0 + (JNIEnv *env, jclass unused) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + + // CALayer* layer = [[CALayer alloc] init]; + CALayer* layer = [CALayer layer]; + + // initial dummy size ! + CGRect lRect = [layer frame]; + lRect.origin.x = 0; + lRect.origin.y = 0; + lRect.size.width = 32; + lRect.size.height = 32; + [layer setFrame: lRect]; + DBG_PRINT("CALayer::CreateCALayer0: %p %lf/%lf %lfx%lf\n", layer, lRect.origin.x, lRect.origin.y, lRect.size.width, lRect.size.height); + + [pool release]; + + return (jlong) ((intptr_t) layer); +} + +/* + * Class: Java_jogamp_nativewindow_macosx_OSXUtil + * Method: AddCASublayer0 + * Signature: (JJ)V + */ +JNIEXPORT void JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_AddCASublayer0 + (JNIEnv *env, jclass unused, jlong rootCALayer, jlong subCALayer) +{ + JNF_COCOA_ENTER(env); + CALayer* rootLayer = (CALayer*) ((intptr_t) rootCALayer); + CALayer* subLayer = (CALayer*) ((intptr_t) subCALayer); + + CGRect lRectRoot = [rootLayer frame]; + // simple 1:1 layout ! + [subLayer setFrame:lRectRoot]; + DBG_PRINT("CALayer::AddCASublayer0.0: %p . %p %lf/%lf %lfx%lf (refcnt %d)\n", + rootLayer, subLayer, lRectRoot.origin.x, lRectRoot.origin.y, lRectRoot.size.width, lRectRoot.size.height, (int)[subLayer retainCount]); + [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){ + [rootLayer addSublayer:subLayer]; + }]; + DBG_PRINT("CALayer::AddCASublayer0.X: %p . %p (refcnt %d)\n", rootLayer, subLayer, (int)[subLayer retainCount]); + JNF_COCOA_EXIT(env); +} + +/* + * Class: Java_jogamp_nativewindow_macosx_OSXUtil + * Method: RemoveCASublayer0 + * Signature: (JJ)V + */ +JNIEXPORT void JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_RemoveCASublayer0 + (JNIEnv *env, jclass unused, jlong rootCALayer, jlong subCALayer) +{ + JNF_COCOA_ENTER(env); + CALayer* rootLayer = (CALayer*) ((intptr_t) rootCALayer); + CALayer* subLayer = (CALayer*) ((intptr_t) subCALayer); + + (void)rootLayer; // no warnings + + DBG_PRINT("CALayer::RemoveCASublayer0.0: %p . %p (refcnt %d)\n", rootLayer, subLayer, (int)[subLayer retainCount]); + [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){ + [subLayer removeFromSuperlayer]; + }]; + DBG_PRINT("CALayer::RemoveCASublayer0.X: %p . %p (refcnt %d)\n", rootLayer, subLayer, (int)[subLayer retainCount]); + JNF_COCOA_EXIT(env); +} + +/* + * Class: Java_jogamp_nativewindow_macosx_OSXUtil + * Method: DestroyCALayer0 + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_DestroyCALayer0 + (JNIEnv *env, jclass unused, jlong caLayer) +{ + JNF_COCOA_ENTER(env); + CALayer* layer = (CALayer*) ((intptr_t) caLayer); + + DBG_PRINT("CALayer::DestroyCALayer0.0: %p (refcnt %d)\n", layer, (int)[layer retainCount]); + [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){ + [layer release]; // performs release! + }]; + DBG_PRINT("CALayer::DestroyCALayer0.X: %p (refcnt %d)\n", layer, (int)[layer retainCount]); + JNF_COCOA_EXIT(env); +} + @interface MainRunnable : NSObject { @@ -212,10 +401,35 @@ JNIEXPORT void JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_RunOnMainThread0 /* * Class: Java_jogamp_nativewindow_macosx_OSXUtil * Method: RunOnMainThread0 - * Signature: (ZLjava/lang/Runnable;)V + * Signature: (V)V */ JNIEXPORT jboolean JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_IsMainThread0 (JNIEnv *env, jclass unused) { return ( [NSThread isMainThread] == YES ) ? JNI_TRUE : JNI_FALSE ; } + +/* + * Class: Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow + * Method: AttachJAWTSurfaceLayer + * Signature: (JJ)Z + */ +JNIEXPORT jboolean JNICALL Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow_AttachJAWTSurfaceLayer0 + (JNIEnv *env, jclass unused, jobject jawtDrawingSurfaceInfoBuffer, jlong caLayer) +{ + JNF_COCOA_ENTER(env); + JAWT_DrawingSurfaceInfo* dsi = (JAWT_DrawingSurfaceInfo*) (*env)->GetDirectBufferAddress(env, jawtDrawingSurfaceInfoBuffer); + if (NULL == dsi) { + NativewindowCommon_throwNewRuntimeException(env, "Argument \"jawtDrawingSurfaceInfoBuffer\" was not a direct buffer"); + return JNI_FALSE; + } + CALayer* layer = (CALayer*) (intptr_t) caLayer; + [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){ + id <JAWT_SurfaceLayers> surfaceLayers = (id <JAWT_SurfaceLayers>)dsi->platformInfo; + DBG_PRINT("CALayer::attachJAWTSurfaceLayer: %p -> %p\n", surfaceLayers.layer, layer); + surfaceLayers.layer = [layer autorelease]; + }]; + JNF_COCOA_EXIT(env); + return JNI_TRUE; +} + |