aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2012-07-25 04:23:35 +0200
committerSven Gothel <[email protected]>2012-07-25 04:23:35 +0200
commit7bb5885fc3a904f49e22f0c8cbf747d9b189a7ba (patch)
treee5617fa74ff4a401fa60a080c5b3e8cf4ee21233 /src
parent00bef95008b02cc71e166da122884402e9381f44 (diff)
SWT Update: SWT GLCanvas creates lazy when resource is ready; Create new NewtCanvasSWT allowing to parent NEWT windows natively.
SWT GLCanvas creates lazy when resource is ready - Ensures drawable and context are created when size > zero and native visualID is valid. The latter is platform dependent. - Note that you cannot utilize custom GLCapabilities w/ this one, since the configurations is already realized - use NewtCanvasSWT. Create new NewtCanvasSWT allowing to parent NEWT windows natively: - Similar to NewtCanvasAWT - Allows attaching / detaching NEWT windows NewtCanvasAWT: Public setNEWTChild(..) fixed Added test cases for the above - tested on Linux, OSX and Windows w/ SWT Note: As usual for OSX, add -XstartOnFirstThread Details: - NEWT Display has new method: 'EDTUtil setEDTUtil(EDTUtil)' allowing to set a custom event dispatch utility. We use this to set our SWTEDTUtil for using NEWT w/ SWT complying w/ SWT threading constraints.
Diffstat (limited to 'src')
-rw-r--r--src/jogl/classes/com/jogamp/gluegen/opengl/BuildComposablePipeline.java2
-rw-r--r--src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java199
-rw-r--r--src/jogl/classes/jogamp/opengl/GLContextImpl.java1
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java25
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java17
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java35
-rw-r--r--src/nativewindow/native/macosx/OSXmisc.m74
-rw-r--r--src/newt/classes/com/jogamp/newt/Display.java17
-rw-r--r--src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java74
-rw-r--r--src/newt/classes/com/jogamp/newt/opengl/GLWindow.java1
-rw-r--r--src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java508
-rw-r--r--src/newt/classes/com/jogamp/newt/swt/SWTEDTUtil.java99
-rw-r--r--src/newt/classes/jogamp/newt/DisplayImpl.java40
-rw-r--r--src/newt/classes/jogamp/newt/WindowImpl.java11
-rw-r--r--src/newt/classes/jogamp/newt/awt/event/AWTParentWindowAdapter.java21
-rw-r--r--src/newt/classes/jogamp/newt/driver/awt/AWTDisplay.java11
-rw-r--r--src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java5
-rw-r--r--src/newt/classes/jogamp/newt/driver/windows/WindowsWindow.java11
-rw-r--r--src/newt/native/MacWindow.m56
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/swt/TestNewtCanvasSWTGLn.java233
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTAccessor02GLn.java278
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTJOGLGLCanvas01GLn.java55
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01aSWT.java210
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting04AWT.java239
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting04SWT.java264
25 files changed, 2038 insertions, 448 deletions
diff --git a/src/jogl/classes/com/jogamp/gluegen/opengl/BuildComposablePipeline.java b/src/jogl/classes/com/jogamp/gluegen/opengl/BuildComposablePipeline.java
index 1d9cf3668..5334d45cf 100644
--- a/src/jogl/classes/com/jogamp/gluegen/opengl/BuildComposablePipeline.java
+++ b/src/jogl/classes/com/jogamp/gluegen/opengl/BuildComposablePipeline.java
@@ -410,7 +410,7 @@ public class BuildComposablePipeline {
output.flush();
output.close();
- System.out.println("wrote to file: " + file); // JAU
+ System.out.println("wrote to file: " + file);
}
/** Get the name of the object through which API calls should be routed. */
diff --git a/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java b/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java
index 64ee1c1ad..8d237162c 100644
--- a/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java
+++ b/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java
@@ -45,6 +45,7 @@ import javax.media.opengl.GLProfile;
import javax.media.opengl.GLRunnable;
import javax.media.opengl.Threading;
+import jogamp.opengl.Debug;
import jogamp.opengl.GLContextImpl;
import jogamp.opengl.GLDrawableHelper;
@@ -70,8 +71,12 @@ import com.jogamp.opengl.JoglVersion;
/**
* Native SWT Canvas implementing GLAutoDrawable
+ *
+ * <p>Note: To employ custom GLCapabilities, NewtCanvasSWT shall be used instead.</p>
+ *
*/
public class GLCanvas extends Canvas implements GLAutoDrawable {
+ private static final boolean DEBUG = Debug.debug("GLCanvas");
/*
* Flag for whether the SWT thread should be used for OpenGL calls when in single-threaded mode. This is controlled
@@ -87,18 +92,20 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
/* GL Stuff */
private final RecursiveLock lock = LockFactory.createRecursiveLock();
private final GLDrawableHelper helper = new GLDrawableHelper();
+
+ private final GLContext shareWith;
+ private final GLCapabilitiesImmutable capsRequested;
+ private final GLCapabilitiesChooser capsChooser;
+
private volatile GLDrawable drawable; // volatile: avoid locking for read-only access
private GLContext context;
/* Native window surface */
private AbstractGraphicsDevice device;
- private final long nativeWindowHandle;
- private final ProxySurface proxySurface;
/* Construction parameters stored for GLAutoDrawable accessor methods */
private int additionalCtxCreationFlags = 0;
- private final GLCapabilitiesImmutable glCapsRequested;
/* Flag indicating whether an unprocessed reshape is pending. */
private volatile boolean sendReshape; // volatile: maybe written by WindowManager thread w/o locking
@@ -218,6 +225,37 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
*/
private volatile Rectangle clientArea;
+ /**
+ * Creates an instance using {@link #GLCanvas(Composite, int, GLCapabilitiesImmutable, GLCapabilitiesChooser, GLContext)}
+ * on the SWT thread.
+ *
+ * @param parent
+ * Required (non-null) parent Composite.
+ * @param style
+ * Optional SWT style bit-field. The {@link SWT#NO_BACKGROUND} bit is set before passing this up to the
+ * Canvas constructor, so OpenGL handles the background.
+ * @param caps
+ * Optional GLCapabilities. If not provided, the default capabilities for the default GLProfile for the
+ * graphics device determined by the parent Composite are used. Note that the GLCapabilities that are
+ * actually used may differ based on the capabilities of the graphics device.
+ * @param chooser
+ * Optional GLCapabilitiesChooser to customize the selection of the used GLCapabilities based on the
+ * requested GLCapabilities, and the available capabilities of the graphics device.
+ * @param shareWith
+ * Optional GLContext to share state (textures, vbos, shaders, etc.) with.
+ * @return a new instance
+ */
+ public static GLCanvas create(final Composite parent, final int style, final GLCapabilitiesImmutable caps,
+ final GLCapabilitiesChooser chooser, final GLContext shareWith) {
+ final GLCanvas[] res = new GLCanvas[] { null };
+ parent.getDisplay().syncExec(new Runnable() {
+ public void run() {
+ res[0] = new GLCanvas( parent, style, caps, chooser, shareWith );
+ }
+ });
+ return res[0];
+ }
+
/**
* Creates a new SWT GLCanvas.
*
@@ -250,35 +288,26 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
/* Get the nativewindow-Graphics Device associated with this control (which is determined by the parent Composite).
* Note: SWT is owner of the native handle, hence no closing operation will be a NOP. */
device = SWTAccessor.getDevice(this);
- /* Since we have no means of querying the screen index yet, assume 0. Good choice due to Xinerama alike settings anyways. */
- final int screenIdx = 0;
- /* Native handle for the control, used to associate with GLContext */
- nativeWindowHandle = SWTAccessor.getWindowHandle(this);
/* Select default GLCapabilities if none was provided, otherwise clone provided caps to ensure safety */
if(null == caps) {
caps = new GLCapabilities(GLProfile.getDefault(device));
}
- glCapsRequested = caps;
-
- final GLDrawableFactory glFactory = GLDrawableFactory.getFactory(caps.getGLProfile());
-
- /* Create a NativeWindow proxy for the SWT canvas */
- proxySurface = glFactory.createProxySurface(device, screenIdx, nativeWindowHandle, caps, chooser, swtCanvasUpStreamHook);
-
- /* Associate a GL surface with the proxy */
- drawable = glFactory.createGLDrawable(proxySurface);
- drawable.setRealized(true);
-
- context = drawable.createContext(shareWith);
-
+ this.capsRequested = caps;
+ this.capsChooser = chooser;
+ this.shareWith = shareWith;
+
+ // post create .. when ready
+ drawable = null;
+ context = null;
+
/* Register SWT listeners (e.g. PaintListener) to render/resize GL surface. */
/* TODO: verify that these do not need to be manually de-registered when destroying the SWT component */
addPaintListener(new PaintListener() {
@Override
public void paintControl(final PaintEvent arg0) {
- if (!helper.isExternalAnimatorAnimating()) {
- display();
+ if ( !helper.isExternalAnimatorAnimating() ) {
+ display(); // checks: null != drawable
}
}
});
@@ -291,39 +320,93 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
});
}
private final ProxySurface.UpstreamSurfaceHook swtCanvasUpStreamHook = new ProxySurface.UpstreamSurfaceHook() {
- @Override
- public final void create(ProxySurface s) { /* nop */ }
-
- @Override
- public final void destroy(ProxySurface s) { /* nop */ }
-
- @Override
- public final int getWidth(ProxySurface s) {
- return clientArea.width;
- }
-
- @Override
- public final int getHeight(ProxySurface s) {
- return clientArea.height;
- }
-
- @Override
- public String toString() {
- return "SETUpstreamSurfaceHook[upstream: "+GLCanvas.this.toString()+"]";
- }
-
+ @Override
+ public final void create(ProxySurface s) { /* nop */ }
+
+ @Override
+ public final void destroy(ProxySurface s) { /* nop */ }
+
+ @Override
+ public final int getWidth(ProxySurface s) {
+ return clientArea.width;
+ }
+
+ @Override
+ public final int getHeight(ProxySurface s) {
+ return clientArea.height;
+ }
+
+ @Override
+ public String toString() {
+ return "SWTCanvasUpstreamSurfaceHook[upstream: "+GLCanvas.this.toString()+", "+clientArea.width+"x"+clientArea.height+"]";
+ }
};
protected final void updateSizeCheck() {
- clientArea = GLCanvas.this.getClientArea();
- if (clientArea != null &&
- proxySurface.getWidth() != clientArea.width &&
- proxySurface.getHeight() != clientArea.height) {
+ final Rectangle oClientArea = clientArea;
+ final Rectangle nClientArea = GLCanvas.this.getClientArea();
+ if ( nClientArea != null &&
+ ( nClientArea.width != oClientArea.width || nClientArea.height != oClientArea.height )
+ ) {
+ clientArea = nClientArea; // write back new value
sendReshape = true; // Mark for OpenGL reshape next time the control is painted
}
- sendReshape = false;
+ }
+
+ @Override
+ public void display() {
+ if( null != drawable || validateDrawableAndContext() ) {
+ runInGLThread(makeCurrentAndDisplayOnEDTAction);
+ }
}
+
+ /** assumes drawable == null ! */
+ protected final boolean validateDrawableAndContext() {
+ if( GLCanvas.this.isDisposed() ) {
+ return false;
+ }
+ final Rectangle nClientArea = clientArea;
+ if(0 == nClientArea.width * nClientArea.height) {
+ return false;
+ }
+
+ final RecursiveLock _lock = lock;
+ _lock.lock();
+ try {
+ final GLDrawableFactory glFactory = GLDrawableFactory.getFactory(capsRequested.getGLProfile());
+
+ /* Native handle for the control, used to associate with GLContext */
+ final long nativeWindowHandle = SWTAccessor.getWindowHandle(this);
+
+ /* Create a NativeWindow proxy for the SWT canvas */
+ ProxySurface proxySurface = null;
+ try {
+ proxySurface = glFactory.createProxySurface(device, 0 /* screenIdx */, nativeWindowHandle,
+ capsRequested, capsChooser, swtCanvasUpStreamHook);
+ } catch (GLException gle) {
+ // not ready yet ..
+ if(DEBUG) { System.err.println(gle.getMessage()); }
+ }
+
+ if(null != proxySurface) {
+ /* Associate a GL surface with the proxy */
+ drawable = glFactory.createGLDrawable(proxySurface);
+ drawable.setRealized(true);
+
+ context = drawable.createContext(shareWith);
+ }
+ } finally {
+ _lock.unlock();
+ }
+ final boolean res = null != drawable;
+ if(DEBUG && res) {
+ System.err.println("SWT GLCanvas realized! "+this+", "+drawable);
+ Thread.dumpStack();
+ }
+ return res;
+ }
+
@Override
public final Object getUpstreamWidget() {
return this;
@@ -363,11 +446,6 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
}
@Override
- public void display() {
- runInGLThread(makeCurrentAndDisplayOnEDTAction);
- }
-
- @Override
public GLAnimatorControl getAnimator() {
return helper.getAnimator();
}
@@ -379,7 +457,7 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
@Override
public GLContext getContext() {
- return context;
+ return null != drawable ? context : null;
}
@Override
@@ -472,7 +550,8 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
@Override
public GLCapabilitiesImmutable getChosenGLCapabilities() {
- return (GLCapabilitiesImmutable)proxySurface.getGraphicsConfiguration().getChosenCapabilities();
+ final GLDrawable _drawable = drawable;
+ return null != _drawable ? (GLCapabilitiesImmutable)_drawable.getChosenGLCapabilities() : null;
}
/**
@@ -481,7 +560,8 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
* @return Non-null GLCapabilities.
*/
public GLCapabilitiesImmutable getRequestedGLCapabilities() {
- return (GLCapabilitiesImmutable)proxySurface.getGraphicsConfiguration().getRequestedCapabilities();
+ final GLDrawable _drawable = drawable;
+ return null != _drawable ? (GLCapabilitiesImmutable)_drawable.getNativeSurface().getGraphicsConfiguration().getRequestedCapabilities() : null;
}
@Override
@@ -492,7 +572,7 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
@Override
public GLProfile getGLProfile() {
- return glCapsRequested.getGLProfile();
+ return capsRequested.getGLProfile();
}
@Override
@@ -523,10 +603,9 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
runInGLThread(makeCurrentAndSwapBuffersOnEDTAction);
}
- // FIXME: API of update() method ?
@Override
public void update() {
- // FIXME: display(); ?
+ // don't paint background etc .. nop avoids flickering
}
@Override
@@ -551,7 +630,7 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
* @see Platform#AWT_AVAILABLE
* @see Platform#getOSType()
*/
- private void runInGLThread(final Runnable action) {
+ private static void runInGLThread(final Runnable action) {
if(Platform.OSType.MACOS == Platform.OS_TYPE) {
SWTAccessor.invoke(true, action);
} else {
diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
index e730bc62e..bf6a0ee6e 100644
--- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
@@ -338,7 +338,6 @@ public abstract class GLContextImpl extends GLContext {
if (TRACE_SWITCH) {
System.err.println(getThreadName() + ": GLContextImpl.destroy.X: obj " + toHexString(hashCode()) + ", ctx " + toHexString(contextHandle) +
", isShared "+GLContextShareSet.isShared(this)+" - "+lock);
- Thread.dumpStack(); // JAU
}
}
} finally {
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java b/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java
index 0494bb408..ba07d97dc 100644
--- a/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java
@@ -34,16 +34,21 @@ import java.lang.reflect.Method;
import org.eclipse.swt.graphics.GCData;
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;
+import javax.media.nativewindow.VisualIDHolder;
import com.jogamp.common.util.ReflectionUtil;
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;
public class SWTAccessor {
static final Field swt_control_handle;
@@ -213,6 +218,26 @@ public class SWTAccessor {
}
throw new UnsupportedOperationException("n/a for this windowing system: "+NativeWindowFactory.getNativeWindowType(false));
}
+ public static AbstractGraphicsScreen getScreen(AbstractGraphicsDevice device, int screen) {
+ if( null != OS_gtk_class ) {
+ return new X11GraphicsScreen((X11GraphicsDevice)device, screen);
+ }
+ if( NativeWindowFactory.TYPE_WINDOWS == NativeWindowFactory.getNativeWindowType(false) ||
+ NativeWindowFactory.TYPE_MACOSX == NativeWindowFactory.getNativeWindowType(false) ) {
+ return new DefaultGraphicsScreen(device, screen);
+ }
+ throw new UnsupportedOperationException("n/a for this windowing system: "+NativeWindowFactory.getNativeWindowType(false));
+ }
+ public static int getNativeVisualID(AbstractGraphicsDevice device, long windowHandle) {
+ if( null != OS_gtk_class ) {
+ return X11Lib.GetVisualIDFromWindow(device.getHandle(), windowHandle);
+ }
+ if( NativeWindowFactory.TYPE_WINDOWS == NativeWindowFactory.getNativeWindowType(false) ||
+ NativeWindowFactory.TYPE_MACOSX == NativeWindowFactory.getNativeWindowType(false) ) {
+ return VisualIDHolder.VID_UNDEFINED;
+ }
+ throw new UnsupportedOperationException("n/a for this windowing system: "+NativeWindowFactory.getNativeWindowType(false));
+ }
public static long getWindowHandle(Control swtControl) {
long handle = getHandle(swtControl);
diff --git a/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java b/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java
index b85ad47f2..6faa9890c 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java
@@ -561,4 +561,21 @@ public abstract class NativeWindowFactory {
}
return null;
}
+
+ /**
+ * Returns true if the given visualID is valid for further processing, i.e. OpenGL usage,
+ * otherwise return false.
+ * <p>
+ * On certain platforms, i.e. X11, a valid visualID is required at window creation.
+ * Other platforms may determine it later on, e.g. OSX and Windows. </p>
+ * <p>
+ * If the visualID is {@link VisualIDHolder#VID_UNDEFINED} and the platform requires it
+ * at creation time (see above), it is not valid for further processing.
+ * </p>
+ */
+ public static boolean isNativeVisualIDValidForProcessing(int visualID) {
+ return NativeWindowFactory.TYPE_X11 != NativeWindowFactory.getNativeWindowType(false) ||
+ VisualIDHolder.VID_UNDEFINED != visualID ;
+ }
+
}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java b/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java
index 4767dff18..894084fce 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java
@@ -28,6 +28,7 @@
package jogamp.nativewindow.macosx;
import javax.media.nativewindow.NativeWindowException;
+import javax.media.nativewindow.util.Insets;
import javax.media.nativewindow.util.Point;
import jogamp.nativewindow.Debug;
@@ -63,8 +64,37 @@ public class OSXUtil {
return isNSView0(object);
}
- public static Point GetLocationOnScreen(long windowOrView, int src_x, int src_y) {
- return (Point) GetLocationOnScreen0(windowOrView, src_x, src_y);
+ /**
+ * In case the <code>windowOrView</code> is top-level,
+ * you shall set <code>topLevel</code> to true where
+ * insets gets into account to compute the client position as follows:
+ * <pre>
+ if(topLevel) {
+ // top-level position -> client window position
+ final Insets insets = GetInsets(windowOrView);
+ los.setX(los.getX() + insets.getLeftWidth());
+ los.setY(los.getY() + insets.getTopHeight());
+ }
+ * </pre>
+ * @param windowOrView
+ * @param topLevel
+ * @param src_x
+ * @param src_y
+ * @return the client position
+ */
+ public static Point GetLocationOnScreen(long windowOrView, boolean topLevel, int src_x, int src_y) {
+ final Point los = (Point) GetLocationOnScreen0(windowOrView, src_x, src_y);
+ if(topLevel) {
+ // top-level position -> client window position
+ final Insets insets = GetInsets(windowOrView);
+ los.setX(los.getX() + insets.getLeftWidth());
+ los.setY(los.getY() + insets.getTopHeight());
+ }
+ return los;
+ }
+
+ public static Insets GetInsets(long windowOrView) {
+ return (Insets) GetInsets0(windowOrView);
}
public static long CreateNSWindow(int x, int y, int width, int height) {
@@ -135,6 +165,7 @@ public class OSXUtil {
private static native boolean initIDs0();
private static native boolean isNSView0(long object);
private static native Object GetLocationOnScreen0(long windowOrView, int src_x, int src_y);
+ private static native Object GetInsets0(long windowOrView);
private static native long CreateNSWindow0(int x, int y, int width, int height);
private static native void DestroyNSWindow0(long nsWindow);
private static native long GetNSView0(long nsWindow);
diff --git a/src/nativewindow/native/macosx/OSXmisc.m b/src/nativewindow/native/macosx/OSXmisc.m
index 37fa4c88f..2c853a43d 100644
--- a/src/nativewindow/native/macosx/OSXmisc.m
+++ b/src/nativewindow/native/macosx/OSXmisc.m
@@ -52,12 +52,18 @@
static const char * const ClazzNameRunnable = "java/lang/Runnable";
static jmethodID runnableRunID = NULL;
-static const char * const ClazzNamePoint = "javax/media/nativewindow/util/Point";
static const char * const ClazzAnyCstrName = "<init>";
+
+static const char * const ClazzNamePoint = "javax/media/nativewindow/util/Point";
static const char * const ClazzNamePointCstrSignature = "(II)V";
static jclass pointClz = NULL;
static jmethodID pointCstr = NULL;
+static const char * const ClazzNameInsets = "javax/media/nativewindow/util/Insets";
+static const char * const ClazzNameInsetsCstrSignature = "(IIII)V";
+static jclass insetsClz = NULL;
+static jmethodID insetsCstr = NULL;
+
static int _initialized=0;
JNIEXPORT jboolean JNICALL
@@ -79,6 +85,21 @@ Java_jogamp_nativewindow_macosx_OSXUtil_initIDs0(JNIEnv *env, jclass _unused) {
ClazzNamePoint, ClazzAnyCstrName, ClazzNamePointCstrSignature);
}
+ c = (*env)->FindClass(env, ClazzNameInsets);
+ if(NULL==c) {
+ NativewindowCommon_FatalError(env, "FatalError Java_jogamp_newt_driver_macosx_MacWindow_initIDs0: can't find %s", ClazzNameInsets);
+ }
+ insetsClz = (jclass)(*env)->NewGlobalRef(env, c);
+ (*env)->DeleteLocalRef(env, c);
+ if(NULL==insetsClz) {
+ NativewindowCommon_FatalError(env, "FatalError Java_jogamp_newt_driver_macosx_MacWindow_initIDs0: can't use %s", ClazzNameInsets);
+ }
+ insetsCstr = (*env)->GetMethodID(env, insetsClz, ClazzAnyCstrName, ClazzNameInsetsCstrSignature);
+ if(NULL==insetsCstr) {
+ NativewindowCommon_FatalError(env, "FatalError Java_jogamp_newt_driver_macosx_MacWindow_initIDs0: can't fetch %s.%s %s",
+ ClazzNameInsets, ClazzAnyCstrName, ClazzNameInsetsCstrSignature);
+ }
+
c = (*env)->FindClass(env, ClazzNameRunnable);
if(NULL==c) {
NativewindowCommon_FatalError(env, "FatalError Java_jogamp_newt_driver_macosx_MacWindow_initIDs0: can't find %s", ClazzNameRunnable);
@@ -156,6 +177,49 @@ JNIEXPORT jobject JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetLocationOnS
/*
* Class: Java_jogamp_nativewindow_macosx_OSXUtil
+ * Method: getInsets0
+ * Signature: (J)Ljavax/media/nativewindow/util/Insets;
+ */
+JNIEXPORT jobject JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetInsets0
+ (JNIEnv *env, jclass unused, jlong winOrView)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+
+ NSObject *nsObj = (NSObject*) (intptr_t) winOrView;
+ NSWindow* win = NULL;
+ NSView* view = NULL;
+ jint il,ir,it,ib;
+
+ if( [nsObj isKindOfClass:[NSWindow class]] ) {
+ win = (NSWindow*) nsObj;
+ view = [win contentView];
+ } else if( nsObj != NULL && [nsObj isKindOfClass:[NSView class]] ) {
+ view = (NSView*) nsObj;
+ win = [view window];
+ } else {
+ NativewindowCommon_throwNewRuntimeException(env, "neither win not view %p\n", nsObj);
+ }
+
+ NSRect frameRect = [win frame];
+ NSRect contentRect = [win contentRectForFrameRect: frameRect];
+
+ // note: this is a simplistic implementation which doesn't take
+ // into account DPI and scaling factor
+ CGFloat l = contentRect.origin.x - frameRect.origin.x;
+ il = (jint)l; // l
+ ir = (jint)(frameRect.size.width - (contentRect.size.width + l)); // r
+ it = (jint)(frameRect.size.height - contentRect.size.height); // t
+ ib = (jint)(contentRect.origin.y - frameRect.origin.y); // b
+
+ jobject res = (*env)->NewObject(env, insetsClz, insetsCstr, il, ir, it, ib);
+
+ [pool release];
+
+ return res;
+}
+
+/*
+ * Class: Java_jogamp_nativewindow_macosx_OSXUtil
* Method: CreateNSWindow0
* Signature: (IIIIZ)J
*/
@@ -172,6 +236,12 @@ JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_CreateNSWindow0
defer: YES];
[myWindow setReleasedWhenClosed: YES]; // default
[myWindow setPreservesContentDuringLiveResize: YES];
+ // Remove animations
+NS_DURING
+ // Available >= 10.7 - Removes default animations
+ [myWindow setAnimationBehavior: NSWindowAnimationBehaviorNone];
+NS_HANDLER
+NS_ENDHANDLER
// invisible ..
[myWindow setOpaque: NO];
@@ -229,7 +299,7 @@ JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_CreateCALayer0
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
CALayer* layer = [[CALayer alloc] init];
- DBG_PRINT("CALayer::CreateCALayer.0: %p %d/%d %dx%d (refcnt %d)\n", layer, x, y, width, height, (int)[layer retainCount]);
+ DBG_PRINT("CALayer::CreateCALayer.0: %p %d/%d %dx%d (refcnt %d)\n", layer, (int)x, (int)y, (int)width, (int)height, (int)[layer retainCount]);
// avoid zero size
if(0 == width) { width = 32; }
if(0 == height) { height = 32; }
diff --git a/src/newt/classes/com/jogamp/newt/Display.java b/src/newt/classes/com/jogamp/newt/Display.java
index 7b6849a30..1e9a0e9eb 100644
--- a/src/newt/classes/com/jogamp/newt/Display.java
+++ b/src/newt/classes/com/jogamp/newt/Display.java
@@ -141,6 +141,23 @@ public abstract class Display {
*/
public abstract String getType();
+ /**
+ * Sets a new {@link EDTUtil} and returns the previous one.
+ * <p>
+ * If <code>newEDTUtil</code> is <code>null</code>,
+ * the device's default EDTUtil is created and used.
+ * </p>
+ * <p>
+ * If a previous one exists and it differs from the new one,
+ * it's being stopped, wait-until-idle and reset to allow restart.
+ * </p>
+ * <p>
+ * If <code>newEDTUtil</code> is not null and equals the previous one,
+ * <code>null</code> is returned and no change is being made.
+ * </p>
+ */
+ public abstract EDTUtil setEDTUtil(EDTUtil newEDTUtil);
+
public abstract EDTUtil getEDTUtil();
public abstract boolean isEDTRunning();
diff --git a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java
index cd0e9aab6..6f0028a77 100644
--- a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java
+++ b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java
@@ -263,17 +263,35 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto
private final FocusPropertyChangeListener focusPropertyChangeListener = new FocusPropertyChangeListener();
private volatile KeyboardFocusManager keyboardFocusManager = null;
- /** sets a new NEWT child, provoking reparenting. */
- private NewtCanvasAWT setNEWTChild(Window child) {
- if(newtChild!=child) {
- newtChild = child;
- if(isDisplayable()) {
- // reparent right away, addNotify has been called already
- final java.awt.Container cont = AWTMisc.getContainer(this);
- reparentWindow( (null!=child) ? true : false, cont );
- }
+ /**
+ * Sets a new NEWT child, provoking reparenting.
+ * <p>
+ * A previously detached <code>newChild</code> will be released to top-level status
+ * and made invisible.
+ * </p>
+ * <p>
+ * Note: When switching NEWT child's, detaching the previous first via <code>setNEWTChild(null)</code>
+ * produced much cleaner visual results.
+ * </p>
+ * @return the previous attached newt child.
+ */
+ public Window setNEWTChild(Window newChild) {
+ final Window prevChild = newtChild;
+ if(DEBUG) {
+ System.err.println("NewtCanvasAWT.setNEWTChild.0: win "+newtWinHandleToHexString(prevChild)+" -> "+newtWinHandleToHexString(newChild));
+ }
+ final java.awt.Container cont = AWTMisc.getContainer(this);
+ // remove old one
+ if(null != newtChild) {
+ reparentWindow( false, cont );
+ newtChild = null;
}
- return this;
+ // add new one, reparent only if ready
+ newtChild = newChild;
+ if( isDisplayable() && null != newChild) {
+ reparentWindow( true, cont );
+ }
+ return prevChild;
}
/** @return the current NEWT child */
@@ -306,13 +324,13 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto
awtKeyAdapter.removeFrom(this);
awtKeyAdapter = null;
}
- newtChild.setKeyboardFocusHandler(null);
if(null != keyboardFocusManager) {
keyboardFocusManager.removePropertyChangeListener("focusOwner", focusPropertyChangeListener);
keyboardFocusManager = null;
}
if( null != newtChild ) {
+ newtChild.setKeyboardFocusHandler(null);
if(attach) {
if(null == jawtWindow.getGraphicsConfiguration()) {
throw new InternalError("XXX");
@@ -360,7 +378,7 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto
// if ( isShowing() == true ) -> Container is already visible.
System.err.println("NewtCanvasAWT.addNotify: "+newtChild+", "+this+", visible "+isVisible()+", showing "+isShowing()+
", displayable "+isDisplayable()+" -> "+cont);
- }
+ }
reparentWindow(true, cont);
}
@@ -375,6 +393,12 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto
ols.detachSurfaceLayer();
}
reparentWindow(false, cont);
+
+ if(null != jawtWindow) {
+ NewtFactoryAWT.destroyNativeWindow(jawtWindow);
+ jawtWindow=null;
+ }
+
super.removeNotify();
}
@@ -382,14 +406,19 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto
if(null==newtChild) {
return; // nop
}
+ if(DEBUG) {
+ System.err.println("NewtCanvasAWT.reparentWindow.0: add="+add+", win "+newtWinHandleToHexString(newtChild)+", EDTUtil: cur "+newtChild.getScreen().getDisplay().getEDTUtil());
+ }
newtChild.setFocusAction(null); // no AWT focus traversal ..
if(add) {
- jawtWindow = NewtFactoryAWT.getNativeWindow(this, newtChild.getRequestedCapabilities());
- jawtWindow.setShallUseOffscreenLayer(shallUseOffscreenLayer);
if(DEBUG) {
System.err.println("NewtCanvasAWT.reparentWindow: newtChild: "+newtChild);
}
+ if(null == jawtWindow) {
+ jawtWindow = NewtFactoryAWT.getNativeWindow(this, newtChild.getRequestedCapabilities());
+ jawtWindow.setShallUseOffscreenLayer(shallUseOffscreenLayer);
+ }
final int w;
final int h;
if(isPreferredSizeSet()) {
@@ -413,7 +442,6 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto
newtChild.setVisible(true);
configureNewtChild(true);
newtChild.sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout to listener
- newtChild.windowRepaint(0, 0, w, h);
// force this AWT Canvas to be focus-able,
// since this it is completely covered by the newtChild (z-order).
@@ -422,10 +450,9 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto
configureNewtChild(false);
newtChild.setVisible(false);
newtChild.reparentWindow(null);
- if(null != jawtWindow) {
- NewtFactoryAWT.destroyNativeWindow(jawtWindow);
- jawtWindow=null;
- }
+ }
+ if(DEBUG) {
+ System.err.println("NewtCanvasAWT.reparentWindow.X: add="+add+", win "+newtWinHandleToHexString(newtChild)+", EDTUtil: cur "+newtChild.getScreen().getDisplay().getEDTUtil());
}
}
@@ -451,7 +478,7 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto
NewtFactoryAWT.destroyNativeWindow(jawtWindow);
jawtWindow=null;
}
- newtChild.setVisible(false);
+ newtChild.setVisible(false);
newtChild.reparentWindow(null);
newtChild.destroy();
newtChild=null;
@@ -569,5 +596,12 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto
}
}
}
+
+ static String newtWinHandleToHexString(Window w) {
+ return null != w ? toHexString(w.getWindowHandle()) : "nil";
+ }
+ static String toHexString(long l) {
+ return "0x"+Long.toHexString(l);
+ }
}
diff --git a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java
index 2205aec8e..d662a743a 100644
--- a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java
+++ b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java
@@ -480,7 +480,6 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
}
if(Window.DEBUG_IMPLEMENTATION) {
System.err.println("GLWindow.setVisibleActionPost("+visible+", "+nativeWindowCreated+") "+WindowImpl.getThreadName()+", fin: dt "+ (System.nanoTime()-t0)/1e6 +"ms");
- Thread.dumpStack(); // JAU
}
}
diff --git a/src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java b/src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java
new file mode 100644
index 000000000..f45b864fa
--- /dev/null
+++ b/src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java
@@ -0,0 +1,508 @@
+/**
+ * Copyright 2012 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 com.jogamp.newt.swt;
+
+import javax.media.nativewindow.AbstractGraphicsConfiguration;
+import javax.media.nativewindow.AbstractGraphicsDevice;
+import javax.media.nativewindow.AbstractGraphicsScreen;
+import javax.media.nativewindow.Capabilities;
+import javax.media.nativewindow.CapabilitiesImmutable;
+import javax.media.nativewindow.GraphicsConfigurationFactory;
+import javax.media.nativewindow.NativeSurface;
+import javax.media.nativewindow.NativeWindow;
+import javax.media.nativewindow.NativeWindowException;
+import javax.media.nativewindow.NativeWindowFactory;
+import javax.media.nativewindow.SurfaceUpdatedListener;
+import javax.media.nativewindow.WindowClosingProtocol;
+import javax.media.nativewindow.util.Insets;
+import javax.media.nativewindow.util.InsetsImmutable;
+import javax.media.nativewindow.util.Point;
+
+import jogamp.nativewindow.macosx.OSXUtil;
+import jogamp.newt.Debug;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ControlAdapter;
+import org.eclipse.swt.events.ControlEvent;
+import org.eclipse.swt.events.PaintEvent;
+import org.eclipse.swt.events.PaintListener;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Canvas;
+import org.eclipse.swt.widgets.Composite;
+
+import com.jogamp.nativewindow.swt.SWTAccessor;
+import com.jogamp.newt.Display;
+import com.jogamp.newt.Window;
+import com.jogamp.newt.event.WindowEvent;
+import com.jogamp.newt.util.EDTUtil;
+
+public class NewtCanvasSWT extends Canvas implements WindowClosingProtocol {
+ private static final boolean DEBUG = Debug.debug("Window");
+ private static final boolean isOSX = NativeWindowFactory.TYPE_MACOSX == NativeWindowFactory.getNativeWindowType(false);
+
+ /** SWT EDTUtil associated w/ parent's SWT Display */
+ private final EDTUtil swtEDTUtil;
+
+ private final AbstractGraphicsScreen screen;
+
+ private WindowClosingMode newtChildCloseOp = WindowClosingMode.DISPOSE_ON_CLOSE;
+ private volatile Rectangle clientArea;
+
+ private volatile SWTNativeWindow nativeWindow;
+ private volatile Window newtChild = null;
+
+ /**
+ * Creates an instance using {@link #NewtCanvasSWT(Composite, int, Window)}
+ * on the SWT thread.
+ *
+ * <p>
+ * Note: The NEWT child {@link Display}'s {@link EDTUtil} is being set to an SWT conform implementation
+ * via {@link Display#setEDTUtil(EDTUtil)}.
+ * </p>
+ *
+ * @param parent the SWT composite
+ * @param style additional styles to SWT#NO_BACKGROUND
+ * @param child optional preassigned {@link #Window}, maybe null
+ * @return a new instance
+ */
+ public static NewtCanvasSWT create(final Composite parent, final int style, final Window child) {
+ final NewtCanvasSWT[] res = new NewtCanvasSWT[] { null };
+ parent.getDisplay().syncExec( new Runnable() {
+ public void run() {
+ res[0] = new NewtCanvasSWT( parent, style, child);
+ }
+ });
+ return res[0];
+ }
+
+ /**
+ * Instantiates a NewtCanvas with a NEWT child.
+ *
+ * <p>
+ * Note: The NEWT child {@link Display}'s {@link EDTUtil} is being set to an SWT conform implementation
+ * via {@link Display#setEDTUtil(EDTUtil)}.
+ * </p>
+ *
+ * @param parent the SWT composite
+ * @param style additional styles to SWT#NO_BACKGROUND
+ * @param child optional preassigned {@link #Window}, maybe null
+ */
+ public NewtCanvasSWT(final Composite parent, final int style, Window child) {
+ super(parent, style | SWT.NO_BACKGROUND);
+
+ swtEDTUtil = new SWTEDTUtil(parent.getDisplay());
+
+ SWTAccessor.setRealized(this, true);
+
+ clientArea = getClientArea();
+
+ final AbstractGraphicsDevice device = SWTAccessor.getDevice(this);
+ screen = SWTAccessor.getScreen(device, 0);
+ nativeWindow = null;
+
+ if(null != child) {
+ setNEWTChild(child);
+ }
+
+ /* Register SWT listeners (e.g. PaintListener) to render/resize GL surface. */
+ /* TODO: verify that these do not need to be manually de-registered when destroying the SWT component */
+ addPaintListener(new PaintListener() {
+ @Override
+ public void paintControl(final PaintEvent arg0) {
+ if( null != nativeWindow || validateNative() ) {
+ if( null !=newtChild ) {
+ newtChild.windowRepaint(0, 0, clientArea.width, clientArea.height);
+ }
+ }
+ }
+ });
+
+ addControlListener(new ControlAdapter() {
+ @Override
+ public void controlResized(final ControlEvent arg0) {
+ updateSizeCheck();
+ }
+ });
+ }
+
+ /** assumes nativeWindow == null ! */
+ protected final boolean validateNative() {
+ if( isDisposed() ) {
+ return false;
+ }
+ updateSizeCheck();
+ final Rectangle nClientArea = clientArea;
+ if(0 == nClientArea.width * nClientArea.height) {
+ return false;
+ }
+
+ /* Native handle for the control, used to associate with GLContext */
+ final long nativeWindowHandle = SWTAccessor.getWindowHandle(this);
+ final int visualID = SWTAccessor.getNativeVisualID(screen.getDevice(), nativeWindowHandle);
+ final boolean visualIDValid = NativeWindowFactory.isNativeVisualIDValidForProcessing(visualID);
+ if(DEBUG) {
+ System.err.println("NewtCanvasSWT.validateNative() windowHandle 0x"+Long.toHexString(nativeWindowHandle)+", visualID 0x"+Integer.toHexString(visualID)+", valid "+visualIDValid);
+ }
+ if( visualIDValid ) {
+ /* Get the nativewindow-Graphics Device associated with this control (which is determined by the parent Composite).
+ * Note: SWT is owner of the native handle, hence no closing operation will be a NOP. */
+ final CapabilitiesImmutable caps = new Capabilities();
+ final GraphicsConfigurationFactory factory = GraphicsConfigurationFactory.getFactory(screen.getDevice(), caps);
+ final AbstractGraphicsConfiguration config = factory.chooseGraphicsConfiguration( caps, caps, null, screen, visualID );
+ if(DEBUG) {
+ System.err.println("NewtCanvasSWT.validateNative() factory: "+factory+", windowHandle 0x"+Long.toHexString(nativeWindowHandle)+", visualID 0x"+Integer.toHexString(visualID)+", chosen config: "+config);
+ // Thread.dumpStack();
+ }
+ if (null == config) {
+ throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this);
+ }
+
+ nativeWindow = new SWTNativeWindow(config, nativeWindowHandle);
+ reparentWindow( true );
+ }
+
+ return null != nativeWindow;
+ }
+
+ protected final void updateSizeCheck() {
+ final Rectangle oClientArea = clientArea;
+ final Rectangle nClientArea = getClientArea();
+ if ( nClientArea != null &&
+ ( nClientArea.width != oClientArea.width || nClientArea.height != oClientArea.height )
+ ) {
+ clientArea = nClientArea; // write back new value
+ if( null != newtChild ) {
+ newtChild.setSize(clientArea.width, clientArea.height);
+ }
+ }
+ }
+
+ @Override
+ public void update() {
+ // don't paint background etc .. nop avoids flickering
+ }
+
+ /**
+ * Destroys this resource:
+ * <ul>
+ * <li> Make the NEWT Child invisible </li>
+ * <li> Disconnects the NEWT Child from this Canvas NativeWindow, reparent to NULL </li>
+ * <li> Issues <code>destroy()</code> on the NEWT Child</li>
+ * <li> Remove reference to the NEWT Child</li>
+ * </ul>
+ * @see Window#destroy()
+ */
+ @Override
+ public void dispose() {
+ if( null != newtChild ) {
+ if(DEBUG) {
+ System.err.println("NewtCanvasSWT.dispose.0: EDTUtil cur "+newtChild.getScreen().getDisplay().getEDTUtil()+
+ ",\n\t"+newtChild);
+ }
+ configureNewtChild(false);
+ newtChild.setVisible(false);
+ newtChild.reparentWindow(null);
+ newtChild.destroy();
+ newtChild = null;
+ }
+ nativeWindow = null;
+ super.dispose();
+ }
+
+ /** @return this SWT Canvas NativeWindow representation, may be null in case it has not been realized. */
+ public NativeWindow getNativeWindow() { return nativeWindow; }
+
+ public WindowClosingMode getDefaultCloseOperation() {
+ return newtChildCloseOp; // FIXME
+ }
+
+ public WindowClosingMode setDefaultCloseOperation(WindowClosingMode op) {
+ return newtChildCloseOp = op; // FIXME
+ }
+
+
+ boolean isParent() {
+ return null!=newtChild ;
+ }
+
+ boolean isFullscreen() {
+ return null != newtChild && newtChild.isFullscreen();
+ }
+
+ /**
+ * Sets a new NEWT child, provoking reparenting.
+ * <p>
+ * A previously detached <code>newChild</code> will be released to top-level status
+ * and made invisible.
+ * </p>
+ * <p>
+ * Note: When switching NEWT child's, detaching the previous first via <code>setNEWTChild(null)</code>
+ * produced much cleaner visual results.
+ * </p>
+ * <p>
+ * Note: The NEWT child {@link Display}'s {@link EDTUtil} is being set to an SWT conform implementation
+ * via {@link Display#setEDTUtil(EDTUtil)}.
+ * </p>
+ * @return the previous attached newt child.
+ */
+ public Window setNEWTChild(final Window newChild) {
+ final Window prevChild = newtChild;
+ if(DEBUG) {
+ System.err.println("NewtCanvasSWT.setNEWTChild.0: win "+newtWinHandleToHexString(prevChild)+" -> "+newtWinHandleToHexString(newChild));
+ }
+ // remove old one
+ if(null != newtChild) {
+ reparentWindow( false );
+ newtChild = null;
+ }
+ // add new one, reparent only if ready
+ newtChild = newChild;
+ if(null != nativeWindow && null != newChild) {
+ reparentWindow( true );
+ }
+ return prevChild;
+ }
+
+ /** @return the current NEWT child */
+ public Window getNEWTChild() {
+ return newtChild;
+ }
+
+ @Override
+ public boolean setParent(Composite parent) {
+ return super.setParent(parent);
+ }
+
+ /* package */ void configureNewtChild(boolean attach) {
+
+ if( null != newtChild ) {
+ newtChild.setKeyboardFocusHandler(null);
+ if(attach) {
+ newtChildCloseOp = newtChild.setDefaultCloseOperation(WindowClosingMode.DO_NOTHING_ON_CLOSE);
+ } else {
+ newtChild.setFocusAction(null);
+ newtChild.setDefaultCloseOperation(newtChildCloseOp);
+ }
+ }
+ }
+
+ void reparentWindow(boolean add) {
+ if( null == newtChild ) {
+ return; // nop
+ }
+ if(DEBUG) {
+ System.err.println("NewtCanvasSWT.reparentWindow.0: add="+add+", win "+newtWinHandleToHexString(newtChild)+", EDTUtil: cur "+newtChild.getScreen().getDisplay().getEDTUtil());
+ }
+
+ newtChild.setFocusAction(null); // no AWT focus traversal ..
+ if(add) {
+ updateSizeCheck();
+ final int w = clientArea.width;
+ final int h = clientArea.height;
+
+ newtChild.getScreen().getDisplay().setEDTUtil(swtEDTUtil);
+
+ newtChild.setSize(w, h);
+ newtChild.reparentWindow(nativeWindow);
+ newtChild.setVisible(true);
+ configureNewtChild(true);
+ newtChild.sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout to listener
+
+ // force this SWT Canvas to be focus-able,
+ // since this it is completely covered by the newtChild (z-order).
+ setEnabled(true);
+ } else {
+ configureNewtChild(false);
+ newtChild.setVisible(false);
+ newtChild.reparentWindow(null);
+ }
+ if(DEBUG) {
+ System.err.println("NewtCanvasSWT.reparentWindow.X: add="+add+", win "+newtWinHandleToHexString(newtChild)+", EDTUtil: cur "+newtChild.getScreen().getDisplay().getEDTUtil());
+ }
+ }
+
+ private final void requestFocusNEWTChild() {
+ if( null != newtChild ) {
+ newtChild.setFocusAction(null);
+ newtChild.requestFocus();
+ }
+ }
+
+ @Override
+ public boolean forceFocus() {
+ final boolean res = NewtCanvasSWT.super.forceFocus();
+ requestFocusNEWTChild();
+ return res;
+ }
+
+ private class SWTNativeWindow implements NativeWindow {
+ private final AbstractGraphicsConfiguration config;
+ private final long nativeWindowHandle;
+ private final InsetsImmutable insets; // only required to allow proper client position calculation on OSX
+
+ public SWTNativeWindow(AbstractGraphicsConfiguration config, long nativeWindowHandle) {
+ this.config = config;
+ this.nativeWindowHandle = nativeWindowHandle;
+ if(isOSX) {
+ this.insets = OSXUtil.GetInsets(nativeWindowHandle);
+ } else {
+ this.insets = new Insets(0, 0, 0, 0);
+ }
+ }
+
+ @Override
+ public int lockSurface() throws NativeWindowException, RuntimeException {
+ return NativeSurface.LOCK_SUCCESS;
+ }
+
+ @Override
+ public void unlockSurface() { }
+
+ @Override
+ public boolean isSurfaceLockedByOtherThread() {
+ return false;
+ }
+
+ @Override
+ public Thread getSurfaceLockOwner() {
+ return null;
+ }
+
+ @Override
+ public boolean surfaceSwap() {
+ return false;
+ }
+
+ @Override
+ public void addSurfaceUpdatedListener(SurfaceUpdatedListener l) { }
+
+ @Override
+ public void addSurfaceUpdatedListener(int index, SurfaceUpdatedListener l) throws IndexOutOfBoundsException {
+ }
+
+ @Override
+ public void removeSurfaceUpdatedListener(SurfaceUpdatedListener l) { }
+
+ @Override
+ public long getSurfaceHandle() {
+ return 0;
+ }
+
+ @Override
+ public int getWidth() {
+ return clientArea.width;
+ }
+
+ @Override
+ public int getHeight() {
+ return clientArea.height;
+ }
+
+ @Override
+ public AbstractGraphicsConfiguration getGraphicsConfiguration() {
+ return config;
+ }
+
+ @Override
+ public long getDisplayHandle() {
+ return config.getScreen().getDevice().getHandle();
+ }
+
+ @Override
+ public int getScreenIndex() {
+ return config.getScreen().getIndex();
+ }
+
+ @Override
+ public void surfaceUpdated(Object updater, NativeSurface ns, long when) { }
+
+ @Override
+ public void destroy() { }
+
+ @Override
+ public NativeWindow getParent() {
+ return null;
+ }
+
+ @Override
+ public long getWindowHandle() {
+ return nativeWindowHandle;
+ }
+
+ @Override
+ public InsetsImmutable getInsets() {
+ return insets;
+ }
+
+ @Override
+ public int getX() {
+ return 0;
+ }
+
+ @Override
+ public int getY() {
+ return 0;
+ }
+
+ @Override
+ public Point getLocationOnScreen(Point point) {
+ if( isOSX ) {
+ final Point los = OSXUtil.GetLocationOnScreen(nativeWindowHandle, false, 0, 0);
+ // top-level position -> client window position
+ los.setX(los.getX() + insets.getLeftWidth());
+ los.setY(los.getY() + insets.getTopHeight());
+ if(null!=point) {
+ return point.translate(los);
+ } else {
+ return los;
+ }
+ } else {
+ // client position on 'normal' windowing systems is 0/0
+ if(null == point) {
+ point = new Point(0, 0);
+ }
+ return point;
+ }
+ }
+
+ @Override
+ public boolean hasFocus() {
+ return isFocusControl();
+ }
+ };
+
+ static String newtWinHandleToHexString(Window w) {
+ return null != w ? toHexString(w.getWindowHandle()) : "nil";
+ }
+ static String toHexString(long l) {
+ return "0x"+Long.toHexString(l);
+ }
+}
+
diff --git a/src/newt/classes/com/jogamp/newt/swt/SWTEDTUtil.java b/src/newt/classes/com/jogamp/newt/swt/SWTEDTUtil.java
new file mode 100644
index 000000000..3538caad2
--- /dev/null
+++ b/src/newt/classes/com/jogamp/newt/swt/SWTEDTUtil.java
@@ -0,0 +1,99 @@
+/**
+ * Copyright 2012 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 com.jogamp.newt.swt;
+
+import org.eclipse.swt.widgets.Display;
+
+import com.jogamp.newt.util.EDTUtil;
+
+/**
+ * Simple {@link EDTUtil} implementation utilizing the SWT UI thread
+ * of the given {@link Display}.
+ */
+public class SWTEDTUtil implements EDTUtil {
+ private final Display swtDisplay;
+
+ public SWTEDTUtil(Display swtDisplay) {
+ this.swtDisplay = swtDisplay;
+ }
+
+ public final Display getDisplay() {
+ return swtDisplay;
+ }
+
+ @Override
+ public long getPollPeriod() {
+ return 0;
+ }
+
+ @Override
+ public void setPollPeriod(long ms) {
+ }
+
+ @Override
+ public void reset() {
+ }
+
+ @Override
+ public void start() {
+ }
+
+ @Override
+ public boolean isCurrentThreadEDT() {
+ return swtDisplay.getThread() == Thread.currentThread();
+ }
+
+ @Override
+ public boolean isRunning() {
+ return true;
+ }
+
+ @Override
+ public void invokeStop(Runnable finalTask) {
+ swtDisplay.syncExec(finalTask);
+ }
+
+ @Override
+ public void invoke(boolean wait, Runnable task) {
+ if(wait) {
+ swtDisplay.syncExec(task);
+ } else {
+ swtDisplay.asyncExec(task);
+ }
+ }
+
+ @Override
+ public void waitUntilIdle() {
+ // all sync ..
+ }
+
+ @Override
+ public void waitUntilStopped() {
+ // all sync ..
+ }
+}
diff --git a/src/newt/classes/jogamp/newt/DisplayImpl.java b/src/newt/classes/jogamp/newt/DisplayImpl.java
index b10561c5b..b178bb5d3 100644
--- a/src/newt/classes/jogamp/newt/DisplayImpl.java
+++ b/src/newt/classes/jogamp/newt/DisplayImpl.java
@@ -101,7 +101,9 @@ public abstract class DisplayImpl extends Display {
display.hashCode = display.fqname.hashCode();
displayList.add(display);
}
- display.createEDTUtil();
+ if(null == display.edtUtil) {
+ display.setEDTUtil(null); // device's default if EDT is used, or null
+ }
if(DEBUG) {
System.err.println("Display.create() NEW: "+display+" "+getThreadName());
}
@@ -168,15 +170,45 @@ public abstract class DisplayImpl extends Display {
return true;
}
- protected void createEDTUtil() {
+ protected EDTUtil createEDTUtil() {
+ final EDTUtil def;
if(NewtFactory.useEDT()) {
- edtUtil = new DefaultEDTUtil(Thread.currentThread().getThreadGroup(), "Display-"+getFQName(), dispatchMessagesRunnable);
+ def = new DefaultEDTUtil(Thread.currentThread().getThreadGroup(), "Display-"+getFQName(), dispatchMessagesRunnable);
if(DEBUG) {
- System.err.println("Display.createNative("+getFQName()+") Create EDTUtil: "+edtUtil.getClass().getName());
+ System.err.println("Display.createNative("+getFQName()+") Create EDTUtil: "+def.getClass().getName());
}
+ } else {
+ def = null;
}
+ return def;
}
+ @Override
+ public EDTUtil setEDTUtil(EDTUtil newEDTUtil) {
+ if(null == newEDTUtil) {
+ newEDTUtil = createEDTUtil();
+ }
+ if( newEDTUtil == edtUtil ) {
+ if(DEBUG) {
+ System.err.println("Display.setEDTUtil: "+newEDTUtil+" - keep!");
+ }
+ return null; // no change
+ }
+ final EDTUtil oldEDTUtil = edtUtil;
+ if(DEBUG) {
+ System.err.println("Display.setEDTUtil: "+oldEDTUtil+" -> "+newEDTUtil);
+ }
+ if(null != oldEDTUtil) {
+ stopEDT( new Runnable() { public void run() {} } );
+ // ready for restart ..
+ oldEDTUtil.waitUntilStopped();
+ oldEDTUtil.reset();
+ }
+ edtUtil = newEDTUtil;
+ return oldEDTUtil;
+ }
+
+ @Override
public final EDTUtil getEDTUtil() {
return edtUtil;
}
diff --git a/src/newt/classes/jogamp/newt/WindowImpl.java b/src/newt/classes/jogamp/newt/WindowImpl.java
index b12e42680..606101ade 100644
--- a/src/newt/classes/jogamp/newt/WindowImpl.java
+++ b/src/newt/classes/jogamp/newt/WindowImpl.java
@@ -445,9 +445,14 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
protected abstract void closeNativeImpl();
/**
- * The native implementation must invoke {@link #focusChanged(boolean, boolean)}
- * to change the focus state, if <code>force == false</code>.
- * This may happen asynchronous within {@link #TIMEOUT_NATIVEWINDOW}.
+ * Async request which shall be performed within {@link #TIMEOUT_NATIVEWINDOW}.
+ * <p>
+ * If if <code>force == false</code> the native implementation
+ * may only request focus if not yet owner.</p>
+ * <p>
+ * {@link #focusChanged(boolean, boolean)} should be called
+ * to notify about the focus traversal.
+ * </p>
*
* @param force if true, bypass {@link #focusChanged(boolean, boolean)} and force focus request
*/
diff --git a/src/newt/classes/jogamp/newt/awt/event/AWTParentWindowAdapter.java b/src/newt/classes/jogamp/newt/awt/event/AWTParentWindowAdapter.java
index ce8ed7c49..747e2368e 100644
--- a/src/newt/classes/jogamp/newt/awt/event/AWTParentWindowAdapter.java
+++ b/src/newt/classes/jogamp/newt/awt/event/AWTParentWindowAdapter.java
@@ -34,6 +34,7 @@ import javax.media.nativewindow.NativeWindow;
import jogamp.newt.driver.DriverUpdatePosition;
+import com.jogamp.newt.Window;
import com.jogamp.newt.event.awt.AWTAdapter;
import com.jogamp.newt.event.awt.AWTWindowAdapter;
@@ -92,19 +93,20 @@ public class AWTParentWindowAdapter
if(DEBUG_IMPLEMENTATION) {
System.err.println("AWT: componentResized: "+comp);
}
- getNewtWindow().runOnEDTIfAvail(false, new Runnable() {
+ final Window newtWindow = getNewtWindow();
+ newtWindow.runOnEDTIfAvail(false, new Runnable() {
public void run() {
int cw = comp.getWidth();
int ch = comp.getHeight();
if( 0 < cw * ch ) {
- if( getNewtWindow().getWidth() != cw || getNewtWindow().getHeight() != ch ) {
- getNewtWindow().setSize(cw, ch);
- if(comp.isVisible() != getNewtWindow().isVisible()) {
- getNewtWindow().setVisible(comp.isVisible());
+ if( newtWindow.getWidth() != cw || newtWindow.getHeight() != ch ) {
+ newtWindow.setSize(cw, ch);
+ if(comp.isVisible() != newtWindow.isVisible()) {
+ newtWindow.setVisible(comp.isVisible());
}
}
- } else if(getNewtWindow().isVisible()) {
- getNewtWindow().setVisible(false);
+ } else if(newtWindow.isVisible()) {
+ newtWindow.setVisible(false);
}
}});
}
@@ -113,8 +115,9 @@ public class AWTParentWindowAdapter
if(DEBUG_IMPLEMENTATION) {
System.err.println("AWT: componentMoved: "+e);
}
- if(getNewtWindow().getDelegatedWindow() instanceof DriverUpdatePosition) {
- ((DriverUpdatePosition)getNewtWindow().getDelegatedWindow()).updatePosition();
+ final Window newtWindow = getNewtWindow();
+ if(newtWindow.getDelegatedWindow() instanceof DriverUpdatePosition) {
+ ((DriverUpdatePosition)newtWindow.getDelegatedWindow()).updatePosition();
}
}
diff --git a/src/newt/classes/jogamp/newt/driver/awt/AWTDisplay.java b/src/newt/classes/jogamp/newt/driver/awt/AWTDisplay.java
index 166da5c1c..65f8b4715 100644
--- a/src/newt/classes/jogamp/newt/driver/awt/AWTDisplay.java
+++ b/src/newt/classes/jogamp/newt/driver/awt/AWTDisplay.java
@@ -36,6 +36,7 @@ package jogamp.newt.driver.awt;
import com.jogamp.nativewindow.awt.AWTGraphicsDevice;
import com.jogamp.newt.NewtFactory;
+import com.jogamp.newt.util.EDTUtil;
import jogamp.newt.DisplayImpl;
@@ -54,13 +55,17 @@ public class AWTDisplay extends DisplayImpl {
protected void closeNativeImpl() { }
@Override
- protected void createEDTUtil() {
+ protected EDTUtil createEDTUtil() {
+ final EDTUtil def;
if(NewtFactory.useEDT()) {
- edtUtil = AWTEDTUtil.getSingleton();
+ def = AWTEDTUtil.getSingleton();
if(DEBUG) {
- System.err.println("AWTDisplay.createNative("+getFQName()+") Create EDTUtil: "+edtUtil.getClass().getName());
+ System.err.println("AWTDisplay.createNative("+getFQName()+") Create EDTUtil: "+def.getClass().getName());
}
+ } else {
+ def = null;
}
+ return def;
}
protected void dispatchMessagesNative() { /* nop */ }
diff --git a/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java b/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java
index 720d4ee4c..27d7a1679 100644
--- a/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java
+++ b/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java
@@ -150,7 +150,7 @@ public class MacWindow extends WindowImpl implements MutableSurface, DriverClear
System.err.println("MacWindow: clearFocus() - requestFocusParent, isOffscreenInstance "+isOffscreenInstance);
}
if(!isOffscreenInstance) {
- requestFocusParent0(getWindowHandle());
+ resignFocus0(getWindowHandle());
} else {
focusChanged(false, false);
}
@@ -360,7 +360,6 @@ public class MacWindow extends WindowImpl implements MutableSurface, DriverClear
if(recreate && 0==surfaceHandle) {
throw new NativeWindowException("Internal Error - recreate, window but no view");
}
- orderOut0(getWindowHandle());
close0(getWindowHandle());
setWindowHandle(0);
} else {
@@ -397,7 +396,7 @@ public class MacWindow extends WindowImpl implements MutableSurface, DriverClear
private native boolean lockSurface0(long window);
private native void unlockSurface0(long window);
private native void requestFocus0(long window, boolean force);
- private native void requestFocusParent0(long window);
+ private native void resignFocus0(long window);
/** in case of a child window, it actually only issues orderBack(..) */
private native void orderOut0(long window);
private native void orderFront0(long window);
diff --git a/src/newt/classes/jogamp/newt/driver/windows/WindowsWindow.java b/src/newt/classes/jogamp/newt/driver/windows/WindowsWindow.java
index 34d76a148..6a8c81f3d 100644
--- a/src/newt/classes/jogamp/newt/driver/windows/WindowsWindow.java
+++ b/src/newt/classes/jogamp/newt/driver/windows/WindowsWindow.java
@@ -151,8 +151,8 @@ public class WindowsWindow extends WindowImpl {
}
protected void closeNativeImpl() {
- if (hdc != 0) {
- if(windowHandleClose != 0) {
+ if(windowHandleClose != 0) {
+ if (hdc != 0) {
try {
GDI.ReleaseDC(windowHandleClose, hdc);
} catch (Throwable t) {
@@ -162,11 +162,8 @@ public class WindowsWindow extends WindowImpl {
}
}
}
- hdc = 0;
- hdc_old = 0;
- }
- if(windowHandleClose != 0) {
try {
+ GDI.SetParent(windowHandleClose, 0); // detach first, experience hang w/ SWT parent
GDI.DestroyWindow(windowHandleClose);
} catch (Throwable t) {
if(DEBUG_IMPLEMENTATION) {
@@ -177,6 +174,8 @@ public class WindowsWindow extends WindowImpl {
windowHandleClose = 0;
}
}
+ hdc = 0;
+ hdc_old = 0;
}
protected boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) {
diff --git a/src/newt/native/MacWindow.m b/src/newt/native/MacWindow.m
index 01cbd80ec..bbadc9dd0 100644
--- a/src/newt/native/MacWindow.m
+++ b/src/newt/native/MacWindow.m
@@ -599,6 +599,15 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_MacWindow_createWindow0
}
DBG_PRINT( "createWindow0 - is visible.1: %d\n", [myWindow isVisible]);
+ // Remove animations for child windows
+ if(NULL != parentWindow) {
+NS_DURING
+ // Available >= 10.7 - Removes default animations
+ [myWindow setAnimationBehavior: NSWindowAnimationBehaviorNone];
+NS_HANDLER
+NS_ENDHANDLER
+ }
+
#ifdef VERBOSE_ON
int dbgIdx = 1;
#endif
@@ -734,7 +743,7 @@ NS_ENDHANDLER
if(NULL!=pWin) {
[mWin detachFromParent: pWin];
}
- [mWin orderOut: mWin];
+ [mWin performSelectorOnMainThread:@selector(orderOut:) withObject:mWin waitUntilDone:NO];
DBG_PRINT( "windowClose.1 - %p,%d view %p,%d, parent %p\n",
mWin, getRetainCount(mWin), mView, getRetainCount(mView), pWin);
@@ -742,11 +751,6 @@ NS_ENDHANDLER
// Only release window, if release is not yet in process.
// E.g. destroyNotifySent:=true set by NewtMacWindow::windowWillClose(), i.e. window-close was clicked.
if(!destroyNotifySent) {
- // '[mWin close]' causes a crash at exit.
- // This probably happens b/c it sends events to the main loop
- // but our resources are gone ?!
- // However, issuing a simple release seems to work quite well.
- // [mWin release];
[mWin performSelectorOnMainThread:@selector(release) withObject:nil waitUntilDone:NO];
}
@@ -806,11 +810,8 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_requestFocus0
DBG_PRINT( "requestFocus - window: %p, force %d, hasFocus %d (START)\n", mWin, force, hasFocus);
[mWin makeFirstResponder: nil];
- [mWin performSelectorOnMainThread:@selector(orderFrontRegardless) withObject:nil waitUntilDone:YES];
- [mWin performSelectorOnMainThread:@selector(makeKeyWindow) withObject:nil waitUntilDone:YES];
- // This will occasionally cause a free of non allocated object crash:
- // [mWin orderFrontRegardless];
- // [mWin makeKeyWindow];
+ [mWin performSelectorOnMainThread:@selector(orderFrontRegardless) withObject:nil waitUntilDone:NO];
+ [mWin performSelectorOnMainThread:@selector(makeKeyWindow) withObject:nil waitUntilDone:NO];
DBG_PRINT( "requestFocus - window: %p, force %d (END)\n", mWin, force);
@@ -819,26 +820,27 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_requestFocus0
/*
* Class: jogamp_newt_driver_macosx_MacWindow
- * Method: requestFocusParent0
+ * Method: resignFocus0
* Signature: (J)V
*/
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_requestFocusParent0
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_resignFocus0
(JNIEnv *env, jobject window, jlong w)
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NSWindow* mWin = (NSWindow*) ((intptr_t) w);
NSWindow* pWin = [mWin parentWindow];
-#ifdef VERBOSE_ON
BOOL hasFocus = [mWin isKeyWindow];
-#endif
- DBG_PRINT( "requestFocusParent0 - window: %p, parent: %p, hasFocus %d (START)\n", mWin, pWin, hasFocus );
- if(NULL != pWin) {
- [pWin performSelectorOnMainThread:@selector(makeKeyWindow) withObject:nil waitUntilDone:YES];
- // This will occasionally cause a free of non allocated object crash:
- // [pWin makeKeyWindow];
+ DBG_PRINT( "requestFocusParent0 - window: %p, parent %p, hasFocus %d (START)\n", mWin, pWin, hasFocus );
+ if( hasFocus ) {
+ if(NULL != pWin) {
+ // [mWin performSelectorOnMainThread:@selector(makeFirstResponder:) withObject:pWin waitUntilDone:NO];
+ [pWin performSelectorOnMainThread:@selector(makeKeyWindow) withObject:nil waitUntilDone:NO];
+ } else {
+ [mWin performSelectorOnMainThread:@selector(resignKeyWindow) withObject:nil waitUntilDone:NO];
+ }
}
- DBG_PRINT( "requestFocusParent0 - window: %p, parent: %p (END)\n", mWin, pWin);
+ DBG_PRINT( "requestFocusParent0 - window: %p (END)\n", mWin);
[pool release];
}
@@ -856,9 +858,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_orderFront0
DBG_PRINT( "orderFront0 - window: %p (START)\n", win);
- [win performSelectorOnMainThread:@selector(orderFrontRegardless) withObject:nil waitUntilDone:YES];
- // This will occasionally cause a free of non allocated object crash:
- // [win orderFrontRegardless];
+ [win performSelectorOnMainThread:@selector(orderFrontRegardless) withObject:nil waitUntilDone:NO];
DBG_PRINT( "orderFront0 - window: %p (END)\n", win);
@@ -880,13 +880,9 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_orderOut0
DBG_PRINT( "orderOut0 - window: (parent %p) %p (START)\n", pWin, mWin);
if(NULL == pWin) {
- [mWin performSelectorOnMainThread:@selector(orderOut:) withObject:mWin waitUntilDone:YES];
- // This will occasionally cause a free of non allocated object crash:
- // [mWin orderOut: mWin];
+ [mWin performSelectorOnMainThread:@selector(orderOut:) withObject:mWin waitUntilDone:NO];
} else {
- [mWin performSelectorOnMainThread:@selector(orderBack:) withObject:mWin waitUntilDone:YES];
- // This will occasionally cause a free of non allocated object crash:
- // [mWin orderBack: mWin];
+ [mWin performSelectorOnMainThread:@selector(orderBack:) withObject:mWin waitUntilDone:NO];
}
DBG_PRINT( "orderOut0 - window: (parent %p) %p (END)\n", pWin, mWin);
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestNewtCanvasSWTGLn.java b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestNewtCanvasSWTGLn.java
new file mode 100644
index 000000000..6a27e6f27
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestNewtCanvasSWTGLn.java
@@ -0,0 +1,233 @@
+/**
+ * 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 com.jogamp.opengl.test.junit.jogl.swt;
+
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLProfile;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.After;
+import org.junit.Test;
+
+import com.jogamp.nativewindow.swt.SWTAccessor;
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.newt.swt.NewtCanvasSWT;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.MultisampleDemoES2;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.util.GLReadBufferUtil;
+import com.jogamp.opengl.util.texture.TextureIO;
+
+/**
+ * Tests that a basic SWT app can open without crashing under different GL profiles
+ * _and_ custom GLCapabilities.
+ * <p>
+ * Uses JOGL's NewtCanvasSWT, which allows to be a native container of a NEWT Window.<br/>
+ * This method allows utilizing custom GLCapability settings,
+ * independent from the already instantiated SWT visual.
+ * </p>
+ * <p>
+ * Note that {@link SWTAccessor#invoke(boolean, Runnable)} is still used to comply w/
+ * SWT running on Mac OSX, i.e. to enforce UI action on the main thread.
+ * </p>
+ */
+public class TestNewtCanvasSWTGLn extends UITestCase {
+
+ static int duration = 250;
+
+ static final int iwidth = 640;
+ static final int iheight = 480;
+
+ Display display = null;
+ Shell shell = null;
+ Composite composite = null;
+
+ @BeforeClass
+ public static void startup() {
+ System.out.println( "GLProfile " + GLProfile.glAvailabilityToString() );
+ }
+
+ @Before
+ public void init() {
+ SWTAccessor.invoke(true, new Runnable() {
+ public void run() {
+ display = new Display();
+ Assert.assertNotNull( display );
+ shell = new Shell( display );
+ Assert.assertNotNull( shell );
+ shell.setLayout( new FillLayout() );
+ composite = new Composite( shell, SWT.NONE );
+ composite.setLayout( new FillLayout() );
+ Assert.assertNotNull( composite );
+ }});
+ }
+
+ @After
+ public void release() {
+ Assert.assertNotNull( display );
+ Assert.assertNotNull( shell );
+ Assert.assertNotNull( composite );
+ try {
+ SWTAccessor.invoke(true, new Runnable() {
+ public void run() {
+ composite.dispose();
+ shell.dispose();
+ display.dispose();
+ }});
+ }
+ catch( Throwable throwable ) {
+ throwable.printStackTrace();
+ Assume.assumeNoException( throwable );
+ }
+ display = null;
+ shell = null;
+ composite = null;
+ }
+
+ protected void runTestAGL( GLCapabilitiesImmutable caps, GLEventListener demo,
+ boolean postAttach, boolean useAnimator ) throws InterruptedException {
+ final GLReadBufferUtil screenshot = new GLReadBufferUtil(false, false);
+
+ final GLWindow glWindow1 = GLWindow.create(caps);
+ Assert.assertNotNull(glWindow1);
+ Assert.assertEquals(false, glWindow1.isVisible());
+ Assert.assertEquals(false, glWindow1.isNativeValid());
+ Assert.assertNull(glWindow1.getParent());
+ glWindow1.addGLEventListener(demo);
+ glWindow1.addGLEventListener(new GLEventListener() {
+ int displayCount = 0;
+ public void init(final GLAutoDrawable drawable) { }
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { }
+ public void display(final GLAutoDrawable drawable) {
+ if(displayCount < 3) {
+ snapshot(getSimpleTestName("."), displayCount++, null, drawable.getGL(), screenshot, TextureIO.PNG, null);
+ }
+ }
+ public void dispose(final GLAutoDrawable drawable) { }
+ });
+
+ final NewtCanvasSWT canvas1 = NewtCanvasSWT.create( composite, 0, postAttach ? null : glWindow1 );
+ Assert.assertNotNull( canvas1 );
+
+ SWTAccessor.invoke(true, new Runnable() {
+ public void run() {
+ shell.setText( getSimpleTestName(".") );
+ shell.setSize( 640, 480 );
+ shell.open();
+ }
+ });
+
+ if(postAttach) {
+ canvas1.setNEWTChild(glWindow1);
+ }
+
+ // canvas1.update();
+
+ Animator anim;
+ if(useAnimator) {
+ anim = new Animator(glWindow1);
+ anim.start();
+ } else {
+ anim = null;
+ }
+
+ long lStartTime = System.currentTimeMillis();
+ long lEndTime = lStartTime + duration;
+ try {
+ while( (System.currentTimeMillis() < lEndTime) && !canvas1.isDisposed() ) {
+ if( !display.readAndDispatch() ) {
+ // blocks on linux .. display.sleep();
+ Thread.sleep(10);
+ }
+ }
+ } catch( Throwable throwable ) {
+ throwable.printStackTrace();
+ Assume.assumeNoException( throwable );
+ }
+ if(null != anim) {
+ anim.stop();
+ }
+
+ canvas1.dispose();
+ }
+
+ @Test
+ public void preAttach_WithAnimator() throws InterruptedException {
+ runTestAGL( new GLCapabilities(GLProfile.getGL2ES2()), new GearsES2(), false /* postAttach */, true /* animator */);
+ }
+
+ @Test
+ public void preAttach_NoAnimator() throws InterruptedException {
+ runTestAGL( new GLCapabilities(GLProfile.getGL2ES2()), new GearsES2(), false /* postAttach */, false /* animator */);
+ }
+
+ @Test
+ public void postAttach_WithAnimator() throws InterruptedException {
+ runTestAGL( new GLCapabilities(GLProfile.getGL2ES2()), new GearsES2(), true /* postAttach */, true /* animator */);
+ }
+
+ @Test
+ public void test_MultisampleAndAlpha() throws InterruptedException {
+ GLCapabilities caps = new GLCapabilities(GLProfile.getGL2ES2());
+ caps.setSampleBuffers(true);
+ caps.setNumSamples(2);
+ runTestAGL( caps, new MultisampleDemoES2(true), false /* postAttach */, false /* animator */);
+ }
+
+ static int atoi(String a) {
+ int i=0;
+ try {
+ i = Integer.parseInt(a);
+ } catch (Exception ex) { ex.printStackTrace(); }
+ return i;
+ }
+
+ public static void main(String args[]) {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ duration = atoi(args[++i]);
+ }
+ }
+ System.out.println("durationPerTest: "+duration);
+ org.junit.runner.JUnitCore.main(TestNewtCanvasSWTGLn.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTAccessor02GLn.java b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTAccessor02GLn.java
deleted file mode 100644
index 2e225ec0e..000000000
--- a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTAccessor02GLn.java
+++ /dev/null
@@ -1,278 +0,0 @@
-/**
- * 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 com.jogamp.opengl.test.junit.jogl.swt;
-
-import javax.media.opengl.GL2ES1;
-import javax.media.opengl.GLContext;
-import javax.media.opengl.GLDrawableFactory;
-import javax.media.opengl.GLProfile;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.ControlEvent;
-import org.eclipse.swt.events.ControlListener;
-import org.eclipse.swt.events.PaintEvent;
-import org.eclipse.swt.events.PaintListener;
-import org.eclipse.swt.graphics.Rectangle;
-import org.eclipse.swt.layout.FillLayout;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Event;
-import org.eclipse.swt.widgets.Listener;
-import org.eclipse.swt.widgets.Shell;
-
-import org.junit.Assert;
-import org.junit.Assume;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.After;
-import org.junit.Test;
-
-import com.jogamp.nativewindow.swt.SWTAccessor;
-import com.jogamp.opengl.test.junit.jogl.demos.es1.OneTriangle;
-import com.jogamp.opengl.test.junit.util.UITestCase;
-import javax.media.nativewindow.AbstractGraphicsDevice;
-import javax.media.nativewindow.ProxySurface;
-import javax.media.opengl.GLCapabilities;
-import javax.media.opengl.GLDrawable;
-import org.eclipse.swt.widgets.Canvas;
-
-/**
- * Tests that a basic SWT app can open without crashing under different GL profiles.
- * <p>
- * Uses JOGL's SWTAccessor only.
- * </p>
- * @author Wade Walker, et.al.
- */
-public class TestSWTAccessor02GLn extends UITestCase {
-
- static int duration = 250;
-
- static final int iwidth = 640;
- static final int iheight = 480;
-
- Display display = null;
- Shell shell = null;
- Composite composite = null;
-
- @BeforeClass
- public static void startup() {
- System.out.println( "GLProfile " + GLProfile.glAvailabilityToString() );
- }
-
- @Before
- public void init() {
- SWTAccessor.invoke(true, new Runnable() {
- public void run() {
- display = new Display();
- Assert.assertNotNull( display );
- shell = new Shell( display );
- Assert.assertNotNull( shell );
- shell.setLayout( new FillLayout() );
- composite = new Composite( shell, SWT.NONE );
- composite.setLayout( new FillLayout() );
- Assert.assertNotNull( composite );
- }});
- }
-
- @After
- public void release() {
- Assert.assertNotNull( display );
- Assert.assertNotNull( shell );
- Assert.assertNotNull( composite );
- try {
- SWTAccessor.invoke(true, new Runnable() {
- public void run() {
- composite.dispose();
- shell.dispose();
- display.dispose();
- }});
- }
- catch( Throwable throwable ) {
- throwable.printStackTrace();
- Assume.assumeNoException( throwable );
- }
- display = null;
- shell = null;
- composite = null;
- }
-
- protected void runTestAGL( GLProfile glprofile ) throws InterruptedException {
- GLCapabilities caps = new GLCapabilities(glprofile);
- GLDrawableFactory factory = GLDrawableFactory.getFactory(glprofile);
-
- // need SWT.NO_BACKGROUND to prevent SWT from clearing the window
- // at the wrong times (we use glClear for this instead)
- final Canvas canvas = new Canvas( composite, SWT.NO_BACKGROUND);
- Assert.assertNotNull( canvas );
- SWTAccessor.setRealized(canvas, true);
-
- AbstractGraphicsDevice device = SWTAccessor.getDevice(canvas);
- long nativeWindowHandle = SWTAccessor.getWindowHandle(canvas);
- System.err.println("*** device: " + device);
- System.err.println("*** window handle: 0x" + Long.toHexString(nativeWindowHandle));
-
- final SWTUpstreamHook swtUpstreamHook = new SWTUpstreamHook(canvas);
- canvas.addControlListener(swtUpstreamHook);
-
- final ProxySurface proxySurface = factory.createProxySurface(device, 0, nativeWindowHandle, caps, null, swtUpstreamHook);
- Assert.assertNotNull( proxySurface );
- System.err.println("*** ProxySurface: " + proxySurface);
-
- final GLDrawable drawable = factory.createGLDrawable(proxySurface);
- Assert.assertNotNull( drawable );
- drawable.setRealized(true);
- System.err.println("*** Drawable: " + drawable);
- Assert.assertTrue( drawable.isRealized() );
-
- final GLContext glcontext = drawable.createContext(null);
- // trigger native creation ..
- if( GLContext.CONTEXT_NOT_CURRENT < glcontext.makeCurrent() ) {
- glcontext.release();
- }
-
- final boolean[] sizeMissing = new boolean[] { false };
-
- // fix the viewport when the user resizes the window
- canvas.addListener( SWT.Resize, new Listener() {
- public void handleEvent( Event event ) {
- Rectangle rectangle = canvas.getClientArea();
- boolean glok=false;
- if( GLContext.CONTEXT_NOT_CURRENT < glcontext.makeCurrent() ) {
- glok=true;
- GL2ES1 gl = glcontext.getGL().getGL2ES1();
- OneTriangle.setup( gl, rectangle.width, rectangle.height );
- glcontext.release();
- } else {
- sizeMissing[0] = true;
- }
- System.err.println("resize: glok " + glok);
- }
- });
-
- // draw the triangle when the OS tells us that any part of the window needs drawing
- canvas.addPaintListener( new PaintListener() {
- public void paintControl( PaintEvent paintevent ) {
- Rectangle rectangle = canvas.getClientArea();
- boolean glok=false;
- if( GLContext.CONTEXT_NOT_CURRENT < glcontext.makeCurrent() ) {
- glok=true;
- GL2ES1 gl = glcontext.getGL().getGL2ES1();
- if(sizeMissing[0]) {
- OneTriangle.setup( gl, rectangle.width, rectangle.height);
- sizeMissing[0] = false;
- }
- OneTriangle.render( gl, rectangle.width, rectangle.height);
- drawable.swapBuffers();
- glcontext.release();
- }
- System.err.println("paint: glok " + glok);
- }
- });
-
- shell.setText( getClass().getName() );
- shell.setSize( 640, 480 );
- shell.open();
-
- long lStartTime = System.currentTimeMillis();
- long lEndTime = lStartTime + duration;
- try {
- while( (System.currentTimeMillis() < lEndTime) && !canvas.isDisposed() ) {
- if( !display.readAndDispatch() ) {
- // blocks on linux .. display.sleep();
- Thread.sleep(10);
- }
- }
- } catch( Throwable throwable ) {
- throwable.printStackTrace();
- Assume.assumeNoException( throwable );
- }
- glcontext.destroy();
- drawable.setRealized(false);
- canvas.dispose();
- }
- private static class SWTUpstreamHook implements ProxySurface.UpstreamSurfaceHook, ControlListener {
- private Canvas c;
- Rectangle clientArea;
- public SWTUpstreamHook(Canvas c) {
- this.c = c ;
- this.clientArea = c.getClientArea();
- }
- @Override
- public final void create(ProxySurface s) { /* nop */ }
-
- @Override
- public final void destroy(ProxySurface s) { /* nop */ }
-
- @Override
- public final int getWidth(ProxySurface s) {
- return clientArea.width;
- }
- @Override
- public final int getHeight(ProxySurface s) {
- return clientArea.width;
- }
-
- @Override
- public void controlResized(final ControlEvent arg0) {
- clientArea = c.getClientArea();
- }
- @Override
- public void controlMoved(ControlEvent e) {
- }
- @Override
- public String toString() {
- final String us_s = null != c ? c.toString() : "nil";
- return "SETUpstreamSurfaceHook[upstream: "+us_s+"]";
- }
- };
-
- @Test
- public void test() throws InterruptedException {
- GLProfile glprofile = GLProfile.getGL2ES1();
- runTestAGL( glprofile );
- }
-
- static int atoi(String a) {
- int i=0;
- try {
- i = Integer.parseInt(a);
- } catch (Exception ex) { ex.printStackTrace(); }
- return i;
- }
-
- public static void main(String args[]) {
- for(int i=0; i<args.length; i++) {
- if(args[i].equals("-time")) {
- duration = atoi(args[++i]);
- }
- }
- System.out.println("durationPerTest: "+duration);
- org.junit.runner.JUnitCore.main(TestSWTAccessor02GLn.class.getName());
- }
-}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTJOGLGLCanvas01GLn.java b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTJOGLGLCanvas01GLn.java
index 19e76419f..4ca1dae0d 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTJOGLGLCanvas01GLn.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTJOGLGLCanvas01GLn.java
@@ -49,8 +49,10 @@ import org.junit.Test;
import com.jogamp.nativewindow.swt.SWTAccessor;
import com.jogamp.opengl.swt.GLCanvas;
-import com.jogamp.opengl.test.junit.jogl.demos.es1.OneTriangle;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.GLReadBufferUtil;
+import com.jogamp.opengl.util.texture.TextureIO;
/**
* Tests that a basic SWT app can open without crashing under different GL profiles.
@@ -58,6 +60,9 @@ import com.jogamp.opengl.test.junit.util.UITestCase;
* Uses JOGL's new SWT GLCanvas.
* </p>
* <p>
+ * Note: To employ custom GLCapabilities, NewtCanvasSWT shall be used.
+ * </p>
+ * <p>
* Note that {@link SWTAccessor#invoke(boolean, Runnable)} is still used to comply w/
* SWT running on Mac OSX, i.e. to enforce UI action on the main thread.
* </p>
@@ -116,34 +121,32 @@ public class TestSWTJOGLGLCanvas01GLn extends UITestCase {
composite = null;
}
- protected void runTestAGL( GLProfile glprofile ) throws InterruptedException {
- // need SWT.NO_BACKGROUND to prevent SWT from clearing the window
- // at the wrong times (we use glClear for this instead)
- final GLCapabilitiesImmutable caps = new GLCapabilities( glprofile );
+ protected void runTestAGL( GLCapabilitiesImmutable caps, GLEventListener demo ) throws InterruptedException {
+ final GLReadBufferUtil screenshot = new GLReadBufferUtil(false, false);
- final GLCanvas canvas = new GLCanvas( composite, 0, caps, null, null);
+ final GLCanvas canvas = GLCanvas.create( composite, 0, caps, null, null);
Assert.assertNotNull( canvas );
+ canvas.addGLEventListener( demo );
canvas.addGLEventListener(new GLEventListener() {
- public void init(final GLAutoDrawable drawable) {
- System.err.println(Thread.currentThread().getName()+" - SWT Canvas - GLEventListener - init()");
- }
- public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
- System.err.println(Thread.currentThread().getName()+" - SWT Canvas - GLEventListener - reshape()");
- OneTriangle.setup( drawable.getGL().getGL2(), width, height );
- }
+ int displayCount = 0;
+ public void init(final GLAutoDrawable drawable) { }
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { }
public void display(final GLAutoDrawable drawable) {
- OneTriangle.render( drawable.getGL().getGL2(), drawable.getWidth(), drawable.getHeight());
+ if(displayCount < 3) {
+ snapshot(getSimpleTestName("."), displayCount++, null, drawable.getGL(), screenshot, TextureIO.PNG, null);
+ }
}
- public void dispose(final GLAutoDrawable drawable) {
- System.err.println(Thread.currentThread().getName()+" - SWT Canvas - GLEventListener - dispose()");
- }
- });
+ public void dispose(final GLAutoDrawable drawable) { }
+ });
- shell.setText( getClass().getName() );
- shell.setSize( 640, 480 );
- shell.open();
-
+ SWTAccessor.invoke(true, new Runnable() {
+ public void run() {
+ shell.setText( getSimpleTestName(".") );
+ shell.setSize( 640, 480 );
+ shell.open();
+ } } );
+
long lStartTime = System.currentTimeMillis();
long lEndTime = lStartTime + duration;
try {
@@ -157,13 +160,15 @@ public class TestSWTJOGLGLCanvas01GLn extends UITestCase {
throwable.printStackTrace();
Assume.assumeNoException( throwable );
}
- canvas.dispose();
+ SWTAccessor.invoke(true, new Runnable() {
+ public void run() {
+ canvas.dispose();
+ } } );
}
@Test
public void test() throws InterruptedException {
- GLProfile glprofile = GLProfile.getGL2ES1();
- runTestAGL( glprofile );
+ runTestAGL( new GLCapabilities(GLProfile.getGL2ES2()), new GearsES2() );
}
static int atoi(String a) {
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01aSWT.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01aSWT.java
new file mode 100644
index 000000000..11aef7c24
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01aSWT.java
@@ -0,0 +1,210 @@
+/**
+ * Copyright 2012 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 com.jogamp.opengl.test.junit.newt.parenting;
+
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLEventListener;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import com.jogamp.nativewindow.swt.SWTAccessor;
+import com.jogamp.newt.Window;
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.newt.swt.NewtCanvasSWT;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+
+/**
+ * Simple visibility test ..
+ */
+public class TestParenting01aSWT extends UITestCase {
+ static int width, height;
+ static long durationPerTest = 800;
+ static GLCapabilities glCaps;
+
+ Display display = null;
+ Shell shell = null;
+ Composite composite1 = null;
+
+ @BeforeClass
+ public static void initClass() {
+ width = 640;
+ height = 480;
+ glCaps = new GLCapabilities(null);
+ }
+
+ @Before
+ public void init() {
+ SWTAccessor.invoke(true, new Runnable() {
+ public void run() {
+ display = new Display();
+ Assert.assertNotNull( display );
+ shell = new Shell( display );
+ Assert.assertNotNull( shell );
+ shell.setLayout( new FillLayout() );
+ composite1 = new Composite( shell, SWT.NONE );
+ composite1.setLayout( new FillLayout() );
+ Assert.assertNotNull( composite1 );
+ }});
+ }
+
+ @After
+ public void release() {
+ Assert.assertNotNull( display );
+ Assert.assertNotNull( shell );
+ Assert.assertNotNull( composite1 );
+ try {
+ SWTAccessor.invoke(true, new Runnable() {
+ public void run() {
+ composite1.dispose();
+ shell.dispose();
+ display.dispose();
+ }});
+ }
+ catch( Throwable throwable ) {
+ throwable.printStackTrace();
+ Assume.assumeNoException( throwable );
+ }
+ display = null;
+ shell = null;
+ composite1 = null;
+ }
+
+ @Test
+ public void testWindowParenting01CreateVisibleDestroy1() throws InterruptedException, InvocationTargetException {
+
+ GLWindow glWindow1 = GLWindow.create(glCaps);
+ Assert.assertNotNull(glWindow1);
+ Assert.assertEquals(false, glWindow1.isVisible());
+ Assert.assertEquals(false, glWindow1.isNativeValid());
+ Assert.assertNull(glWindow1.getParent());
+ glWindow1.setTitle("testWindowParenting01CreateVisibleDestroy");
+ GLEventListener demo1 = new RedSquareES2();
+ setDemoFields(demo1, glWindow1, false);
+ glWindow1.addGLEventListener(demo1);
+
+ final NewtCanvasSWT canvas1 = NewtCanvasSWT.create( composite1, 0, glWindow1 );
+ Assert.assertNotNull(canvas1);
+ Assert.assertEquals(false, glWindow1.isVisible());
+ Assert.assertEquals(false, glWindow1.isNativeValid());
+ Assert.assertNull(glWindow1.getParent());
+
+ SWTAccessor.invoke(true, new Runnable() {
+ public void run() {
+ shell.setText( getSimpleTestName(".") );
+ shell.setSize( 640, 480 );
+ shell.open();
+ }
+ });
+
+ // visible test
+ Assert.assertEquals(canvas1.getNativeWindow(),glWindow1.getParent());
+
+ for(int i=0; i*10<durationPerTest; i++) {
+ if( !display.readAndDispatch() ) {
+ // blocks on linux .. display.sleep();
+ Thread.sleep(10);
+ }
+ }
+
+ SWTAccessor.invoke(true, new Runnable() {
+ public void run() {
+ canvas1.setVisible(false);
+ }
+ });
+ Assert.assertEquals(true, glWindow1.isNativeValid());
+
+ SWTAccessor.invoke(true, new Runnable() {
+ public void run() {
+ canvas1.setVisible(true);
+ }
+ });
+ Assert.assertEquals(true, glWindow1.isNativeValid());
+
+ canvas1.dispose();
+
+ Assert.assertEquals(false, glWindow1.isNativeValid());
+ }
+
+ public static void setDemoFields(GLEventListener demo, GLWindow glWindow, boolean debug) {
+ Assert.assertNotNull(demo);
+ Assert.assertNotNull(glWindow);
+ Window window = glWindow.getDelegatedWindow();
+ if(debug) {
+ MiscUtils.setFieldIfExists(demo, "glDebug", true);
+ MiscUtils.setFieldIfExists(demo, "glTrace", true);
+ }
+ if(!MiscUtils.setFieldIfExists(demo, "window", window)) {
+ MiscUtils.setFieldIfExists(demo, "glWindow", glWindow);
+ }
+ }
+
+ static int atoi(String a) {
+ int i=0;
+ try {
+ i = Integer.parseInt(a);
+ } catch (Exception ex) { ex.printStackTrace(); }
+ return i;
+ }
+
+ public static void main(String args[]) throws IOException {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ durationPerTest = atoi(args[++i]);
+ }
+ }
+ String tstname = TestParenting01aSWT.class.getName();
+ org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(new String[] {
+ tstname,
+ "filtertrace=true",
+ "haltOnError=false",
+ "haltOnFailure=false",
+ "showoutput=true",
+ "outputtoformatters=true",
+ "logfailedtests=true",
+ "logtestlistenerevents=true",
+ "formatter=org.apache.tools.ant.taskdefs.optional.junit.PlainJUnitResultFormatter",
+ "formatter=org.apache.tools.ant.taskdefs.optional.junit.XMLJUnitResultFormatter,TEST-"+tstname+".xml" } );
+ }
+
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting04AWT.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting04AWT.java
new file mode 100644
index 000000000..09b6d048c
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting04AWT.java
@@ -0,0 +1,239 @@
+/**
+ * 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 com.jogamp.opengl.test.junit.newt.parenting;
+
+import java.awt.BorderLayout;
+import java.awt.Button;
+import java.awt.Frame;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLEventListener;
+import javax.swing.SwingUtilities;
+
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import com.jogamp.newt.Window;
+import com.jogamp.newt.awt.NewtCanvasAWT;
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.Animator;
+
+/**
+ * Using {@link NewtCanvasAWT#setNEWTChild(Window)} for reparenting, i.e. NEWT/AWT hopping
+ */
+public class TestParenting04AWT extends UITestCase {
+ static int width, height;
+ static long durationPerTest = 800;
+ static GLCapabilities glCaps;
+
+ @BeforeClass
+ public static void initClass() {
+ width = 400;
+ height = 400;
+ glCaps = new GLCapabilities(null);
+ }
+
+ @Test
+ public void winHopFrame2FrameDirectHop() throws InterruptedException, InvocationTargetException {
+ // Will produce some artifacts .. resizing etc
+ winHopFrame2Frame(false);
+ }
+
+ @Test
+ public void winHopFrame2FrameDetachFirst() throws InterruptedException, InvocationTargetException {
+ // Note: detaching first setNEWTChild(null) is much cleaner visually
+ winHopFrame2Frame(true);
+ }
+
+ protected void winHopFrame2Frame(final boolean detachFirst) throws InterruptedException, InvocationTargetException {
+ final GLWindow glWindow1 = GLWindow.create(glCaps);
+ GLEventListener demo1 = new RedSquareES2();
+ setDemoFields(demo1, glWindow1, false);
+ glWindow1.addGLEventListener(demo1);
+ Animator anim1 = new Animator(glWindow1);
+
+ final GLWindow glWindow2 = GLWindow.create(glCaps);
+ GLEventListener demo2 = new GearsES2();
+ setDemoFields(demo2, glWindow2, false);
+ glWindow2.addGLEventListener(demo2);
+ Animator anim2 = new Animator(glWindow2);
+
+ final NewtCanvasAWT canvas1 = new NewtCanvasAWT(glWindow1);
+ final NewtCanvasAWT canvas2 = new NewtCanvasAWT(glWindow2);
+
+ final Frame frame1 = new Frame("AWT Parent Frame");
+ frame1.setLayout(new BorderLayout());
+ frame1.add(new Button("North"), BorderLayout.NORTH);
+ frame1.add(new Button("South"), BorderLayout.SOUTH);
+ frame1.add(new Button("East"), BorderLayout.EAST);
+ frame1.add(new Button("West"), BorderLayout.WEST);
+ frame1.setSize(width, height);
+ frame1.setLocation(0, 0);
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame1.setVisible(true);
+ frame1.validate();
+ }
+ });
+
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame1.add(canvas1, BorderLayout.CENTER);
+ frame1.validate();
+ }
+ });
+ Assert.assertEquals(canvas1.getNativeWindow(),glWindow1.getParent());
+
+ final Frame frame2 = new Frame("AWT Parent Frame");
+ frame2.setLayout(new BorderLayout());
+ frame2.add(new Button("North"), BorderLayout.NORTH);
+ frame2.add(new Button("South"), BorderLayout.SOUTH);
+ frame2.add(new Button("East"), BorderLayout.EAST);
+ frame2.add(new Button("West"), BorderLayout.WEST);
+ frame2.setSize(width, height);
+ frame2.setLocation(width+50, 0);
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame2.setVisible(true);
+ frame2.validate();
+ }
+ });
+
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame2.add(canvas2, BorderLayout.CENTER);
+ frame2.validate();
+ }
+ });
+ Assert.assertEquals(canvas2.getNativeWindow(),glWindow2.getParent());
+
+ anim1.start();
+ anim2.start();
+
+ int state;
+ for(state=0; state<3; state++) {
+ Thread.sleep(durationPerTest);
+ switch(state) {
+ case 0:
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ // 1 -> 2
+ if(detachFirst) {
+ canvas1.setNEWTChild(null);
+ canvas2.setNEWTChild(null);
+ } else {
+ canvas2.setNEWTChild(null); // free g2 of w2
+ }
+ canvas1.setNEWTChild(glWindow2); // put g2 -> w1. free g1 of w1
+ canvas2.setNEWTChild(glWindow1); // put g1 -> w2
+ frame1.validate();
+ frame2.validate();
+ }
+ });
+ break;
+ case 1:
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ // 2 -> 1
+ if(detachFirst) {
+ canvas1.setNEWTChild(null);
+ canvas2.setNEWTChild(null);
+ } else {
+ canvas2.setNEWTChild(null);
+ }
+ canvas1.setNEWTChild(glWindow1);
+ canvas2.setNEWTChild(glWindow2);
+ frame1.validate();
+ frame2.validate();
+ }
+ });
+ break;
+ }
+ }
+
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame1.dispose();
+ frame2.dispose();
+ } } );
+ glWindow1.destroy();
+ glWindow2.destroy();
+ Assert.assertEquals(false, glWindow1.isNativeValid());
+ Assert.assertEquals(false, glWindow2.isNativeValid());
+ }
+
+ public static void setDemoFields(GLEventListener demo, GLWindow glWindow, boolean debug) {
+ Assert.assertNotNull(demo);
+ Assert.assertNotNull(glWindow);
+ Window window = glWindow.getDelegatedWindow();
+ if(debug) {
+ MiscUtils.setFieldIfExists(demo, "glDebug", true);
+ MiscUtils.setFieldIfExists(demo, "glTrace", true);
+ }
+ if(!MiscUtils.setFieldIfExists(demo, "window", window)) {
+ MiscUtils.setFieldIfExists(demo, "glWindow", glWindow);
+ }
+ }
+
+ static int atoi(String a) {
+ int i=0;
+ try {
+ i = Integer.parseInt(a);
+ } catch (Exception ex) { ex.printStackTrace(); }
+ return i;
+ }
+
+ public static void main(String args[]) throws IOException {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ durationPerTest = atoi(args[++i]);
+ }
+ }
+ String tstname = TestParenting04AWT.class.getName();
+ org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(new String[] {
+ tstname,
+ "filtertrace=true",
+ "haltOnError=false",
+ "haltOnFailure=false",
+ "showoutput=true",
+ "outputtoformatters=true",
+ "logfailedtests=true",
+ "logtestlistenerevents=true",
+ "formatter=org.apache.tools.ant.taskdefs.optional.junit.PlainJUnitResultFormatter",
+ "formatter=org.apache.tools.ant.taskdefs.optional.junit.XMLJUnitResultFormatter,TEST-"+tstname+".xml" } );
+ }
+
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting04SWT.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting04SWT.java
new file mode 100644
index 000000000..14a36c573
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting04SWT.java
@@ -0,0 +1,264 @@
+/**
+ * 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 com.jogamp.opengl.test.junit.newt.parenting;
+
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLEventListener;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import com.jogamp.nativewindow.swt.SWTAccessor;
+import com.jogamp.newt.Window;
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.newt.swt.NewtCanvasSWT;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.Animator;
+
+/**
+ * Using {@link NewtCanvasSWT#setNEWTChild(Window)} for reparenting, i.e. NEWT/AWT hopping
+ */
+public class TestParenting04SWT extends UITestCase {
+ static int width, height;
+ static long durationPerTest = 800;
+ static GLCapabilities glCaps;
+
+ Display display = null;
+ Shell shell1 = null;
+ Shell shell2 = null;
+ Composite composite1 = null;
+ Composite composite2 = null;
+
+ @BeforeClass
+ public static void initClass() {
+ width = 400;
+ height = 400;
+ glCaps = new GLCapabilities(null);
+ }
+
+ @Before
+ public void init() {
+ SWTAccessor.invoke(true, new Runnable() {
+ public void run() {
+ display = new Display();
+ Assert.assertNotNull( display );
+
+ shell1 = new Shell( display );
+ Assert.assertNotNull( shell1 );
+ shell1.setLayout( new FillLayout() );
+ composite1 = new Composite( shell1, SWT.NONE );
+ composite1.setLayout( new FillLayout() );
+ Assert.assertNotNull( composite1 );
+
+ shell2 = new Shell( display );
+ Assert.assertNotNull( shell2 );
+ shell2.setLayout( new FillLayout() );
+ composite2 = new Composite( shell2, SWT.NONE );
+ composite2.setLayout( new FillLayout() );
+ Assert.assertNotNull( composite2 );
+ }});
+ }
+
+ @After
+ public void release() {
+ Assert.assertNotNull( display );
+ Assert.assertNotNull( shell1 );
+ Assert.assertNotNull( shell2 );
+ Assert.assertNotNull( composite1 );
+ Assert.assertNotNull( composite2 );
+ try {
+ SWTAccessor.invoke(true, new Runnable() {
+ public void run() {
+ composite1.dispose();
+ composite2.dispose();
+ shell1.dispose();
+ shell2.dispose();
+ display.dispose();
+ }});
+ }
+ catch( Throwable throwable ) {
+ throwable.printStackTrace();
+ Assume.assumeNoException( throwable );
+ }
+ display = null;
+ shell1 = null;
+ shell2 = null;
+ composite1 = null;
+ composite2 = null;
+ }
+
+ @Test
+ public void winHopFrame2FrameDirectHop() throws InterruptedException, InvocationTargetException {
+ // Will produce some artifacts .. resizing etc
+ winHopFrame2Frame(false);
+ }
+
+ @Test
+ public void winHopFrame2FrameDetachFirst() throws InterruptedException, InvocationTargetException {
+ // Note: detaching first setNEWTChild(null) is much cleaner visually
+ winHopFrame2Frame(true);
+ }
+
+ protected void winHopFrame2Frame(final boolean detachFirst) throws InterruptedException, InvocationTargetException {
+ final GLWindow glWindow1 = GLWindow.create(glCaps);
+ GLEventListener demo1 = new RedSquareES2();
+ setDemoFields(demo1, glWindow1, false);
+ glWindow1.addGLEventListener(demo1);
+ Animator anim1 = new Animator(glWindow1);
+
+ final GLWindow glWindow2 = GLWindow.create(glCaps);
+ GLEventListener demo2 = new GearsES2();
+ setDemoFields(demo2, glWindow2, false);
+ glWindow2.addGLEventListener(demo2);
+ Animator anim2 = new Animator(glWindow2);
+
+ final NewtCanvasSWT canvas1 = NewtCanvasSWT.create( composite1, 0, glWindow1 );
+ final NewtCanvasSWT canvas2 = NewtCanvasSWT.create( composite2, 0, glWindow2 );
+
+ SWTAccessor.invoke(true, new Runnable() {
+ public void run() {
+ shell1.setText( getSimpleTestName(".")+"-Win1" );
+ shell1.setSize( width, height);
+ shell1.setLocation(0, 0);
+ shell1.open();
+ shell2.setText( getSimpleTestName(".")+"-Win2" );
+ shell2.setSize( width, height);
+ shell2.setLocation(width + 50, 0);
+ shell2.open();
+ }
+ });
+ Assert.assertEquals(canvas1.getNativeWindow(),glWindow1.getParent());
+ Assert.assertEquals(canvas2.getNativeWindow(),glWindow2.getParent());
+
+ anim1.start();
+ anim2.start();
+
+ int state;
+ for(state=0; state<3; state++) {
+ for(int i=0; i*10<durationPerTest; i++) {
+ if( !display.readAndDispatch() ) {
+ // blocks on linux .. display.sleep();
+ Thread.sleep(10);
+ }
+ }
+ switch(state) {
+ case 0:
+ SWTAccessor.invoke(true, new Runnable() {
+ public void run() {
+ // 1 -> 2
+ if(detachFirst) {
+ canvas1.setNEWTChild(null);
+ canvas2.setNEWTChild(null);
+ } else {
+ canvas2.setNEWTChild(null); // free g2 of w2
+ }
+ canvas1.setNEWTChild(glWindow2); // put g2 -> w1. free g1 of w1
+ canvas2.setNEWTChild(glWindow1); // put g1 -> w2
+ } } );
+ break;
+ case 1:
+ SWTAccessor.invoke(true, new Runnable() {
+ public void run() {
+ // 2 -> 1
+ if(detachFirst) {
+ canvas1.setNEWTChild(null);
+ canvas2.setNEWTChild(null);
+ } else {
+ canvas2.setNEWTChild(null);
+ }
+ canvas1.setNEWTChild(glWindow1);
+ canvas2.setNEWTChild(glWindow2);
+ } } );
+ break;
+ }
+ }
+
+ canvas1.dispose();
+ canvas2.dispose();
+ Assert.assertEquals(false, glWindow1.isNativeValid());
+ Assert.assertEquals(false, glWindow2.isNativeValid());
+ }
+
+ public static void setDemoFields(GLEventListener demo, GLWindow glWindow, boolean debug) {
+ Assert.assertNotNull(demo);
+ Assert.assertNotNull(glWindow);
+ Window window = glWindow.getDelegatedWindow();
+ if(debug) {
+ MiscUtils.setFieldIfExists(demo, "glDebug", true);
+ MiscUtils.setFieldIfExists(demo, "glTrace", true);
+ }
+ if(!MiscUtils.setFieldIfExists(demo, "window", window)) {
+ MiscUtils.setFieldIfExists(demo, "glWindow", glWindow);
+ }
+ }
+
+ static int atoi(String a) {
+ int i=0;
+ try {
+ i = Integer.parseInt(a);
+ } catch (Exception ex) { ex.printStackTrace(); }
+ return i;
+ }
+
+ public static void main(String args[]) throws IOException {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ durationPerTest = atoi(args[++i]);
+ }
+ }
+ String tstname = TestParenting04SWT.class.getName();
+ org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(new String[] {
+ tstname,
+ "filtertrace=true",
+ "haltOnError=false",
+ "haltOnFailure=false",
+ "showoutput=true",
+ "outputtoformatters=true",
+ "logfailedtests=true",
+ "logtestlistenerevents=true",
+ "formatter=org.apache.tools.ant.taskdefs.optional.junit.PlainJUnitResultFormatter",
+ "formatter=org.apache.tools.ant.taskdefs.optional.junit.XMLJUnitResultFormatter,TEST-"+tstname+".xml" } );
+ }
+
+}