From 58dd634261ebb815771dcd3d59dbf972f1c79106 Mon Sep 17 00:00:00 2001
From: Sven Gothel
Date: Tue, 9 Apr 2019 12:15:58 +0200
Subject: Bug 1362: Add two self contained unit tests to validate SWT >= 4.10 +
GTK3 issues
TestSWTAccessor01: Simply tests SWTAccessor's returned native window handle. Works on SWT + GTK2 and SWT + GTK3.
TestSWTAccessor02NewtGLWindow: Uses same returned native window handle and tests a GLWindow.reparentWindow(..) operation
all rolled out and implemented here ad-hock (comparable to NewtCanvasSWT).
This shall allow simplified debugging.
Testing:
- SWT + GTK2: Works
- SWT + GTK3: Bug reproduced
---
make/scripts/tests.sh | 4 +-
.../test/junit/jogl/swt/TestSWTAccessor01.java | 198 ++++++++++++++++
.../jogl/swt/TestSWTAccessor02NewtGLWindow.java | 249 +++++++++++++++++++++
3 files changed, 450 insertions(+), 1 deletion(-)
create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTAccessor01.java
create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTAccessor02NewtGLWindow.java
diff --git a/make/scripts/tests.sh b/make/scripts/tests.sh
index 58142e117..30b66bfe4 100644
--- a/make/scripts/tests.sh
+++ b/make/scripts/tests.sh
@@ -757,13 +757,15 @@ function testawtswt() {
#
# SWT (testswt)
#
+#testswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTAccessor01 $*
+testswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTAccessor02NewtGLWindow $*
#testswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTEclipseGLCanvas01GLn $*
#testswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTJOGLGLCanvas01GLn $*
#testswt com.jogamp.opengl.test.junit.jogl.swt.TestNewtCanvasSWTGLn $*
#testswt com.jogamp.opengl.test.junit.jogl.swt.TestBug672NewtCanvasSWTSashForm $*
#testswt com.jogamp.opengl.test.junit.jogl.swt.TestBug672NewtCanvasSWTSashFormComposite $*
#testswt com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextVBOES2SWT3 $*
-testswt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NewtCanvasSWT $*
+#testswt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NewtCanvasSWT $*
#testswt com.jogamp.opengl.test.junit.jogl.demos.es2.swt.TestGearsES2SWT $*
#
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTAccessor01.java b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTAccessor01.java
new file mode 100644
index 000000000..126553162
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTAccessor01.java
@@ -0,0 +1,198 @@
+/**
+ * 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 java.lang.reflect.InvocationTargetException;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.PaintEvent;
+import org.eclipse.swt.events.PaintListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Canvas;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.common.os.Platform;
+import com.jogamp.junit.util.JunitTracer;
+import com.jogamp.nativewindow.swt.SWTAccessor;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+
+/**
+ * Tests {@link SWTAccessor#getWindowHandle(org.eclipse.swt.widgets.Control)} on a basic simple SWT window.
+ *
+ * Bug 1362 inspired this unit test, i.e. finding the issue of SWT >= 4.10 + GTK3.
+ *
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestSWTAccessor01 extends UITestCase {
+
+ static int duration = 250;
+
+ Display display = null;
+ Shell shell = null;
+ Composite composite = null;
+
+ @BeforeClass
+ public static void startup() {
+ if( Platform.getOSType() == Platform.OSType.MACOS ) {
+ // NSLocking issues on OSX and AWT, able to freeze whole test suite!
+ // Since this test is merely a technical nature to validate the accessor w/ SWT
+ // we can drop it w/o bothering.
+ JunitTracer.setTestSupported(false);
+ return;
+ }
+ }
+
+ protected void init() throws InterruptedException, InvocationTargetException {
+ SWTAccessor.invoke(true, new Runnable() {
+ public void run() {
+ display = new Display();
+ Assert.assertNotNull( display );
+ shell = new Shell( display );
+ Assert.assertNotNull( shell );
+ shell.setLayout( new GridLayout(3, false) );
+ shell.setBackground(new Color(display, 0, 0, 255));
+ new Text(shell, SWT.NONE).setText("1");
+ new Text(shell, SWT.NONE).setText("2");
+ new Text(shell, SWT.NONE).setText("3");
+ new Text(shell, SWT.NONE).setText("4");
+ composite = new Composite( shell, SWT.NO_BACKGROUND /** | SWT.EMBEDDED */ );
+ composite.setLayout( new FillLayout() );
+ composite.setBackground(new Color(display, 0, 255, 0));
+ final GridData gd = new GridData (GridData.FILL, GridData.FILL, true /* grabExcessHorizontalSpace */, true /* grabExcessVerticalSpace */);
+ composite.setLayoutData(gd);
+ new Text(shell, SWT.NONE).setText("6");
+ new Text(shell, SWT.NONE).setText("7");
+ new Text(shell, SWT.NONE).setText("8");
+ new Text(shell, SWT.NONE).setText("9");
+ Assert.assertNotNull( composite );
+ }});
+ }
+
+ protected void release() throws InterruptedException, InvocationTargetException {
+ Assert.assertNotNull( display );
+ Assert.assertNotNull( shell );
+ Assert.assertNotNull( composite );
+
+ SWTAccessor.invoke(true, new Runnable() {
+ public void run() {
+ composite.dispose();
+ shell.close();
+ shell.dispose();
+ display.dispose();
+ display = null;
+ shell = null;
+ composite = null;
+ }});
+ }
+
+ protected void runTest() throws InterruptedException, InvocationTargetException {
+ init();
+ final Canvas canvas[] = { null };
+ try {
+ SWTAccessor.invoke(true, new Runnable() {
+ public void run() {
+ canvas[0] = new Canvas (composite, SWT.NONE);
+ canvas[0].setBackground(new Color(display, 255, 255, 255));
+ canvas[0].setForeground(new Color(display, 255, 0, 0));
+ canvas[0].addPaintListener (new PaintListener() {
+ public void paintControl(final PaintEvent e) {
+ final Rectangle r = canvas[0].getClientArea();
+ e.gc.fillRectangle(0, 0, r.width, r.height);
+ e.gc.drawRectangle(50, 50, r.width-100, r.height-100);
+ e.gc.drawString("I am a Canvas", r.width/2, r.height/2);
+ }});
+ try {
+ System.err.println("Window handle.0 0x"+Long.toHexString(SWTAccessor.getWindowHandle(canvas[0])));
+ } catch (final Exception e) {
+ System.err.println(e.getMessage());
+ }
+ shell.setText( getClass().getName() );
+ shell.setBounds( 0, 0, 700, 700 );
+ shell.open();
+ canvas[0].redraw();
+ }});
+
+ System.err.println("Window handle.1 0x"+Long.toHexString(SWTAccessor.getWindowHandle(canvas[0])));
+
+ final long lStartTime = System.currentTimeMillis();
+ final long lEndTime = lStartTime + duration;
+ try {
+ while( (System.currentTimeMillis() < lEndTime) && !composite.isDisposed() ) {
+ SWTAccessor.invoke(true, new Runnable() {
+ public void run() {
+ if( !display.readAndDispatch() ) {
+ // blocks on linux .. display.sleep();
+ try {
+ Thread.sleep(10);
+ } catch (final InterruptedException e) { }
+ }
+ }});
+ }
+ SWTAccessor.invoke(true, new Runnable() {
+ public void run() {
+ System.err.println("Window handle.X 0x"+Long.toHexString(SWTAccessor.getWindowHandle(canvas[0])));
+ }});
+ }
+ catch( final Throwable throwable ) {
+ throwable.printStackTrace();
+ Assume.assumeNoException( throwable );
+ }
+ } finally {
+ release();
+ }
+ }
+
+ @Test
+ public void test() throws InterruptedException, InvocationTargetException {
+ runTest();
+ }
+
+ public static void main(final String args[]) {
+ for(int i=0; i
+ * This tests re-creates {@link NewtCanvasSWT}'s implementation ad-hock, allowing simplified debugging.
+ *
+ *
+ * Enhanced version of {@link TestSWTAccessor01}.
+ *
+ *
+ * Bug 1362 inspired this unit test, i.e. finding the issue of SWT >= 4.10 + GTK3.
+ *
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestSWTAccessor02NewtGLWindow extends UITestCase {
+
+ static int duration = 250;
+
+ Display display = null;
+ Shell shell = null;
+ Composite composite = null;
+
+ @BeforeClass
+ public static void startup() {
+ if( Platform.getOSType() == Platform.OSType.MACOS ) {
+ // NSLocking issues on OSX and AWT, able to freeze whole test suite!
+ // Since this test is merely a technical nature to validate the accessor w/ SWT
+ // we can drop it w/o bothering.
+ JunitTracer.setTestSupported(false);
+ return;
+ }
+ }
+
+ protected void init() throws InterruptedException, InvocationTargetException {
+ SWTAccessor.invoke(true, new Runnable() {
+ public void run() {
+ display = new Display();
+ Assert.assertNotNull( display );
+ shell = new Shell( display );
+ Assert.assertNotNull( shell );
+ shell.setLayout( new GridLayout(3, false) );
+ shell.setBackground(new Color(display, 0, 0, 255));
+ new Text(shell, SWT.NONE).setText("1");
+ new Text(shell, SWT.NONE).setText("2");
+ new Text(shell, SWT.NONE).setText("3");
+ new Text(shell, SWT.NONE).setText("4");
+ composite = new Composite( shell, SWT.NO_BACKGROUND /** | SWT.EMBEDDED */ );
+ composite.setLayout( new FillLayout() );
+ composite.setBackground(new Color(display, 0, 255, 0));
+ final GridData gd = new GridData (GridData.FILL, GridData.FILL, true /* grabExcessHorizontalSpace */, true /* grabExcessVerticalSpace */);
+ composite.setLayoutData(gd);
+ new Text(shell, SWT.NONE).setText("6");
+ new Text(shell, SWT.NONE).setText("7");
+ new Text(shell, SWT.NONE).setText("8");
+ new Text(shell, SWT.NONE).setText("9");
+ Assert.assertNotNull( composite );
+ }});
+ }
+
+ protected void release(final GLWindow glwin) throws InterruptedException, InvocationTargetException {
+ Assert.assertNotNull( display );
+ Assert.assertNotNull( shell );
+ Assert.assertNotNull( composite );
+
+ SWTAccessor.invoke(true, new Runnable() {
+ public void run() {
+ glwin.destroy();
+ composite.dispose();
+ shell.close();
+ shell.dispose();
+ display.dispose();
+ display = null;
+ shell = null;
+ composite = null;
+ }});
+ }
+
+ protected void runTest() throws InterruptedException, InvocationTargetException {
+ init();
+
+ final GLCapabilities caps = new GLCapabilities(GLProfile.getGL2ES2());
+ final GLWindow glwin = GLWindow.create(caps);
+ final GearsES2 demo = new GearsES2();
+ glwin.addGLEventListener(demo);
+ glwin.setSize(600, 600);
+
+ final Canvas canvas[] = { null };
+ try {
+ SWTAccessor.invoke(true, new Runnable() {
+ public void run() {
+ canvas[0] = new Canvas (composite, SWT.NO_BACKGROUND);
+ shell.setText( getClass().getName() );
+ shell.setBounds( 0, 0, 700, 700 );
+ shell.open();
+
+ // A full rolled-out native window reparenting example, very suitable to debug
+ final long parentWinHandle = SWTAccessor.getWindowHandle(canvas[0]);
+ final AbstractGraphicsScreen aScreen = NativeWindowFactory.createScreen(NativeWindowFactory.createDevice(null, true /* own */), -1);
+ final UpstreamWindowHookMutableSizePos upstreamSizePosHook = new UpstreamWindowHookMutableSizePos(0, 0, 600, 600, 600, 600);
+ final Listener listener = new Listener () {
+ @Override
+ public void handleEvent (final Event event) {
+ switch (event.type) {
+ case SWT.Paint:
+ glwin.display();
+ break;
+ case SWT.Move:
+ case SWT.Resize: {
+ final Rectangle nClientArea = canvas[0].getClientArea();
+ if( null != nClientArea ) {
+ upstreamSizePosHook.setSurfaceSize(nClientArea.width, nClientArea.height);
+ upstreamSizePosHook.setWinSize(nClientArea.width, nClientArea.height);
+ upstreamSizePosHook.setWinPos(nClientArea.x, nClientArea.y);
+ if( SWT.Resize == event.type ) {
+ glwin.setSize(nClientArea.width, nClientArea.height);
+ }
+ }
+ }
+ break;
+ case SWT.Dispose:
+ glwin.destroy();
+ break;
+ }
+ }
+ };
+ canvas[0].addListener (SWT.Move, listener);
+ canvas[0].addListener (SWT.Resize, listener);
+ canvas[0].addListener (SWT.Paint, listener);
+ canvas[0].addListener (SWT.Dispose, listener);
+
+ final NativeWindow parentWindow = NativeWindowFactory.createWrappedWindow(aScreen, 0 /* surfaceHandle*/, parentWinHandle, upstreamSizePosHook);
+ glwin.reparentWindow(parentWindow, 0, 0, 0);
+ final Rectangle r = canvas[0].getClientArea();
+ glwin.setSize(r.width, r.height);
+ glwin.setVisible(true);
+ canvas[0].redraw();
+ }});
+
+ System.err.println("Window handle.1 0x"+Long.toHexString(SWTAccessor.getWindowHandle(canvas[0])));
+
+ final long lStartTime = System.currentTimeMillis();
+ final long lEndTime = lStartTime + duration;
+ try {
+ while( (System.currentTimeMillis() < lEndTime) && !composite.isDisposed() ) {
+ SWTAccessor.invoke(true, new Runnable() {
+ public void run() {
+ if( !display.readAndDispatch() ) {
+ // blocks on linux .. display.sleep();
+ try {
+ Thread.sleep(10);
+ } catch (final InterruptedException e) { }
+ }
+ }});
+ }
+ SWTAccessor.invoke(true, new Runnable() {
+ public void run() {
+ System.err.println("Window handle.X 0x"+Long.toHexString(SWTAccessor.getWindowHandle(canvas[0])));
+ }});
+ }
+ catch( final Throwable throwable ) {
+ throwable.printStackTrace();
+ Assume.assumeNoException( throwable );
+ }
+ } finally {
+ release(glwin);
+ }
+ }
+
+ @Test
+ public void test() throws InterruptedException, InvocationTargetException {
+ runTest();
+ }
+
+ public static void main(final String args[]) {
+ for(int i=0; i