summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2012-10-31 04:04:39 +0100
committerSven Gothel <[email protected]>2012-10-31 04:04:39 +0100
commitb62e1d027c289877686d6008ea8dd40e4e1541ec (patch)
treef0af41cb2c9bdd92c37192880439843de1b85f32 /src
parentdda5e1611fc41089a5f8d486435d3d2d7e9b76d6 (diff)
Fix NEWT KeyEvent: Deliver keyChar w/ pressed and released; Deliver proper modified flags and modifier-key events; Simplify Windows key handling
Preface: Modifier-keys are SHIFT, CTRL, ALT and META and they have a matching modifier-bit. - Simplify Windows key handling - Employ MapVirtualKey(..) for virtual-key to character and scancode to virtual-key mappings, allowing to drop tracking of keyCode to keyChar in java code. This also removes the platform restriction of delivering keyChar at TYPED only. - Deliver keyChar w/ pressed and released - Due to the lift restriction on the Windows platform (see above), we can deliver keyChar w/ all key events on all platforms. - Deliver proper modified flags and modifier-key events All modifier-keys deliver pressed, released and typed events with their modifier-bit set. The above is covered by unit tests, which passed on X11, Windows and OSX (manual test run).
Diffstat (limited to 'src')
-rw-r--r--src/newt/classes/com/jogamp/newt/event/KeyEvent.java111
-rw-r--r--src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java11
-rw-r--r--src/newt/classes/jogamp/newt/driver/windows/WindowDriver.java40
-rw-r--r--src/newt/native/NewtMacWindow.m7
-rw-r--r--src/newt/native/WindowsWindow.c199
-rw-r--r--src/newt/native/X11Display.c26
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/TestNewtKeyCodeModifiersAWT.java275
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/TestNewtKeyCodesAWT.java (renamed from src/test/com/jogamp/opengl/test/junit/newt/TestNewtKeyCodeAWT.java)35
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/TestNewtKeyEventAutoRepeatAWT.java25
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/TestNewtKeyEventOrderAWT.java6
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/TestNewtKeyPressReleaseUnmaskRepeatAWT.java2
-rw-r--r--src/test/com/jogamp/opengl/test/junit/util/AWTKeyAdapter.java26
-rw-r--r--src/test/com/jogamp/opengl/test/junit/util/AWTMouseAdapter.java20
-rw-r--r--src/test/com/jogamp/opengl/test/junit/util/AWTRobotUtil.java14
-rw-r--r--src/test/com/jogamp/opengl/test/junit/util/InputEventCountAdapter.java3
-rw-r--r--src/test/com/jogamp/opengl/test/junit/util/NEWTKeyAdapter.java26
-rw-r--r--src/test/com/jogamp/opengl/test/junit/util/NEWTKeyUtil.java46
-rw-r--r--src/test/com/jogamp/opengl/test/junit/util/NEWTMouseAdapter.java20
18 files changed, 622 insertions, 270 deletions
diff --git a/src/newt/classes/com/jogamp/newt/event/KeyEvent.java b/src/newt/classes/com/jogamp/newt/event/KeyEvent.java
index 8d3d9e88f..927c9aa85 100644
--- a/src/newt/classes/com/jogamp/newt/event/KeyEvent.java
+++ b/src/newt/classes/com/jogamp/newt/event/KeyEvent.java
@@ -59,6 +59,10 @@ package com.jogamp.newt.event;
* The idea is if you mask out auto-repeat in your event listener
* you just get one long pressed key D/U/T triple.
* </p>
+ * <p>
+ * {@link #isModifierKey() Modifiers keys} will produce regular events (pressed, released and typed),
+ * however they will not produce Auto-Repeat events itself.
+ * </p>
*/
@SuppressWarnings("serial")
public class KeyEvent extends InputEvent
@@ -69,12 +73,12 @@ public class KeyEvent extends InputEvent
this.keyChar=keyChar;
}
- /** Only valid on all platforms at {@link KeyListener#keyTyped(KeyEvent)} */
+ /** Returns the character matching the {@link #getKeyCode() virtual key code}, if exist. */
public char getKeyChar() {
return keyChar;
}
- /** Always valid. */
+ /** Returns the virtual key code. */
public int getKeyCode() {
return keyCode;
}
@@ -100,49 +104,68 @@ public class KeyEvent extends InputEvent
}
}
- public boolean isActionKey() {
+ /** Returns true if <code>keyCode</code> represents a modifier key, i.e. one of {@link #VK_SHIFT}, {@link #VK_CONTROL}, {@link #VK_ALT}, {@link #VK_ALT_GRAPH}, {@link #VK_META}. */
+ public static boolean isModifierKey(int keyCode) {
+ switch (keyCode) {
+ case VK_SHIFT:
+ case VK_CONTROL:
+ case VK_ALT:
+ case VK_ALT_GRAPH:
+ case VK_META:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ /** Returns true if {@link #getKeyCode()} represents a modifier key, i.e. one of {@link #VK_SHIFT}, {@link #VK_CONTROL}, {@link #VK_ALT}, {@link #VK_ALT_GRAPH}, {@link #VK_META}. */
+ public boolean isModifierKey() {
+ return isModifierKey(keyCode);
+ }
+
+ public boolean isActionKey() {
switch (keyCode) {
- case VK_HOME:
- case VK_END:
- case VK_PAGE_UP:
- case VK_PAGE_DOWN:
- case VK_UP:
- case VK_DOWN:
- case VK_LEFT:
- case VK_RIGHT:
-
- case VK_F1:
- case VK_F2:
- case VK_F3:
- case VK_F4:
- case VK_F5:
- case VK_F6:
- case VK_F7:
- case VK_F8:
- case VK_F9:
- case VK_F10:
- case VK_F11:
- case VK_F12:
- case VK_F13:
- case VK_F14:
- case VK_F15:
- case VK_F16:
- case VK_F17:
- case VK_F18:
- case VK_F19:
- case VK_F20:
- case VK_F21:
- case VK_F22:
- case VK_F23:
- case VK_F24:
- case VK_PRINTSCREEN:
- case VK_CAPS_LOCK:
- case VK_PAUSE:
- case VK_INSERT:
-
- case VK_HELP:
- case VK_WINDOWS:
- return true;
+ case VK_HOME:
+ case VK_END:
+ case VK_PAGE_UP:
+ case VK_PAGE_DOWN:
+ case VK_UP:
+ case VK_DOWN:
+ case VK_LEFT:
+ case VK_RIGHT:
+
+ case VK_F1:
+ case VK_F2:
+ case VK_F3:
+ case VK_F4:
+ case VK_F5:
+ case VK_F6:
+ case VK_F7:
+ case VK_F8:
+ case VK_F9:
+ case VK_F10:
+ case VK_F11:
+ case VK_F12:
+ case VK_F13:
+ case VK_F14:
+ case VK_F15:
+ case VK_F16:
+ case VK_F17:
+ case VK_F18:
+ case VK_F19:
+ case VK_F20:
+ case VK_F21:
+ case VK_F22:
+ case VK_F23:
+ case VK_F24:
+ case VK_PRINTSCREEN:
+ case VK_CAPS_LOCK:
+ case VK_PAUSE:
+ case VK_INSERT:
+
+ case VK_HELP:
+ case VK_WINDOWS:
+ return true;
}
return false;
}
diff --git a/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java
index 121c3fa99..5755bdf11 100644
--- a/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java
@@ -324,9 +324,10 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl
// Note that we send the key char for the key code on this
// platform -- we do not get any useful key codes out of the system
final int keyCode = MacKeyUtil.validateKeyCode(_keyCode, keyChar);
- if(DEBUG_IMPLEMENTATION) {
- System.err.println("MacWindow.sendKeyEvent "+Thread.currentThread().getName()+" char: 0x"+Integer.toHexString(keyChar)+", code 0x"+Integer.toHexString(_keyCode)+" -> 0x"+Integer.toHexString(keyCode));
- }
+ // final boolean isModifierKeyCode = KeyEvent.isModifierKey(keyCode);
+ // System.err.println("*** handleKeyEvent: event "+KeyEvent.getEventTypeString(eventType)+", key 0x"+Integer.toHexString(_keyCode)+" -> 0x"+Integer.toHexString(keyCode)+", mods "+toHexString(modifiers)+", was: pressed "+isKeyPressed(keyCode)+", repeat "+isKeyInAutoRepeat(keyCode)+", isModifierKeyCode "+isModifierKeyCode);
+
+ // 1:1 Order: OSX and NEWT delivery order is PRESSED, RELEASED and TYPED
// Auto-Repeat: OSX delivers only PRESSED, inject auto-repeat RELEASE and TYPED keys _before_ PRESSED
switch(eventType) {
case KeyEvent.EVENT_KEY_RELEASED:
@@ -334,7 +335,6 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl
keyRepeatState.put(keyCode, false); // prev == true -> AR out
keyPressedState.put(keyCode, false);
}
- keyChar = (char)-1;
break;
case KeyEvent.EVENT_KEY_PRESSED:
if( isKeyCodeTracked(keyCode) ) {
@@ -342,11 +342,10 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl
// key was already pressed
keyRepeatState.put(keyCode, true); // prev == false -> AR in
modifiers |= InputEvent.AUTOREPEAT_MASK;
- emitKeyEvent(send, wait, KeyEvent.EVENT_KEY_RELEASED, modifiers, keyCode, (char)-1); // RELEASED
+ emitKeyEvent(send, wait, KeyEvent.EVENT_KEY_RELEASED, modifiers, keyCode, keyChar); // RELEASED
emitKeyEvent(send, wait, KeyEvent.EVENT_KEY_TYPED, modifiers, keyCode, keyChar); // TYPED
}
}
- keyChar = (char)-1;
break;
case KeyEvent.EVENT_KEY_TYPED:
break;
diff --git a/src/newt/classes/jogamp/newt/driver/windows/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/windows/WindowDriver.java
index 8b57a241d..c513b9e84 100644
--- a/src/newt/classes/jogamp/newt/driver/windows/WindowDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/windows/WindowDriver.java
@@ -46,7 +46,6 @@ import javax.media.nativewindow.util.Insets;
import javax.media.nativewindow.util.InsetsImmutable;
import javax.media.nativewindow.util.Point;
-import com.jogamp.common.util.IntIntHashMap;
import com.jogamp.newt.event.InputEvent;
import com.jogamp.newt.event.KeyEvent;
import com.jogamp.newt.event.MouseAdapter;
@@ -260,11 +259,6 @@ public class WindowDriver extends WindowImpl {
// nop - using event driven insetsChange(..)
}
- /** We have to regenerate the keyCode for EVENT_KEY_TYPED on this platform. */
- private int lastPressedKeyCode = 0;
- /** We have to reorder the native key events to match NEWT's order */
- private IntIntHashMap typedKeyCode2KeyChar = new IntIntHashMap(KeyEvent.VK_CONTEXT_MENU+1);
-
private final void emitKeyEvent(boolean send, boolean wait, int eventType, int modifiers, int keyCode, char keyChar) {
if( send ) {
super.sendKeyEvent(eventType, modifiers, keyCode, keyChar);
@@ -274,52 +268,42 @@ public class WindowDriver extends WindowImpl {
}
private final void handleKeyEvent(boolean send, boolean wait, int eventType, int modifiers, int keyCode, char keyChar) {
- // final int kc = 0 <= keyCode ? keyCode : lastPressedKeyCode;
- // System.err.println("*** handleKeyEvent: event "+KeyEvent.getEventTypeString(eventType)+", key "+toHexString(kc)+", mods "+toHexString(modifiers)+", was: pressed "+isKeyPressed(kc)+", repeat "+isKeyInAutoRepeat(kc));
-
+ final boolean isModifierKeyCode = KeyEvent.isModifierKey(keyCode);
+ // System.err.println("*** handleKeyEvent: event "+KeyEvent.getEventTypeString(eventType)+", keyCode "+toHexString(keyCode)+", keyChar <"+keyChar+">, mods "+toHexString(modifiers)+", was: pressed "+isKeyPressed(keyCode)+", repeat "+isKeyInAutoRepeat(keyCode)+", isModifierKeyCode "+isModifierKeyCode);
+
// Reorder: WINDOWS delivery order is PRESSED, TYPED and RELEASED -> NEWT order: PRESSED, RELEASED and TYPED
// Auto-Repeat: WINDOWS delivers only PRESSED and TYPED.
switch(eventType) {
case KeyEvent.EVENT_KEY_RELEASED:
if( isKeyCodeTracked(keyCode) ) {
- if( keyRepeatState.put(keyCode, false) ) {
+ if( keyRepeatState.put(keyCode, false) && !isModifierKeyCode ) {
// AR out - send out missing PRESSED
- emitKeyEvent(send, wait, KeyEvent.EVENT_KEY_PRESSED, modifiers | InputEvent.AUTOREPEAT_MASK, keyCode, (char)-1);
+ emitKeyEvent(send, wait, KeyEvent.EVENT_KEY_PRESSED, modifiers | InputEvent.AUTOREPEAT_MASK, keyCode, keyChar);
}
keyPressedState.put(keyCode, false);
}
emitKeyEvent(send, wait, eventType, modifiers, keyCode, keyChar);
- final char lastTypedKeyChar = (char) typedKeyCode2KeyChar.put(keyCode, 0);
- if( 0 < lastTypedKeyChar ) {
- emitKeyEvent(send, wait, KeyEvent.EVENT_KEY_TYPED, modifiers, keyCode, lastTypedKeyChar);
- }
+ emitKeyEvent(send, wait, KeyEvent.EVENT_KEY_TYPED, modifiers, keyCode, keyChar);
break;
case KeyEvent.EVENT_KEY_PRESSED:
- lastPressedKeyCode = keyCode;
if( isKeyCodeTracked(keyCode) ) {
if( keyPressedState.put(keyCode, true) ) {
// key was already pressed
- if( keyRepeatState.put(keyCode, true) ) {
- emitKeyEvent(send, wait, eventType, modifiers | InputEvent.AUTOREPEAT_MASK, keyCode, (char)-1);
- } // else AR in - skip already send PRESSED
+ if( keyRepeatState.put(keyCode, true) && !isModifierKeyCode ) {
+ emitKeyEvent(send, wait, eventType, modifiers | InputEvent.AUTOREPEAT_MASK, keyCode, keyChar);
+ } // else AR in - skip already send PRESSED ; or ALT
} else {
- emitKeyEvent(send, wait, eventType, modifiers, keyCode, (char)-1);
+ emitKeyEvent(send, wait, eventType, modifiers, keyCode, keyChar);
}
} else {
- emitKeyEvent(send, wait, eventType, modifiers, keyCode, (char)-1);
+ emitKeyEvent(send, wait, eventType, modifiers, keyCode, keyChar);
}
break;
case KeyEvent.EVENT_KEY_TYPED:
- if(-1==keyCode) {
- keyCode = lastPressedKeyCode;
- }
- lastPressedKeyCode = -1;
if( 1 == isKeyInAutoRepeat(keyCode) ) {
modifiers |= InputEvent.AUTOREPEAT_MASK;
- emitKeyEvent(send, wait, KeyEvent.EVENT_KEY_RELEASED, modifiers, keyCode, (char)-1);
+ emitKeyEvent(send, wait, KeyEvent.EVENT_KEY_RELEASED, modifiers, keyCode, keyChar);
emitKeyEvent(send, wait, eventType, modifiers, keyCode, keyChar);
- } else {
- typedKeyCode2KeyChar.put(keyCode, keyChar);
}
break;
}
diff --git a/src/newt/native/NewtMacWindow.m b/src/newt/native/NewtMacWindow.m
index de5f3773c..b89b5c21d 100644
--- a/src/newt/native/NewtMacWindow.m
+++ b/src/newt/native/NewtMacWindow.m
@@ -840,12 +840,11 @@ static jint mods2JavaMods(NSUInteger mods)
{
if ( NO == modsDown[keyIdx] && 0 != ( mods & keyMask ) ) {
modsDown[keyIdx] = YES;
- mods &= ~keyMask;
- [self sendKeyEvent: keyCode characters: NULL modifiers: mods eventType: EVENT_KEY_TYPED];
+ [self sendKeyEvent: keyCode characters: NULL modifiers: mods|keyMask eventType: EVENT_KEY_PRESSED];
} else if ( YES == modsDown[keyIdx] && 0 == ( mods & keyMask ) ) {
modsDown[keyIdx] = NO;
- [self sendKeyEvent: keyCode characters: NULL modifiers: mods eventType: EVENT_KEY_RELEASED];
- [self sendKeyEvent: keyCode characters: NULL modifiers: mods eventType: EVENT_KEY_TYPED];
+ [self sendKeyEvent: keyCode characters: NULL modifiers: mods|keyMask eventType: EVENT_KEY_RELEASED];
+ [self sendKeyEvent: keyCode characters: NULL modifiers: mods|keyMask eventType: EVENT_KEY_TYPED];
}
}
diff --git a/src/newt/native/WindowsWindow.c b/src/newt/native/WindowsWindow.c
index bb90a2dce..2152166e4 100644
--- a/src/newt/native/WindowsWindow.c
+++ b/src/newt/native/WindowsWindow.c
@@ -463,87 +463,108 @@ static void BuildDynamicKeyMapTable()
} // for each VK_OEM_*
}
-static jint GetModifiers() {
+static jint GetModifiers(BOOL altKeyFlagged, UINT jkey) {
jint modifiers = 0;
// have to do &0xFFFF to avoid runtime assert caused by compiling with
// /RTCcsu
- if (HIBYTE((GetKeyState(VK_CONTROL) & 0xFFFF)) != 0) {
+ if ( HIBYTE((GetKeyState(VK_CONTROL) & 0xFFFF)) != 0 || J_VK_CONTROL == jkey ) {
modifiers |= EVENT_CTRL_MASK;
}
- if (HIBYTE((GetKeyState(VK_SHIFT) & 0xFFFF)) != 0) {
+ if ( HIBYTE((GetKeyState(VK_SHIFT) & 0xFFFF)) != 0 || J_VK_SHIFT == jkey ) {
modifiers |= EVENT_SHIFT_MASK;
}
- if (HIBYTE((GetKeyState(VK_MENU) & 0xFFFF)) != 0) {
+ if ( altKeyFlagged || HIBYTE((GetKeyState(VK_MENU) & 0xFFFF)) != 0 || J_VK_ALT == jkey ) {
modifiers |= EVENT_ALT_MASK;
}
- if (HIBYTE((GetKeyState(VK_LBUTTON) & 0xFFFF)) != 0) {
+ if ( HIBYTE((GetKeyState(VK_LBUTTON) & 0xFFFF)) != 0 ) {
modifiers |= EVENT_BUTTON1_MASK;
}
- if (HIBYTE((GetKeyState(VK_MBUTTON) & 0xFFFF)) != 0) {
+ if ( HIBYTE((GetKeyState(VK_MBUTTON) & 0xFFFF)) != 0 ) {
modifiers |= EVENT_BUTTON2_MASK;
}
- if (HIBYTE((GetKeyState(VK_RBUTTON) & 0xFFFF)) != 0) {
+ if ( HIBYTE((GetKeyState(VK_RBUTTON) & 0xFFFF)) != 0 ) {
modifiers |= EVENT_BUTTON3_MASK;
}
return modifiers;
}
-static int WmChar(JNIEnv *env, jobject window, UINT character, UINT repCnt,
- UINT flags, BOOL system)
-{
+static BOOL IsAltKeyDown(BYTE flags, BOOL system) {
// The Alt modifier is reported in the 29th bit of the lParam,
- // i.e., it is the 13th bit of `flags' (which is HIWORD(lParam)).
- BOOL alt_is_down = (flags & (1<<13)) != 0;
- if (system && alt_is_down) {
- if (character == VK_SPACE) {
- return 1;
- }
- }
-
- if (character == VK_RETURN) {
- character = J_VK_ENTER;
- }
- (*env)->CallVoidMethod(env, window, sendKeyEventID,
- (jint) EVENT_KEY_TYPED,
- GetModifiers(),
- (jint) -1,
- (jchar) character);
- return 1;
+ // i.e., it is the 5th bit of `flags' (which is HIBYTE(HIWORD(lParam))).
+ return system && ( flags & (1<<5) ) != 0;
}
-UINT WindowsKeyToJavaKey(UINT windowsKey, UINT modifiers)
+UINT WindowsKeyToJavaKey(UINT windowsKey)
{
- int i, j;
+ int i, j, javaKey = J_VK_UNDEFINED;
// for the general case, use a bi-directional table
for (i = 0; keyMapTable[i].windowsKey != 0; i++) {
if (keyMapTable[i].windowsKey == windowsKey) {
- return keyMapTable[i].javaKey;
+ javaKey = keyMapTable[i].javaKey;
}
}
- for (j = 0; dynamicKeyMapTable[j].windowsKey != 0; j++) {
- if (dynamicKeyMapTable[j].windowsKey == windowsKey) {
- if (dynamicKeyMapTable[j].javaKey != J_VK_UNDEFINED) {
- return dynamicKeyMapTable[j].javaKey;
- } else {
- break;
+ if( J_VK_UNDEFINED == javaKey ) {
+ for (j = 0; dynamicKeyMapTable[j].windowsKey != 0; j++) {
+ if (dynamicKeyMapTable[j].windowsKey == windowsKey) {
+ if (dynamicKeyMapTable[j].javaKey != J_VK_UNDEFINED) {
+ javaKey = dynamicKeyMapTable[j].javaKey;
+ } else {
+ break;
+ }
}
}
}
- return J_VK_UNDEFINED;
+#ifdef DEBUG_KEYS
+ STD_PRINT("*** WindowsWindow: WindowsKeyToJavaKey 0x%X -> 0x%X\n", windowsKey, javaKey);
+#endif
+ return javaKey;
}
-static int WmKeyDown(JNIEnv *env, jobject window, UINT wkey, UINT repCnt,
- UINT flags, BOOL system)
-{
+#ifndef MAPVK_VSC_TO_VK
+ #define MAPVK_VSC_TO_VK 1
+#endif
+#ifndef MAPVK_VK_TO_CHAR
+ #define MAPVK_VK_TO_CHAR 2
+#endif
+
+static UINT WmVKey2ShiftedChar(UINT wkey, UINT modifiers) {
+ UINT c = MapVirtualKey(wkey, MAPVK_VK_TO_CHAR);
+ if( 0 != ( modifiers & EVENT_SHIFT_MASK ) ) {
+ return islower(c) ? toupper(c) : c;
+ }
+ return isupper(c) ? tolower(c) : c;
+}
+
+static int WmChar(JNIEnv *env, jobject window, UINT character, WORD repCnt, BYTE scanCode, BYTE flags, BOOL system) {
+ UINT modifiers = 0, jkey = 0, wkey = 0;
+
+ wkey = MapVirtualKey(scanCode, MAPVK_VSC_TO_VK);
+ jkey = WindowsKeyToJavaKey(wkey);
+ modifiers = GetModifiers( IsAltKeyDown(flags, system), 0 );
+
+ if (character == VK_RETURN) {
+ character = J_VK_ENTER;
+ }
+
+ (*env)->CallVoidMethod(env, window, sendKeyEventID,
+ (jint) EVENT_KEY_TYPED,
+ modifiers,
+ (jint) jkey,
+ (jchar) character);
+ return 1;
+}
+
+static int WmKeyDown(JNIEnv *env, jobject window, UINT wkey, WORD repCnt, BYTE scanCode, BYTE flags, BOOL system) {
UINT modifiers = 0, jkey = 0, character = -1;
if (wkey == VK_PROCESSKEY) {
return 1;
}
- modifiers = GetModifiers();
- jkey = WindowsKeyToJavaKey(wkey, modifiers);
+ jkey = WindowsKeyToJavaKey(wkey);
+ modifiers = GetModifiers( IsAltKeyDown(flags, system), jkey );
+ character = WmVKey2ShiftedChar(wkey, modifiers);
/*
character = WindowsKeyToJavaChar(wkey, modifiers, SAVE);
@@ -562,7 +583,7 @@ static int WmKeyDown(JNIEnv *env, jobject window, UINT wkey, UINT repCnt,
if (jkey == J_VK_DELETE) {
(*env)->CallVoidMethod(env, window, sendKeyEventID,
(jint) EVENT_KEY_TYPED,
- GetModifiers(),
+ modifiers,
(jint) -1,
(jchar) '\177');
}
@@ -570,16 +591,16 @@ static int WmKeyDown(JNIEnv *env, jobject window, UINT wkey, UINT repCnt,
return 0;
}
-static int WmKeyUp(JNIEnv *env, jobject window, UINT wkey, UINT repCnt,
- UINT flags, BOOL system)
-{
+static int WmKeyUp(JNIEnv *env, jobject window, UINT wkey, WORD repCnt, BYTE scanCode, BYTE flags, BOOL system) {
UINT modifiers = 0, jkey = 0, character = -1;
if (wkey == VK_PROCESSKEY) {
return 1;
}
- modifiers = GetModifiers();
- jkey = WindowsKeyToJavaKey(wkey, modifiers);
+ jkey = WindowsKeyToJavaKey(wkey);
+ modifiers = GetModifiers( IsAltKeyDown(flags, system), jkey );
+ character = WmVKey2ShiftedChar(wkey, modifiers);
+
/*
character = WindowsKeyToJavaChar(wkey, modifiers, SAVE);
*/
@@ -775,21 +796,15 @@ static void WmSize(JNIEnv *env, jobject window, HWND wnd, UINT type)
(*env)->CallVoidMethod(env, window, sizeChangedID, JNI_FALSE, w, h, JNI_FALSE);
}
-static LRESULT CALLBACK wndProc(HWND wnd, UINT message,
- WPARAM wParam, LPARAM lParam)
-{
+static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lParam) {
LRESULT res = 0;
int useDefWindowProc = 0;
JNIEnv *env = NULL;
jobject window = NULL;
BOOL isKeyDown = FALSE;
WindowUserData * wud;
-
-#ifdef DEBUG_KEYS
- if ( WM_KEYDOWN == message ) {
- STD_PRINT("*** WindowsWindow: wndProc window %p, 0x%X %d/%d\n", wnd, message, (int)LOWORD(lParam), (int)HIWORD(lParam));
- }
-#endif
+ WORD repCnt;
+ BYTE scanCode, flags;
#if !defined(__MINGW64__) && ( defined(UNDER_CE) || _MSC_VER <= 1200 )
wud = (WindowUserData *) GetWindowLong(wnd, GWL_USERDATA);
@@ -831,26 +846,57 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message,
break;
case WM_SYSCHAR:
- useDefWindowProc = WmChar(env, window, wParam,
- LOWORD(lParam), HIWORD(lParam), FALSE);
+ repCnt = HIWORD(lParam); scanCode = LOBYTE(repCnt); flags = HIBYTE(repCnt);
+ repCnt = LOWORD(lParam);
+#ifdef DEBUG_KEYS
+ STD_PRINT("*** WindowsWindow: windProc WM_SYSCHAR sending window %p -> %p, char 0x%X, repCnt %d, scanCode 0x%X, flags 0x%X\n", wnd, window, (int)wParam, (int)repCnt, (int)scanCode, (int)flags);
+#endif
+ useDefWindowProc = WmChar(env, window, wParam, repCnt, scanCode, flags, TRUE);
+ break;
+
+ case WM_SYSKEYDOWN:
+ repCnt = HIWORD(lParam); scanCode = LOBYTE(repCnt); flags = HIBYTE(repCnt);
+ repCnt = LOWORD(lParam);
+#ifdef DEBUG_KEYS
+ STD_PRINT("*** WindowsWindow: windProc WM_SYSKEYDOWN sending window %p -> %p, code 0x%X, repCnt %d, scanCode 0x%X, flags 0x%X\n", wnd, window, (int)wParam, (int)repCnt, (int)scanCode, (int)flags);
+#endif
+ useDefWindowProc = WmKeyDown(env, window, wParam, repCnt, scanCode, flags, TRUE);
+ break;
+
+ case WM_SYSKEYUP:
+ repCnt = HIWORD(lParam); scanCode = LOBYTE(repCnt); flags = HIBYTE(repCnt);
+ repCnt = LOWORD(lParam);
+#ifdef DEBUG_KEYS
+ STD_PRINT("*** WindowsWindow: windProc WM_SYSKEYUP sending window %p -> %p, code 0x%X, repCnt %d, scanCode 0x%X, flags 0x%X\n", wnd, window, (int)wParam, (int)repCnt, (int)scanCode, (int)flags);
+#endif
+ useDefWindowProc = WmKeyUp(env, window, wParam, repCnt, scanCode, flags, TRUE);
break;
case WM_CHAR:
- useDefWindowProc = WmChar(env, window, wParam,
- LOWORD(lParam), HIWORD(lParam), TRUE);
+ repCnt = HIWORD(lParam); scanCode = LOBYTE(repCnt); flags = HIBYTE(repCnt);
+ repCnt = LOWORD(lParam);
+#ifdef DEBUG_KEYS
+ STD_PRINT("*** WindowsWindow: windProc WM_CHAR sending window %p -> %p, char 0x%X, repCnt %d, scanCode 0x%X, flags 0x%X\n", wnd, window, (int)wParam, (int)repCnt, (int)scanCode, (int)flags);
+#endif
+ useDefWindowProc = WmChar(env, window, wParam, repCnt, scanCode, flags, FALSE);
break;
case WM_KEYDOWN:
+ repCnt = HIWORD(lParam); scanCode = LOBYTE(repCnt); flags = HIBYTE(repCnt);
+ repCnt = LOWORD(lParam);
#ifdef DEBUG_KEYS
- STD_PRINT("*** WindowsWindow: windProc sending window %p -> %p, 0x%X %d/%d\n", wnd, window, message, (int)LOWORD(lParam), (int)HIWORD(lParam));
+ STD_PRINT("*** WindowsWindow: windProc WM_KEYDOWN sending window %p -> %p, code 0x%X, repCnt %d, scanCode 0x%X, flags 0x%X\n", wnd, window, (int)wParam, (int)repCnt, (int)scanCode, (int)flags);
#endif
- useDefWindowProc = WmKeyDown(env, window, wParam,
- LOWORD(lParam), HIWORD(lParam), FALSE);
+ useDefWindowProc = WmKeyDown(env, window, wParam, repCnt, scanCode, flags, FALSE);
break;
case WM_KEYUP:
- useDefWindowProc = WmKeyUp(env, window, wParam,
- LOWORD(lParam), HIWORD(lParam), FALSE);
+ repCnt = HIWORD(lParam); scanCode = LOBYTE(repCnt); flags = HIBYTE(repCnt);
+ repCnt = LOWORD(lParam);
+#ifdef DEBUG_KEYS
+ STD_PRINT("*** WindowsWindow: windProc WM_KEYUP sending window %p -> %p, code 0x%X, repCnt %d, scanCode 0x%X, flags 0x%X\n", wnd, window, (int)wParam, (int)repCnt, (int)scanCode, (int)flags);
+#endif
+ useDefWindowProc = WmKeyUp(env, window, wParam, repCnt, scanCode, flags, FALSE);
break;
case WM_SIZE:
@@ -873,7 +919,7 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message,
(*env)->CallVoidMethod(env, window, requestFocusID, JNI_FALSE);
(*env)->CallVoidMethod(env, window, sendMouseEventID,
(jint) EVENT_MOUSE_PRESSED,
- GetModifiers(),
+ GetModifiers( FALSE, 0 ),
(jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
(jint) 1, (jint) 0);
useDefWindowProc = 1;
@@ -882,7 +928,7 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message,
case WM_LBUTTONUP:
(*env)->CallVoidMethod(env, window, sendMouseEventID,
(jint) EVENT_MOUSE_RELEASED,
- GetModifiers(),
+ GetModifiers( FALSE, 0 ),
(jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
(jint) 1, (jint) 0);
useDefWindowProc = 1;
@@ -893,7 +939,7 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message,
(*env)->CallVoidMethod(env, window, requestFocusID, JNI_FALSE);
(*env)->CallVoidMethod(env, window, sendMouseEventID,
(jint) EVENT_MOUSE_PRESSED,
- GetModifiers(),
+ GetModifiers( FALSE, 0 ),
(jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
(jint) 2, (jint) 0);
useDefWindowProc = 1;
@@ -902,7 +948,7 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message,
case WM_MBUTTONUP:
(*env)->CallVoidMethod(env, window, sendMouseEventID,
(jint) EVENT_MOUSE_RELEASED,
- GetModifiers(),
+ GetModifiers( FALSE, 0 ),
(jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
(jint) 2, (jint) 0);
useDefWindowProc = 1;
@@ -913,7 +959,7 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message,
(*env)->CallVoidMethod(env, window, requestFocusID, JNI_FALSE);
(*env)->CallVoidMethod(env, window, sendMouseEventID,
(jint) EVENT_MOUSE_PRESSED,
- GetModifiers(),
+ GetModifiers( FALSE, 0 ),
(jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
(jint) 3, (jint) 0);
useDefWindowProc = 1;
@@ -922,7 +968,7 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message,
case WM_RBUTTONUP:
(*env)->CallVoidMethod(env, window, sendMouseEventID,
(jint) EVENT_MOUSE_RELEASED,
- GetModifiers(),
+ GetModifiers( FALSE, 0 ),
(jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
(jint) 3, (jint) 0);
useDefWindowProc = 1;
@@ -931,7 +977,7 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message,
case WM_MOUSEMOVE:
(*env)->CallVoidMethod(env, window, sendMouseEventID,
(jint) EVENT_MOUSE_MOVED,
- GetModifiers(),
+ GetModifiers( FALSE, 0 ),
(jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
(jint) 0, (jint) 0);
useDefWindowProc = 1;
@@ -956,7 +1002,7 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message,
ScreenToClient(wnd, &eventPt);
(*env)->CallVoidMethod(env, window, sendMouseEventID,
(jint) EVENT_MOUSE_WHEEL_MOVED,
- GetModifiers(),
+ GetModifiers( FALSE, 0 ),
(jint) eventPt.x, (jint) eventPt.y,
(jint) 1, (jint) (GET_WHEEL_DELTA_WPARAM(wParam)/120.0f));
useDefWindowProc = 1;
@@ -1035,11 +1081,6 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_DisplayDriver_DispatchMes
// DBG_PRINT("*** WindowsWindow.DispatchMessages0: thread 0x%X - gotOne %d\n", (int)GetCurrentThreadId(), (int)gotOne);
if (gotOne) {
++i;
-#ifdef DEBUG_KEYS
- if(WM_KEYDOWN == msg.message) {
- STD_PRINT("*** WindowsWindow: DispatchMessages window %p, 0x%X %d/%d\n", msg.hwnd, msg.message, (int)LOWORD(msg.lParam), (int)HIWORD(msg.lParam));
- }
-#endif
TranslateMessage(&msg);
DispatchMessage(&msg);
}
diff --git a/src/newt/native/X11Display.c b/src/newt/native/X11Display.c
index 89cf75043..3f34a16b6 100644
--- a/src/newt/native/X11Display.c
+++ b/src/newt/native/X11Display.c
@@ -154,24 +154,24 @@ static jint X11KeySym2NewtVKey(KeySym keySym) {
return keySym;
}
-static jint X11InputState2NewtModifiers(unsigned int xstate) {
+static jint X11InputState2NewtModifiers(unsigned int xstate, KeySym keySym) {
jint modifiers = 0;
- if ((ControlMask & xstate) != 0) {
+ if ( (ControlMask & xstate) != 0 || J_VK_CONTROL == keySym ) {
modifiers |= EVENT_CTRL_MASK;
}
- if ((ShiftMask & xstate) != 0) {
+ if ( (ShiftMask & xstate) != 0 || J_VK_SHIFT == keySym ) {
modifiers |= EVENT_SHIFT_MASK;
}
- if ((Mod1Mask & xstate) != 0) {
+ if ( (Mod1Mask & xstate) != 0 || J_VK_ALT == keySym ) {
modifiers |= EVENT_ALT_MASK;
}
- if ((Button1Mask & xstate) != 0) {
+ if ( (Button1Mask & xstate) != 0 ) {
modifiers |= EVENT_BUTTON1_MASK;
}
- if ((Button2Mask & xstate) != 0) {
+ if ( (Button2Mask & xstate) != 0 ) {
modifiers |= EVENT_BUTTON2_MASK;
}
- if ((Button3Mask & xstate) != 0) {
+ if ( (Button3Mask & xstate) != 0 ) {
modifiers |= EVENT_BUTTON3_MASK;
}
@@ -397,13 +397,13 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage
keyChar=0;
keySym = X11KeySym2NewtVKey(keySym);
}
- modifiers |= X11InputState2NewtModifiers(evt.xkey.state) | autoRepeatModifiers;
+ modifiers |= X11InputState2NewtModifiers(evt.xkey.state, keySym) | autoRepeatModifiers;
break;
case ButtonPress:
case ButtonRelease:
case MotionNotify:
- modifiers |= X11InputState2NewtModifiers(evt.xbutton.state);
+ modifiers |= X11InputState2NewtModifiers(evt.xbutton.state, 0);
break;
default:
@@ -472,23 +472,23 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage
case KeyPress:
#ifdef USE_SENDIO_DIRECT
(*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jint) EVENT_KEY_PRESSED,
- modifiers, keySym, (jchar) -1);
+ modifiers, keySym, (jchar) keyChar);
#else
(*env)->CallVoidMethod(env, jwindow, enqueueKeyEventID, JNI_FALSE, (jint) EVENT_KEY_PRESSED,
- modifiers, keySym, (jchar) -1);
+ modifiers, keySym, (jchar) keyChar);
#endif
break;
case KeyRelease:
#ifdef USE_SENDIO_DIRECT
(*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jint) EVENT_KEY_RELEASED,
- modifiers, keySym, (jchar) -1);
+ modifiers, keySym, (jchar) keyChar);
(*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jint) EVENT_KEY_TYPED,
modifiers, keySym, (jchar) keyChar);
#else
(*env)->CallVoidMethod(env, jwindow, enqueueKeyEventID, JNI_FALSE, (jint) EVENT_KEY_RELEASED,
- modifiers, keySym, (jchar) -1);
+ modifiers, keySym, (jchar) keyChar);
(*env)->CallVoidMethod(env, jwindow, enqueueKeyEventID, JNI_FALSE, (jint) EVENT_KEY_TYPED,
modifiers, keySym, (jchar) keyChar);
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestNewtKeyCodeModifiersAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestNewtKeyCodeModifiersAWT.java
new file mode 100644
index 000000000..b06788386
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/newt/TestNewtKeyCodeModifiersAWT.java
@@ -0,0 +1,275 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.newt;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.AfterClass;
+import org.junit.Assume;
+import org.junit.Before;
+
+import java.awt.AWTException;
+import java.awt.BorderLayout;
+import java.awt.Robot;
+import java.lang.reflect.InvocationTargetException;
+import java.util.EventObject;
+import java.util.List;
+
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLEventListener;
+import javax.swing.JFrame;
+
+import java.io.IOException;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import com.jogamp.newt.awt.NewtCanvasAWT;
+import com.jogamp.newt.event.InputEvent;
+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;
+
+import com.jogamp.opengl.test.junit.util.*;
+
+/**
+ * Testing combinations of key code modifiers of key event.
+ */
+public class TestNewtKeyCodeModifiersAWT extends UITestCase {
+ static int width, height;
+ static long durationPerTest = 100;
+ static long awtWaitTimeout = 1000;
+
+ static GLCapabilities glCaps;
+
+ @BeforeClass
+ public static void initClass() {
+ width = 640;
+ height = 480;
+ glCaps = new GLCapabilities(null);
+ }
+
+ @AfterClass
+ public static void release() {
+ }
+
+ @Before
+ public void initTest() {
+ }
+
+ @After
+ public void releaseTest() {
+ }
+
+ @Test
+ public void test01NEWT() throws AWTException, InterruptedException, InvocationTargetException {
+ GLWindow glWindow = GLWindow.create(glCaps);
+ glWindow.setSize(width, height);
+ glWindow.setVisible(true);
+
+ testImpl(glWindow);
+
+ glWindow.destroy();
+ }
+
+ @Test
+ public void test02NewtCanvasAWT() throws AWTException, InterruptedException, InvocationTargetException {
+ GLWindow glWindow = GLWindow.create(glCaps);
+
+ // Wrap the window in a canvas.
+ final NewtCanvasAWT newtCanvasAWT = new NewtCanvasAWT(glWindow);
+
+ // Add the canvas to a frame, and make it all visible.
+ final JFrame frame1 = new JFrame("Swing AWT Parent Frame: "+ glWindow.getTitle());
+ frame1.getContentPane().add(newtCanvasAWT, BorderLayout.CENTER);
+ frame1.setSize(width, height);
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame1.setVisible(true);
+ } } );
+
+ Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame1, true));
+
+ testImpl(glWindow);
+
+ try {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame1.setVisible(false);
+ frame1.dispose();
+ }});
+ } catch( Throwable throwable ) {
+ throwable.printStackTrace();
+ Assume.assumeNoException( throwable );
+ }
+ glWindow.destroy();
+ }
+
+ static void testKeyCodeModifier(Robot robot, NEWTKeyAdapter keyAdapter, int modifierKey, int modifierMask) {
+ 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
+ robot.waitForIdle();
+ for(int j=0; j < 10 && 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
+ robot.waitForIdle();
+ for(int j=0; j < 10 && keyAdapter.getQueueSize() < 3+6; j++) { // wait until events are collected
+ robot.delay(100);
+ }
+ NEWTKeyUtil.validateKeyAdapterStats(keyAdapter, 3+6, 0);
+
+ 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, 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);
+ }
+
+ static void testKeyCodeAllModifierV1(Robot robot, NEWTKeyAdapter keyAdapter) {
+ final int m1k = KeyEvent.VK_ALT;
+ final int m1m = InputEvent.ALT_MASK;
+ final int m2k = KeyEvent.VK_CONTROL;
+ final int m2m = InputEvent.CTRL_MASK;
+ final int m3k = KeyEvent.VK_SHIFT;
+ final int m3m = InputEvent.SHIFT_MASK;
+
+ keyAdapter.reset();
+ AWTRobotUtil.keyPress(0, robot, true, m1k, 10); // press MOD1
+ AWTRobotUtil.keyPress(0, robot, true, m2k, 10); // press MOD2
+ AWTRobotUtil.keyPress(0, robot, true, m3k, 10); // press MOD3
+ 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
+
+ robot.waitForIdle();
+ for(int j=0; j < 10 && keyAdapter.getQueueSize() < 3*4; j++) { // wait until events are collected
+ robot.delay(100);
+ }
+ NEWTKeyUtil.validateKeyAdapterStats(keyAdapter, 3*4, 0);
+
+ 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|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_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);
+ }
+
+ void testImpl(GLWindow glWindow) throws AWTException, InterruptedException, InvocationTargetException {
+ final Robot robot = new Robot();
+ robot.setAutoWaitForIdle(true);
+
+ GLEventListener demo1 = new RedSquareES2();
+ TestListenerCom01AWT.setDemoFields(demo1, glWindow, false);
+ glWindow.addGLEventListener(demo1);
+
+ // NEWTFocusAdapter glWindow1FA = new NEWTFocusAdapter("GLWindow1");
+ // glWindow.addWindowListener(glWindow1FA);
+ NEWTKeyAdapter glWindow1KA = new NEWTKeyAdapter("GLWindow1");
+ glWindow1KA.setVerbose(false);
+ glWindow.addKeyListener(glWindow1KA);
+
+ Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glWindow, true));
+
+ // Continuous animation ..
+ Animator animator = new Animator(glWindow);
+ animator.start();
+
+ Thread.sleep(durationPerTest); // manual testing
+
+ AWTRobotUtil.assertRequestFocusAndWait(null, glWindow, glWindow, null, null); // programmatic
+ 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);
+
+ testKeyCodeAllModifierV1(robot, glWindow1KA);
+
+ // Remove listeners to avoid logging during dispose/destroy.
+ glWindow.removeKeyListener(glWindow1KA);
+
+ // Shutdown the test.
+ animator.stop();
+ }
+
+ static int atoi(String a) {
+ int i=0;
+ try {
+ i = Integer.parseInt(a);
+ } catch (Exception ex) { ex.printStackTrace(); }
+ return i;
+ }
+
+ public static void main(String args[]) throws IOException {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ durationPerTest = atoi(args[++i]);
+ }
+ }
+ /**
+ BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
+ System.err.println("Press enter to continue");
+ System.err.println(stdin.readLine());
+ */
+ System.out.println("durationPerTest: "+durationPerTest);
+ String tstname = TestNewtKeyCodeModifiersAWT.class.getName();
+ org.junit.runner.JUnitCore.main(tstname);
+ }
+
+
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestNewtKeyCodeAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestNewtKeyCodesAWT.java
index 37debfcc2..e786eaf74 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/TestNewtKeyCodeAWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/TestNewtKeyCodesAWT.java
@@ -60,18 +60,9 @@ import com.jogamp.opengl.test.junit.util.*;
import com.jogamp.opengl.test.junit.util.NEWTKeyUtil.CodeSeg;
/**
- * Testing key event order incl. auto-repeat (Bug 601)
- *
- * <p>
- * Note Event order:
- * <ol>
- * <li>{@link #EVENT_KEY_PRESSED}</li>
- * <li>{@link #EVENT_KEY_RELEASED}</li>
- * <li>{@link #EVENT_KEY_TYPED}</li>
- * </ol>
- * </p>
+ * Testing key code of key events.
*/
-public class TestNewtKeyCodeAWT extends UITestCase {
+public class TestNewtKeyCodesAWT extends UITestCase {
static int width, height;
static long durationPerTest = 100;
static long awtWaitTimeout = 1000;
@@ -108,7 +99,7 @@ public class TestNewtKeyCodeAWT extends UITestCase {
glWindow.destroy();
}
- // @Test
+ @Test
public void test02NewtCanvasAWT() throws AWTException, InterruptedException, InvocationTargetException {
GLWindow glWindow = GLWindow.create(glCaps);
@@ -145,7 +136,7 @@ public class TestNewtKeyCodeAWT extends UITestCase {
new CodeSeg(0x008, 0x008, "bs"),
// new CodeSeg(0x009, 0x009, "tab"), // TAB functions as focus traversal key
new CodeSeg(0x00a, 0x00a, "cr"),
- new CodeSeg(0x010, 0x011, "shift, ctrl"), // single alt n/a on windows
+ new CodeSeg(0x010, 0x012, "shift, ctrl, alt"),
new CodeSeg(0x01B, 0x01B, "esc"),
new CodeSeg(0x020, 0x024, "space, up, down, end, home"),
new CodeSeg(0x025, 0x028, "cursor"),
@@ -169,9 +160,8 @@ public class TestNewtKeyCodeAWT extends UITestCase {
// new CodeSeg(0x200, 0x20D, "extra-2"), // @ ; ..
};
- static void testKeyCode(Robot robot, NEWTKeyAdapter keyAdapter) {
+ static void testKeyCodes(Robot robot, NEWTKeyAdapter keyAdapter) {
final List<List<EventObject>> cse = new ArrayList<List<EventObject>>();
- final List<EventObject> queue = keyAdapter.getQueued();
for(int i=0; i<codeSegments.length; i++) {
keyAdapter.reset();
@@ -184,13 +174,13 @@ public class TestNewtKeyCodeAWT extends UITestCase {
robot.waitForIdle();
}
final int codeCount = codeSeg.max - codeSeg.min + 1;
- for(int j=0; j < 10 && queue.size() < 3 * codeCount; j++) { // wait until events are collected
+ for(int j=0; j < 10 && keyAdapter.getQueueSize() < 3 * codeCount; j++) { // wait until events are collected
robot.delay(100);
}
- final ArrayList<EventObject> events = new ArrayList<EventObject>(queue);
+ final ArrayList<EventObject> events = new ArrayList<EventObject>(keyAdapter.getQueued());
cse.add(events);
}
- Assert.assertEquals("KeyCode impl. incomplete", true, NEWTKeyUtil.validateKeyCode(codeSegments, cse, true));
+ Assert.assertEquals("KeyCode impl. incomplete", true, NEWTKeyUtil.validateKeyCodes(codeSegments, cse, true));
}
void testImpl(GLWindow glWindow) throws AWTException, InterruptedException, InvocationTargetException {
@@ -216,13 +206,10 @@ public class TestNewtKeyCodeAWT extends UITestCase {
Thread.sleep(durationPerTest); // manual testing
AWTRobotUtil.assertRequestFocusAndWait(null, glWindow, glWindow, null, null); // programmatic
- AWTRobotUtil.requestFocus(robot, glWindow); // within unit framework, prev. tests (TestFocus02SwingAWTRobot) 'confuses' Windows keyboard input
+ AWTRobotUtil.requestFocus(robot, glWindow, false); // within unit framework, prev. tests (TestFocus02SwingAWTRobot) 'confuses' Windows keyboard input
glWindow1KA.reset();
- //
- // Test the key event order w/o auto-repeat
- //
- testKeyCode(robot, glWindow1KA);
+ testKeyCodes(robot, glWindow1KA);
// Remove listeners to avoid logging during dispose/destroy.
glWindow.removeKeyListener(glWindow1KA);
@@ -251,7 +238,7 @@ public class TestNewtKeyCodeAWT extends UITestCase {
System.err.println(stdin.readLine());
*/
System.out.println("durationPerTest: "+durationPerTest);
- String tstname = TestNewtKeyCodeAWT.class.getName();
+ String tstname = TestNewtKeyCodesAWT.class.getName();
org.junit.runner.JUnitCore.main(tstname);
}
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestNewtKeyEventAutoRepeatAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestNewtKeyEventAutoRepeatAWT.java
index 6816863da..7b6fe0596 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/TestNewtKeyEventAutoRepeatAWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/TestNewtKeyEventAutoRepeatAWT.java
@@ -159,7 +159,6 @@ public class TestNewtKeyEventAutoRepeatAWT extends UITestCase {
EventObject[][] last = new EventObject[loops][3];
keyAdapter.reset();
- final List<EventObject> keyEvents = keyAdapter.getQueued();
int firstIdx = 0;
for(int i=0; i<loops; i++) {
System.err.println("+++ KEY Event Auto-Repeat START Input Loop: "+i);
@@ -169,11 +168,12 @@ public class TestNewtKeyEventAutoRepeatAWT extends UITestCase {
robot.waitForIdle();
final int minCodeCount = firstIdx + 3;
final int desiredCodeCount = firstIdx + 6;
- for(int j=0; j < 10 && keyEvents.size() < desiredCodeCount; j++) { // wait until events are collected
+ for(int j=0; j < 10 && keyAdapter.getQueueSize() < desiredCodeCount; j++) { // wait until events are collected
robot.delay(100);
}
- Assert.assertTrue("AR Test didn't collect enough key events: required min "+minCodeCount+", received "+(keyEvents.size()-firstIdx)+", "+keyEvents,
- keyEvents.size() >= minCodeCount );
+ Assert.assertTrue("AR Test didn't collect enough key events: required min "+minCodeCount+", received "+(keyAdapter.getQueueSize()-firstIdx)+", "+keyAdapter.getQueued(),
+ keyAdapter.getQueueSize() >= minCodeCount );
+ final List<EventObject> keyEvents = keyAdapter.getQueued();
first[i][0] = (KeyEvent) keyEvents.get(firstIdx+0);
first[i][1] = (KeyEvent) keyEvents.get(firstIdx+1);
first[i][2] = (KeyEvent) keyEvents.get(firstIdx+2);
@@ -184,22 +184,27 @@ public class TestNewtKeyEventAutoRepeatAWT extends UITestCase {
System.err.println("+++ KEY Event Auto-Repeat END Input Loop: "+i);
// add a pair of normal press/release in between auto-repeat!
+ firstIdx = keyEvents.size();
AWTRobotUtil.keyPress(0, robot, true, java.awt.event.KeyEvent.VK_B, 10);
robot.waitForIdle();
AWTRobotUtil.keyPress(0, robot, false, java.awt.event.KeyEvent.VK_B, 250);
robot.waitForIdle();
+ for(int j=0; j < 10 && keyAdapter.getQueueSize() < firstIdx+3; j++) { // wait until events are collected
+ robot.delay(100);
+ }
firstIdx = keyEvents.size();
}
// dumpKeyEvents(keyEvents);
-
+ final List<EventObject> keyEvents = keyAdapter.getQueued();
NEWTKeyUtil.validateKeyEventOrder(keyEvents);
final boolean hasAR = 0 < keyAdapter.getKeyPressedCount(true) ;
- Assert.assertEquals("Key event count not multiple of 3", 0, keyEvents.size()%3);
- final int expTotal = keyEvents.size()/3;
- final int expAR = hasAR ? expTotal - loops - loops : 0;
- NEWTKeyUtil.validateKeyAdapterStats(keyAdapter, expTotal, expAR);
+ {
+ 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);
+ }
if( !hasAR ) {
System.err.println("No AUTO-REPEAT triggered by AWT Robot .. aborting test analysis");
@@ -266,7 +271,7 @@ public class TestNewtKeyEventAutoRepeatAWT extends UITestCase {
Thread.sleep(durationPerTest); // manual testing
AWTRobotUtil.assertRequestFocusAndWait(null, glWindow, glWindow, null, null); // programmatic
- AWTRobotUtil.requestFocus(robot, glWindow); // within unit framework, prev. tests (TestFocus02SwingAWTRobot) 'confuses' Windows keyboard input
+ AWTRobotUtil.requestFocus(robot, glWindow, false); // within unit framework, prev. tests (TestFocus02SwingAWTRobot) 'confuses' Windows keyboard input
glWindow1KA.reset();
//
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestNewtKeyEventOrderAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestNewtKeyEventOrderAWT.java
index 11f552ecb..cf5016173 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/TestNewtKeyEventOrderAWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/TestNewtKeyEventOrderAWT.java
@@ -56,7 +56,7 @@ import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2;
import com.jogamp.opengl.test.junit.util.*;
/**
- * Testing key event order incl. auto-repeat (Bug 601)
+ * Testing key event order excl. auto-repeat (Bug 601)
*
* <p>
* Note Event order:
@@ -167,7 +167,7 @@ public class TestNewtKeyEventOrderAWT extends UITestCase {
NEWTKeyUtil.validateKeyEventOrder(keyAdapter.getQueued());
- NEWTKeyUtil.validateKeyAdapterStats(keyAdapter, 6*loops, 0);
+ NEWTKeyUtil.validateKeyAdapterStats(keyAdapter, 6*3*loops, 0);
}
void testImpl(GLWindow glWindow) throws AWTException, InterruptedException, InvocationTargetException {
@@ -191,7 +191,7 @@ public class TestNewtKeyEventOrderAWT extends UITestCase {
Thread.sleep(durationPerTest); // manual testing
AWTRobotUtil.assertRequestFocusAndWait(null, glWindow, glWindow, null, null); // programmatic
- AWTRobotUtil.requestFocus(robot, glWindow); // within unit framework, prev. tests (TestFocus02SwingAWTRobot) 'confuses' Windows keyboard input
+ AWTRobotUtil.requestFocus(robot, glWindow, false); // within unit framework, prev. tests (TestFocus02SwingAWTRobot) 'confuses' Windows keyboard input
glWindow1KA.reset();
//
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestNewtKeyPressReleaseUnmaskRepeatAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestNewtKeyPressReleaseUnmaskRepeatAWT.java
index 6ebaf2707..c27513905 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/TestNewtKeyPressReleaseUnmaskRepeatAWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/TestNewtKeyPressReleaseUnmaskRepeatAWT.java
@@ -151,7 +151,7 @@ public class TestNewtKeyPressReleaseUnmaskRepeatAWT extends UITestCase {
Thread.sleep(durationPerTest); // manual testing
AWTRobotUtil.assertRequestFocusAndWait(null, glWindow, glWindow, null, null); // programmatic
- AWTRobotUtil.requestFocus(robot, glWindow); // within unit framework, prev. tests (TestFocus02SwingAWTRobot) 'confuses' Windows keyboard input
+ AWTRobotUtil.requestFocus(robot, glWindow, false); // within unit framework, prev. tests (TestFocus02SwingAWTRobot) 'confuses' Windows keyboard input
// Remove listeners to avoid logging during dispose/destroy.
glWindow.removeKeyListener(simpleKeyPressRelease);
diff --git a/src/test/com/jogamp/opengl/test/junit/util/AWTKeyAdapter.java b/src/test/com/jogamp/opengl/test/junit/util/AWTKeyAdapter.java
index a9fa373b5..837ba5da1 100644
--- a/src/test/com/jogamp/opengl/test/junit/util/AWTKeyAdapter.java
+++ b/src/test/com/jogamp/opengl/test/junit/util/AWTKeyAdapter.java
@@ -46,33 +46,37 @@ public class AWTKeyAdapter extends java.awt.event.KeyAdapter implements KeyEvent
reset();
}
- public void setVerbose(boolean v) { verbose = false; }
+ public synchronized void setVerbose(boolean v) { verbose = false; }
- public boolean isPressed() {
+ public synchronized boolean isPressed() {
return pressed;
}
- public int getCount() {
+ public synchronized int getCount() {
return keyTyped;
}
- public int getKeyPressedCount(boolean autoRepeatOnly) {
+ public synchronized int getKeyPressedCount(boolean autoRepeatOnly) {
return keyPressed;
}
- public int getKeyReleasedCount(boolean autoRepeatOnly) {
+ public synchronized int getKeyReleasedCount(boolean autoRepeatOnly) {
return keyReleased;
}
- public int getKeyTypedCount(boolean autoRepeatOnly) {
+ public synchronized int getKeyTypedCount(boolean autoRepeatOnly) {
return keyTyped;
}
- public List<EventObject> getQueued() {
+ public synchronized List<EventObject> getQueued() {
return queue;
}
- public void reset() {
+ public synchronized int getQueueSize() {
+ return queue.size();
+ }
+
+ public synchronized void reset() {
keyTyped = 0;
keyPressed = 0;
keyReleased = 0;
@@ -80,7 +84,7 @@ public class AWTKeyAdapter extends java.awt.event.KeyAdapter implements KeyEvent
queue.clear();
}
- public void keyPressed(KeyEvent e) {
+ public synchronized void keyPressed(KeyEvent e) {
pressed = true;
keyPressed++;
queue.add(e);
@@ -89,7 +93,7 @@ public class AWTKeyAdapter extends java.awt.event.KeyAdapter implements KeyEvent
}
}
- public void keyReleased(KeyEvent e) {
+ public synchronized void keyReleased(KeyEvent e) {
pressed = false;
keyReleased++;
queue.add(e);
@@ -98,7 +102,7 @@ public class AWTKeyAdapter extends java.awt.event.KeyAdapter implements KeyEvent
}
}
- public void keyTyped(java.awt.event.KeyEvent e) {
+ public synchronized void keyTyped(java.awt.event.KeyEvent e) {
keyTyped++;
queue.add(e);
if( verbose ) {
diff --git a/src/test/com/jogamp/opengl/test/junit/util/AWTMouseAdapter.java b/src/test/com/jogamp/opengl/test/junit/util/AWTMouseAdapter.java
index 3334f18ea..31362bfa1 100644
--- a/src/test/com/jogamp/opengl/test/junit/util/AWTMouseAdapter.java
+++ b/src/test/com/jogamp/opengl/test/junit/util/AWTMouseAdapter.java
@@ -45,27 +45,31 @@ public class AWTMouseAdapter extends java.awt.event.MouseAdapter implements Inpu
reset();
}
- public void setVerbose(boolean v) { verbose = false; }
+ public synchronized void setVerbose(boolean v) { verbose = false; }
- public boolean isPressed() {
+ public synchronized boolean isPressed() {
return pressed;
}
- public int getCount() {
+ public synchronized int getCount() {
return mouseClicked;
}
- public List<EventObject> getQueued() {
+ public synchronized List<EventObject> getQueued() {
return queue;
}
- public void reset() {
+ public synchronized int getQueueSize() {
+ return queue.size();
+ }
+
+ public synchronized void reset() {
mouseClicked = 0;
pressed = false;
queue.clear();
}
- public void mousePressed(MouseEvent e) {
+ public synchronized void mousePressed(MouseEvent e) {
pressed = true;
queue.add(e);
if( verbose ) {
@@ -73,7 +77,7 @@ public class AWTMouseAdapter extends java.awt.event.MouseAdapter implements Inpu
}
}
- public void mouseReleased(MouseEvent e) {
+ public synchronized void mouseReleased(MouseEvent e) {
pressed = false;
queue.add(e);
if( verbose ) {
@@ -81,7 +85,7 @@ public class AWTMouseAdapter extends java.awt.event.MouseAdapter implements Inpu
}
}
- public void mouseClicked(java.awt.event.MouseEvent e) {
+ public synchronized void mouseClicked(java.awt.event.MouseEvent e) {
mouseClicked+=e.getClickCount();
queue.add(e);
if( verbose ) {
diff --git a/src/test/com/jogamp/opengl/test/junit/util/AWTRobotUtil.java b/src/test/com/jogamp/opengl/test/junit/util/AWTRobotUtil.java
index f48033ae0..e64b3208e 100644
--- a/src/test/com/jogamp/opengl/test/junit/util/AWTRobotUtil.java
+++ b/src/test/com/jogamp/opengl/test/junit/util/AWTRobotUtil.java
@@ -196,10 +196,20 @@ public class AWTRobotUtil {
/**
* requestFocus, if robot is valid, use mouse operation,
- * otherwise programatic, ie call requestFocus
+ * otherwise programmatic, ie call requestFocus
*/
public static void requestFocus(Robot robot, Object obj)
throws AWTException, InterruptedException, InvocationTargetException {
+ requestFocus(robot, obj, true);
+ }
+
+ /**
+ * requestFocus, if robot is valid, use mouse operation,
+ * otherwise programmatic, ie call requestFocus
+ */
+ public static void requestFocus(Robot robot, Object obj, boolean onTitleBarIfWindow)
+ throws AWTException, InterruptedException, InvocationTargetException {
+
final Component comp;
final com.jogamp.newt.Window win;
@@ -226,7 +236,7 @@ public class AWTRobotUtil {
}
} else {
final int mouseButton = java.awt.event.InputEvent.BUTTON1_MASK;
- centerMouse(robot, obj, true);
+ centerMouse(robot, obj, onTitleBarIfWindow);
robot.waitForIdle();
robot.mousePress(mouseButton);
diff --git a/src/test/com/jogamp/opengl/test/junit/util/InputEventCountAdapter.java b/src/test/com/jogamp/opengl/test/junit/util/InputEventCountAdapter.java
index ed7485951..c4078436f 100644
--- a/src/test/com/jogamp/opengl/test/junit/util/InputEventCountAdapter.java
+++ b/src/test/com/jogamp/opengl/test/junit/util/InputEventCountAdapter.java
@@ -35,6 +35,7 @@ public interface InputEventCountAdapter extends EventCountAdapter {
int getCount();
boolean isPressed();
- public List<EventObject> getQueued();
+ public List<EventObject> getQueued();
+ public int getQueueSize();
}
diff --git a/src/test/com/jogamp/opengl/test/junit/util/NEWTKeyAdapter.java b/src/test/com/jogamp/opengl/test/junit/util/NEWTKeyAdapter.java
index 42235254a..f19169b42 100644
--- a/src/test/com/jogamp/opengl/test/junit/util/NEWTKeyAdapter.java
+++ b/src/test/com/jogamp/opengl/test/junit/util/NEWTKeyAdapter.java
@@ -50,33 +50,37 @@ public class NEWTKeyAdapter extends KeyAdapter implements KeyEventCountAdapter {
reset();
}
- public void setVerbose(boolean v) { verbose = false; }
+ public synchronized void setVerbose(boolean v) { verbose = false; }
- public boolean isPressed() {
+ public synchronized boolean isPressed() {
return pressed;
}
- public int getCount() {
+ public synchronized int getCount() {
return keyTyped;
}
- public int getKeyPressedCount(boolean autoRepeatOnly) {
+ public synchronized int getKeyPressedCount(boolean autoRepeatOnly) {
return autoRepeatOnly ? keyPressedAR: keyPressed;
}
- public int getKeyReleasedCount(boolean autoRepeatOnly) {
+ public synchronized int getKeyReleasedCount(boolean autoRepeatOnly) {
return autoRepeatOnly ? keyReleasedAR: keyReleased;
}
- public int getKeyTypedCount(boolean autoRepeatOnly) {
+ public synchronized int getKeyTypedCount(boolean autoRepeatOnly) {
return autoRepeatOnly ? keyTypedAR: keyTyped;
}
- public List<EventObject> getQueued() {
+ public synchronized List<EventObject> getQueued() {
return queue;
}
- public void reset() {
+ public synchronized int getQueueSize() {
+ return queue.size();
+ }
+
+ public synchronized void reset() {
keyTyped = 0;
keyPressed = 0;
keyReleased = 0;
@@ -87,7 +91,7 @@ public class NEWTKeyAdapter extends KeyAdapter implements KeyEventCountAdapter {
queue.clear();
}
- public void keyPressed(KeyEvent e) {
+ public synchronized void keyPressed(KeyEvent e) {
pressed = true;
keyPressed++;
if( 0 != ( e.getModifiers() & InputEvent.AUTOREPEAT_MASK ) ) {
@@ -99,7 +103,7 @@ public class NEWTKeyAdapter extends KeyAdapter implements KeyEventCountAdapter {
}
}
- public void keyReleased(KeyEvent e) {
+ public synchronized void keyReleased(KeyEvent e) {
pressed = false;
keyReleased++;
if( 0 != ( e.getModifiers() & InputEvent.AUTOREPEAT_MASK ) ) {
@@ -112,7 +116,7 @@ public class NEWTKeyAdapter extends KeyAdapter implements KeyEventCountAdapter {
}
@Override
- public void keyTyped(KeyEvent e) {
+ public synchronized void keyTyped(KeyEvent e) {
keyTyped++;
if( 0 != ( e.getModifiers() & InputEvent.AUTOREPEAT_MASK ) ) {
keyTypedAR++;
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 95818845e..e090ed4cf 100644
--- a/src/test/com/jogamp/opengl/test/junit/util/NEWTKeyUtil.java
+++ b/src/test/com/jogamp/opengl/test/junit/util/NEWTKeyUtil.java
@@ -62,14 +62,14 @@ public class NEWTKeyUtil {
return "Code 0x"+Integer.toHexString(code)+" != "+event+" // "+description;
}
}
-
+
public static void dumpKeyEvents(List<EventObject> keyEvents) {
for(int i=0; i<keyEvents.size(); i++) {
System.err.println(i+": "+keyEvents.get(i));
}
}
-
- public static boolean validateKeyCode(CodeSeg[] codeSegments, List<List<EventObject>> keyEventsList, boolean verbose) {
+
+ public static boolean validateKeyCodes(CodeSeg[] codeSegments, List<List<EventObject>> keyEventsList, boolean verbose) {
final List<CodeEvent> missCodes = new ArrayList<CodeEvent>();
int totalCodeCount = 0;
boolean res = true;
@@ -77,7 +77,7 @@ public class NEWTKeyUtil {
final CodeSeg codeSeg = codeSegments[i];
totalCodeCount += codeSeg.max - codeSeg.min + 1;
final List<EventObject> keyEvents = keyEventsList.get(i);
- res &= validateKeyCode(missCodes, codeSeg, keyEvents, verbose);
+ res &= validateKeyCodes(missCodes, codeSeg, keyEvents, verbose);
}
if(verbose) {
System.err.println("*** Total KeyCode Misses "+missCodes.size()+" / "+totalCodeCount+", valid "+res);
@@ -87,7 +87,7 @@ public class NEWTKeyUtil {
}
return res;
}
- public static boolean validateKeyCode(List<CodeEvent> missCodes, CodeSeg codeSeg, List<EventObject> keyEvents, boolean verbose) {
+ 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;
for(int i=0; i<codeCount; i++) {
@@ -106,6 +106,18 @@ public class NEWTKeyUtil {
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());
+ }
+ 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());
+ }
+ }
+
public static int getNextKeyEventType(int et) {
switch( et ) {
case KeyEvent.EVENT_KEY_PRESSED:
@@ -138,8 +150,8 @@ public class NEWTKeyUtil {
/**
*
* @param keyAdapter
- * @param expTotalCount number of physical key press/release, i.e. 1 shall result in 3 events (press, release and typed)
- * @param expARCount as auto-release ..
+ * @param expTotalCount number of key press/release/types events
+ * @param expARCount number of key press/release/types Auto-Release events
*/
public static void validateKeyAdapterStats(NEWTKeyAdapter keyAdapter, int expTotalCount, int expARCount) {
final int keyPressed = keyAdapter.getKeyPressedCount(false);
@@ -157,17 +169,17 @@ public class NEWTKeyUtil {
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", 3*expTotalCount, keyEvents.size());
- Assert.assertEquals("Key press count failure", expTotalCount, keyPressed);
- Assert.assertEquals("Key press count failure (AR)", expARCount, keyPressedAR);
- Assert.assertEquals("Key released count failure", expTotalCount, keyReleased);
- Assert.assertEquals("Key released count failure (AR)", expARCount, keyReleasedAR);
- Assert.assertEquals("Key typed count failure", expTotalCount, keyTyped);
- Assert.assertEquals("Key typed count failure (AR)", expARCount, keyTypedAR);
+ 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, keyPressedNR);
- Assert.assertEquals(expTotalCount-expARCount, keyReleasedNR);
- Assert.assertEquals(expTotalCount-expARCount, keyTypedNR);
+ Assert.assertEquals( ( expTotalCount - expARCount ) / 3, keyPressedNR);
+ Assert.assertEquals( ( expTotalCount - expARCount ) / 3, keyReleasedNR);
+ Assert.assertEquals( ( expTotalCount - expARCount ) / 3, keyTypedNR);
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/util/NEWTMouseAdapter.java b/src/test/com/jogamp/opengl/test/junit/util/NEWTMouseAdapter.java
index c77462884..644523782 100644
--- a/src/test/com/jogamp/opengl/test/junit/util/NEWTMouseAdapter.java
+++ b/src/test/com/jogamp/opengl/test/junit/util/NEWTMouseAdapter.java
@@ -48,27 +48,31 @@ public class NEWTMouseAdapter extends MouseAdapter implements InputEventCountAda
reset();
}
- public void setVerbose(boolean v) { verbose = false; }
+ public synchronized void setVerbose(boolean v) { verbose = false; }
- public boolean isPressed() {
+ public synchronized boolean isPressed() {
return pressed;
}
- public int getCount() {
+ public synchronized int getCount() {
return mouseClicked;
}
- public List<EventObject> getQueued() {
+ public synchronized List<EventObject> getQueued() {
return queue;
}
- public void reset() {
+ public synchronized int getQueueSize() {
+ return queue.size();
+ }
+
+ public synchronized void reset() {
mouseClicked = 0;
pressed = false;
queue.clear();
}
- public void mousePressed(MouseEvent e) {
+ public synchronized void mousePressed(MouseEvent e) {
pressed = true;
queue.add(e);
if( verbose ) {
@@ -76,7 +80,7 @@ public class NEWTMouseAdapter extends MouseAdapter implements InputEventCountAda
}
}
- public void mouseReleased(MouseEvent e) {
+ public synchronized void mouseReleased(MouseEvent e) {
pressed = false;
queue.add(e);
if( verbose ) {
@@ -84,7 +88,7 @@ public class NEWTMouseAdapter extends MouseAdapter implements InputEventCountAda
}
}
- public void mouseClicked(MouseEvent e) {
+ public synchronized void mouseClicked(MouseEvent e) {
mouseClicked+=e.getClickCount();
queue.add(e);
if( verbose ) {