JOGL v2.6.0-rc-20250706
JOGL, High-Performance Graphics Binding for Java™ (public API).
TestNewtKeyCodeModifiersAWT.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.EventObject;
42import java.util.List;
43
44import com.jogamp.opengl.GLCapabilities;
45import com.jogamp.opengl.GLEventListener;
46import javax.swing.JFrame;
47
48import java.io.IOException;
49
50import jogamp.nativewindow.jawt.JAWTUtil;
51
52import org.junit.BeforeClass;
53import org.junit.Test;
54import org.junit.FixMethodOrder;
55import org.junit.runners.MethodSorters;
56
57import com.jogamp.newt.awt.NewtCanvasAWT;
58import com.jogamp.newt.event.InputEvent;
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;
63
64import com.jogamp.opengl.test.junit.util.*;
65
66/**
67 * Testing combinations of key code modifiers of key event.
68 *
69 * <p>
70 * Due to limitation of AWT Robot, the test machine needs to have US keyboard enabled,
71 * even though we do unify VK codes to US keyboard across all layouts.
72 * </p>
73 */
74@FixMethodOrder(MethodSorters.NAME_ASCENDING)
76 static int width, height;
77 static long durationPerTest = 100;
78 static long awtWaitTimeout = 1000;
79
80 static GLCapabilities glCaps;
81
82 @BeforeClass
83 public static void initClass() {
84 width = 640;
85 height = 480;
86 glCaps = new GLCapabilities(null);
87 }
88
89 @AfterClass
90 public static void release() {
91 }
92
93 @Before
94 public void initTest() {
95 }
96
97 @After
98 public void releaseTest() {
99 }
100
101 @Test(timeout=180000) // TO 3 min
102 public void test01NEWT() throws AWTException, InterruptedException, InvocationTargetException {
103 final GLWindow glWindow = GLWindow.create(glCaps);
104 glWindow.setSize(width, height);
105 glWindow.setVisible(true);
106
107 testImpl(glWindow);
108
109 glWindow.destroy();
110 }
111
112 private void testNewtCanvasAWT_Impl(final boolean onscreen) throws AWTException, InterruptedException, InvocationTargetException {
113 final GLWindow glWindow = GLWindow.create(glCaps);
114
115 // Wrap the window in a canvas.
116 final NewtCanvasAWT newtCanvasAWT = new NewtCanvasAWT(glWindow);
117 if( !onscreen ) {
118 newtCanvasAWT.setShallUseOffscreenLayer(true);
119 }
120
121 // Add the canvas to a frame, and make it all visible.
122 final JFrame frame1 = new JFrame("Swing AWT Parent Frame: "+ glWindow.getTitle());
123 frame1.getContentPane().add(newtCanvasAWT, BorderLayout.CENTER);
124 frame1.setSize(width, height);
125 javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
126 public void run() {
127 frame1.setVisible(true);
128 } } );
129
130 Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame1, true, null));
131
132 testImpl(glWindow);
133
134 try {
135 javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
136 public void run() {
137 frame1.setVisible(false);
138 frame1.dispose();
139 }});
140 } catch( final Throwable throwable ) {
141 throwable.printStackTrace();
142 Assume.assumeNoException( throwable );
143 }
144 glWindow.destroy();
145 }
146
147 @Test(timeout=180000) // TO 3 min
148 public void test02NewtCanvasAWT_Onscreen() throws AWTException, InterruptedException, InvocationTargetException {
149 if( JAWTUtil.isOffscreenLayerRequired() ) {
150 System.err.println("Platform doesn't support onscreen rendering.");
151 return;
152 }
153 testNewtCanvasAWT_Impl(true);
154 }
155
156 @Test(timeout=180000) // TO 3 min
157 public void test03NewtCanvasAWT_Offsccreen() throws AWTException, InterruptedException, InvocationTargetException {
158 if( !JAWTUtil.isOffscreenLayerSupported() ) {
159 System.err.println("Platform doesn't support offscreen rendering.");
160 return;
161 }
162 testNewtCanvasAWT_Impl(false);
163 }
164
165 static void testKeyCodeModifier(final Robot robot, final NEWTKeyAdapter keyAdapter, final short modifierKey, final int modifierMask, final short keyCode,
166 final char keyCharOnly, final char keyCharMod) {
167 keyAdapter.reset();
169 AWTRobotUtil.newtKeyPress(0, robot, true, keyCode, 10); // press keyCode
170 AWTRobotUtil.newtKeyPress(0, robot, false, keyCode, 100); // release keyCode
172 for(int j=0; j < 100 && keyAdapter.getQueueSize() < 2; j++) { // wait until events are collected
173 robot.delay(100);
174 }
175
177 AWTRobotUtil.newtKeyPress(0, robot, true, modifierKey, 10); // press MOD
178 AWTRobotUtil.newtKeyPress(0, robot, true, keyCode, 10); // press keyCode
179 AWTRobotUtil.newtKeyPress(0, robot, false, keyCode, 10); // release keyCode
180 AWTRobotUtil.newtKeyPress(0, robot, false, modifierKey, 100); // release MOD
182 for(int j=0; j < 100 && keyAdapter.getQueueSize() < 2+4; j++) { // wait until events are collected
183 robot.delay(100);
184 }
186 3 /* press-SI */, 3 /* release-SI */,
187 0 /* press-AR */, 0 /* release-AR */ );
188
189 final List<EventObject> queue = keyAdapter.copyQueue();
190 int i=0;
191 NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_PRESSED, 0, keyCode, keyCharOnly);
192 NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_RELEASED, 0, keyCode, keyCharOnly);
193
194 NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_PRESSED, modifierMask, modifierKey, KeyEvent.NULL_CHAR);
195 NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_PRESSED, modifierMask, keyCode, keyCharMod);
196 NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_RELEASED, modifierMask, keyCode, keyCharMod);
197 final KeyEvent e = (KeyEvent) queue.get(i++);
199 }
200
201 static void testKeyCodeAllModifierV1(final Robot robot, final NEWTKeyAdapter keyAdapter) {
202 final short m1k = KeyEvent.VK_ALT;
203 final int m1m = InputEvent.ALT_MASK;
204 final short m2k = KeyEvent.VK_CONTROL;
205 final int m2m = InputEvent.CTRL_MASK;
206 final short m3k = KeyEvent.VK_SHIFT;
207 final int m3m = InputEvent.SHIFT_MASK;
208
209 keyAdapter.reset();
211 AWTRobotUtil.newtKeyPress(0, robot, true, m1k, 10); // press MOD1
212 AWTRobotUtil.newtKeyPress(0, robot, true, m2k, 10); // press MOD2
213 AWTRobotUtil.newtKeyPress(0, robot, true, m3k, 10); // press MOD3
214 AWTRobotUtil.newtKeyPress(0, robot, true, KeyEvent.VK_1, 10); // press P
215
216 AWTRobotUtil.newtKeyPress(0, robot, false, KeyEvent.VK_1, 100); // release P
217 AWTRobotUtil.newtKeyPress(0, robot, false, m3k, 10); // release MOD
218 AWTRobotUtil.newtKeyPress(0, robot, false, m2k, 10); // release MOD
219 AWTRobotUtil.newtKeyPress(0, robot, false, m1k, 10); // release MOD
221
222 for(int j=0; j < 100 && keyAdapter.getQueueSize() < 4+4; j++) { // wait until events are collected
223 robot.delay(100);
224 }
226 4 /* press-SI */, 4 /* release-SI */,
227 0 /* press-AR */, 0 /* release-AR */ );
228
229 final List<EventObject> queue = keyAdapter.copyQueue();
230 int i=0;
234
237 final KeyEvent e = (KeyEvent) queue.get(i++);
241 }
242
243 void testImpl(final GLWindow glWindow) throws AWTException, InterruptedException, InvocationTargetException {
244 final Robot robot = new Robot();
245 robot.setAutoWaitForIdle(true);
246
247 final GLEventListener demo1 = new RedSquareES2();
248 glWindow.addGLEventListener(demo1);
249
250 // NEWTFocusAdapter glWindow1FA = new NEWTFocusAdapter("GLWindow1");
251 // glWindow.addWindowListener(glWindow1FA);
252 final NEWTKeyAdapter glWindow1KA = new NEWTKeyAdapter("GLWindow1");
253 glWindow1KA.setVerbose(false);
254 glWindow.addKeyListener(glWindow1KA);
255
256 Assert.assertEquals(true, NewtTestUtil.waitForRealized(glWindow, true, null));
257
258 // Continuous animation ..
259 final Animator animator = new Animator(glWindow);
260 animator.start();
261
262 Thread.sleep(durationPerTest); // manual testing
263
264 AWTRobotUtil.assertRequestFocusAndWait(null, glWindow, glWindow, null, null); // programmatic
265 AWTRobotUtil.requestFocus(robot, glWindow, false); // within unit framework, prev. tests (TestFocus02SwingAWTRobot) 'confuses' Windows keyboard input
266 glWindow1KA.reset();
267
268 testKeyCodeModifier(robot, glWindow1KA, KeyEvent.VK_SHIFT, InputEvent.SHIFT_MASK, KeyEvent.VK_1, '1', '!');
269 testKeyCodeModifier(robot, glWindow1KA, KeyEvent.VK_SHIFT, InputEvent.SHIFT_MASK, KeyEvent.VK_Y, 'y', 'Y'); // US: Y, DE: Z
270 testKeyCodeModifier(robot, glWindow1KA, KeyEvent.VK_SHIFT, InputEvent.SHIFT_MASK, KeyEvent.VK_P, 'p', 'P');
271 testKeyCodeModifier(robot, glWindow1KA, KeyEvent.VK_CONTROL, InputEvent.CTRL_MASK, KeyEvent.VK_1, '1', KeyEvent.NULL_CHAR);
272 testKeyCodeModifier(robot, glWindow1KA, KeyEvent.VK_ALT, InputEvent.ALT_MASK, KeyEvent.VK_1, '1', KeyEvent.NULL_CHAR);
273
274 testKeyCodeAllModifierV1(robot, glWindow1KA);
275
276 // Remove listeners to avoid logging during dispose/destroy.
277 glWindow.removeKeyListener(glWindow1KA);
278
279 // Shutdown the test.
280 animator.stop();
281 }
282
283 static int atoi(final String a) {
284 int i=0;
285 try {
286 i = Integer.parseInt(a);
287 } catch (final Exception ex) { ex.printStackTrace(); }
288 return i;
289 }
290
291 public static void main(final String args[]) throws IOException {
292 for(int i=0; i<args.length; i++) {
293 if(args[i].equals("-time")) {
294 durationPerTest = atoi(args[++i]);
295 }
296 }
297 /**
298 BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
299 System.err.println("Press enter to continue");
300 System.err.println(stdin.readLine());
301 */
302 System.out.println("durationPerTest: "+durationPerTest);
303 final String tstname = TestNewtKeyCodeModifiersAWT.class.getName();
304 org.junit.runner.JUnitCore.main(tstname);
305 }
306
307
308}
AWT Canvas containing a NEWT Window using native parenting.
void setShallUseOffscreenLayer(final boolean v)
Request an offscreen layer, if supported.
static final short VK_SHIFT
Constant for the CTRL function key.
Definition: KeyEvent.java:451
static final char NULL_CHAR
This value, '\0', is used to indicate that the keyChar is unknown or not printable.
Definition: KeyEvent.java:369
static final short VK_P
See VK_A.
Definition: KeyEvent.java:625
static final short VK_ALT
Constant for the left ALT function key.
Definition: KeyEvent.java:460
static final short EVENT_KEY_PRESSED
A key has been pressed, excluding auto-repeat-modifier keys.
Definition: KeyEvent.java:362
static final short VK_Y
See VK_A.
Definition: KeyEvent.java:643
static final short VK_1
See VK_0.
Definition: KeyEvent.java:555
static final short EVENT_KEY_RELEASED
A key has been released, excluding auto-repeat-modifier keys.
Definition: KeyEvent.java:364
static final short VK_CONTROL
Constant for the CTRL function key.
Definition: KeyEvent.java:457
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.
Testing combinations of key code modifiers of key event.
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 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().
synchronized List< EventObject > copyQueue()
synchronized void setVerbose(final boolean v)
Instance starts in verbose mode, call w/ false to disable verbosity.
static void validateKeyEvent(final KeyEvent e, final short eventType, final int modifiers, final short keyCode, final char keyChar)
static void validateKeyAdapterStats(final NEWTKeyAdapter keyAdapter, final int expPressedCountSI, final int expReleasedCountSI, final int expPressedCountAR, final int expReleasedCountAR)
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.