JOGL v2.6.0-rc-20250706
JOGL, High-Performance Graphics Binding for Java™ (public API).
TestNewtKeyCodesAWT.java
Go to the documentation of this file.
1/**
2 * Copyright 2012 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 org.junit.After;
32import org.junit.Assert;
33import org.junit.AfterClass;
34import org.junit.Assume;
35import org.junit.Before;
36
37import java.awt.AWTException;
38import java.awt.BorderLayout;
39import java.awt.Robot;
40import java.lang.reflect.InvocationTargetException;
41import java.util.ArrayList;
42import java.util.EventObject;
43import java.util.List;
44
45import com.jogamp.opengl.GLCapabilities;
46import com.jogamp.opengl.GLEventListener;
47import javax.swing.JFrame;
48
49import java.io.IOException;
50
51import jogamp.nativewindow.jawt.JAWTUtil;
52
53import org.junit.BeforeClass;
54import org.junit.Test;
55import org.junit.FixMethodOrder;
56import org.junit.runners.MethodSorters;
57
58import com.jogamp.newt.awt.NewtCanvasAWT;
59import com.jogamp.newt.event.KeyEvent;
60import com.jogamp.newt.opengl.GLWindow;
61import com.jogamp.opengl.util.Animator;
62import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2;
63import com.jogamp.opengl.test.junit.util.*;
64import com.jogamp.opengl.test.junit.util.NEWTKeyUtil.CodeSeg;
65
66/**
67 * Testing key code of key events.
68 */
69@FixMethodOrder(MethodSorters.NAME_ASCENDING)
70public class TestNewtKeyCodesAWT extends UITestCase {
71 static int width, height;
72 static long durationPerTest = 100;
73 static long awtWaitTimeout = 1000;
74
75 static GLCapabilities glCaps;
76
77 @BeforeClass
78 public static void initClass() {
79 width = 640;
80 height = 480;
81 glCaps = new GLCapabilities(null);
82 }
83
84 @AfterClass
85 public static void release() {
86 }
87
88 @Before
89 public void initTest() {
90 }
91
92 @After
93 public void releaseTest() {
94 }
95
96 @Test(timeout=180000) // TO 3 min
97 public void test01NEWT() throws AWTException, InterruptedException, InvocationTargetException {
98 final GLWindow glWindow = GLWindow.create(glCaps);
99 glWindow.setSize(width, height);
100 glWindow.setVisible(true);
101
102 testImpl(glWindow);
103
104 glWindow.destroy();
105 }
106
107 private void testNewtCanvasAWT_Impl(final boolean onscreen) throws AWTException, InterruptedException, InvocationTargetException {
108 final GLWindow glWindow = GLWindow.create(glCaps);
109
110 // Wrap the window in a canvas.
111 final NewtCanvasAWT newtCanvasAWT = new NewtCanvasAWT(glWindow);
112 if( !onscreen ) {
113 newtCanvasAWT.setShallUseOffscreenLayer(true);
114 }
115
116 // Add the canvas to a frame, and make it all visible.
117 final JFrame frame1 = new JFrame("Swing AWT Parent Frame: "+ glWindow.getTitle());
118 frame1.getContentPane().add(newtCanvasAWT, BorderLayout.CENTER);
119 javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
120 public void run() {
121 frame1.setSize(width, height);
122 frame1.setVisible(true);
123 } } );
124
125 Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame1, true, null));
126
127 testImpl(glWindow);
128
129 try {
130 javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
131 public void run() {
132 frame1.setVisible(false);
133 frame1.dispose();
134 }});
135 } catch( final Throwable throwable ) {
136 throwable.printStackTrace();
137 Assume.assumeNoException( throwable );
138 }
139 glWindow.destroy();
140 }
141
142 @Test(timeout=180000) // TO 3 min
143 public void test02NewtCanvasAWT_Onscreen() throws AWTException, InterruptedException, InvocationTargetException {
144 if( JAWTUtil.isOffscreenLayerRequired() ) {
145 System.err.println("Platform doesn't support onscreen rendering.");
146 return;
147 }
148 testNewtCanvasAWT_Impl(true);
149 }
150
151 @Test(timeout=180000) // TO 3 min
152 public void test03NewtCanvasAWT_Offsccreen() throws AWTException, InterruptedException, InvocationTargetException {
153 if( !JAWTUtil.isOffscreenLayerSupported() ) {
154 System.err.println("Platform doesn't support offscreen rendering.");
155 return;
156 }
157 testNewtCanvasAWT_Impl(false);
158 }
159
160 /** Almost all keyCodes reachable w/o modifiers [shift, alt, ..] on US keyboard! */
161 static CodeSeg[] codeSegments = new CodeSeg[] {
162 // new CodeSeg(KeyEvent.VK_HOME, KeyEvent.VK_PRINTSCREEN, "home, end, final, prnt"),
164 // new CodeSeg(KeyEvent.VK_TAB, KeyEvent.VK_TAB, "tab"), // TAB functions as focus traversal key
167 new CodeSeg(KeyEvent.VK_SHIFT, KeyEvent.VK_ALT, "shift, pg_up, ctrl, alt"),
168 // new CodeSeg(KeyEvent.VK_ALT_GRAPH, KeyEvent.VK_ALT_GRAPH, "alt_gr"), // AWT Robot produces 0xff7e on X11
169 // new CodeSeg(KeyEvent.VK_SCROLL_LOCK, KeyEvent.VK_SCROLL_LOCK, "scroll lock"),
173 new CodeSeg(KeyEvent.VK_COMMA, KeyEvent.VK_SLASH, ", - . /"),
174 new CodeSeg(KeyEvent.VK_0, KeyEvent.VK_9, "0 - 9"),
177 new CodeSeg(KeyEvent.VK_A, KeyEvent.VK_Z, "a - z"),
180 new CodeSeg(KeyEvent.VK_F1, KeyEvent.VK_F8, "f1..f8"),
181 // new CodeSeg(KeyEvent.VK_F1, KeyEvent.VK_F12, "f1..f12"), // f9-f12 may cause some odd desktop functions!
183 // new CodeSeg(KeyEvent.VK_NUMPAD0, KeyEvent.VK_NUMPAD9, "numpad0-9"), // can be mapped to normal keycodes
184 // new CodeSeg(KeyEvent.VK_DECIMAL, KeyEvent.VK_DIVIDE, "numpad ops"), // can be mapped to normal keycodes
185 // new CodeSeg(KeyEvent.VK_NUM_LOCK, KeyEvent.VK_NUM_LOCK, "num lock"),
186 // new CodeSeg(KeyEvent.VK_KP_LEFT, KeyEvent.VK_KP_DOWN, "numpad cursor arrows"),
187 new CodeSeg(KeyEvent.VK_LEFT, KeyEvent.VK_DOWN, "cursor arrows"),
188 // new CodeSeg(KeyEvent.VK_WINDOWS, KeyEvent.VK_HELP, "windows, meta, hlp"),
189 };
190
191 static void testKeyCodes(final Robot robot, final Object obj, final NEWTKeyAdapter keyAdapter) throws InterruptedException, InvocationTargetException {
192 final List<List<EventObject>> cse = new ArrayList<List<EventObject>>();
193
194 keyAdapter.setVerbose(true); // FIXME
195 final int[] objCenter = AWTRobotUtil.getCenterLocation(obj, false /* onTitleBarIfWindow */);
196
197 for(int i=0; i<codeSegments.length; i++) {
198 keyAdapter.reset();
199 final CodeSeg codeSeg = codeSegments[i];
200 // System.err.println("*** Segment "+codeSeg.description);
201 int eventCount = 0;
202 for(short c=codeSeg.min; c<=codeSeg.max; c++) {
204 // System.err.println("*** KeyCode 0x"+Integer.toHexString(c));
205 try {
206 AWTRobotUtil.newtKeyPress(0, robot, true, c, 10);
207 } catch (final Exception e) {
208 System.err.println("Exception @ AWT Robot.PRESS "+MiscUtils.toHexString(c)+" - "+e.getMessage());
209 break;
210 }
211 eventCount++;
212 try {
213 AWTRobotUtil.newtKeyPress(0, robot, false, c, 100);
214 } catch (final Exception e) {
215 System.err.println("Exception @ AWT Robot.RELEASE "+MiscUtils.toHexString(c)+" - "+e.getMessage());
216 break;
217 }
218 eventCount++;
219 }
221 for(int j=0; j < NEWTKeyUtil.POLL_DIVIDER && keyAdapter.getQueueSize() < eventCount; j++) { // wait until events are collected
222 robot.delay(NEWTKeyUtil.TIME_SLICE);
223 // Bug 919 - TestNewtKeyCodesAWT w/ NewtCanvasAWT Fails on Windows Due to Clogged Key-Release Event by AWT Robot
224 final int off = 0==j%2 ? 1 : -1;
225 AWTRobotUtil.awtRobotMouseMove(robot, objCenter[0]+off, objCenter[1]);
226 }
227 AWTRobotUtil.awtRobotMouseMove(robot, objCenter[0], objCenter[1]); // Bug 919: Reset mouse position
228 cse.add(keyAdapter.copyQueue());
229 }
230 Assert.assertEquals("KeyCode impl. incomplete", true, NEWTKeyUtil.validateKeyCodes(codeSegments, cse, true));
231 }
232
233 void testImpl(final GLWindow glWindow) throws AWTException, InterruptedException, InvocationTargetException {
234 final Robot robot = new Robot();
235 robot.setAutoWaitForIdle(true);
236
237 final GLEventListener demo1 = new RedSquareES2();
238 glWindow.addGLEventListener(demo1);
239
240 // NEWTFocusAdapter glWindow1FA = new NEWTFocusAdapter("GLWindow1");
241 // glWindow.addWindowListener(glWindow1FA);
242 final NEWTKeyAdapter glWindow1KA = new NEWTKeyAdapter("GLWindow1");
243 glWindow1KA.setVerbose(false);
244 glWindow.addKeyListener(glWindow1KA);
245
246 Assert.assertEquals(true, NewtTestUtil.waitForRealized(glWindow, true, null));
247
248 // Continuous animation ..
249 final Animator animator = new Animator(glWindow);
250 animator.start();
251
252 Thread.sleep(durationPerTest); // manual testing
253
254 AWTRobotUtil.assertRequestFocusAndWait(null, glWindow, glWindow, null, null); // programmatic
255 AWTRobotUtil.requestFocus(robot, glWindow, false); // within unit framework, prev. tests (TestFocus02SwingAWTRobot) 'confuses' Windows keyboard input
256 glWindow1KA.reset();
257
258 testKeyCodes(robot, glWindow, glWindow1KA);
259
260 // Remove listeners to avoid logging during dispose/destroy.
261 glWindow.removeKeyListener(glWindow1KA);
262
263 // Shutdown the test.
264 animator.stop();
265 }
266
267 static int atoi(final String a) {
268 int i=0;
269 try {
270 i = Integer.parseInt(a);
271 } catch (final Exception ex) { ex.printStackTrace(); }
272 return i;
273 }
274
275 public static void main(final String args[]) throws IOException {
276 for(int i=0; i<args.length; i++) {
277 if(args[i].equals("-time")) {
278 durationPerTest = atoi(args[++i]);
279 }
280 }
281 /**
282 BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
283 System.err.println("Press enter to continue");
284 System.err.println(stdin.readLine());
285 */
286 System.out.println("durationPerTest: "+durationPerTest);
287 final String tstname = TestNewtKeyCodesAWT.class.getName();
288 org.junit.runner.JUnitCore.main(tstname);
289 }
290
291
292}
AWT Canvas containing a NEWT Window using native parenting.
void setShallUseOffscreenLayer(final boolean v)
Request an offscreen layer, if supported.
static final short VK_DELETE
Constant for the DEL key, matching ASCII.
Definition: KeyEvent.java:805
static final short VK_COMMA
Constant for the comma key, ",".
Definition: KeyEvent.java:541
static final short VK_SHIFT
Constant for the CTRL function key.
Definition: KeyEvent.java:451
static final short VK_CLOSE_BRACKET
Constant for the close bracket key, "]".
Definition: KeyEvent.java:654
static final short VK_A
VK_A thru VK_Z are the same as Capital UTF16/ASCII 'A' thru 'Z' (0x41 - 0x5A)
Definition: KeyEvent.java:595
static final short VK_ESCAPE
Constant for the ESCAPE function key.
Definition: KeyEvent.java:485
static final short VK_ENTER
Constant for the ENTER key, i.e.
Definition: KeyEvent.java:446
static final short VK_OPEN_BRACKET
Constant for the open bracket key, "[".
Definition: KeyEvent.java:648
static final short VK_LEFT
Constant for the cursor- or numerical-pad left arrow key.
Definition: KeyEvent.java:811
static final short VK_SEMICOLON
Constant for the semicolon key, ";".
Definition: KeyEvent.java:577
static final short VK_BACK_QUOTE
Constant for the "`" key.
Definition: KeyEvent.java:663
static final short VK_DOWN
Constant for the cursor- or numerical pad down arrow key.
Definition: KeyEvent.java:820
static final short VK_PAGE_DOWN
Constant for the PAGE DOWN function key.
Definition: KeyEvent.java:440
static final short VK_SPACE
Constant for the SPACE function key.
Definition: KeyEvent.java:505
static final short VK_9
See VK_0.
Definition: KeyEvent.java:571
static final short VK_ALT
Constant for the left ALT function key.
Definition: KeyEvent.java:460
static final short VK_Z
See VK_A.
Definition: KeyEvent.java:645
static final short VK_0
VK_0 thru VK_9 are the same as UTF16/ASCII '0' thru '9' [0x30 - 0x39].
Definition: KeyEvent.java:553
static final short VK_QUOTE
Constant for the "'" key.
Definition: KeyEvent.java:526
static final short VK_F8
Constant for the F8 function key.
Definition: KeyEvent.java:698
static final short VK_SLASH
Constant for the forward slash key, "/".
Definition: KeyEvent.java:550
static final short VK_F1
Small UTF/ASCII 'a' thru 'z' (0x61 - 0x7a) - Not used for keyCode / keySym.
Definition: KeyEvent.java:677
static final short VK_BACK_SPACE
Constant for the BACK SPACE key "\b", matching ASCII.
Definition: KeyEvent.java:431
static final short VK_EQUALS
Constant for the equals key, "=".
Definition: KeyEvent.java:583
An implementation of GLAutoDrawable and Window interface, using a delegated Window instance,...
Definition: GLWindow.java:121
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 setSize(final int width, final int height)
Sets the size of the window's client area in window units, excluding decorations.
Definition: GLWindow.java:625
final void setVisible(final boolean visible)
Calls setVisible(true, visible), i.e.
Definition: GLWindow.java:615
final void removeKeyListener(final KeyListener l)
Definition: GLWindow.java:912
final void destroy()
Destroys all resources associated with this GLAutoDrawable, inclusive the GLContext.
Definition: GLWindow.java:605
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.
static void awtRobotMouseMove(final Robot robot, final int x, final int y)
static int newtKeyPress(final int i, final Robot robot, final boolean press, final short newtKeyCode, final int msDelay)
No validation is performed .
static void requestFocus(final Robot robot, final Object obj)
FIXME: AWTRobotUtil Cleanup: Use specific type for argument object.
static int[] getCenterLocation(final Object obj, final boolean onTitleBarIfWindow)
static boolean waitForVisible(final java.awt.Component comp, final boolean visible, final Runnable waitAction)
static void assertRequestFocusAndWait(final Robot robot, final Object requestFocus, final Object waitForFocus, final FocusEventCountAdapter gain, final FocusEventCountAdapter lost)
static void waitForIdle(final Robot robot)
Issuing validateAWTEDTIsAlive() before calling Robot#waitForIdle().
static String toHexString(final byte hex)
Definition: MiscUtils.java:84
synchronized void setVerbose(final boolean v)
Instance starts in verbose mode, call w/ false to disable verbosity.
static boolean validateKeyCodes(final CodeSeg[] codeSegments, final List< List< EventObject > > keyEventsList, final boolean verbose)
static boolean waitForRealized(final Screen screen, final boolean realized, final Runnable waitAction)
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.