summaryrefslogtreecommitdiffstats
path: root/src/nativewindow/classes
diff options
context:
space:
mode:
Diffstat (limited to 'src/nativewindow/classes')
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/awt/AWTWindowClosingProtocol.java85
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java27
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java19
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/NativeWindow.java3
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerSurface.java23
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/WindowClosingProtocol.java4
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java69
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java153
8 files changed, 310 insertions, 73 deletions
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/awt/AWTWindowClosingProtocol.java b/src/nativewindow/classes/com/jogamp/nativewindow/awt/AWTWindowClosingProtocol.java
index d78b4ac15..e3f85b948 100644
--- a/src/nativewindow/classes/com/jogamp/nativewindow/awt/AWTWindowClosingProtocol.java
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/awt/AWTWindowClosingProtocol.java
@@ -33,22 +33,31 @@ import java.awt.Window;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
+
import javax.media.nativewindow.WindowClosingProtocol;
+import jogamp.common.awt.AWTEDTExecutor;
import jogamp.nativewindow.awt.AWTMisc;
public class AWTWindowClosingProtocol implements WindowClosingProtocol {
private Component comp;
- private Runnable closingOperation;
- private volatile boolean closingListenerSet = false;
+ private Runnable closingOperationClose;
+ private Runnable closingOperationNOP;
+ private boolean closingListenerSet = false;
private Object closingListenerLock = new Object();
private WindowClosingMode defaultCloseOperation = WindowClosingMode.DISPOSE_ON_CLOSE;
private boolean defaultCloseOperationSetByUser = false;
- public AWTWindowClosingProtocol(Component comp, Runnable closingOperation) {
+ /**
+ * @param comp mandatory AWT component which AWT Window is being queried by parent traversal
+ * @param closingOperationClose mandatory closing operation, triggered if windowClosing and {@link WindowClosingMode#DISPOSE_ON_CLOSE}
+ * @param closingOperationNOP optional closing operation, triggered if windowClosing and {@link WindowClosingMode#DO_NOTHING_ON_CLOSE}
+ */
+ public AWTWindowClosingProtocol(Component comp, Runnable closingOperationClose, Runnable closingOperationNOP) {
this.comp = comp;
- this.closingOperation = closingOperation;
+ this.closingOperationClose = closingOperationClose;
+ this.closingOperationNOP = closingOperationNOP;
}
class WindowClosingAdapter extends WindowAdapter {
@@ -59,54 +68,56 @@ public class AWTWindowClosingProtocol implements WindowClosingProtocol {
if( WindowClosingMode.DISPOSE_ON_CLOSE == op ) {
// we have to issue this call right away,
// otherwise the window gets destroyed
- closingOperation.run();
+ closingOperationClose.run();
+ } else if( null != closingOperationNOP ){
+ closingOperationNOP.run();
}
}
}
WindowListener windowClosingAdapter = new WindowClosingAdapter();
- final boolean addClosingListenerImpl() {
- Window w = AWTMisc.getWindow(comp);
- if(null!=w) {
- w.addWindowListener(windowClosingAdapter);
- return true;
- }
- return false;
- }
-
/**
- * Adds this closing listener to the components Window if exist and only one time.<br>
- * Hence you may call this method every time to ensure it has been set,
- * ie in case the Window parent is not available yet.
+ * Adds this closing listener to the components Window if exist and only one time.
+ * <p>
+ * If the closing listener is already added, and {@link IllegalStateException} is thrown.
+ * </p>
*
- * @return
+ * @return true if added, otherwise false.
+ * @throws IllegalStateException
*/
- public final boolean addClosingListenerOneShot() {
- if(!closingListenerSet) { // volatile: ok
+ public final boolean addClosingListener() throws IllegalStateException {
synchronized(closingListenerLock) {
- if(!closingListenerSet) {
- closingListenerSet=addClosingListenerImpl();
- return closingListenerSet;
- }
+ if(closingListenerSet) {
+ throw new IllegalStateException("WindowClosingListener already set");
+ }
+ final Window w = AWTMisc.getWindow(comp);
+ if(null!=w) {
+ AWTEDTExecutor.singleton.invoke(true, new Runnable() {
+ public void run() {
+ w.addWindowListener(windowClosingAdapter);
+ } } );
+ closingListenerSet = true;
+ return true;
+ }
}
- }
- return false;
+ return false;
}
public final boolean removeClosingListener() {
- if(closingListenerSet) { // volatile: ok
synchronized(closingListenerLock) {
- if(closingListenerSet) {
- Window w = AWTMisc.getWindow(comp);
- if(null!=w) {
- w.removeWindowListener(windowClosingAdapter);
- closingListenerSet = false;
- return true;
- }
- }
+ if(closingListenerSet) {
+ final Window w = AWTMisc.getWindow(comp);
+ if(null!=w) {
+ AWTEDTExecutor.singleton.invoke(true, new Runnable() {
+ public void run() {
+ w.removeWindowListener(windowClosingAdapter);
+ } } );
+ closingListenerSet = false;
+ return true;
+ }
+ }
}
- }
- return false;
+ return false;
}
/**
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java b/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java
index 8527a0200..d65f8c231 100644
--- a/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java
@@ -130,7 +130,7 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface,
if(changed) {
if(DEBUG) {
System.err.println("JAWTWindow.updateBounds: "+bounds+" -> "+jb);
- Thread.dumpStack();
+ // Thread.dumpStack();
}
bounds.setX(jawtBounds.getX());
bounds.setY(jawtBounds.getY());
@@ -205,7 +205,7 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface,
}
try {
if(DEBUG) {
- System.err.println("JAWTWindow.attachSurfaceHandle(): 0x"+Long.toHexString(layerHandle) + ", bounds "+bounds);
+ System.err.println("JAWTWindow.attachSurfaceHandle: "+toHexString(layerHandle) + ", bounds "+bounds);
}
attachSurfaceLayerImpl(layerHandle);
offscreenSurfaceLayer = layerHandle;
@@ -216,6 +216,17 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface,
protected abstract void attachSurfaceLayerImpl(final long layerHandle);
@Override
+ public void layoutSurfaceLayer() throws NativeWindowException {
+ if( !isOffscreenLayerSurfaceEnabled() ) {
+ throw new NativeWindowException("Not an offscreen layer surface");
+ }
+ if( 0 != offscreenSurfaceLayer) {
+ layoutSurfaceLayerImpl();
+ }
+ }
+ protected void layoutSurfaceLayerImpl() {}
+
+ @Override
public final void detachSurfaceLayer() throws NativeWindowException {
if( !isOffscreenLayerSurfaceEnabled() ) {
throw new java.lang.UnsupportedOperationException("Not an offscreen layer surface");
@@ -229,7 +240,7 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface,
}
try {
if(DEBUG) {
- System.err.println("JAWTWindow.detachSurfaceHandle(): 0x"+Long.toHexString(offscreenSurfaceLayer));
+ System.err.println("JAWTWindow.detachSurfaceHandle(): osh "+toHexString(offscreenSurfaceLayer));
}
detachSurfaceLayerImpl(offscreenSurfaceLayer);
offscreenSurfaceLayer = 0;
@@ -341,7 +352,7 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface,
if(LOCK_SUCCESS == res && drawable_old != drawable) {
res = LOCK_SURFACE_CHANGED;
if(DEBUG) {
- System.err.println("JAWTWindow: surface change 0x"+Long.toHexString(drawable_old)+" -> 0x"+Long.toHexString(drawable));
+ System.err.println("JAWTWindow: surface change "+toHexString(drawable_old)+" -> "+toHexString(drawable));
// Thread.dumpStack();
}
}
@@ -549,8 +560,8 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface,
StringBuilder sb = new StringBuilder();
sb.append("JAWT-Window["+
- "windowHandle 0x"+Long.toHexString(getWindowHandle())+
- ", surfaceHandle 0x"+Long.toHexString(getSurfaceHandle())+
+ "windowHandle "+toHexString(getWindowHandle())+
+ ", surfaceHandle "+toHexString(getSurfaceHandle())+
", bounds "+bounds+", insets "+insets+
", shallUseOffscreenLayer "+shallUseOffscreenLayer+", isOffscreenLayerSurface "+isOffscreenLayerSurface);
if(null!=component) {
@@ -566,4 +577,8 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface,
return sb.toString();
}
+
+ protected final String toHexString(long l) {
+ return "0x"+Long.toHexString(l);
+ }
}
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java b/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java
index 2b49f6745..5c4fd82d2 100644
--- a/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java
@@ -38,7 +38,6 @@ import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Control;
import javax.media.nativewindow.AbstractGraphicsScreen;
-import javax.media.nativewindow.DefaultGraphicsScreen;
import javax.media.nativewindow.NativeWindowException;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.NativeWindowFactory;
@@ -49,7 +48,6 @@ import com.jogamp.common.util.VersionNumber;
import com.jogamp.nativewindow.macosx.MacOSXGraphicsDevice;
import com.jogamp.nativewindow.windows.WindowsGraphicsDevice;
import com.jogamp.nativewindow.x11.X11GraphicsDevice;
-import com.jogamp.nativewindow.x11.X11GraphicsScreen;
import jogamp.nativewindow.macosx.OSXUtil;
import jogamp.nativewindow.x11.X11Lib;
@@ -484,6 +482,23 @@ public class SWTAccessor {
}
}
+ /**
+ * Runs the specified action on the SWT UI thread.
+ * <p>
+ * If <code>display</code> is disposed or the current thread is the SWT UI thread
+ * {@link #invoke(boolean, Runnable)} is being used.
+ * @see #invoke(boolean, Runnable)
+ */
+ public static void invoke(org.eclipse.swt.widgets.Display display, boolean wait, Runnable runnable) {
+ if( display.isDisposed() || Thread.currentThread() == display.getThread() ) {
+ invoke(wait, runnable);
+ } else if( wait ) {
+ display.syncExec(runnable);
+ } else {
+ display.asyncExec(runnable);
+ }
+ }
+
//
// Specific X11 GTK ChildWindow - Using plain X11 native parenting (works well)
//
diff --git a/src/nativewindow/classes/javax/media/nativewindow/NativeWindow.java b/src/nativewindow/classes/javax/media/nativewindow/NativeWindow.java
index 12e202975..a740ebbe0 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/NativeWindow.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/NativeWindow.java
@@ -54,8 +54,7 @@ import javax.media.nativewindow.util.Point;
public interface NativeWindow extends NativeSurface {
/**
- * destroys the window and releases
- * windowing related resources.
+ * Destroys this window incl. releasing all related resources.
*/
public void destroy();
diff --git a/src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerSurface.java b/src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerSurface.java
index f6bc5822b..4885d5a4c 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerSurface.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerSurface.java
@@ -33,11 +33,34 @@ package javax.media.nativewindow;
public interface OffscreenLayerSurface {
/**
* Attach the offscreen layer to this offscreen layer surface.
+ * <p>
+ * Implementation may realize all required resources at this point.
+ * </p>
+ * <p>
+ * It is mandatory that any related resources, e.g. a shared context,
+ * are not locked while calling this method.
+ * </p>
+ *
* @see #isOffscreenLayerSurfaceEnabled()
* @throws NativeWindowException if {@link #isOffscreenLayerSurfaceEnabled()} == false
*/
public void attachSurfaceLayer(final long layerHandle) throws NativeWindowException;
+ /**
+ * Layout the offscreen layer according to the implementing class's constraints.
+ * <p>
+ * This method allows triggering a re-layout of the offscreen surface
+ * in case the implementation requires it.
+ * </p>
+ * <p>
+ * Call this method if any parent or ancestor's layout has been changed,
+ * which could affects the layout of this surface.
+ * </p>
+ * @see #isOffscreenLayerSurfaceEnabled()
+ * @throws NativeWindowException if {@link #isOffscreenLayerSurfaceEnabled()} == false
+ */
+ public void layoutSurfaceLayer() throws NativeWindowException;
+
/**
* Detaches a previously attached offscreen layer from this offscreen layer surface.
* @see #attachSurfaceLayer(long)
diff --git a/src/nativewindow/classes/javax/media/nativewindow/WindowClosingProtocol.java b/src/nativewindow/classes/javax/media/nativewindow/WindowClosingProtocol.java
index 884c916e4..02f68f442 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/WindowClosingProtocol.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/WindowClosingProtocol.java
@@ -37,6 +37,10 @@ package javax.media.nativewindow;
* this protocol default behavior {@link WindowClosingMode#DISPOSE_ON_CLOSE DISPOSE_ON_CLOSE} shall be used.</p>
*/
public interface WindowClosingProtocol {
+
+ /**
+ * Window closing mode if triggered by toolkit close operation.
+ */
public enum WindowClosingMode {
/**
* Do nothing on native window close operation.<br>
diff --git a/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java b/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java
index 9e270d403..3ec54ca78 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java
@@ -51,6 +51,7 @@ import javax.media.nativewindow.NativeWindowException;
import javax.media.nativewindow.MutableSurface;
import javax.media.nativewindow.util.Point;
+import com.jogamp.common.util.Function;
import com.jogamp.nativewindow.awt.JAWTWindow;
import jogamp.nativewindow.jawt.JAWT;
@@ -70,11 +71,40 @@ public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface {
}
protected void invalidateNative() {
+ if(DEBUG) {
+ System.err.println("MacOSXJAWTWindow.invalidateNative(): osh-enabled "+isOffscreenLayerSurfaceEnabled()+
+ ", osh-set "+offscreenSurfaceHandleSet+
+ ", osh "+toHexString(offscreenSurfaceHandle)+
+ ", rsh "+toHexString(rootSurfaceLayerHandle)+
+ ", wh "+toHexString(windowHandle));
+ }
offscreenSurfaceHandle=0;
offscreenSurfaceHandleSet=false;
- if(isOffscreenLayerSurfaceEnabled()) {
+ if( isOffscreenLayerSurfaceEnabled() ) {
if(0 != rootSurfaceLayerHandle) {
+ final JAWT jawt = getJAWT();
+ if( null != jawt ) {
+ final JAWT_DrawingSurface ds = jawt.GetDrawingSurface(component);
+ if (ds != null) {
+ if ( 0 == ( ds.Lock() & JAWTFactory.JAWT_LOCK_ERROR ) ) {
+ JAWT_DrawingSurfaceInfo dsi = null;
+ try {
+ dsi = ds.GetDrawingSurfaceInfo();
+ if(! UnsetJAWTRootSurfaceLayer(dsi.getBuffer(), rootSurfaceLayerHandle)) {
+ System.err.println("Error clearing JAWT rootSurfaceLayerHandle "+toHexString(rootSurfaceLayerHandle));
+ }
+ } finally {
+ if ( null != dsi ) {
+ ds.FreeDrawingSurfaceInfo(dsi);
+ }
+ ds.Unlock();
+ }
+ }
+ jawt.FreeDrawingSurface(ds);
+ }
+ }
OSXUtil.DestroyCALayer(rootSurfaceLayerHandle);
+
rootSurfaceLayerHandle = 0;
}
if(0 != windowHandle) {
@@ -88,10 +118,20 @@ public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface {
OSXUtil.AddCASublayer(rootSurfaceLayerHandle, layerHandle);
}
+ protected void layoutSurfaceLayerImpl() {
+ final long osl = getAttachedSurfaceLayer();
+ final int w = getWidth();
+ final int h = getHeight();
+ if(DEBUG) {
+ System.err.println("JAWTWindow.fixSurfaceLayerLayout: "+toHexString(osl) + ", bounds "+bounds+", "+w+"x"+h);
+ }
+ OSXUtil.FixCALayerLayout(rootSurfaceLayerHandle, osl, w, h);
+ }
+
protected void detachSurfaceLayerImpl(final long layerHandle) {
OSXUtil.RemoveCASublayer(rootSurfaceLayerHandle, layerHandle);
}
-
+
@Override
public final long getWindowHandle() {
return windowHandle;
@@ -107,7 +147,7 @@ public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface {
throw new java.lang.UnsupportedOperationException("Not using CALAYER");
}
if(DEBUG) {
- System.err.println("MacOSXJAWTWindow.setSurfaceHandle(): 0x"+Long.toHexString(surfaceHandle));
+ System.err.println("MacOSXJAWTWindow.setSurfaceHandle(): "+toHexString(surfaceHandle));
}
this.offscreenSurfaceHandle = surfaceHandle;
this.offscreenSurfaceHandleSet = true;
@@ -117,6 +157,7 @@ public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface {
// use offscreen if supported and [ applet or requested ]
return JAWTUtil.getJAWT(getShallUseOffscreenLayer() || isApplet());
}
+
protected int lockSurfaceImpl() throws NativeWindowException {
int ret = NativeWindow.LOCK_SURFACE_NOT_READY;
ds = getJAWT().GetDrawingSurface(component);
@@ -189,7 +230,7 @@ public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface {
} else {
drawable = OSXUtil.GetNSView(windowHandle);
if(0 == drawable) {
- errMsg = "Null NSView of NSWindow 0x"+Long.toHexString(windowHandle);
+ errMsg = "Null NSView of NSWindow "+toHexString(windowHandle);
}
}
if(null == errMsg) {
@@ -204,8 +245,8 @@ public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface {
rootSurfaceLayerHandle = OSXUtil.CreateCALayer(bounds.getX(), bounds.getY(), bounds.getWidth(), bounds.getHeight());
if(0 == rootSurfaceLayerHandle) {
errMsg = "Could not create root CALayer";
- } else if(!SetJAWTRootSurfaceLayer0(dsi.getBuffer(), rootSurfaceLayerHandle)) {
- errMsg = "Could not set JAWT rootSurfaceLayerHandle 0x"+Long.toHexString(rootSurfaceLayerHandle);
+ } else if(!SetJAWTRootSurfaceLayer(dsi.getBuffer(), rootSurfaceLayerHandle)) {
+ errMsg = "Could not set JAWT rootSurfaceLayerHandle "+toHexString(rootSurfaceLayerHandle);
}
}
}
@@ -265,9 +306,23 @@ public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface {
return getLocationOnScreenNonBlocking(storage, component);
}
protected Point getLocationOnScreenNativeImpl(final int x0, final int y0) { return null; }
+
+ private static boolean SetJAWTRootSurfaceLayer(final Buffer jawtDrawingSurfaceInfoBuffer, final long caLayer) {
+ return OSXUtil.RunOnMainThread(true, new Function<Boolean, Object>() {
+ public Boolean eval(Object... args) {
+ return Boolean.valueOf( SetJAWTRootSurfaceLayer0(jawtDrawingSurfaceInfoBuffer, caLayer) );
+ } } ).booleanValue();
+ }
+
+ private static boolean UnsetJAWTRootSurfaceLayer(final Buffer jawtDrawingSurfaceInfoBuffer, final long caLayer) {
+ return OSXUtil.RunOnMainThread(true, new Function<Boolean, Object>() {
+ public Boolean eval(Object... args) {
+ return Boolean.valueOf( UnsetJAWTRootSurfaceLayer0(jawtDrawingSurfaceInfoBuffer, caLayer) );
+ } } ).booleanValue();
+ }
private static native boolean SetJAWTRootSurfaceLayer0(Buffer jawtDrawingSurfaceInfoBuffer, long caLayer);
- // private static native boolean UnsetJAWTRootSurfaceLayer0(Buffer jawtDrawingSurfaceInfoBuffer, long caLayer);
+ private static native boolean UnsetJAWTRootSurfaceLayer0(Buffer jawtDrawingSurfaceInfoBuffer, long caLayer);
// Variables for lockSurface/unlockSurface
private JAWT_DrawingSurface ds;
diff --git a/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java b/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java
index f06f97064..aa44e2d64 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java
@@ -32,6 +32,8 @@ import javax.media.nativewindow.NativeWindowFactory;
import javax.media.nativewindow.util.Insets;
import javax.media.nativewindow.util.Point;
+import com.jogamp.common.util.Function;
+import com.jogamp.common.util.FunctionTask;
import com.jogamp.common.util.RunnableTask;
import jogamp.nativewindow.Debug;
@@ -134,26 +136,94 @@ public class OSXUtil implements ToolkitProperties {
return GetNSWindow0(nsView);
}
- public static long CreateCALayer(int x, int y, int width, int height) {
- return CreateCALayer0(x, y, width, height);
+ /**
+ * Create a CALayer suitable to act as a root CALayer on the main-thread.
+ * @see #DestroyCALayer(long)
+ * @see #AddCASublayer(long, long)
+ */
+ public static long CreateCALayer(final int x, final int y, final int width, final int height) {
+ return OSXUtil.RunOnMainThread(true, new Function<Long, Object>() {
+ public Long eval(Object... args) {
+ return Long.valueOf( CreateCALayer0(x, y, width, height) );
+ } } ).longValue();
}
- public static void AddCASublayer(long rootCALayer, long subCALayer) {
+
+ /**
+ * Attach a sub CALayer to the root CALayer on the main-thread w/ blocking.
+ * <p>
+ * Method will trigger a <code>display</code>
+ * call to the CALayer hierarchy to enforce resource creation if required, e.g. an NSOpenGLContext.
+ * </p>
+ * <p>
+ * It is mandatory that any related resources, e.g. a shared NSOpenGLContext,
+ * are not locked while calling this method.
+ * </p>
+ * @see #CreateCALayer(int, int, int, int)
+ * @see #RemoveCASublayer(long, long)
+ */
+ public static void AddCASublayer(final long rootCALayer, final long subCALayer) {
if(0==rootCALayer || 0==subCALayer) {
throw new IllegalArgumentException("rootCALayer 0x"+Long.toHexString(rootCALayer)+", subCALayer 0x"+Long.toHexString(subCALayer));
}
- AddCASublayer0(rootCALayer, subCALayer);
+ RunOnMainThread(true, new Runnable() {
+ public void run() {
+ AddCASublayer0(rootCALayer, subCALayer);
+ }
+ });
+ }
+
+ /**
+ * Fix root and sub CALayer position to 0/0 and size on the main-thread w/o blocking.
+ * <p>
+ * If the sub CALayer implements the Objective-C NativeWindow protocol NWDedicatedSize (e.g. JOGL's MyNSOpenGLLayer),
+ * the dedicated size is passed to the layer, which propagates it appropriately.
+ * </p>
+ * <p>
+ * On OSX/Java7 our root CALayer's frame position and size gets corrupted by its NSView,
+ * hence we have created the NWDedicatedSize protocol.
+ * </p>
+ *
+ * @param rootCALayer the root surface layer, maybe null.
+ * @param subCALayer the client surface layer, maybe null.
+ * @param width the expected width
+ * @param height the expected height
+ */
+ public static void FixCALayerLayout(final long rootCALayer, final long subCALayer, final int width, final int height) {
+ if( 0==rootCALayer && 0==subCALayer ) {
+ return;
+ }
+ RunOnMainThread(false, new Runnable() {
+ public void run() {
+ FixCALayerLayout0(rootCALayer, subCALayer, width, height);
+ }
+ });
}
- public static void RemoveCASublayer(long rootCALayer, long subCALayer) {
+
+ /**
+ * Detach a sub CALayer from the root CALayer on the main-thread w/ blocking.
+ */
+ public static void RemoveCASublayer(final long rootCALayer, final long subCALayer) {
if(0==rootCALayer || 0==subCALayer) {
throw new IllegalArgumentException("rootCALayer 0x"+Long.toHexString(rootCALayer)+", subCALayer 0x"+Long.toHexString(subCALayer));
}
- RemoveCASublayer0(rootCALayer, subCALayer);
+ RunOnMainThread(true, new Runnable() {
+ public void run() {
+ RemoveCASublayer0(rootCALayer, subCALayer);
+ } } );
}
- public static void DestroyCALayer(long caLayer) {
+
+ /**
+ * Destroy a CALayer on the main-thread w/ blocking.
+ * @see #CreateCALayer(int, int, int, int)
+ */
+ public static void DestroyCALayer(final long caLayer) {
if(0==caLayer) {
throw new IllegalArgumentException("caLayer 0x"+Long.toHexString(caLayer));
}
- DestroyCALayer0(caLayer);
+ RunOnMainThread(true, new Runnable() {
+ public void run() {
+ DestroyCALayer0(caLayer);
+ } } );
}
/**
@@ -169,14 +239,14 @@ public class OSXUtil implements ToolkitProperties {
if( IsMainThread0() ) {
runnable.run(); // don't leave the JVM
} else {
- if( waitUntilDone ) {
- // Utilize Java side lock/wait and simply pass the Runnable async to OSX main thread,
- // otherwise we may freeze the OSX main thread.
- Throwable throwable = null;
- final Object sync = new Object();
- final RunnableTask rt = new RunnableTask( runnable, sync, true );
- synchronized(sync) {
- RunOnMainThread0(rt);
+ // Utilize Java side lock/wait and simply pass the Runnable async to OSX main thread,
+ // otherwise we may freeze the OSX main thread.
+ Throwable throwable = null;
+ final Object sync = new Object();
+ final RunnableTask rt = new RunnableTask( runnable, waitUntilDone ? sync : null, true );
+ synchronized(sync) {
+ RunOnMainThread0(rt);
+ if( waitUntilDone ) {
try {
sync.wait();
} catch (InterruptedException ie) {
@@ -188,10 +258,54 @@ public class OSXUtil implements ToolkitProperties {
if(null!=throwable) {
throw new RuntimeException(throwable);
}
- }
- } else {
- RunOnMainThread0(runnable);
+ }
+ }
+ }
+ }
+
+ private static Runnable _nop = new Runnable() { public void run() {}; };
+
+ /** Issues a {@link #RunOnMainThread(boolean, Runnable)} w/ an <i>NOP</i> runnable, while waiting until done. */
+ public static void WaitUntilFinish() {
+ RunOnMainThread(true, _nop);
+ }
+
+ /**
+ * Run on OSX UI main thread.
+ * <p>
+ * 'waitUntilDone' is implemented on Java site via lock/wait on {@link FunctionTask} to not freeze OSX main thread.
+ * </p>
+ *
+ * @param waitUntilDone
+ * @param func
+ */
+ public static <R,A> R RunOnMainThread(boolean waitUntilDone, Function<R,A> func, A... args) {
+ if( IsMainThread0() ) {
+ return func.eval(args); // don't leave the JVM
+ } else {
+ // Utilize Java side lock/wait and simply pass the Runnable async to OSX main thread,
+ // otherwise we may freeze the OSX main thread.
+ Throwable throwable = null;
+ final Object sync = new Object();
+ final FunctionTask<R,A> rt = new FunctionTask<R,A>( func, waitUntilDone ? sync : null, true );
+ synchronized(sync) {
+ rt.setArgs(args);
+ RunOnMainThread0(rt);
+ if( waitUntilDone ) {
+ try {
+ sync.wait();
+ } catch (InterruptedException ie) {
+ throwable = ie;
+ }
+ if(null==throwable) {
+ throwable = rt.getThrowable();
+ }
+ if(null!=throwable) {
+ throw new RuntimeException(throwable);
+ }
+ }
}
+ return rt.getResult();
}
}
@@ -236,6 +350,7 @@ public class OSXUtil implements ToolkitProperties {
private static native long GetNSWindow0(long nsView);
private static native long CreateCALayer0(int x, int y, int width, int height);
private static native void AddCASublayer0(long rootCALayer, long subCALayer);
+ private static native void FixCALayerLayout0(long rootCALayer, long subCALayer, int width, int height);
private static native void RemoveCASublayer0(long rootCALayer, long subCALayer);
private static native void DestroyCALayer0(long caLayer);
private static native void RunOnMainThread0(Runnable runnable);