1 /**
2  * Copyright 2010 JogAmp Community. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without modification, are
5  * permitted provided that the following conditions are met:
6  *
7  *    1. Redistributions of source code must retain the above copyright notice, this list of
8  *       conditions and the following disclaimer.
9  *
10  *    2. Redistributions in binary form must reproduce the above copyright notice, this list
11  *       of conditions and the following disclaimer in the documentation and/or other materials
12  *       provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
15  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
16  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
21  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
22  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  *
24  * The views and conclusions contained in the software and documentation are those of the
25  * authors and should not be interpreted as representing official policies, either expressed
26  * or implied, of JogAmp Community.
27  */
28 
29 package com.jogamp.opengl.test.junit.newt.event;
30 
31 import java.lang.reflect.*;
32 import java.util.HashSet;
33 import java.util.Iterator;
34 import java.util.Set;
35 
36 import org.junit.Assert;
37 import org.junit.BeforeClass;
38 import org.junit.Test;
39 import org.junit.FixMethodOrder;
40 import org.junit.runners.MethodSorters;
41 
42 import java.awt.AWTException;
43 import java.awt.AWTKeyStroke;
44 import java.awt.BorderLayout;
45 import java.awt.Button;
46 import java.awt.Dimension;
47 import java.awt.Frame;
48 import java.awt.KeyboardFocusManager;
49 import java.awt.Robot;
50 
51 import com.jogamp.opengl.*;
52 
53 import com.jogamp.opengl.util.Animator;
54 import com.jogamp.newt.*;
55 import com.jogamp.newt.opengl.*;
56 import com.jogamp.newt.awt.NewtCanvasAWT;
57 import com.jogamp.newt.event.KeyAdapter;
58 import com.jogamp.newt.event.KeyEvent;
59 
60 import java.io.IOException;
61 
62 import jogamp.newt.driver.DriverClearFocus;
63 
64 import com.jogamp.opengl.test.junit.util.*;
65 import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
66 import com.jogamp.opengl.test.junit.newt.parenting.NewtAWTReparentingKeyAdapter;
67 
68 /**
69  * Testing focus <i>key</i> traversal of an AWT component tree with {@link NewtCanvasAWT} attached.
70  * <p>
71  * {@link Frame} [ Button*, {@link NewtCanvasAWT} . {@link GLWindow} ]
72  * </p>
73  */
74 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
75 public class TestParentingFocus03KeyTraversalAWT extends UITestCase {
76     static Dimension glSize, fSize;
77     static int numFocus = 8;
78     static long durationPerTest = numFocus * 200;
79     static GLCapabilities glCaps;
80     static boolean manual = false;
81     static boolean forceGL3 = false;
82 
83     @BeforeClass
initClass()84     public static void initClass() {
85         glSize = new Dimension(200,200);
86         fSize = new Dimension(300,300);
87         glCaps = new GLCapabilities( forceGL3 ? GLProfile.get(GLProfile.GL3) : null );
88     }
89 
90     @Test
testWindowParentingAWTFocusTraversal01Onscreen()91     public void testWindowParentingAWTFocusTraversal01Onscreen() throws InterruptedException, InvocationTargetException, AWTException {
92         testWindowParentingAWTFocusTraversal(true);
93     }
94 
95     @Test
testWindowParentingAWTFocusTraversal02Offscreen()96     public void testWindowParentingAWTFocusTraversal02Offscreen() throws InterruptedException, InvocationTargetException, AWTException {
97         testWindowParentingAWTFocusTraversal(false);
98     }
99 
testWindowParentingAWTFocusTraversal(final boolean onscreen)100     public void testWindowParentingAWTFocusTraversal(final boolean onscreen) throws InterruptedException, InvocationTargetException, AWTException {
101         final Robot robot = new Robot();
102 
103         // Bug 4908075 - http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4908075
104         // Bug 6463168 - http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6463168
105         {
106             final KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
107             final Set<AWTKeyStroke> bwdKeys = kfm.getDefaultFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);
108             final AWTKeyStroke newBack = AWTKeyStroke.getAWTKeyStroke(java.awt.event.KeyEvent.VK_BACK_SPACE, 0, false);
109             Assert.assertNotNull(newBack);
110             final Set<AWTKeyStroke> bwdKeys2 = new HashSet<AWTKeyStroke>(bwdKeys);
111             bwdKeys2.add(newBack);
112             kfm.setDefaultFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, bwdKeys2);
113         }
114         {
115             final KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
116             final Set<AWTKeyStroke> fwdKeys = kfm.getDefaultFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
117             final Set<AWTKeyStroke> bwdKeys = kfm.getDefaultFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);
118             Iterator<AWTKeyStroke> iter;
119             for(iter = fwdKeys.iterator(); iter.hasNext(); ) {
120                 System.err.println("FTKL.fwd-keys: "+iter.next());
121             }
122             for(iter = bwdKeys.iterator(); iter.hasNext(); ) {
123                 System.err.println("FTKL.bwd-keys: "+iter.next());
124             }
125         }
126 
127         final Frame frame1 = new Frame("AWT Parent Frame");
128         final Button cWest = new Button("WEST");
129         final Button cEast = new Button("EAST");
130         final GLWindow glWindow1 = GLWindow.create(glCaps);
131         glWindow1.setUpdateFPSFrames(1, null);
132         final NewtCanvasAWT newtCanvasAWT1 = new NewtCanvasAWT(glWindow1);
133         newtCanvasAWT1.setPreferredSize(glSize);
134         newtCanvasAWT1.setShallUseOffscreenLayer(!onscreen);
135         newtCanvasAWT1.setFocusable(true);
136 
137         // Test FocusAdapter
138         final NEWTFocusAdapter glWindow1FA = new NEWTFocusAdapter("GLWindow1");
139         glWindow1.addWindowListener(glWindow1FA);
140         final AWTFocusAdapter bWestFA = new AWTFocusAdapter("WEST");
141         cWest.addFocusListener(bWestFA);
142         final AWTFocusAdapter bEastFA = new AWTFocusAdapter("EAST");
143         cEast.addFocusListener(bEastFA);
144 
145         // Test KeyAdapter
146         final NEWTKeyAdapter glWindow1KA = new NEWTKeyAdapter("GLWindow1");
147         glWindow1.addKeyListener(glWindow1KA);
148         final AWTKeyAdapter bWestKA = new AWTKeyAdapter("West");
149         cWest.addKeyListener(bWestKA);
150         final AWTKeyAdapter bEastKA = new AWTKeyAdapter("East");
151         cEast.addKeyListener(bEastKA);
152 
153         // demo ..
154         final GLEventListener demo1 = new GearsES2(1);
155         setDemoFields(demo1, glWindow1, false);
156         glWindow1.addGLEventListener(demo1);
157         glWindow1.addKeyListener(new NewtAWTReparentingKeyAdapter(frame1, newtCanvasAWT1, glWindow1));
158         glWindow1.addKeyListener(new KeyAdapter() {
159             public void keyReleased(final KeyEvent e) {
160                 if( !e.isPrintableKey() || e.isAutoRepeat() ) {
161                     return;
162                 }
163                 if(e.getKeyChar()=='c') {
164                     System.err.println("Focus Clear");
165                     if(glWindow1.getDelegatedWindow() instanceof DriverClearFocus) {
166                          ((DriverClearFocus)glWindow1.getDelegatedWindow()).clearFocus();
167                     }
168                 } else if(e.getKeyChar()=='e') {
169                     System.err.println("Focus East");
170                     try {
171                         java.awt.EventQueue.invokeLater(new Runnable() {
172                            public void run() {
173                                cEast.requestFocusInWindow();
174                            }
175                         });
176                     } catch (final Exception ex) { ex.printStackTrace(); }
177                 } else if(e.getKeyChar()=='w') {
178                     System.err.println("Focus West");
179                     try {
180                         java.awt.EventQueue.invokeLater(new Runnable() {
181                            public void run() {
182                                cWest.requestFocusInWindow();
183                            }
184                         });
185                     } catch (final Exception ex) { ex.printStackTrace(); }
186                 }
187             }
188         });
189         final GLAnimatorControl animator1 = new Animator(glWindow1);
190         animator1.start();
191 
192         // make frame
193         frame1.setLayout(new BorderLayout());
194         frame1.setLayout(new BorderLayout());
195         frame1.add(cWest, BorderLayout.WEST);
196         frame1.add(newtCanvasAWT1, BorderLayout.CENTER);
197         frame1.add(cEast, BorderLayout.EAST);
198 
199         javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
200             public void run() {
201                 frame1.setLocation(0, 0);
202                 frame1.setSize(fSize);
203                 frame1.validate();
204                 frame1.setVisible(true);
205             }});
206         Assert.assertEquals(true, AWTRobotUtil.waitForVisible(glWindow1, true));
207         Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow1, true));
208         Assert.assertEquals(newtCanvasAWT1.getNativeWindow(),glWindow1.getParent());
209         AWTRobotUtil.clearAWTFocus(robot);
210         Assert.assertTrue(AWTRobotUtil.toFrontAndRequestFocus(robot, frame1));
211 
212         Assert.assertEquals(true, animator1.isAnimating());
213         // Assert.assertEquals(false, animator1.isPaused());
214         Assert.assertNotNull(animator1.getThread());
215 
216         if(manual) {
217             Thread.sleep(durationPerTest);
218         } else {
219             //
220             // initial focus on bWest
221             //
222             AWTRobotUtil.assertRequestFocusAndWait(robot, cWest, cWest, bWestFA, null);
223             Thread.sleep(durationPerTest/numFocus);
224 
225             //
226             // forth
227             //
228 
229             // bWest -> glWin
230             AWTRobotUtil.keyType(0, robot, java.awt.event.KeyEvent.VK_TAB, cWest, null);
231             Assert.assertTrue("Did not gain focus", AWTRobotUtil.waitForFocus(glWindow1, glWindow1FA, bWestFA));
232             Assert.assertEquals(true,  glWindow1FA.focusGained());
233             Assert.assertEquals(true,  bWestFA.focusLost());
234             Thread.sleep(durationPerTest/numFocus);
235 
236             // glWin -> bEast
237             AWTRobotUtil.keyType(0, robot, java.awt.event.KeyEvent.VK_TAB, glWindow1, null);
238             Assert.assertTrue("Did not gain focus", AWTRobotUtil.waitForFocus(cEast, bEastFA, glWindow1FA));
239             Assert.assertEquals(true,  bEastFA.focusGained());
240             Assert.assertEquals(true,  glWindow1FA.focusLost());
241             Thread.sleep(durationPerTest/numFocus);
242 
243             //
244             // back (using custom back traversal key 'backspace')
245             //
246             // bEast -> glWin
247             AWTRobotUtil.keyType(0, robot, java.awt.event.KeyEvent.VK_BACK_SPACE, cEast, null);
248             Assert.assertTrue("Did not gain focus", AWTRobotUtil.waitForFocus(glWindow1, glWindow1FA, bEastFA));
249             Assert.assertEquals(true,  glWindow1FA.focusGained());
250             Assert.assertEquals(true,  bEastFA.focusLost());
251             Thread.sleep(durationPerTest/numFocus);
252 
253             AWTRobotUtil.keyType(0, robot, java.awt.event.KeyEvent.VK_BACK_SPACE, glWindow1, null);
254             Assert.assertTrue("Did not gain focus", AWTRobotUtil.waitForFocus(cWest, bWestFA, glWindow1FA));
255             Assert.assertEquals(true,  bWestFA.focusGained());
256             Assert.assertEquals(true,  glWindow1FA.focusLost());
257             Thread.sleep(durationPerTest/numFocus);
258 
259             System.err.println("Test: Direct NewtCanvasAWT focus");
260             try {
261                 java.awt.EventQueue.invokeAndWait(new Runnable() {
262                    public void run() {
263                        newtCanvasAWT1.requestFocus();
264                    }
265                 });
266             } catch (final Exception ex) { ex.printStackTrace(); }
267             Assert.assertTrue("Did not gain focus", AWTRobotUtil.waitForFocus(glWindow1, glWindow1FA, bWestFA));
268             Assert.assertEquals(true,  glWindow1FA.focusGained());
269             Assert.assertEquals(true,  bWestFA.focusLost());
270             Thread.sleep(durationPerTest/numFocus);
271 
272             System.err.println("Test: Direct AWT Button-West focus");
273             try {
274                 java.awt.EventQueue.invokeAndWait(new Runnable() {
275                    public void run() {
276                        cWest.requestFocus();
277                    }
278                 });
279             } catch (final Exception ex) { ex.printStackTrace(); }
280             Assert.assertTrue("Did not gain focus", AWTRobotUtil.waitForFocus(cWest, bWestFA, glWindow1FA));
281             Assert.assertEquals(true,  bWestFA.focusGained());
282             Assert.assertEquals(true,  glWindow1FA.focusLost());
283             Thread.sleep(durationPerTest/numFocus);
284 
285             System.err.println("Test: Direct NEWT-Child request focus");
286             glWindow1.requestFocus();
287             {
288                 // Short: Assert.assertTrue("Did not gain focus", AWTRobotUtil.waitForFocus(glWindow1, glWindow1FA, bWestFA));
289                 // More verbose:
290                 final boolean ok = AWTRobotUtil.waitForFocus(glWindow1, glWindow1FA, bWestFA);
291                 System.err.println("glWindow hasFocus "+glWindow1.hasFocus());
292                 System.err.println("glWindow1FA "+glWindow1FA);
293                 System.err.println("bWestFA "+bWestFA);
294                 Assert.assertTrue("Did not gain focus", ok);
295             }
296             Assert.assertEquals(true,  glWindow1FA.focusGained());
297             Assert.assertEquals(true,  bWestFA.focusLost());
298             Thread.sleep(durationPerTest/numFocus);
299         }
300 
301         animator1.stop();
302         Assert.assertEquals(false, animator1.isAnimating());
303         Assert.assertEquals(false, animator1.isPaused());
304         Assert.assertEquals(null, animator1.getThread());
305 
306         javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
307             public void run() {
308                 frame1.dispose();
309             } } );
310         glWindow1.destroy();
311     }
312 
setDemoFields(final GLEventListener demo, final GLWindow glWindow, final boolean debug)313     public static void setDemoFields(final GLEventListener demo, final GLWindow glWindow, final boolean debug) {
314         Assert.assertNotNull(demo);
315         Assert.assertNotNull(glWindow);
316         final Window window = glWindow.getDelegatedWindow();
317         if(debug) {
318             MiscUtils.setFieldIfExists(demo, "glDebug", true);
319             MiscUtils.setFieldIfExists(demo, "glTrace", true);
320         }
321         if(!MiscUtils.setFieldIfExists(demo, "window", window)) {
322             MiscUtils.setFieldIfExists(demo, "glWindow", glWindow);
323         }
324     }
325 
atoi(final String a)326     static int atoi(final String a) {
327         int i=0;
328         try {
329             i = Integer.parseInt(a);
330         } catch (final Exception ex) { ex.printStackTrace(); }
331         return i;
332     }
333 
main(final String args[])334     public static void main(final String args[]) throws IOException {
335         for(int i=0; i<args.length; i++) {
336             if(args[i].equals("-time")) {
337                 durationPerTest = atoi(args[++i]);
338             } else if(args[i].equals("-manual")) {
339                 manual = true;
340             } else if(args[i].equals("-gl3")) {
341                 forceGL3 = true;
342             }
343         }
344         final String tstname = TestParentingFocus03KeyTraversalAWT.class.getName();
345         /*
346         org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(new String[] {
347             tstname,
348             "filtertrace=true",
349             "haltOnError=false",
350             "haltOnFailure=false",
351             "showoutput=true",
352             "outputtoformatters=true",
353             "logfailedtests=true",
354             "logtestlistenerevents=true",
355             "formatter=org.apache.tools.ant.taskdefs.optional.junit.PlainJUnitResultFormatter",
356             "formatter=org.apache.tools.ant.taskdefs.optional.junit.XMLJUnitResultFormatter,TEST-"+tstname+".xml" } ); */
357         org.junit.runner.JUnitCore.main(tstname);
358     }
359 
360 }
361