JOGL v2.6.0-rc-20250706
JOGL, High-Performance Graphics Binding for Java™ (public API).
TestParentingFocus02SwingAWTRobot.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.*;
32
33import org.junit.Assert;
34import org.junit.BeforeClass;
35import org.junit.AfterClass;
36import org.junit.Test;
37import org.junit.FixMethodOrder;
38import org.junit.runners.MethodSorters;
39
40import java.awt.AWTException;
41import java.awt.Button;
42import java.awt.BorderLayout;
43import java.awt.Container;
44import java.awt.Robot;
45
46import javax.swing.JFrame;
47import javax.swing.JPanel;
48import javax.swing.SwingUtilities;
49import javax.swing.WindowConstants;
50
51import java.util.ArrayList;
52
53import com.jogamp.opengl.*;
54
55import com.jogamp.opengl.util.Animator;
56import com.jogamp.newt.opengl.*;
57import com.jogamp.newt.awt.NewtCanvasAWT;
58
59import java.io.IOException;
60
61import com.jogamp.opengl.test.junit.util.*;
62import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
63
64/**
65 * Testing focus <i>mouse-click</i> and <i>programmatic</i> traversal of an AWT component tree with {@link NewtCanvasAWT} attached.
66 * <p>
67 * {@link JFrame} . {@link JPanel}+ . {@link Container} [ Button*, {@link NewtCanvasAWT} . {@link GLWindow} ]
68 * </p>
69 * <p>
70 * <i>+ JPanel is set as JFrame's root content pane</i><br/>
71 * </p>
72 */
73@FixMethodOrder(MethodSorters.NAME_ASCENDING)
75 static int width, height;
76 static long durationPerTest = 10;
77 static long awtWaitTimeout = 1000;
78 static GLCapabilities glCaps;
79
80 @BeforeClass
81 public static void initClass() throws AWTException, InterruptedException, InvocationTargetException {
82 width = 640;
83 height = 480;
84
85 final JFrame f = new JFrame();
86 javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
87 @Override
88 public void run() {
89 f.setSize(100,100);
90 f.setVisible(true);
91 } } );
92 javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
93 @Override
94 public void run() {
95 f.dispose();
96 } } );
97
98 glCaps = new GLCapabilities(null);
99 }
100
101 @AfterClass
102 public static void release() {
103 }
104
105 private void testFocus01ProgrFocusImpl(final Robot robot)
106 throws AWTException, InterruptedException, InvocationTargetException {
107
108 final ArrayList<EventCountAdapter> eventCountAdapters = new ArrayList<EventCountAdapter>();
109
110 final GLWindow glWindow1 = GLWindow.create(glCaps);
111 glWindow1.setTitle("testWindowParenting01CreateVisibleDestroy");
112 final GLEventListener demo1 = new GearsES2();
113 glWindow1.addGLEventListener(demo1);
114 final NEWTFocusAdapter glWindow1FA = new NEWTFocusAdapter("GLWindow1");
115 glWindow1.addWindowListener(glWindow1FA);
116 final NEWTKeyAdapter glWindow1KA = new NEWTKeyAdapter("GLWindow1");
117 glWindow1.addKeyListener(glWindow1KA);
118 eventCountAdapters.add(glWindow1KA);
119 final NEWTMouseAdapter glWindow1MA = new NEWTMouseAdapter("GLWindow1");
120 glWindow1.addMouseListener(glWindow1MA);
121 eventCountAdapters.add(glWindow1MA);
122
123 final NewtCanvasAWT newtCanvasAWT = new NewtCanvasAWT(glWindow1);
124 final AWTFocusAdapter newtCanvasAWTFA = new AWTFocusAdapter("NewtCanvasAWT");
125 newtCanvasAWT.addFocusListener(newtCanvasAWTFA);
126 final AWTKeyAdapter newtCanvasAWTKA = new AWTKeyAdapter("NewtCanvasAWT");
127 newtCanvasAWT.addKeyListener(newtCanvasAWTKA);
128 eventCountAdapters.add(newtCanvasAWTKA);
129 final AWTMouseAdapter newtCanvasAWTMA = new AWTMouseAdapter("NewtCanvasAWT");
130 newtCanvasAWT.addMouseListener(newtCanvasAWTMA);
131 eventCountAdapters.add(newtCanvasAWTMA);
132
133 final Button buttonNorthInner = new Button("north");
134 final AWTFocusAdapter buttonNorthInnerFA = new AWTFocusAdapter("ButtonNorthInner");
135 buttonNorthInner.addFocusListener(buttonNorthInnerFA);
136 final AWTKeyAdapter buttonNorthInnerKA = new AWTKeyAdapter("ButtonNorthInner");
137 buttonNorthInner.addKeyListener(buttonNorthInnerKA);
138 eventCountAdapters.add(buttonNorthInnerKA);
139 final AWTMouseAdapter buttonNorthInnerMA = new AWTMouseAdapter("ButtonNorthInner");
140 buttonNorthInner.addMouseListener(buttonNorthInnerMA);
141 eventCountAdapters.add(buttonNorthInnerMA);
142 final Container container1 = new Container();
143 container1.setLayout(new BorderLayout());
144 container1.add(buttonNorthInner, BorderLayout.NORTH);
145 container1.add(new Button("south"), BorderLayout.SOUTH);
146 container1.add(new Button("east"), BorderLayout.EAST);
147 container1.add(new Button("west"), BorderLayout.WEST);
148 container1.add(newtCanvasAWT, BorderLayout.CENTER);
149
150 final Button buttonNorthOuter = new Button("north");
151 final AWTFocusAdapter buttonNorthOuterFA = new AWTFocusAdapter("ButtonNorthOuter");
152 buttonNorthOuter.addFocusListener(buttonNorthOuterFA);
153 final AWTKeyAdapter buttonNorthOuterKA = new AWTKeyAdapter("ButtonNorthOuter");
154 buttonNorthOuter.addKeyListener(buttonNorthOuterKA);
155 eventCountAdapters.add(buttonNorthOuterKA);
156 final AWTMouseAdapter buttonNorthOuterMA = new AWTMouseAdapter("ButtonNorthOuter");
157 buttonNorthOuter.addMouseListener(buttonNorthOuterMA);
158 eventCountAdapters.add(buttonNorthOuterMA);
159 final JPanel jPanel1 = new JPanel();
160 jPanel1.setLayout(new BorderLayout());
161 jPanel1.add(buttonNorthOuter, BorderLayout.NORTH);
162 jPanel1.add(new Button("south"), BorderLayout.SOUTH);
163 jPanel1.add(new Button("east"), BorderLayout.EAST);
164 jPanel1.add(new Button("west"), BorderLayout.WEST);
165 jPanel1.add(container1, BorderLayout.CENTER);
166
167 final JFrame jFrame1 = new JFrame("Swing Parent JFrame");
168 // jFrame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
169 jFrame1.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); // equivalent to Frame, use windowClosing event!
170 jFrame1.setContentPane(jPanel1);
171 jFrame1.setSize(width, height);
172 javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
173 @Override
174 public void run() {
175 jFrame1.setVisible(true);
176 } } );
177 Assert.assertEquals(true, AWTRobotUtil.waitForVisible(jFrame1, true, null));
178 Assert.assertEquals(true, NewtTestUtil.waitForRealized(glWindow1, true, null));
180 Assert.assertTrue(AWTRobotUtil.toFrontAndRequestFocus(robot, jFrame1));
181
182 int wait=0;
183 while(wait<awtWaitTimeout/10 && glWindow1.getTotalFPSFrames()<1) { Thread.sleep(awtWaitTimeout/100); wait++; }
184 System.err.println("Frames for initial setVisible(true): "+glWindow1.getTotalFPSFrames());
185 Assert.assertTrue(glWindow1.isVisible());
186 Assert.assertTrue(0 < glWindow1.getTotalFPSFrames());
187
188 // Continuous animation ..
189 final Animator animator1 = new Animator(glWindow1);
190 animator1.start();
191
192 Thread.sleep(durationPerTest); // manual testing
193
194 // Button Outer Focus
195 Thread.sleep(100); // allow event sync
196 System.err.println("FOCUS AWT Button Outer request.1");
197 EventCountAdapterUtil.reset(eventCountAdapters);
198 AWTRobotUtil.assertRequestFocusAndWait(robot, buttonNorthOuter, buttonNorthOuter, buttonNorthOuterFA, null); // OSX sporadically buttonNorthOuter did not gain - major UI failure
199 Assert.assertEquals(false, glWindow1FA.focusGained());
200 Assert.assertEquals(false, newtCanvasAWTFA.focusGained());
201 Assert.assertEquals(false, buttonNorthInnerFA.focusGained());
202 System.err.println("FOCUS AWT Button Outer sync.1");
203 AWTRobotUtil.assertKeyType(robot, java.awt.event.KeyEvent.VK_A, 2, buttonNorthOuter, buttonNorthOuterKA); // OSX sporadically won't receive the keyboard input - major UI failure
204 AWTRobotUtil.assertMouseClick(robot, java.awt.event.InputEvent.BUTTON1_MASK, 1,
205 buttonNorthOuter, buttonNorthOuterMA);
206 AWTRobotUtil.assertMouseClick(robot, java.awt.event.InputEvent.BUTTON1_MASK, 2,
207 buttonNorthOuter, buttonNorthOuterMA);
208
209 // NEWT Focus
210 Thread.sleep(100); // allow event sync
211 System.err.println("FOCUS NEWT Canvas/GLWindow request.2");
212 EventCountAdapterUtil.reset(eventCountAdapters);
213 AWTRobotUtil.assertRequestFocusAndWait(robot, newtCanvasAWT, newtCanvasAWT.getNEWTChild(), glWindow1FA, buttonNorthOuterFA);
214 // Manually tested on Java7/[Linux,Windows] (where this assertion failed),
215 // Should be OK to have the AWT component assume it also has the focus.
216 // Assert.assertTrue("Focus prev. gained, but NewtCanvasAWT didn't loose it. Gainer: "+glWindow1FA+"; Looser "+newtCanvasAWTFA,
217 // AWTRobotUtil.waitForFocus(glWindow1FA, newtCanvasAWTFA));
218 if( !TestUtil.waitForFocus(glWindow1FA, newtCanvasAWTFA, null) ) {
219 System.err.println("Info: Focus prev. gained, but NewtCanvasAWT didn't loose it. Gainer: "+glWindow1FA+"; Looser "+newtCanvasAWTFA);
220 }
221 Assert.assertEquals(false, buttonNorthInnerFA.focusGained());
222 System.err.println("FOCUS NEWT Canvas/GLWindow sync.2");
223 AWTRobotUtil.assertKeyType(robot, java.awt.event.KeyEvent.VK_A, 2, glWindow1, glWindow1KA);
224 Assert.assertEquals("AWT parent canvas received non consumed keyboard events", newtCanvasAWTKA.getConsumedCount(), newtCanvasAWTKA.getCount());
225 System.err.println("FOCUS NEWT Canvas/GLWindow sync.2.2");
226 AWTRobotUtil.assertMouseClick(robot, java.awt.event.InputEvent.BUTTON1_MASK, 1,
227 glWindow1, glWindow1MA);
228 System.err.println("FOCUS NEWT Canvas/GLWindow sync.2.3");
229 AWTRobotUtil.assertMouseClick(robot, java.awt.event.InputEvent.BUTTON1_MASK, 2,
230 glWindow1, glWindow1MA);
231 System.err.println("FOCUS NEWT Canvas/GLWindow sync.2.4");
232 if( !newtCanvasAWT.isAWTEventPassThrough() ) {
233 Assert.assertEquals("AWT parent canvas received consumed keyboard events", 0, newtCanvasAWTKA.getConsumedCount());
234 Assert.assertEquals("AWT parent canvas received mouse events", 0, newtCanvasAWTMA.getCount());
235 }
236
237 // Button Inner Focus
238 Thread.sleep(100); // allow event sync
239 System.err.println("FOCUS AWT Button request.3");
240 EventCountAdapterUtil.reset(eventCountAdapters);
241 AWTRobotUtil.assertRequestFocusAndWait(robot, buttonNorthInner, buttonNorthInner, buttonNorthInnerFA, glWindow1FA);
242 Assert.assertEquals(false, glWindow1FA.focusGained());
243 Assert.assertEquals(false, newtCanvasAWTFA.focusGained());
244 Assert.assertEquals(false, buttonNorthOuterFA.focusGained());
245 System.err.println("FOCUS AWT Button sync.3");
246 AWTRobotUtil.assertKeyType(robot, java.awt.event.KeyEvent.VK_A, 2, buttonNorthInner, buttonNorthInnerKA);
247 AWTRobotUtil.assertMouseClick(robot, java.awt.event.InputEvent.BUTTON1_MASK, 1,
248 buttonNorthInner, buttonNorthInnerMA);
249 AWTRobotUtil.assertMouseClick(robot, java.awt.event.InputEvent.BUTTON1_MASK, 2,
250 buttonNorthInner, buttonNorthInnerMA);
251
252 // NEWT Focus
253 Thread.sleep(100); // allow event sync
254 System.err.println("FOCUS NEWT Canvas/GLWindow request.4");
255 EventCountAdapterUtil.reset(eventCountAdapters);
256 AWTRobotUtil.assertRequestFocusAndWait(robot, newtCanvasAWT, newtCanvasAWT.getNEWTChild(), glWindow1FA, buttonNorthInnerFA);
257 // Manually tested on Java7/[Linux,Windows] (where this assertion failed),
258 // Should be OK to have the AWT component assume it also has the focus.
259 // Assert.assertTrue("Focus prev. gained, but NewtCanvasAWT didn't loose it. Gainer: "+glWindow1FA+"; Looser "+newtCanvasAWTFA,
260 // AWTRobotUtil.waitForFocus(glWindow1FA, newtCanvasAWTFA));
261 if( !TestUtil.waitForFocus(glWindow1FA, newtCanvasAWTFA, null) ) {
262 System.err.println("Info: Focus prev. gained, but NewtCanvasAWT didn't loose it. Gainer: "+glWindow1FA+"; Looser "+newtCanvasAWTFA);
263 }
264
265 Assert.assertEquals(false, buttonNorthOuterFA.focusGained());
266 System.err.println("FOCUS NEWT Canvas/GLWindow sync.4");
267 AWTRobotUtil.assertKeyType(robot, java.awt.event.KeyEvent.VK_A, 2, glWindow1, glWindow1KA);
268 Assert.assertEquals("AWT parent canvas received non consumed keyboard events", newtCanvasAWTKA.getConsumedCount(), newtCanvasAWTKA.getCount());
269 AWTRobotUtil.assertMouseClick(robot, java.awt.event.InputEvent.BUTTON1_MASK, 1,
270 glWindow1, glWindow1MA);
271 AWTRobotUtil.assertMouseClick(robot, java.awt.event.InputEvent.BUTTON1_MASK, 2,
272 glWindow1, glWindow1MA);
273 if( !newtCanvasAWT.isAWTEventPassThrough() ) {
274 Assert.assertEquals("AWT parent canvas received consumed keyboard events", 0, newtCanvasAWTKA.getConsumedCount());
275 Assert.assertEquals("AWT parent canvas received mouse events", 0, newtCanvasAWTMA.getCount());
276 }
277
278 animator1.stop();
279 Assert.assertEquals(false, animator1.isAnimating());
280
281 SwingUtilities.invokeAndWait(new Runnable() {
282 @Override
283 public void run() {
284 jFrame1.setVisible(false);
285 jPanel1.remove(container1);
286 jFrame1.dispose();
287 } });
288
289 glWindow1.destroy();
290 Assert.assertEquals(true, NewtTestUtil.waitForRealized(glWindow1, false, null));
291 }
292
293 @Test
294 public void testFocus01ProgrFocus() throws AWTException, InterruptedException, InvocationTargetException {
295 testFocus01ProgrFocusImpl(null);
296 }
297
298 @Test
299 public void testFocus02RobotFocus() throws AWTException, InterruptedException, InvocationTargetException {
300 final Robot robot = new Robot();
301 robot.setAutoWaitForIdle(true);
302 testFocus01ProgrFocusImpl(robot);
303 }
304
305 static int atoi(final String a) {
306 int i=0;
307 try {
308 i = Integer.parseInt(a);
309 } catch (final Exception ex) { ex.printStackTrace(); }
310 return i;
311 }
312
313 @SuppressWarnings("unused")
314 public static void main(final String args[])
315 throws IOException, AWTException, InterruptedException, InvocationTargetException
316 {
317 for(int i=0; i<args.length; i++) {
318 if(args[i].equals("-time")) {
319 durationPerTest = atoi(args[++i]);
320 }
321 }
322 if(true) {
323 final String tstname = TestParentingFocus02SwingAWTRobot.class.getName();
324 org.junit.runner.JUnitCore.main(tstname);
325 } else {
331 }
332 }
333}
334
AWT Canvas containing a NEWT Window using native parenting.
final boolean isAWTEventPassThrough()
Returns true if Key and Mouse input events will be passed through AWT, otherwise only the NEWT child ...
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 addWindowListener(final WindowListener l)
Appends the given com.jogamp.newt.event.WindowListener to the end of the list.
Definition: GLWindow.java:882
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 focus mouse-click and programmatic traversal of an AWT component tree with NewtCanvasAWT atta...
static void assertKeyType(Robot robot, final int keyCode, final int typeCount, final Object obj, final KeyEventCountAdapter counter)
FIXME: AWTRobotUtil Cleanup: Use specific type for argument object.
static void assertMouseClick(Robot robot, final int mouseButton, final int clickCount, final Object obj, final InputEventCountAdapter counter)
FIXME: AWTRobotUtil Cleanup: Use specific type for argument object.
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 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 reset(final EventCountAdapter[] adapters)
static boolean waitForRealized(final Screen screen, final boolean realized, final Runnable waitAction)
static boolean waitForFocus(final FocusEventCountAdapter gain, final FocusEventCountAdapter lost, final Runnable waitAction)
Definition: TestUtil.java:50
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.