diff options
author | Sven Gothel <[email protected]> | 2013-02-19 08:00:38 +0100 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2013-02-19 08:00:38 +0100 |
commit | 85338858f5c58694fa88e77df1386d0556887944 (patch) | |
tree | 3fc6ff607520b6781c22fd50dd63aa62e79cfb10 /src/test | |
parent | a40ee817a3bd537b0de7018772b0835f995a1bed (diff) |
Bug 678 (fix), Bug 641 (API + Windows Impl.), Bug 688 (prep): Update NEWT's KeyEvent handling while distinguish keyCode (kbd layout independent) and keySym (kbd layout dependent)
API Changes:
- Virtual key codes and symbols are of type short.
- KeyEvent.keySymbol() shall return a layout dependent value (Bug 641)
- Method returns former keyCode() value, which was layout dependent.
- Returns 'short' value
- KeyEvent.keyCode() returns a short value, instead of int
- KeyEvent.keyCode() shall return a layout independent value (Bug 641)
- To ease implementation, we only 'require' the scan code to be mapped to a 'US Keyboard layout',
which allows reusing layout dependent code while preserving the goal to have a fixed physical key association
- Implementation status:
- Windows OK
- X11 TODO
- OSX: 50/50 TODO
- Using layout independent 'action keys'
- Using layout dependent 'printable keys'
- returning above semantics for both, keyCode and keySym
- Android 50/50 TODO
- Returning the layout independent keyCode
- Mapping probably incomplete
- KeyEvent.EVENT_KEY_TYPED and KeyListener.keyTyped(KeyEvent) (Bug 688)
- Marked DEPRECATED
- No more called for auto-repeat events
- Synthesized in WindowImpl.consumeKeyEvent(..): No more injection by native- or java driver code
- NEWTEvent.eventType: int -> short
- field, as well as all method involving eventType changed to short.
- NEWTEvent.isSystemEvent: REMOVED
- Never used as well as never being implemented properly
Internal Changes:
- Simplified keyEvent driver code
- Especially the Windows native driver's mapping code
could be simplified using scanCode and MapVirtualKeyEx
- NEWT Event Factories: hashMap -> switch/case
Unit Tests:
-
- Added NewtCanvasAWT Offscreen Layer Tests
important to test the AWT -> NEWT translation on OSX/CALayer:
- TestNewtKeyCodeModifiersAWT
- TestNewtKeyCodesAWT
- TestNewtKeyEventAutoRepeatAWT
- TestNewtKeyEventOrderAWT
- TestNewtKeyPressReleaseUnmaskRepeatAWT
Diffstat (limited to 'src/test')
7 files changed, 290 insertions, 106 deletions
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyCodeModifiersAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyCodeModifiersAWT.java index ec06379e0..08a181e10 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyCodeModifiersAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyCodeModifiersAWT.java @@ -47,6 +47,8 @@ import javax.swing.JFrame; import java.io.IOException; +import jogamp.nativewindow.jawt.JAWTUtil; + import org.junit.BeforeClass; import org.junit.Test; @@ -61,6 +63,11 @@ import com.jogamp.opengl.test.junit.util.*; /** * Testing combinations of key code modifiers of key event. + * + * <p> + * Due to limitation of AWT Robot, the test machine needs to have US keyboard enabled, + * even though we do unify VK codes to US keyboard across all layouts. + * </p> */ public class TestNewtKeyCodeModifiersAWT extends UITestCase { static int width, height; @@ -99,12 +106,14 @@ public class TestNewtKeyCodeModifiersAWT extends UITestCase { glWindow.destroy(); } - @Test - public void test02NewtCanvasAWT() throws AWTException, InterruptedException, InvocationTargetException { + private void testNewtCanvasAWT_Impl(boolean onscreen) throws AWTException, InterruptedException, InvocationTargetException { GLWindow glWindow = GLWindow.create(glCaps); // Wrap the window in a canvas. final NewtCanvasAWT newtCanvasAWT = new NewtCanvasAWT(glWindow); + if( !onscreen ) { + newtCanvasAWT.setShallUseOffscreenLayer(true); + } // Add the canvas to a frame, and make it all visible. final JFrame frame1 = new JFrame("Swing AWT Parent Frame: "+ glWindow.getTitle()); @@ -129,42 +138,63 @@ public class TestNewtKeyCodeModifiersAWT extends UITestCase { throwable.printStackTrace(); Assume.assumeNoException( throwable ); } - glWindow.destroy(); + glWindow.destroy(); + } + + @Test + public void test02NewtCanvasAWT_Onscreen() throws AWTException, InterruptedException, InvocationTargetException { + if( JAWTUtil.isOffscreenLayerRequired() ) { + System.err.println("Platform doesn't support onscreen rendering."); + return; + } + testNewtCanvasAWT_Impl(true); } - static void testKeyCodeModifier(Robot robot, NEWTKeyAdapter keyAdapter, int modifierKey, int modifierMask) { + @Test + public void test03NewtCanvasAWT_Offsccreen() throws AWTException, InterruptedException, InvocationTargetException { + if( !JAWTUtil.isOffscreenLayerSupported() ) { + System.err.println("Platform doesn't support offscreen rendering."); + return; + } + testNewtCanvasAWT_Impl(false); + } + + @SuppressWarnings("deprecation") + static void testKeyCodeModifier(Robot robot, NEWTKeyAdapter keyAdapter, int modifierKey, int modifierMask, int keyCode, char keyCharOnly, char keyCharMod) { keyAdapter.reset(); - AWTRobotUtil.keyPress(0, robot, true, KeyEvent.VK_P, 10); // press P - AWTRobotUtil.keyPress(0, robot, false, KeyEvent.VK_P, 100); // release+typed P + AWTRobotUtil.keyPress(0, robot, true, keyCode, 10); // press keyCode + AWTRobotUtil.keyPress(0, robot, false, keyCode, 100); // release+typed keyCode robot.waitForIdle(); - for(int j=0; j < 10 && keyAdapter.getQueueSize() < 3; j++) { // wait until events are collected + for(int j=0; j < 40 && keyAdapter.getQueueSize() < 3; j++) { // wait until events are collected robot.delay(100); } AWTRobotUtil.keyPress(0, robot, true, modifierKey, 10); // press MOD - AWTRobotUtil.keyPress(0, robot, true, KeyEvent.VK_P, 10); // press P - AWTRobotUtil.keyPress(0, robot, false, KeyEvent.VK_P, 10); // release+typed P - AWTRobotUtil.keyPress(0, robot, false, modifierKey, 100); // release+typed MOD + AWTRobotUtil.keyPress(0, robot, true, keyCode, 10); // press keyCode + AWTRobotUtil.keyPress(0, robot, false, keyCode, 10); // release+typed keyCode + AWTRobotUtil.keyPress(0, robot, false, modifierKey, 100); // release MOD robot.waitForIdle(); - for(int j=0; j < 20 && keyAdapter.getQueueSize() < 3+6; j++) { // wait until events are collected + for(int j=0; j < 40 && keyAdapter.getQueueSize() < 3+5; j++) { // wait until events are collected robot.delay(100); } - NEWTKeyUtil.validateKeyAdapterStats(keyAdapter, 3+6, 0); + NEWTKeyUtil.validateKeyAdapterStats(keyAdapter, + 3 /* press-SI */, 3 /* release-SI */, 2 /* typed-SI */, + 0 /* press-AR */, 0 /* release-AR */, 0 /* typed-AR */ ); final List<EventObject> queue = keyAdapter.getQueued(); int i=0; - NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_PRESSED, 0, KeyEvent.VK_P); - NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_RELEASED, 0, KeyEvent.VK_P); - NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_TYPED, 0, KeyEvent.VK_P); + NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_PRESSED, 0, keyCode, keyCharOnly); + NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_RELEASED, 0, keyCode, keyCharOnly); + NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_TYPED, 0, keyCode, keyCharOnly); - NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_PRESSED, modifierMask, modifierKey); - NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_PRESSED, modifierMask, KeyEvent.VK_P); - NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_RELEASED, modifierMask, KeyEvent.VK_P); - NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_TYPED, modifierMask, KeyEvent.VK_P); - NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_RELEASED, modifierMask, modifierKey); - NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_TYPED, modifierMask, modifierKey); + NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_PRESSED, modifierMask, modifierKey, (char)0); + NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_PRESSED, modifierMask, keyCode, keyCharMod); + NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_RELEASED, modifierMask, keyCode, keyCharMod); + NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_TYPED, modifierMask, keyCode, keyCharMod); + NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_RELEASED, modifierMask, modifierKey, (char)0); } + @SuppressWarnings("deprecation") static void testKeyCodeAllModifierV1(Robot robot, NEWTKeyAdapter keyAdapter) { final int m1k = KeyEvent.VK_ALT; final int m1m = InputEvent.ALT_MASK; @@ -180,32 +210,31 @@ public class TestNewtKeyCodeModifiersAWT extends UITestCase { AWTRobotUtil.keyPress(0, robot, true, KeyEvent.VK_P, 10); // press P AWTRobotUtil.keyPress(0, robot, false, KeyEvent.VK_P, 100); // release+typed P - AWTRobotUtil.keyPress(0, robot, false, m3k, 10); // release+typed MOD - AWTRobotUtil.keyPress(0, robot, false, m2k, 10); // release+typed MOD - AWTRobotUtil.keyPress(0, robot, false, m1k, 10); // release+typed MOD + AWTRobotUtil.keyPress(0, robot, false, m3k, 10); // release MOD + AWTRobotUtil.keyPress(0, robot, false, m2k, 10); // release MOD + AWTRobotUtil.keyPress(0, robot, false, m1k, 10); // release MOD robot.waitForIdle(); - for(int j=0; j < 20 && keyAdapter.getQueueSize() < 3*4; j++) { // wait until events are collected + for(int j=0; j < 40 && keyAdapter.getQueueSize() < 4+4+1; j++) { // wait until events are collected robot.delay(100); } - NEWTKeyUtil.validateKeyAdapterStats(keyAdapter, 3*4, 0); + NEWTKeyUtil.validateKeyAdapterStats(keyAdapter, + 4 /* press-SI */, 4 /* release-SI */, 1 /* typed-SI */, + 0 /* press-AR */, 0 /* release-AR */, 0 /* typed-AR */ ); final List<EventObject> queue = keyAdapter.getQueued(); int i=0; - NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_PRESSED, m1m, m1k); - NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_PRESSED, m1m|m2m, m2k); - NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_PRESSED, m1m|m2m|m3m, m3k); + NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_PRESSED, m1m, m1k, (char)0); + NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_PRESSED, m1m|m2m, m2k, (char)0); + NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_PRESSED, m1m|m2m|m3m, m3k, (char)0); - NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_PRESSED, m1m|m2m|m3m, KeyEvent.VK_P); - NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_RELEASED, m1m|m2m|m3m, KeyEvent.VK_P); - NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_TYPED, m1m|m2m|m3m, KeyEvent.VK_P); + NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_PRESSED, m1m|m2m|m3m, KeyEvent.VK_P, (char)0); + NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_RELEASED, m1m|m2m|m3m, KeyEvent.VK_P, (char)0); + NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_TYPED, m1m|m2m|m3m, KeyEvent.VK_P, (char)0); - NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_RELEASED, m1m|m2m|m3m, m3k); - NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_TYPED, m1m|m2m|m3m, m3k); - NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_RELEASED, m1m|m2m, m2k); - NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_TYPED, m1m|m2m, m2k); - NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_RELEASED, m1m, m1k); - NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_TYPED, m1m, m1k); + NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_RELEASED, m1m|m2m|m3m, m3k, (char)0); + NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_RELEASED, m1m|m2m, m2k, (char)0); + NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_RELEASED, m1m, m1k, (char)0); } void testImpl(GLWindow glWindow) throws AWTException, InterruptedException, InvocationTargetException { @@ -233,9 +262,11 @@ public class TestNewtKeyCodeModifiersAWT extends UITestCase { AWTRobotUtil.requestFocus(robot, glWindow, false); // within unit framework, prev. tests (TestFocus02SwingAWTRobot) 'confuses' Windows keyboard input glWindow1KA.reset(); - testKeyCodeModifier(robot, glWindow1KA, KeyEvent.VK_SHIFT, InputEvent.SHIFT_MASK); - testKeyCodeModifier(robot, glWindow1KA, KeyEvent.VK_CONTROL, InputEvent.CTRL_MASK); - testKeyCodeModifier(robot, glWindow1KA, KeyEvent.VK_ALT, InputEvent.ALT_MASK); + testKeyCodeModifier(robot, glWindow1KA, KeyEvent.VK_SHIFT, InputEvent.SHIFT_MASK, KeyEvent.VK_1, '1', '!'); + testKeyCodeModifier(robot, glWindow1KA, KeyEvent.VK_SHIFT, InputEvent.SHIFT_MASK, KeyEvent.VK_Y, 'y', 'Y'); // US: Y, DE: Z + testKeyCodeModifier(robot, glWindow1KA, KeyEvent.VK_SHIFT, InputEvent.SHIFT_MASK, KeyEvent.VK_P, 'p', 'P'); + testKeyCodeModifier(robot, glWindow1KA, KeyEvent.VK_CONTROL, InputEvent.CTRL_MASK, KeyEvent.VK_P, 'p', (char)0); + testKeyCodeModifier(robot, glWindow1KA, KeyEvent.VK_ALT, InputEvent.ALT_MASK, KeyEvent.VK_P, 'p', (char)0); testKeyCodeAllModifierV1(robot, glWindow1KA); diff --git a/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyCodesAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyCodesAWT.java index ef4b17375..b3ba71795 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyCodesAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyCodesAWT.java @@ -48,10 +48,13 @@ import javax.swing.JFrame; import java.io.IOException; +import jogamp.nativewindow.jawt.JAWTUtil; + import org.junit.BeforeClass; import org.junit.Test; import com.jogamp.newt.awt.NewtCanvasAWT; +import com.jogamp.newt.event.KeyEvent; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.util.Animator; import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2; @@ -99,12 +102,14 @@ public class TestNewtKeyCodesAWT extends UITestCase { glWindow.destroy(); } - @Test - public void test02NewtCanvasAWT() throws AWTException, InterruptedException, InvocationTargetException { + private void testNewtCanvasAWT_Impl(boolean onscreen) throws AWTException, InterruptedException, InvocationTargetException { GLWindow glWindow = GLWindow.create(glCaps); // Wrap the window in a canvas. final NewtCanvasAWT newtCanvasAWT = new NewtCanvasAWT(glWindow); + if( !onscreen ) { + newtCanvasAWT.setShallUseOffscreenLayer(true); + } // Add the canvas to a frame, and make it all visible. final JFrame frame1 = new JFrame("Swing AWT Parent Frame: "+ glWindow.getTitle()); @@ -131,7 +136,25 @@ public class TestNewtKeyCodesAWT extends UITestCase { } glWindow.destroy(); } + + @Test + public void test02NewtCanvasAWT_Onscreen() throws AWTException, InterruptedException, InvocationTargetException { + if( JAWTUtil.isOffscreenLayerRequired() ) { + System.err.println("Platform doesn't support onscreen rendering."); + return; + } + testNewtCanvasAWT_Impl(true); + } + @Test + public void test03NewtCanvasAWT_Offsccreen() throws AWTException, InterruptedException, InvocationTargetException { + if( !JAWTUtil.isOffscreenLayerSupported() ) { + System.err.println("Platform doesn't support offscreen rendering."); + return; + } + testNewtCanvasAWT_Impl(false); + } + static CodeSeg[] codeSegments = new CodeSeg[] { new CodeSeg(0x008, 0x008, "bs"), // new CodeSeg(0x009, 0x009, "tab"), // TAB functions as focus traversal key @@ -167,14 +190,29 @@ public class TestNewtKeyCodesAWT extends UITestCase { keyAdapter.reset(); final CodeSeg codeSeg = codeSegments[i]; // System.err.println("*** Segment "+codeSeg.description); - for(int c=codeSeg.min; c<=codeSeg.max; c++) { + int eventCount = 0; + for(short c=codeSeg.min; c<=codeSeg.max; c++) { // System.err.println("*** KeyCode 0x"+Integer.toHexString(c)); - AWTRobotUtil.keyPress(0, robot, true, c, 10); - AWTRobotUtil.keyPress(0, robot, false, c, 100); + try { + AWTRobotUtil.keyPress(0, robot, true, c, 10); + } catch (Exception e) { + System.err.println("Exception @ AWT Robot.PRESS "+MiscUtils.toHexString(c)+" - "+e.getMessage()); + break; + } + eventCount++; + try { + AWTRobotUtil.keyPress(0, robot, false, c, 100); + } catch (Exception e) { + System.err.println("Exception @ AWT Robot.RELEASE "+MiscUtils.toHexString(c)+" - "+e.getMessage()); + break; + } + eventCount++; + if( KeyEvent.isPrintableKey(c) ) { + eventCount++; + } robot.waitForIdle(); } - final int codeCount = codeSeg.max - codeSeg.min + 1; - for(int j=0; j < 20 && keyAdapter.getQueueSize() < 3 * codeCount; j++) { // wait until events are collected + for(int j=0; j < 20 && keyAdapter.getQueueSize() < eventCount; j++) { // wait until events are collected robot.delay(100); } final ArrayList<EventObject> events = new ArrayList<EventObject>(keyAdapter.getQueued()); diff --git a/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyEventAutoRepeatAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyEventAutoRepeatAWT.java index 00fbc0500..d7de4e735 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyEventAutoRepeatAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyEventAutoRepeatAWT.java @@ -153,6 +153,7 @@ public class TestNewtKeyEventAutoRepeatAWT extends UITestCase { glWindow.destroy(); } + @SuppressWarnings("deprecation") static void testKeyEventAutoRepeat(Robot robot, NEWTKeyAdapter keyAdapter, int loops, int pressDurationMS) { System.err.println("KEY Event Auto-Repeat Test: "+loops); EventObject[][] first = new EventObject[loops][3]; @@ -201,9 +202,19 @@ public class TestNewtKeyEventAutoRepeatAWT extends UITestCase { final boolean hasAR = 0 < keyAdapter.getKeyPressedCount(true) ; { - final int expTotal = keyEvents.size(); - final int expAR = hasAR ? expTotal - 3 * 2 * loops : 0; // per loop: 3 for non AR events and 3 for non AR 'B' - NEWTKeyUtil.validateKeyAdapterStats(keyAdapter, expTotal, expAR); + final int perLoopSI = 2; // per loop: 1 non AR event and 1 for non AR 'B' + final int expSI, expAR; + if( hasAR ) { + expSI = perLoopSI * loops; + expAR = ( keyEvents.size() - expSI*3 ) / 2; // AR: no typed -> 2, SI: typed -> 3 + } else { + expSI = keyEvents.size() / 3; // all typed events + expAR = 0; + } + + NEWTKeyUtil.validateKeyAdapterStats(keyAdapter, + expSI /* press-SI */, expSI /* release-SI */, expSI /* typed-SI */, + expAR /* press-AR */, expAR /* release-AR */, 0 /* typed-AR */ ); } if( !hasAR ) { @@ -216,7 +227,7 @@ public class TestNewtKeyEventAutoRepeatAWT extends UITestCase { NEWTKeyUtil.dumpKeyEvents(Arrays.asList(first[i])); System.err.println("Auto-Repeat Loop "+i+" - Tail:"); NEWTKeyUtil.dumpKeyEvents(Arrays.asList(last[i])); - } + } for(int i=0; i<loops; i++) { KeyEvent e = (KeyEvent) first[i][0]; Assert.assertTrue("1st Shall be A, but is "+e, KeyEvent.VK_A == e.getKeyCode() ); @@ -230,7 +241,7 @@ public class TestNewtKeyEventAutoRepeatAWT extends UITestCase { e = (KeyEvent) first[i][2]; Assert.assertTrue("3rd Shall be A, but is "+e, KeyEvent.VK_A == e.getKeyCode() ); - Assert.assertTrue("3rd Shall be TYPED, but is "+e, KeyEvent.EVENT_KEY_TYPED == e.getEventType() ); + Assert.assertTrue("3rd Shall be PRESSED, but is "+e, KeyEvent.EVENT_KEY_PRESSED == e.getEventType() ); Assert.assertTrue("3rd Shall be AR, but is "+e, 0 != ( InputEvent.AUTOREPEAT_MASK & e.getModifiers() ) ); e = (KeyEvent) last[i][0]; diff --git a/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyEventOrderAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyEventOrderAWT.java index 256536bbb..bdf932904 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyEventOrderAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyEventOrderAWT.java @@ -45,6 +45,8 @@ import javax.swing.JFrame; import java.io.IOException; +import jogamp.nativewindow.jawt.JAWTUtil; + import org.junit.BeforeClass; import org.junit.Test; @@ -104,12 +106,14 @@ public class TestNewtKeyEventOrderAWT extends UITestCase { glWindow.destroy(); } - @Test - public void test02NewtCanvasAWT() throws AWTException, InterruptedException, InvocationTargetException { + private void testNewtCanvasAWT_Impl(boolean onscreen) throws AWTException, InterruptedException, InvocationTargetException { GLWindow glWindow = GLWindow.create(glCaps); // Wrap the window in a canvas. final NewtCanvasAWT newtCanvasAWT = new NewtCanvasAWT(glWindow); + if( !onscreen ) { + newtCanvasAWT.setShallUseOffscreenLayer(true); + } // Add the canvas to a frame, and make it all visible. final JFrame frame1 = new JFrame("Swing AWT Parent Frame: "+ glWindow.getTitle()); @@ -137,6 +141,24 @@ public class TestNewtKeyEventOrderAWT extends UITestCase { glWindow.destroy(); } + @Test + public void test02NewtCanvasAWT_Onscreen() throws AWTException, InterruptedException, InvocationTargetException { + if( JAWTUtil.isOffscreenLayerRequired() ) { + System.err.println("Platform doesn't support onscreen rendering."); + return; + } + testNewtCanvasAWT_Impl(true); + } + + @Test + public void test03NewtCanvasAWT_Offsccreen() throws AWTException, InterruptedException, InvocationTargetException { + if( !JAWTUtil.isOffscreenLayerSupported() ) { + System.err.println("Platform doesn't support offscreen rendering."); + return; + } + testNewtCanvasAWT_Impl(false); + } + static void testKeyEventOrder(Robot robot, NEWTKeyAdapter keyAdapter, int loops) { System.err.println("KEY Event Order Test: "+loops); keyAdapter.reset(); @@ -167,7 +189,11 @@ public class TestNewtKeyEventOrderAWT extends UITestCase { NEWTKeyUtil.validateKeyEventOrder(keyAdapter.getQueued()); - NEWTKeyUtil.validateKeyAdapterStats(keyAdapter, 6*3*loops, 0); + final int expTotal = 6*loops; // all typed events + NEWTKeyUtil.validateKeyAdapterStats(keyAdapter, + expTotal /* press-SI */, expTotal /* release-SI */, expTotal /* typed-SI */, + 0 /* press-AR */, 0 /* release-AR */, 0 /* typed-AR */ ); + } void testImpl(GLWindow glWindow) throws AWTException, InterruptedException, InvocationTargetException { diff --git a/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyPressReleaseUnmaskRepeatAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyPressReleaseUnmaskRepeatAWT.java index 61579998e..2a35a15eb 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyPressReleaseUnmaskRepeatAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyPressReleaseUnmaskRepeatAWT.java @@ -45,6 +45,8 @@ import javax.swing.JFrame; import java.io.IOException; +import jogamp.nativewindow.jawt.JAWTUtil; + import org.junit.BeforeClass; import org.junit.Test; @@ -98,12 +100,14 @@ public class TestNewtKeyPressReleaseUnmaskRepeatAWT extends UITestCase { glWindow.destroy(); } - @Test - public void test02NewtCanvasAWT() throws AWTException, InterruptedException, InvocationTargetException { + private void testNewtCanvasAWT_Impl(boolean onscreen) throws AWTException, InterruptedException, InvocationTargetException { GLWindow glWindow = GLWindow.create(glCaps); // Wrap the window in a canvas. final NewtCanvasAWT newtCanvasAWT = new NewtCanvasAWT(glWindow); + if( !onscreen ) { + newtCanvasAWT.setShallUseOffscreenLayer(true); + } // Add the canvas to a frame, and make it all visible. final JFrame frame1 = new JFrame("Swing AWT Parent Frame: "+ glWindow.getTitle()); @@ -131,6 +135,24 @@ public class TestNewtKeyPressReleaseUnmaskRepeatAWT extends UITestCase { glWindow.destroy(); } + @Test + public void test02NewtCanvasAWT_Onscreen() throws AWTException, InterruptedException, InvocationTargetException { + if( JAWTUtil.isOffscreenLayerRequired() ) { + System.err.println("Platform doesn't support onscreen rendering."); + return; + } + testNewtCanvasAWT_Impl(true); + } + + @Test + public void test03NewtCanvasAWT_Offsccreen() throws AWTException, InterruptedException, InvocationTargetException { + if( !JAWTUtil.isOffscreenLayerSupported() ) { + System.err.println("Platform doesn't support offscreen rendering."); + return; + } + testNewtCanvasAWT_Impl(false); + } + void testImpl(GLWindow glWindow) throws AWTException, InterruptedException, InvocationTargetException { final Robot robot = new Robot(); robot.setAutoWaitForIdle(true); diff --git a/src/test/com/jogamp/opengl/test/junit/util/MiscUtils.java b/src/test/com/jogamp/opengl/test/junit/util/MiscUtils.java index c230f0aa1..0aee0f087 100644 --- a/src/test/com/jogamp/opengl/test/junit/util/MiscUtils.java +++ b/src/test/com/jogamp/opengl/test/junit/util/MiscUtils.java @@ -51,6 +51,22 @@ public class MiscUtils { return def; } + public static String toHexString(byte hex) { + return "0x" + Integer.toHexString( (int)hex & 0x000000FF ); + } + + public static String toHexString(short hex) { + return "0x" + Integer.toHexString( (int)hex & 0x0000FFFF ); + } + + public static String toHexString(int hex) { + return "0x" + Integer.toHexString( hex ); + } + + public static String toHexString(long hex) { + return "0x" + Long.toHexString( hex ); + } + public static void assertFloatBufferEquals(String errmsg, FloatBuffer expected, FloatBuffer actual, float delta) { if(null == expected && null == actual) { return; diff --git a/src/test/com/jogamp/opengl/test/junit/util/NEWTKeyUtil.java b/src/test/com/jogamp/opengl/test/junit/util/NEWTKeyUtil.java index e090ed4cf..d007d2424 100644 --- a/src/test/com/jogamp/opengl/test/junit/util/NEWTKeyUtil.java +++ b/src/test/com/jogamp/opengl/test/junit/util/NEWTKeyUtil.java @@ -38,28 +38,28 @@ import com.jogamp.newt.event.KeyEvent; public class NEWTKeyUtil { public static class CodeSeg { - public final int min; - public final int max; + public final short min; + public final short max; public final String description; public CodeSeg(int min, int max, String description) { - this.min = min; - this.max = max; + this.min = (short)min; + this.max = (short)max; this.description = description; } } public static class CodeEvent { - public final int code; + public final short code; public final String description; public final KeyEvent event; - public CodeEvent(int code, String description, KeyEvent event) { + public CodeEvent(short code, String description, KeyEvent event) { this.code = code; this.description = description; this.event = event; } public String toString() { - return "Code 0x"+Integer.toHexString(code)+" != "+event+" // "+description; + return "Code 0x"+Integer.toHexString( (int)code & 0x0000FFFF )+" != "+event+" // "+description; } } @@ -90,46 +90,63 @@ public class NEWTKeyUtil { public static boolean validateKeyCodes(List<CodeEvent> missCodes, CodeSeg codeSeg, List<EventObject> keyEvents, boolean verbose) { final int codeCount = codeSeg.max - codeSeg.min + 1; int misses = 0; + int evtIdx = 0; for(int i=0; i<codeCount; i++) { - final int c = codeSeg.min + i; - final int j = i*3+0; // KEY_PRESSED - final KeyEvent e = (KeyEvent) ( j < keyEvents.size() ? keyEvents.get(j) : null ); - if( null == e || c != e.getKeyCode() ) { + // evtIdx -> KEY_PRESSED ! + final short c = (short) ( codeSeg.min + i ); + final KeyEvent e = (KeyEvent) ( evtIdx < keyEvents.size() ? keyEvents.get(evtIdx) : null ); + if( null == e ) { missCodes.add(new CodeEvent(c, codeSeg.description, e)); misses++; + evtIdx++; + } else { + if( c != e.getKeyCode() ) { + missCodes.add(new CodeEvent(c, codeSeg.description, e)); + misses++; + } + if( KeyEvent.isPrintableKey(c) ) { + evtIdx += 3; // w/ TYPED + } else { + evtIdx += 2; + } } } - final boolean res = 3*codeCount == keyEvents.size() && 0 == missCodes.size(); + final boolean res = evtIdx == keyEvents.size() && 0 == missCodes.size(); if(verbose) { System.err.println("+++ Code Segment "+codeSeg.description+", Misses: "+misses+" / "+codeCount+", events "+keyEvents.size()+", valid "+res); } return res; } - public static void validateKeyEvent(KeyEvent e, int eventType, int modifier, int keyCode) { - if(0 <= keyCode) { - Assert.assertTrue("KeyEvent code mismatch, expected 0x"+Integer.toHexString(keyCode)+", has "+e, keyCode == e.getKeyCode()); - } + public static void validateKeyEvent(KeyEvent e, int eventType, int modifier, int keyCode, char keyChar) { if(0 <= eventType) { Assert.assertTrue("KeyEvent type mismatch, expected 0x"+Integer.toHexString(eventType)+", has "+e, eventType == e.getEventType()); } if(0 <= modifier) { Assert.assertTrue("KeyEvent modifier mismatch, expected 0x"+Integer.toHexString(modifier)+", has "+e, modifier == e.getModifiers()); } + if(0 < keyCode) { + Assert.assertTrue("KeyEvent code mismatch, expected 0x"+Integer.toHexString(keyCode)+", has "+e, keyCode == e.getKeyCode()); + } + if(0 < keyChar) { + Assert.assertTrue("KeyEvent char mismatch, expected 0x"+Integer.toHexString(keyChar)+", has "+e, keyChar == e.getKeyChar()); + } } - public static int getNextKeyEventType(int et) { + @SuppressWarnings("deprecation") + public static short getNextKeyEventType(KeyEvent e) { + final int et = e.getEventType(); switch( et ) { case KeyEvent.EVENT_KEY_PRESSED: return KeyEvent.EVENT_KEY_RELEASED; case KeyEvent.EVENT_KEY_RELEASED: - return KeyEvent.EVENT_KEY_TYPED; + return e.isPrintableKey() && !e.isAutoRepeat() ? KeyEvent.EVENT_KEY_TYPED : KeyEvent.EVENT_KEY_PRESSED; case KeyEvent.EVENT_KEY_TYPED: return KeyEvent.EVENT_KEY_PRESSED; default: - Assert.assertTrue("Invalid event type "+et, false); + Assert.assertTrue("Invalid event "+e, false); return 0; - } + } } public static void validateKeyEventOrder(List<EventObject> keyEvents) { @@ -141,45 +158,68 @@ public class NEWTKeyUtil { eet = KeyEvent.EVENT_KEY_PRESSED; } final int et = e.getEventType(); - Assert.assertEquals("Key event not in proper order", eet, et); - eet = getNextKeyEventType(et); + Assert.assertEquals("Key event not in proper order "+i+"/"+keyEvents.size()+" - event "+e, eet, et); + eet = getNextKeyEventType(e); keyCode2NextEvent.put(e.getKeyCode(), eet); } } /** - * * @param keyAdapter - * @param expTotalCount number of key press/release/types events - * @param expARCount number of key press/release/types Auto-Release events + * @param expPressedCountSI number of single key press events + * @param expReleasedCountSI number of single key release events + * @param expTypedCountSI number of single key types events + * @param expPressedCountAR number of auto-repeat key press events + * @param expReleasedCountAR number of auto-repeat key release events + * @param expTypedCountAR number of auto-repeat key types events */ - public static void validateKeyAdapterStats(NEWTKeyAdapter keyAdapter, int expTotalCount, int expARCount) { - final int keyPressed = keyAdapter.getKeyPressedCount(false); + public static void validateKeyAdapterStats(NEWTKeyAdapter keyAdapter, + int expPressedCountSI, int expReleasedCountSI, int expTypedCountSI, + int expPressedCountAR, int expReleasedCountAR, int expTypedCountAR) { + final int expTotalCountSI = expPressedCountSI + expReleasedCountSI + expTypedCountSI; + final int expTotalCountAR = expPressedCountAR + expReleasedCountAR + expTypedCountAR; + final int expTotalCountALL = expTotalCountSI + expTotalCountAR; + + final int keyPressedALL = keyAdapter.getKeyPressedCount(false); final int keyPressedAR = keyAdapter.getKeyPressedCount(true); - final int keyReleased = keyAdapter.getKeyReleasedCount(false); + final int keyReleasedALL = keyAdapter.getKeyReleasedCount(false); final int keyReleasedAR = keyAdapter.getKeyReleasedCount(true); - final int keyTyped = keyAdapter.getKeyTypedCount(false); + final int keyTypedALL = keyAdapter.getKeyTypedCount(false); final int keyTypedAR = keyAdapter.getKeyTypedCount(true); - final int keyPressedNR = keyPressed-keyPressedAR; - final int keyReleasedNR = keyReleased-keyReleasedAR; - final int keyTypedNR = keyTyped-keyTypedAR; - System.err.println("Total Press "+keyPressed +", Release "+keyReleased +", Typed "+keyTyped); - System.err.println("AutoR Press "+keyPressedAR+", Release "+keyReleasedAR+", Typed "+keyTypedAR); - System.err.println("No AR Press "+keyPressedNR+", Release "+keyReleasedNR+", Typed "+keyTypedNR); + + final int keyPressedSI = keyPressedALL-keyPressedAR; + final int keyReleasedSI = keyReleasedALL-keyReleasedAR; + final int keyTypedSI = keyTypedALL-keyTypedAR; + + final int totalCountALL = keyPressedALL + keyReleasedALL + keyTypedALL; + final int totalCountSI = keyPressedSI + keyReleasedSI + keyTypedSI; + final int totalCountAR = keyPressedAR + keyReleasedAR + keyTypedAR; + + System.err.println("Expec Single Press "+expPressedCountSI +", Release "+expReleasedCountSI +", Typed "+expTypedCountSI +", Events "+expTotalCountSI); + System.err.println("Expec AutoRp Press "+expPressedCountAR +", Release "+expReleasedCountAR +", Typed "+expTypedCountAR +", Events "+expTotalCountAR); + + System.err.println("Total Single Press "+keyPressedSI +", Release "+keyReleasedSI +", Typed "+keyTypedSI +", Events "+totalCountSI); + System.err.println("Total AutoRp Press "+keyPressedAR +", Release "+keyReleasedAR +", Typed "+keyTypedAR +", Events "+totalCountAR); + System.err.println("Total ALL Press "+keyPressedALL +", Release "+keyReleasedALL +", Typed "+keyTypedALL+", Events "+totalCountALL); + + Assert.assertEquals("Internal Error: totalSI != totalALL - totalAR", totalCountSI, totalCountALL - totalCountAR); + + Assert.assertEquals("Invalid: Has AR Typed events", 0, keyTypedAR); + Assert.assertEquals("Invalid: Exp AR Typed events", 0, expTypedCountAR); + + Assert.assertEquals("Key press count failure (SI)", expPressedCountSI, keyPressedSI); + Assert.assertEquals("Key released count failure (SI)", expReleasedCountSI, keyReleasedSI); + Assert.assertEquals("Key typed count failure (SI)", expTypedCountSI, keyTypedSI); + + Assert.assertEquals("Key press count failure (AR)", expPressedCountAR, keyPressedAR); + Assert.assertEquals("Key released count failure (AR)", expReleasedCountAR, keyReleasedAR); + + Assert.assertEquals("Key total count failure (SI)", expTotalCountSI, totalCountSI); + Assert.assertEquals("Key total count failure (AR)", expTotalCountAR, totalCountAR); final List<EventObject> keyEvents = keyAdapter.getQueued(); - Assert.assertEquals("Key event count not multiple of 3", 0, keyEvents.size()%3); - Assert.assertEquals("Key event count not 3 * press_release_count", expTotalCount, keyEvents.size()); - Assert.assertEquals("Key press count failure", expTotalCount/3, keyPressed); - Assert.assertEquals("Key press count failure (AR)", expARCount/3, keyPressedAR); - Assert.assertEquals("Key released count failure", expTotalCount/3, keyReleased); - Assert.assertEquals("Key released count failure (AR)", expARCount/3, keyReleasedAR); - Assert.assertEquals("Key typed count failure", expTotalCount/3, keyTyped); - Assert.assertEquals("Key typed count failure (AR)", expARCount/3, keyTypedAR); - // should be true - always, reaching this point - duh! - Assert.assertEquals( ( expTotalCount - expARCount ) / 3, keyPressedNR); - Assert.assertEquals( ( expTotalCount - expARCount ) / 3, keyReleasedNR); - Assert.assertEquals( ( expTotalCount - expARCount ) / 3, keyTypedNR); - } + Assert.assertEquals("Key total count failure (ALL) w/ list sum ", expTotalCountALL, totalCountALL); + Assert.assertEquals("Key total count failure (ALL) w/ list size ", expTotalCountALL, keyEvents.size()); + } } |