JOGL v2.6.0-rc-20250706
JOGL, High-Performance Graphics Binding for Java™ (public API).
TestParentingFocus03KeyTraversalAWT.java
Go to the documentation of this file.
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
29package com.jogamp.opengl.test.junit.newt.event;
30
31import java.lang.reflect.*;
32import java.util.HashSet;
33import java.util.Iterator;
34import java.util.Set;
35
36import org.junit.Assert;
37import org.junit.BeforeClass;
38import org.junit.Test;
39import org.junit.FixMethodOrder;
40import org.junit.runners.MethodSorters;
41
42import java.awt.AWTException;
43import java.awt.AWTKeyStroke;
44import java.awt.BorderLayout;
45import java.awt.Button;
46import java.awt.Dimension;
47import java.awt.Frame;
48import java.awt.KeyboardFocusManager;
49import java.awt.Robot;
50
51import com.jogamp.opengl.*;
52
53import com.jogamp.opengl.util.Animator;
54import com.jogamp.newt.*;
55import com.jogamp.newt.opengl.*;
56import com.jogamp.newt.opengl.util.NEWTDemoListener;
57import com.jogamp.newt.awt.NewtCanvasAWT;
58import com.jogamp.newt.event.KeyAdapter;
59import com.jogamp.newt.event.KeyEvent;
60
61import java.io.IOException;
62
63import jogamp.newt.driver.DriverClearFocus;
64
65import com.jogamp.opengl.test.junit.util.*;
66import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
67import com.jogamp.opengl.test.junit.newt.parenting.NewtAWTReparentingKeyAdapter;
68import com.jogamp.opengl.test.junit.newt.parenting.NewtReparentingKeyAdapter;
69
70/**
71 * Testing focus <i>key</i> traversal of an AWT component tree with {@link NewtCanvasAWT} attached.
72 * <p>
73 * {@link Frame} [ Button*, {@link NewtCanvasAWT} . {@link GLWindow} ]
74 * </p>
75 * <p>
76 * The demo code uses {@link NewtReparentingKeyAdapter} including {@link NEWTDemoListener} functionality.
77 * </p>
78 * <p>
79 * Manual invocation via main allows setting each tests's duration in milliseconds, e.g.{@code -duration 10000}, and many more, see {@link #main(String[])}
80 * </p>
81 */
82@FixMethodOrder(MethodSorters.NAME_ASCENDING)
84 static Dimension glSize, fSize;
85 static int numFocus = 8;
86 static long durationPerTest = numFocus * 200;
87 static GLCapabilities glCaps;
88 static boolean manual = false;
89 static boolean forceGL3 = false;
90
91 @BeforeClass
92 public static void initClass() {
93 glSize = new Dimension(200,200);
94 fSize = new Dimension(300,300);
95 glCaps = new GLCapabilities( forceGL3 ? GLProfile.get(GLProfile.GL3) : null );
96 }
97
98 @Test
99 public void testWindowParentingAWTFocusTraversal01Onscreen() throws InterruptedException, InvocationTargetException, AWTException {
100 testWindowParentingAWTFocusTraversal(true);
101 }
102
103 @Test
104 public void testWindowParentingAWTFocusTraversal02Offscreen() throws InterruptedException, InvocationTargetException, AWTException {
105 testWindowParentingAWTFocusTraversal(false);
106 }
107
108 public void testWindowParentingAWTFocusTraversal(final boolean onscreen) throws InterruptedException, InvocationTargetException, AWTException {
109 final Robot robot = new Robot();
110
111 // Bug 4908075 - http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4908075
112 // Bug 6463168 - http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6463168
113 {
114 final KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
115 final Set<AWTKeyStroke> bwdKeys = kfm.getDefaultFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);
116 final AWTKeyStroke newBack = AWTKeyStroke.getAWTKeyStroke(java.awt.event.KeyEvent.VK_BACK_SPACE, 0, false);
117 Assert.assertNotNull(newBack);
118 final Set<AWTKeyStroke> bwdKeys2 = new HashSet<AWTKeyStroke>(bwdKeys);
119 bwdKeys2.add(newBack);
120 kfm.setDefaultFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, bwdKeys2);
121 }
122 {
123 final KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
124 final Set<AWTKeyStroke> fwdKeys = kfm.getDefaultFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
125 final Set<AWTKeyStroke> bwdKeys = kfm.getDefaultFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);
126 Iterator<AWTKeyStroke> iter;
127 for(iter = fwdKeys.iterator(); iter.hasNext(); ) {
128 System.err.println("FTKL.fwd-keys: "+iter.next());
129 }
130 for(iter = bwdKeys.iterator(); iter.hasNext(); ) {
131 System.err.println("FTKL.bwd-keys: "+iter.next());
132 }
133 }
134
135 final Frame frame1 = new Frame("AWT Parent Frame");
136 final Button cWest = new Button("WEST");
137 final Button cEast = new Button("EAST");
138 final GLWindow glWindow1 = GLWindow.create(glCaps);
139 glWindow1.setUpdateFPSFrames(1, null);
140 final NewtCanvasAWT newtCanvasAWT1 = new NewtCanvasAWT(glWindow1);
141 newtCanvasAWT1.setPreferredSize(glSize);
142 newtCanvasAWT1.setShallUseOffscreenLayer(!onscreen);
143 newtCanvasAWT1.setFocusable(true);
144
145 // Test FocusAdapter
146 final NEWTFocusAdapter glWindow1FA = new NEWTFocusAdapter("GLWindow1");
147 glWindow1.addWindowListener(glWindow1FA);
148 final AWTFocusAdapter bWestFA = new AWTFocusAdapter("WEST");
149 cWest.addFocusListener(bWestFA);
150 final AWTFocusAdapter bEastFA = new AWTFocusAdapter("EAST");
151 cEast.addFocusListener(bEastFA);
152
153 // Test KeyAdapter
154 final NEWTKeyAdapter glWindow1KA = new NEWTKeyAdapter("GLWindow1");
155 glWindow1.addKeyListener(glWindow1KA);
156 final AWTKeyAdapter bWestKA = new AWTKeyAdapter("West");
157 cWest.addKeyListener(bWestKA);
158 final AWTKeyAdapter bEastKA = new AWTKeyAdapter("East");
159 cEast.addKeyListener(bEastKA);
160
161 // demo ..
162 final GLEventListener demo1 = new GearsES2(1);
163 setDemoFields(demo1, glWindow1, false);
164 glWindow1.addGLEventListener(demo1);
165 glWindow1.addKeyListener(new NewtAWTReparentingKeyAdapter(frame1, newtCanvasAWT1, glWindow1));
166 glWindow1.addKeyListener(new KeyAdapter() {
167 public void keyReleased(final KeyEvent e) {
168 if( !e.isPrintableKey() || e.isAutoRepeat() ) {
169 return;
170 }
171 if(e.getKeyChar()=='c') {
172 System.err.println("Focus Clear");
173 if(glWindow1.getDelegatedWindow() instanceof DriverClearFocus) {
174 ((DriverClearFocus)glWindow1.getDelegatedWindow()).clearFocus();
175 }
176 } else if(e.getKeyChar()=='e') {
177 System.err.println("Focus East");
178 try {
179 java.awt.EventQueue.invokeLater(new Runnable() {
180 public void run() {
181 cEast.requestFocusInWindow();
182 }
183 });
184 } catch (final Exception ex) { ex.printStackTrace(); }
185 } else if(e.getKeyChar()=='w') {
186 System.err.println("Focus West");
187 try {
188 java.awt.EventQueue.invokeLater(new Runnable() {
189 public void run() {
190 cWest.requestFocusInWindow();
191 }
192 });
193 } catch (final Exception ex) { ex.printStackTrace(); }
194 }
195 }
196 });
197 final GLAnimatorControl animator1 = new Animator(glWindow1);
198 animator1.start();
199
200 // make frame
201 frame1.setLayout(new BorderLayout());
202 frame1.setLayout(new BorderLayout());
203 frame1.add(cWest, BorderLayout.WEST);
204 frame1.add(newtCanvasAWT1, BorderLayout.CENTER);
205 frame1.add(cEast, BorderLayout.EAST);
206
207 javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
208 public void run() {
209 frame1.setLocation(0, 0);
210 frame1.setSize(fSize);
211 frame1.validate();
212 frame1.setVisible(true);
213 }});
214 Assert.assertEquals(true, NewtTestUtil.waitForVisible(glWindow1, true, null));
215 Assert.assertEquals(true, NewtTestUtil.waitForRealized(glWindow1, true, null));
216 Assert.assertEquals(newtCanvasAWT1.getNativeWindow(),glWindow1.getParent());
218 Assert.assertTrue(AWTRobotUtil.toFrontAndRequestFocus(robot, frame1));
219
220 Assert.assertEquals(true, animator1.isAnimating());
221 // Assert.assertEquals(false, animator1.isPaused());
222 Assert.assertNotNull(animator1.getThread());
223
224 if(manual) {
225 Thread.sleep(durationPerTest);
226 } else {
227 //
228 // initial focus on bWest
229 //
230 AWTRobotUtil.assertRequestFocusAndWait(robot, cWest, cWest, bWestFA, null);
231 Thread.sleep(durationPerTest/numFocus);
232
233 //
234 // forth
235 //
236
237 // bWest -> glWin
238 AWTRobotUtil.keyType(0, robot, java.awt.event.KeyEvent.VK_TAB, cWest, null);
239 Assert.assertTrue("Did not gain focus", NewtTestUtil.waitForFocus(glWindow1, glWindow1FA, bWestFA, null));
240 Assert.assertEquals(true, glWindow1FA.focusGained());
241 Assert.assertEquals(true, bWestFA.focusLost());
242 Thread.sleep(durationPerTest/numFocus);
243
244 // glWin -> bEast
245 AWTRobotUtil.keyType(0, robot, java.awt.event.KeyEvent.VK_TAB, glWindow1, null);
246 Assert.assertTrue("Did not gain focus", AWTRobotUtil.waitForFocus(cEast, bEastFA, glWindow1FA, null));
247 Assert.assertEquals(true, bEastFA.focusGained());
248 Assert.assertEquals(true, glWindow1FA.focusLost());
249 Thread.sleep(durationPerTest/numFocus);
250
251 //
252 // back (using custom back traversal key 'backspace')
253 //
254 // bEast -> glWin
255 AWTRobotUtil.keyType(0, robot, java.awt.event.KeyEvent.VK_BACK_SPACE, cEast, null);
256 Assert.assertTrue("Did not gain focus", NewtTestUtil.waitForFocus(glWindow1, glWindow1FA, bEastFA, null));
257 Assert.assertEquals(true, glWindow1FA.focusGained());
258 Assert.assertEquals(true, bEastFA.focusLost());
259 Thread.sleep(durationPerTest/numFocus);
260
261 AWTRobotUtil.keyType(0, robot, java.awt.event.KeyEvent.VK_BACK_SPACE, glWindow1, null);
262 Assert.assertTrue("Did not gain focus", AWTRobotUtil.waitForFocus(cWest, bWestFA, glWindow1FA, null));
263 Assert.assertEquals(true, bWestFA.focusGained());
264 Assert.assertEquals(true, glWindow1FA.focusLost());
265 Thread.sleep(durationPerTest/numFocus);
266
267 System.err.println("Test: Direct NewtCanvasAWT focus");
268 try {
269 java.awt.EventQueue.invokeAndWait(new Runnable() {
270 public void run() {
271 newtCanvasAWT1.requestFocus();
272 }
273 });
274 } catch (final Exception ex) { ex.printStackTrace(); }
275 Assert.assertTrue("Did not gain focus", NewtTestUtil.waitForFocus(glWindow1, glWindow1FA, bWestFA, null));
276 Assert.assertEquals(true, glWindow1FA.focusGained());
277 Assert.assertEquals(true, bWestFA.focusLost());
278 Thread.sleep(durationPerTest/numFocus);
279
280 System.err.println("Test: Direct AWT Button-West focus");
281 try {
282 java.awt.EventQueue.invokeAndWait(new Runnable() {
283 public void run() {
284 cWest.requestFocus();
285 }
286 });
287 } catch (final Exception ex) { ex.printStackTrace(); }
288 Assert.assertTrue("Did not gain focus", AWTRobotUtil.waitForFocus(cWest, bWestFA, glWindow1FA, null));
289 Assert.assertEquals(true, bWestFA.focusGained());
290 Assert.assertEquals(true, glWindow1FA.focusLost());
291 Thread.sleep(durationPerTest/numFocus);
292
293 System.err.println("Test: Direct NEWT-Child request focus");
294 glWindow1.requestFocus();
295 {
296 // Short: Assert.assertTrue("Did not gain focus", AWTRobotUtil.waitForFocus(glWindow1, glWindow1FA, bWestFA));
297 // More verbose:
298 final boolean ok = NewtTestUtil.waitForFocus(glWindow1, glWindow1FA, bWestFA, null);
299 System.err.println("glWindow hasFocus "+glWindow1.hasFocus());
300 System.err.println("glWindow1FA "+glWindow1FA);
301 System.err.println("bWestFA "+bWestFA);
302 Assert.assertTrue("Did not gain focus", ok);
303 }
304 Assert.assertEquals(true, glWindow1FA.focusGained());
305 Assert.assertEquals(true, bWestFA.focusLost());
306 Thread.sleep(durationPerTest/numFocus);
307 }
308
309 animator1.stop();
310 Assert.assertEquals(false, animator1.isAnimating());
311 Assert.assertEquals(false, animator1.isPaused());
312 Assert.assertEquals(null, animator1.getThread());
313
314 javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
315 public void run() {
316 frame1.dispose();
317 } } );
318 glWindow1.destroy();
319 }
320
321 public static void setDemoFields(final GLEventListener demo, final GLWindow glWindow, final boolean debug) {
322 Assert.assertNotNull(demo);
323 Assert.assertNotNull(glWindow);
324 final Window window = glWindow.getDelegatedWindow();
325 if(debug) {
326 MiscUtils.setFieldIfExists(demo, "glDebug", true);
327 MiscUtils.setFieldIfExists(demo, "glTrace", true);
328 }
329 if(!MiscUtils.setFieldIfExists(demo, "window", window)) {
330 MiscUtils.setFieldIfExists(demo, "glWindow", glWindow);
331 }
332 }
333
334 static int atoi(final String a) {
335 int i=0;
336 try {
337 i = Integer.parseInt(a);
338 } catch (final Exception ex) { ex.printStackTrace(); }
339 return i;
340 }
341
342 public static void main(final String args[]) throws IOException {
343 for(int i=0; i<args.length; i++) {
344 if(args[i].equals("-time")) {
345 durationPerTest = atoi(args[++i]);
346 } else if(args[i].equals("-manual")) {
347 manual = true;
348 } else if(args[i].equals("-gl3")) {
349 forceGL3 = true;
350 }
351 }
352 final String tstname = TestParentingFocus03KeyTraversalAWT.class.getName();
353 /*
354 org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(new String[] {
355 tstname,
356 "filtertrace=true",
357 "haltOnError=false",
358 "haltOnFailure=false",
359 "showoutput=true",
360 "outputtoformatters=true",
361 "logfailedtests=true",
362 "logtestlistenerevents=true",
363 "formatter=org.apache.tools.ant.taskdefs.optional.junit.PlainJUnitResultFormatter",
364 "formatter=org.apache.tools.ant.taskdefs.optional.junit.XMLJUnitResultFormatter,TEST-"+tstname+".xml" } ); */
365 org.junit.runner.JUnitCore.main(tstname);
366 }
367
368}
AWT Canvas containing a NEWT Window using native parenting.
NativeWindow getNativeWindow()
Returns the associated NativeWindow of this NativeWindowHolder, which is identical to getNativeSurfac...
void setShallUseOffscreenLayer(final boolean v)
Request an offscreen layer, if supported.
final boolean isAutoRepeat()
getModifiers() contains AUTOREPEAT_MASK.
final char getKeyChar()
Returns the UTF-16 character reflecting the key symbol incl.
Definition: KeyEvent.java:161
static boolean isPrintableKey(final short uniChar, final boolean isKeyChar)
Returns true if given uniChar represents a printable character, i.e.
Definition: KeyEvent.java:316
An implementation of GLAutoDrawable and Window interface, using a delegated Window instance,...
Definition: GLWindow.java:121
final NativeWindow getParent()
Definition: GLWindow.java:282
final void addKeyListener(final KeyListener l)
Appends the given com.jogamp.newt.event.KeyListener to the end of the list.
Definition: GLWindow.java:902
final void addWindowListener(final WindowListener l)
Appends the given com.jogamp.newt.event.WindowListener to the end of the list.
Definition: GLWindow.java:882
boolean hasFocus()
Returns true if this native window owns the focus, otherwise false.
Definition: GLWindow.java:426
final void destroy()
Destroys all resources associated with this GLAutoDrawable, inclusive the GLContext.
Definition: GLWindow.java:605
final Window getDelegatedWindow()
If the implementation uses delegation, return the delegated Window instance, otherwise return this in...
Definition: GLWindow.java:277
final void requestFocus()
Request focus for this native window.
Definition: GLWindow.java:416
static GLWindow create(final GLCapabilitiesImmutable caps)
Creates a new GLWindow attaching a new Window referencing a new default Screen and default Display wi...
Definition: GLWindow.java:169
Specifies a set of OpenGL capabilities.
Specifies the the OpenGL profile.
Definition: GLProfile.java:77
static final String GL3
The desktop OpenGL core profile 3.x, with x >= 1.
Definition: GLProfile.java:576
static GLProfile get(final AbstractGraphicsDevice device, String profile)
Returns a GLProfile object.
Testing focus key traversal of an AWT component tree with NewtCanvasAWT attached.
static void setDemoFields(final GLEventListener demo, final GLWindow glWindow, final boolean debug)
AWT specializing demo functionality of NewtReparentingKeyAdapter, includes NEWTDemoListener.
static int keyType(final int i, final Robot robot, final int keyCode, final Object obj, final KeyEventCountAdapter counter)
static boolean waitForFocus(final java.awt.Component comp, final Runnable waitAction)
static boolean toFrontAndRequestFocus(Robot robot, final java.awt.Window window)
toFront, call setVisible(true) and toFront(), after positioning the mouse in the middle of the window...
static void assertRequestFocusAndWait(final Robot robot, final Object requestFocus, final Object waitForFocus, final FocusEventCountAdapter gain, final FocusEventCountAdapter lost)
static boolean setFieldIfExists(final Object instance, final String fieldName, final Object value)
Definition: MiscUtils.java:193
static boolean waitForFocus(final Window win, final Runnable waitAction)
static boolean waitForRealized(final Screen screen, final boolean realized, final Runnable waitAction)
static boolean waitForVisible(final Window win, final boolean visible, final Runnable waitAction)
Specifying NEWT's Window functionality:
Definition: Window.java:115
void setUpdateFPSFrames(int frames, PrintStream out)
An animator control interface, which implementation may drive a com.jogamp.opengl....
boolean start()
Starts this animator, if not running.
boolean isPaused()
Indicates whether this animator is started and either manually paused or paused automatically due to ...
boolean isAnimating()
Indicates whether this animator is started and is not paused.
boolean stop()
Stops this animator.
void addGLEventListener(GLEventListener listener)
Adds the given listener to the end of this drawable queue.
Declares events which client code can use to manage OpenGL rendering into a GLAutoDrawable.