diff options
author | Sven Gothel <[email protected]> | 2012-10-31 04:04:39 +0100 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2012-10-31 04:04:39 +0100 |
commit | b62e1d027c289877686d6008ea8dd40e4e1541ec (patch) | |
tree | f0af41cb2c9bdd92c37192880439843de1b85f32 /src | |
parent | dda5e1611fc41089a5f8d486435d3d2d7e9b76d6 (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')
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 ) { |