JOGL v2.6.0-rc-20250712
JOGL, High-Performance Graphics Binding for Java™ (public API).
TestDestroyGLAutoDrawableNewtAWT.java
Go to the documentation of this file.
1/**
2 * Copyright 2010-2023 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.jogl.acore;
30
31import java.awt.AWTException;
32import java.awt.Robot;
33import java.io.IOException;
34import java.lang.reflect.InvocationTargetException;
35
36import com.jogamp.opengl.GLAutoDrawable;
37import com.jogamp.opengl.GLCapabilities;
38import com.jogamp.opengl.GLException;
39import com.jogamp.opengl.GLProfile;
40
41import org.junit.Assert;
42import org.junit.Test;
43import org.junit.FixMethodOrder;
44import org.junit.runners.MethodSorters;
45
46import com.jogamp.common.util.InterruptSource;
47import com.jogamp.newt.event.KeyEvent;
48import com.jogamp.newt.event.KeyListener;
49import com.jogamp.newt.event.MouseAdapter;
50import com.jogamp.newt.event.MouseEvent;
51import com.jogamp.newt.event.MouseListener;
52import com.jogamp.newt.event.WindowAdapter;
53import com.jogamp.newt.event.WindowEvent;
54import com.jogamp.newt.opengl.GLWindow;
55import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2;
56import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
57import com.jogamp.opengl.test.junit.util.NewtTestUtil;
58import com.jogamp.opengl.test.junit.util.UITestCase;
59import com.jogamp.opengl.util.Animator;
60
61@FixMethodOrder(MethodSorters.NAME_ASCENDING)
63
64 static long duration = 100; // ms
65
66 static void destroyGLAD(final GLAutoDrawable glad, final int mode) {
67 final String tname = Thread.currentThread().toString();
68 System.err.println(tname+": Destroy mode "+mode+": Start: Realised "+glad.isRealized());
69 glad.destroy();
70 System.err.println(tname+": Destroy mode "+mode+": End: Realised "+glad.isRealized());
71 }
72
73 /**
74 *
75 * @param destroyMode 0 on-thread, 1 render-thread, 2 edt-thread, 3 external-thread, 10 key-press, 11 mouse-click
76 * @throws InterruptedException
77 * @throws AWTException
78 * @throws InvocationTargetException
79 */
80 protected void runTestGL(final int destroyMode) throws InterruptedException, InvocationTargetException, AWTException {
81 final Robot robot = new Robot();
82 robot.setAutoWaitForIdle(true);
83
85
86 final GLWindow glWindow = GLWindow.create(caps);
87 Assert.assertNotNull(glWindow);
88 glWindow.setTitle("TestDestroyGLAutoDrawableNewtAWT Mode "+destroyMode);
89 glWindow.addGLEventListener(new RedSquareES2().setVerbose(false));
90
91 final short quitKey = KeyEvent.VK_Q;
92
93 glWindow.addWindowListener(new WindowAdapter() {
94 @Override
95 public void windowDestroyNotify(final WindowEvent e) {
96 System.err.println("Window DestroyNotify: "+e);
97 }
98
99 @Override
100 public void windowDestroyed(final WindowEvent e) {
101 System.err.println("Window Destroyed: "+e);
102 }
103
104 @Override
105 public void windowGainedFocus(final WindowEvent e) {
106 System.err.println("Window Focus Gained: "+e);
107 }
108
109 @Override
110 public void windowLostFocus(final WindowEvent e) {
111 System.err.println("Window Focus Lost: "+e);
112 }
113 });
114 final KeyListener keyAction = new KeyListener() {
115 @Override
116 public void keyPressed(final KeyEvent e) {
117 System.err.println("KEY PRESSED: "+e);
118 }
119 @Override
120 public void keyReleased(final KeyEvent e) {
121 System.err.println("KEY RELEASED: "+e);
122 if( e.isAutoRepeat() ) {
123 return;
124 }
125 switch(e.getKeyCode()) {
126 case quitKey:
127 destroyGLAD(glWindow, 10);
128 break;
129 }
130 }
131 };
132 final MouseListener mouseAction = new MouseAdapter() {
133 @Override
134 public void mousePressed(final MouseEvent e) {
135 System.err.println("MOUSE PRESSED: "+e);
136 }
137 @Override
138 public void mouseReleased(final MouseEvent e) {
139 System.err.println("MOUSE RELEASED: "+e);
140 }
141 @Override
142 public void mouseClicked(final MouseEvent e) {
143 System.err.println("MOUSE CLICKED: "+e);
144 destroyGLAD(glWindow, 11);
145 }
146 };
147
148 glWindow.setSize(256, 256);
149 glWindow.setVisible(true);
150 Assert.assertEquals(true, NewtTestUtil.waitForRealized(glWindow, true, null));
151
152 final Animator animator = new Animator(glWindow);
153 animator.setUpdateFPSFrames(30, null);
154 animator.start();
155
156 while(animator.isAnimating() && animator.getTotalFPSDuration()<duration) {
157 Thread.sleep(30);
158 }
159
160 System.err.println("AWT Robot Init");
161 final java.awt.Point objCenter;
162 {
163 final int[] oc = AWTRobotUtil.getCenterLocation(glWindow, false /* onTitleBarIfWindow */);
164 objCenter = new java.awt.Point(oc[0], oc[1]);
165 }
166 AWTRobotUtil.awtRobotMouseMove(robot, objCenter.x, objCenter.y); // Bug 919: Reset mouse position
167 AWTRobotUtil.assertRequestFocusAndWait(null, glWindow, glWindow, null, null); // programmatic
168 AWTRobotUtil.awtRobotMouseMove(robot, objCenter.x, objCenter.y); // Bug 919: Reset mouse position
170 System.err.println("AWT Robot OK");
171
172 switch( destroyMode ) {
173 case 1: {
174 // Since we pull the resources under the GLAutoDrawable
175 // while destroying it within the display call - it causes an exception:
176 // - WindowImpl.getGraphicsConfiguration(WindowImpl.java:1173) (NPE this.config)
177 // - ...
178 // - GLDrawableImpl.unlockSurface(GLDrawableImpl.java:340) ->
179 animator.stop(); // let's have the exception thrown here to catch it, not on animator
180 try {
181 glWindow.invoke(true, (final GLAutoDrawable glad) -> { destroyGLAD(glad, 1); return true; } );
182 } catch( final GLException gle ) {
183 // OK, since
184 System.err.println("Expected exception: "+gle.getMessage());
185 }
186 }
187 break;
188 case 2: {
189 glWindow.runOnEDTIfAvail(true, () -> { destroyGLAD(glWindow, 2); } );
190 }
191 break;
192 case 3: {
193 new InterruptSource.Thread( () -> { destroyGLAD(glWindow, 3); } ).start();
194 }
195 break;
196 case 10: {
197 glWindow.addKeyListener(keyAction);
199 AWTRobotUtil.newtKeyPress(0, robot, true, quitKey, 10);
200 AWTRobotUtil.newtKeyPress(0, robot, false, quitKey, 100);
201 }
202 break;
203 case 11: {
204 glWindow.addMouseListener(mouseAction);
206 AWTRobotUtil.mouseClick(robot, objCenter, 1, AWTRobotUtil.ROBOT_DELAY, 0);
207 }
208 break;
209 default: {
210 destroyGLAD(glWindow, 0);
211 }
212 break;
213 }
214 Assert.assertEquals(true, NewtTestUtil.waitForRealized(glWindow, false, null));
215 Assert.assertEquals(false, glWindow.isNativeValid());
216 animator.stop(); // Avoiding a ThreadDeath of animator at shutdown
217 Assert.assertEquals(false, animator.isAnimating());
218 }
219
220 @Test
221 public void test00OnThread() throws InterruptedException, InvocationTargetException, AWTException {
222 runTestGL(0);
223 }
224
225 @Test
226 public void test01RenderThread() throws InterruptedException, InvocationTargetException, AWTException {
227 runTestGL(1);
228 }
229
230 @Test
231 public void test02EDTThread() throws InterruptedException, InvocationTargetException, AWTException {
232 runTestGL(2);
233 }
234
235 @Test
236 public void test03ExtThread() throws InterruptedException, InvocationTargetException, AWTException {
237 runTestGL(3);
238 }
239
240 @Test
241 public void test10EDTKeyEvent() throws InterruptedException, InvocationTargetException, AWTException {
242 runTestGL(10);
243 }
244
245 @Test
246 public void test11EDTMouseEvent() throws InterruptedException, InvocationTargetException, AWTException {
247 runTestGL(11);
248 }
249
250 public static void main(final String args[]) throws IOException {
251 final String tstname = TestDestroyGLAutoDrawableNewtAWT.class.getName();
252 org.junit.runner.JUnitCore.main(tstname);
253 }
254
255}
final boolean isAutoRepeat()
getModifiers() contains AUTOREPEAT_MASK.
static final short VK_Q
See VK_A.
Definition: KeyEvent.java:627
final short getKeyCode()
Returns the virtual key code using a fixed mapping to the US keyboard layout.
Definition: KeyEvent.java:195
Pointer event of type PointerType.
Definition: MouseEvent.java:74
NEWT Window events are provided for notification purposes ONLY.
An implementation of GLAutoDrawable and Window interface, using a delegated Window instance,...
Definition: GLWindow.java:121
final void addMouseListener(final MouseListener l)
Appends the given MouseListener to the end of the list.
Definition: GLWindow.java:927
final void setTitle(final String title)
Definition: GLWindow.java:297
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 addWindowListener(final WindowListener l)
Appends the given com.jogamp.newt.event.WindowListener to the end of the list.
Definition: GLWindow.java:882
final void runOnEDTIfAvail(final boolean wait, final Runnable task)
Definition: GLWindow.java:857
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.
A generic exception for OpenGL errors used throughout the binding as a substitute for RuntimeExceptio...
Specifies the the OpenGL profile.
Definition: GLProfile.java:77
static GLProfile getGL2ES2(final AbstractGraphicsDevice device)
Returns the GL2ES2 profile implementation, hence compatible w/ GL2ES2.
Definition: GLProfile.java:913
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 int[] getCenterLocation(final Object obj, final boolean onTitleBarIfWindow)
static void mouseClick(final Robot robot, final Point pos, final int moveIter, final int moveDelay, final int actionDelay)
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 boolean waitForRealized(final Screen screen, final boolean realized, final Runnable waitAction)
final void setUpdateFPSFrames(final int frames, final PrintStream out)
final synchronized boolean start()
Starts this animator, if not running.
Definition: Animator.java:344
final synchronized boolean stop()
Stops this animator.
Definition: Animator.java:368
Listener for KeyEvents.
A higher-level abstraction than GLDrawable which supplies an event based mechanism (GLEventListener) ...
boolean invoke(boolean wait, GLRunnable glRunnable)
Enqueues a one-shot GLRunnable, which will be executed within the next display() call after all regis...
void addGLEventListener(GLEventListener listener)
Adds the given listener to the end of this drawable queue.
void destroy()
Destroys all resources associated with this GLAutoDrawable, inclusive the GLContext.
boolean isRealized()
Returns true if this drawable is realized, otherwise false.