From 45ce96db65fa7cbfd3bcb3dd4503bc6251d2e493 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Sun, 10 Nov 2013 20:59:03 +0100 Subject: Fix Bug 889 [Related: Bug 816, Bug 849, Bug 729] - GLCanvas disappear when moves between two JFrame When JAWTWindow's visibility tracker updates component's local visibility, it should read it's local visibility state instead 'trusting' the passed state. Make JAWTWindow's visibility tracker DEBUG output more brief for readability. --- make/scripts/tests.sh | 3 +- .../com/jogamp/nativewindow/awt/JAWTWindow.java | 31 ++- .../TestBug816GLCanvasFrameHoppingB849B889AWT.java | 262 +++++++++++++++++++++ .../jogl/awt/TestBug816OSXCALayerPos01AWT.java | 87 ++++--- .../jogl/awt/TestBug816OSXCALayerPos02AWT.java | 43 ++-- .../awt/TestBug816OSXCALayerPos03aB729AWT.java | 35 ++- .../awt/TestBug816OSXCALayerPos03bB849AWT.java | 35 ++- .../awt/TestBug816OSXCALayerPos03cB849AWT.java | 37 ++- 8 files changed, 401 insertions(+), 132 deletions(-) create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816GLCanvasFrameHoppingB849B889AWT.java diff --git a/make/scripts/tests.sh b/make/scripts/tests.sh index 432f8f346..b7db47e11 100644 --- a/make/scripts/tests.sh +++ b/make/scripts/tests.sh @@ -478,7 +478,7 @@ function testawtswt() { #testnoawt com.jogamp.opengl.test.junit.newt.TestWindowClosingProtocol02NEWT $* #testnoawt com.jogamp.opengl.test.junit.newt.TestGLWindows01NEWT $* #testnoawt com.jogamp.opengl.test.junit.newt.TestGLWindows02NEWTAnimated $* -testnoawt com.jogamp.opengl.test.junit.newt.TestGLWindows03NEWTAnimResize $* +#testnoawt com.jogamp.opengl.test.junit.newt.TestGLWindows03NEWTAnimResize $* #testnoawt com.jogamp.opengl.test.junit.newt.TestGLWindowInvisiblePointer01NEWT $* #testnoawt com.jogamp.opengl.test.junit.newt.TestDisplayLifecycle01NEWT #testnoawt com.jogamp.opengl.test.junit.newt.TestDisplayLifecycle02NEWT @@ -504,6 +504,7 @@ testnoawt com.jogamp.opengl.test.junit.newt.TestGLWindows03NEWTAnimResize $* #testawt com.jogamp.opengl.test.junit.jogl.awt.TestBug816OSXCALayerPos03bB849AWT $* #testawt com.jogamp.opengl.test.junit.jogl.awt.TestBug816OSXCALayerPos03cB849AWT $* #testawt com.jogamp.opengl.test.junit.jogl.awt.TestBug816JTabbedPanelVisibilityB849B878AWT $* +testawt com.jogamp.opengl.test.junit.jogl.awt.TestBug816GLCanvasFrameHoppingB849B889AWT $* #testawt com.jogamp.opengl.test.junit.jogl.awt.TestBug816OSXCALayerPos04aAWT $* #testawt com.jogamp.opengl.test.junit.jogl.awt.TestBug816OSXCALayerPos04bAWT $* #testawt com.jogamp.opengl.test.junit.jogl.awt.TestBug675BeansInDesignTimeAWT $* diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java b/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java index a99737613..87966c9c6 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java @@ -124,21 +124,32 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface, private boolean globalVisibility = localVisibility; private boolean visibilityPropagation = false; - private String id(Object obj) { return "0x"+Integer.toHexString(obj.hashCode()); } + private String id(Object obj) { return "0x" + ( null!=obj ? Integer.toHexString(obj.hashCode()) : "nil" ); } + private String str(Object obj) { + if( null == obj ) { + return "null"; + } else if( obj instanceof Component ) { + final Component c = (Component)obj; + return c.getClass().getSimpleName()+"[visible "+c.isVisible()+", showing "+c.isShowing()+", valid "+c.isValid()+ + ", displayable "+c.isDisplayable()+", "+c.getX()+"/"+c.getY()+" "+c.getWidth()+"x"+c.getHeight()+"]"; + } else { + return obj.getClass().getSimpleName()+"[..]"; + } + } private String s(ComponentEvent e) { return "visible[local "+localVisibility+", global "+globalVisibility+", propag. "+visibilityPropagation+"],"+Platform.getNewline()+ - " ** COMP "+id(e.getComponent())+": "+e.getComponent()+Platform.getNewline()+ - " ** SOURCE "+id(e.getSource())+": "+e.getSource()+Platform.getNewline()+ - " ** THIS "+component; + " ** COMP "+id(e.getComponent())+": "+str(e.getComponent())+Platform.getNewline()+ + " ** SOURCE "+id(e.getSource())+": "+str(e.getSource())+Platform.getNewline()+ + " ** THIS "+id(component)+": "+str(component); } private String s(HierarchyEvent e) { return "visible[local "+localVisibility+", global "+globalVisibility+", propag. "+visibilityPropagation+"], changeBits 0x"+Long.toHexString(e.getChangeFlags())+Platform.getNewline()+ - " ** COMP "+id(e.getComponent())+": "+e.getComponent()+Platform.getNewline()+ - " ** SOURCE "+id(e.getSource())+": "+e.getSource()+Platform.getNewline()+ - " ** CHANGED "+id(e.getChanged())+": "+e.getChanged()+Platform.getNewline()+ - " ** CHANGEDPARENT "+id(e.getChangedParent())+": "+e.getChangedParent()+Platform.getNewline()+ - " ** THIS "+component; + " ** COMP "+id(e.getComponent())+": "+str(e.getComponent())+Platform.getNewline()+ + " ** SOURCE "+id(e.getSource())+": "+str(e.getSource())+Platform.getNewline()+ + " ** CHANGED "+id(e.getChanged())+": "+str(e.getChanged())+Platform.getNewline()+ + " ** CHANGEDPARENT "+id(e.getChangedParent())+": "+str(e.getChangedParent())+Platform.getNewline()+ + " ** THIS "+id(component)+": "+str(component); } @Override @@ -207,7 +218,7 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface, } else if( changed == component ) { // Update component's local visibility state if(!visibilityPropagation) { - localVisibility = showing; + localVisibility = component.isVisible(); } visibilityPropagation = false; if(DEBUG) { diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816GLCanvasFrameHoppingB849B889AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816GLCanvasFrameHoppingB849B889AWT.java new file mode 100644 index 000000000..51d00a5a1 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug816GLCanvasFrameHoppingB849B889AWT.java @@ -0,0 +1,262 @@ +/** + * Copyright 2013 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.awt; + +import java.awt.BorderLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.lang.reflect.InvocationTargetException; + +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLProfile; +import javax.media.opengl.awt.GLCanvas; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; + +import org.junit.Assert; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; + +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.UITestCase; + +/** + * Moving GLCanvas between 2 AWT JFrame + *

+ * Validates bugs: + *

+ *

+ */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestBug816GLCanvasFrameHoppingB849B889AWT extends UITestCase { + static long durationPerTest = 500*4; // ms + static boolean manual = false; + + @Test + public void test01AllVisible() throws InterruptedException, InvocationTargetException { + test(false); + } + + @Test + public void test02VisibleWithCanvas() throws InterruptedException, InvocationTargetException { + test(true); + } + + private void test(final boolean onlyVisibleWithCanvas) throws InterruptedException, InvocationTargetException { + final JFrame frame1 = new JFrame("Bug889 #1"); + final JPanel panel1 = new javax.swing.JPanel(); + panel1.setLayout(new BorderLayout()); + panel1.setSize(new java.awt.Dimension(640, 480)); + frame1.setContentPane(panel1); + frame1.setSize(640, 480); + frame1.setLocation(64, 64); + + final JFrame frame2 = new JFrame("Bug889 #2"); + final JPanel panel2 = new javax.swing.JPanel(); + panel2.setLayout(new BorderLayout()); + panel2.setSize(new java.awt.Dimension(640, 480)); + frame2.setContentPane(panel2); + frame2.setSize(640, 480); + frame2.setLocation(800, 64); + + GLProfile profile = GLProfile.get(GLProfile.GL2ES2); + GLCapabilities glCapabilities = new GLCapabilities(profile); + final GLCanvas glCanvas = new GLCanvas(glCapabilities); + glCanvas.setSize(new java.awt.Dimension(640, 480)); + glCanvas.addGLEventListener(new GearsES2(1)); + panel1.add(glCanvas, BorderLayout.CENTER); + + JButton bMoveP1toP2 = new JButton("Move to Panel2"); + bMoveP1toP2.addActionListener(new ActionListener() { + @Override + public void actionPerformed(java.awt.event.ActionEvent evt) { + System.err.println("XXXX Move P1 -> P2 - START"); + dumpGLCanvasStats(glCanvas); + panel2.add(glCanvas, BorderLayout.CENTER); + if( onlyVisibleWithCanvas ) { + frame1.setVisible(false); + frame2.setVisible(true); + frame2.toFront(); + } else { + frame1.validate(); + frame2.validate(); + } + dumpGLCanvasStats(glCanvas); + System.err.println("XXXX Move P1 -> P2 - END"); + } + }); + panel1.add(bMoveP1toP2, BorderLayout.NORTH); + + JButton bMoveP2toP1 = new JButton("Move to Panel1"); + bMoveP2toP1.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + System.err.println("XXXX Move P2 -> P1 - START"); + dumpGLCanvasStats(glCanvas); + panel1.add(glCanvas, BorderLayout.CENTER); + if( onlyVisibleWithCanvas ) { + frame2.setVisible(false); + frame1.setVisible(true); + frame1.toFront(); + } else { + frame2.validate(); + frame1.validate(); + } + dumpGLCanvasStats(glCanvas); + System.err.println("XXXX Move P2 -> P1 - END"); + } + }); + panel2.add(bMoveP2toP1, BorderLayout.NORTH); + + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + // frame1.pack(); + System.err.println("XXX SetVisible ON XXX GLCanvas on Panel1("+id(panel1)+")"); + if( onlyVisibleWithCanvas ) { + frame1.setVisible(true); + } else { + frame1.setVisible(true); + frame2.setVisible(true); + } + }}); + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame1, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas, true)); + dumpGLCanvasStats(glCanvas); + + if(manual) { + for(long w=durationPerTest; w>0; w-=100) { + Thread.sleep(100); + } + } else { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + System.err.println("XXXX Add GLCanvas Panel1("+id(panel1)+" -> Panel2("+id(panel2)+") START"); + dumpGLCanvasStats(glCanvas); + panel2.add(glCanvas, BorderLayout.CENTER); + if( onlyVisibleWithCanvas ) { + frame1.setVisible(false); + frame2.setVisible(true); + frame2.toFront(); + } else { + frame1.validate(); + frame2.validate(); + } + dumpGLCanvasStats(glCanvas); + }}); + Thread.sleep(durationPerTest/4); + + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + System.err.println("XXXX Add GLCanvas Panel2("+id(panel2)+") -> Panel1("+id(panel1)+" START"); + dumpGLCanvasStats(glCanvas); + panel1.add(glCanvas, BorderLayout.CENTER); + if( onlyVisibleWithCanvas ) { + frame2.setVisible(false); + frame1.setVisible(true); + frame1.toFront(); + } else { + frame2.validate(); + frame1.validate(); + } + dumpGLCanvasStats(glCanvas); + }}); + Thread.sleep(durationPerTest/4); + + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + System.err.println("XXXX Add GLCanvas Panel1("+id(panel1)+" -> Panel2("+id(panel2)+") START"); + dumpGLCanvasStats(glCanvas); + panel2.add(glCanvas, BorderLayout.CENTER); + if( onlyVisibleWithCanvas ) { + frame1.setVisible(false); + frame2.setVisible(true); + frame2.toFront(); + } else { + frame1.validate(); + frame2.validate(); + } + dumpGLCanvasStats(glCanvas); + }}); + Thread.sleep(durationPerTest/4); + + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + System.err.println("XXXX Add GLCanvas Panel2("+id(panel2)+") -> Panel1("+id(panel1)+" START"); + dumpGLCanvasStats(glCanvas); + panel1.add(glCanvas, BorderLayout.CENTER); + if( onlyVisibleWithCanvas ) { + frame2.setVisible(false); + frame1.setVisible(true); + frame1.toFront(); + } else { + frame2.validate(); + frame1.validate(); + } + dumpGLCanvasStats(glCanvas); + }}); + Thread.sleep(durationPerTest/4); + } + + SwingUtilities.invokeLater(new Runnable() { + public void run() { + System.err.println("XXX SetVisible OFF XXX"); + frame1.dispose(); + frame2.dispose(); + } }); + } + + private static String id(Object obj) { return "0x"+Integer.toHexString(obj.hashCode()); } + + static void dumpGLCanvasStats(GLCanvas glCanvas) { + System.err.println("XXXX GLCanvas: comp "+glCanvas+", visible "+glCanvas.isVisible()+", showing "+glCanvas.isShowing()+ + ", displayable "+glCanvas.isDisplayable()+", "+glCanvas.getWidth()+"x"+glCanvas.getHeight()); + } + + public static void main(String args[]) { + for(int i=0; i