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