/**
* 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.event;
import java.lang.reflect.*;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.FixMethodOrder;
import org.junit.runners.MethodSorters;
import java.awt.AWTException;
import java.awt.AWTKeyStroke;
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.KeyboardFocusManager;
import java.awt.Robot;
import com.jogamp.opengl.*;
import com.jogamp.opengl.util.Animator;
import com.jogamp.newt.*;
import com.jogamp.newt.opengl.*;
import com.jogamp.newt.awt.NewtCanvasAWT;
import com.jogamp.newt.event.KeyAdapter;
import com.jogamp.newt.event.KeyEvent;
import java.io.IOException;
import jogamp.newt.driver.DriverClearFocus;
import com.jogamp.opengl.test.junit.util.*;
import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
import com.jogamp.opengl.test.junit.newt.parenting.NewtAWTReparentingKeyAdapter;
/**
* Testing focus <i>key</i> traversal of an AWT component tree with {@link NewtCanvasAWT} attached.
* <p>
* {@link Frame} [ Button*, {@link NewtCanvasAWT} . {@link GLWindow} ]
* </p>
*/
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestParentingFocus03KeyTraversalAWT extends UITestCase {
static Dimension glSize, fSize;
static int numFocus = 8;
static long durationPerTest = numFocus * 200;
static GLCapabilities glCaps;
static boolean manual = false;
static boolean forceGL3 = false;
@BeforeClass
public static void initClass() {
glSize = new Dimension(200,200);
fSize = new Dimension(300,300);
glCaps = new GLCapabilities( forceGL3 ? GLProfile.get(GLProfile.GL3) : null );
}
@Test
public void testWindowParentingAWTFocusTraversal01Onscreen() throws InterruptedException, InvocationTargetException, AWTException {
testWindowParentingAWTFocusTraversal(true);
}
@Test
public void testWindowParentingAWTFocusTraversal02Offscreen() throws InterruptedException, InvocationTargetException, AWTException {
testWindowParentingAWTFocusTraversal(false);
}
public void testWindowParentingAWTFocusTraversal(final boolean onscreen) throws InterruptedException, InvocationTargetException, AWTException {
final Robot robot = new Robot();
// Bug 4908075 - http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4908075
// Bug 6463168 - http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6463168
{
final KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
final Set<AWTKeyStroke> bwdKeys = kfm.getDefaultFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);
final AWTKeyStroke newBack = AWTKeyStroke.getAWTKeyStroke(java.awt.event.KeyEvent.VK_BACK_SPACE, 0, false);
Assert.assertNotNull(newBack);
final Set<AWTKeyStroke> bwdKeys2 = new HashSet<AWTKeyStroke>(bwdKeys);
bwdKeys2.add(newBack);
kfm.setDefaultFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, bwdKeys2);
}
{
final KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
final Set<AWTKeyStroke> fwdKeys = kfm.getDefaultFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
final Set<AWTKeyStroke> bwdKeys = kfm.getDefaultFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);
Iterator<AWTKeyStroke> iter;
for(iter = fwdKeys.iterator(); iter.hasNext(); ) {
System.err.println("FTKL.fwd-keys: "+iter.next());
}
for(iter = bwdKeys.iterator(); iter.hasNext(); ) {
System.err.println("FTKL.bwd-keys: "+iter.next());
}
}
final Frame frame1 = new Frame("AWT Parent Frame");
final Button cWest = new Button("WEST");
final Button cEast = new Button("EAST");
final GLWindow glWindow1 = GLWindow.create(glCaps);
glWindow1.setUpdateFPSFrames(1, null);
final NewtCanvasAWT newtCanvasAWT1 = new NewtCanvasAWT(glWindow1);
newtCanvasAWT1.setPreferredSize(glSize);
newtCanvasAWT1.setShallUseOffscreenLayer(!onscreen);
newtCanvasAWT1.setFocusable(true);
// Test FocusAdapter
final NEWTFocusAdapter glWindow1FA = new NEWTFocusAdapter("GLWindow1");
glWindow1.addWindowListener(glWindow1FA);
final AWTFocusAdapter bWestFA = new AWTFocusAdapter("WEST");
cWest.addFocusListener(bWestFA);
final AWTFocusAdapter bEastFA = new AWTFocusAdapter("EAST");
cEast.addFocusListener(bEastFA);
// Test KeyAdapter
final NEWTKeyAdapter glWindow1KA = new NEWTKeyAdapter("GLWindow1");
glWindow1.addKeyListener(glWindow1KA);
final AWTKeyAdapter bWestKA = new AWTKeyAdapter("West");
cWest.addKeyListener(bWestKA);
final AWTKeyAdapter bEastKA = new AWTKeyAdapter("East");
cEast.addKeyListener(bEastKA);
// demo ..
final GLEventListener demo1 = new GearsES2(1);
setDemoFields(demo1, glWindow1, false);
glWindow1.addGLEventListener(demo1);
glWindow1.addKeyListener(new NewtAWTReparentingKeyAdapter(frame1, newtCanvasAWT1, glWindow1));
glWindow1.addKeyListener(new KeyAdapter() {
public void keyReleased(final KeyEvent e) {
if( !e.isPrintableKey() || e.isAutoRepeat() ) {
return;
}
if(e.getKeyChar()=='c') {
System.err.println("Focus Clear");
if(glWindow1.getDelegatedWindow() instanceof DriverClearFocus) {
((DriverClearFocus)glWindow1.getDelegatedWindow()).clearFocus();
}
} else if(e.getKeyChar()=='e') {
System.err.println("Focus East");
try {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
cEast.requestFocusInWindow();
}
});
} catch (final Exception ex) { ex.printStackTrace(); }
} else if(e.getKeyChar()=='w') {
System.err.println("Focus West");
try {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
cWest.requestFocusInWindow();
}
});
} catch (final Exception ex) { ex.printStackTrace(); }
}
}
});
final GLAnimatorControl animator1 = new Animator(glWindow1);
animator1.start();
// make frame
frame1.setLayout(new BorderLayout());
frame1.setLayout(new BorderLayout());
frame1.add(cWest, BorderLayout.WEST);
frame1.add(newtCanvasAWT1, BorderLayout.CENTER);
frame1.add(cEast, BorderLayout.EAST);
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
frame1.setLocation(0, 0);
frame1.setSize(fSize);
frame1.validate();
frame1.setVisible(true);
}});
Assert.assertEquals(true, AWTRobotUtil.waitForVisible(glWindow1, true));
Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow1, true));
Assert.assertEquals(newtCanvasAWT1.getNativeWindow(),glWindow1.getParent());
AWTRobotUtil.clearAWTFocus(robot);
Assert.assertTrue(AWTRobotUtil.toFrontAndRequestFocus(robot, frame1));
Assert.assertEquals(true, animator1.isAnimating());
// Assert.assertEquals(false, animator1.isPaused());
Assert.assertNotNull(animator1.getThread());
if(manual) {
Thread.sleep(durationPerTest);
} else {
//
// initial focus on bWest
//
AWTRobotUtil.assertRequestFocusAndWait(robot, cWest, cWest, bWestFA, null);
Thread.sleep(durationPerTest/numFocus);
//
// forth
//
// bWest -> glWin
AWTRobotUtil.keyType(0, robot, java.awt.event.KeyEvent.VK_TAB, cWest, null);
Assert.assertTrue("Did not gain focus", AWTRobotUtil.waitForFocus(glWindow1, glWindow1FA, bWestFA));
Assert.assertEquals(true, glWindow1FA.focusGained());
Assert.assertEquals(true, bWestFA.focusLost());
Thread.sleep(durationPerTest/numFocus);
// glWin -> bEast
AWTRobotUtil.keyType(0, robot, java.awt.event.KeyEvent.VK_TAB, glWindow1, null);
Assert.assertTrue("Did not gain focus", AWTRobotUtil.waitForFocus(cEast, bEastFA, glWindow1FA));
Assert.assertEquals(true, bEastFA.focusGained());
Assert.assertEquals(true, glWindow1FA.focusLost());
Thread.sleep(durationPerTest/numFocus);
//
// back (using custom back traversal key 'backspace')
//
// bEast -> glWin
AWTRobotUtil.keyType(0, robot, java.awt.event.KeyEvent.VK_BACK_SPACE, cEast, null);
Assert.assertTrue("Did not gain focus", AWTRobotUtil.waitForFocus(glWindow1, glWindow1FA, bEastFA));
Assert.assertEquals(true, glWindow1FA.focusGained());
Assert.assertEquals(true, bEastFA.focusLost());
Thread.sleep(durationPerTest/numFocus);
AWTRobotUtil.keyType(0, robot, java.awt.event.KeyEvent.VK_BACK_SPACE, glWindow1, null);
Assert.assertTrue("Did not gain focus", AWTRobotUtil.waitForFocus(cWest, bWestFA, glWindow1FA));
Assert.assertEquals(true, bWestFA.focusGained());
Assert.assertEquals(true, glWindow1FA.focusLost());
Thread.sleep(durationPerTest/numFocus);
System.err.println("Test: Direct NewtCanvasAWT focus");
try {
java.awt.EventQueue.invokeAndWait(new Runnable() {
public void run() {
newtCanvasAWT1.requestFocus();
}
});
} catch (final Exception ex) { ex.printStackTrace(); }
Assert.assertTrue("Did not gain focus", AWTRobotUtil.waitForFocus(glWindow1, glWindow1FA, bWestFA));
Assert.assertEquals(true, glWindow1FA.focusGained());
Assert.assertEquals(true, bWestFA.focusLost());
Thread.sleep(durationPerTest/numFocus);
System.err.println("Test: Direct AWT Button-West focus");
try {
java.awt.EventQueue.invokeAndWait(new Runnable() {
public void run() {
cWest.requestFocus();
}
});
} catch (final Exception ex) { ex.printStackTrace(); }
Assert.assertTrue("Did not gain focus", AWTRobotUtil.waitForFocus(cWest, bWestFA, glWindow1FA));
Assert.assertEquals(true, bWestFA.focusGained());
Assert.assertEquals(true, glWindow1FA.focusLost());
Thread.sleep(durationPerTest/numFocus);
System.err.println("Test: Direct NEWT-Child request focus");
glWindow1.requestFocus();
{
// Short: Assert.assertTrue("Did not gain focus", AWTRobotUtil.waitForFocus(glWindow1, glWindow1FA, bWestFA));
// More verbose:
final boolean ok = AWTRobotUtil.waitForFocus(glWindow1, glWindow1FA, bWestFA);
System.err.println("glWindow hasFocus "+glWindow1.hasFocus());
System.err.println("glWindow1FA "+glWindow1FA);
System.err.println("bWestFA "+bWestFA);
Assert.assertTrue("Did not gain focus", ok);
}
Assert.assertEquals(true, glWindow1FA.focusGained());
Assert.assertEquals(true, bWestFA.focusLost());
Thread.sleep(durationPerTest/numFocus);
}
animator1.stop();
Assert.assertEquals(false, animator1.isAnimating());
Assert.assertEquals(false, animator1.isPaused());
Assert.assertEquals(null, animator1.getThread());
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
frame1.dispose();
} } );
glWindow1.destroy();
}
public static void setDemoFields(final GLEventListener demo, final GLWindow glWindow, final boolean debug) {
Assert.assertNotNull(demo);
Assert.assertNotNull(glWindow);
final 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(final String a) {
int i=0;
try {
i = Integer.parseInt(a);
} catch (final Exception ex) { ex.printStackTrace(); }
return i;
}
public static void main(final String args[]) throws IOException {
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
durationPerTest = atoi(args[++i]);
} else if(args[i].equals("-manual")) {
manual = true;
} else if(args[i].equals("-gl3")) {
forceGL3 = true;
}
}
final String tstname = TestParentingFocus03KeyTraversalAWT.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" } ); */
org.junit.runner.JUnitCore.main(tstname);
}
}