aboutsummaryrefslogtreecommitdiffstats
path: root/src/newt
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2013-01-29 21:27:57 +0100
committerSven Gothel <[email protected]>2013-01-29 21:27:57 +0100
commit90e136b65a10d8daf8c3a2df6cc193e55a63722c (patch)
tree863f8a3679a70065b031aaf83bd7cc6053fd69ab /src/newt
parent2f63a43fd6ff9964251c43e248c51bc821f3ecbd (diff)
Fix Bug 678: Deliver key-char value for printable chars on all KeyEventListener (-> On Windows as well)
The following is observed, where t0 and t1 refer to subsequent different timestamps: NEWT delivery order: PRESSED (t0), RELEASED (t1) and TYPED (t1) WINDOWS delivery order: PRESSED (t0), TYPED (t0) and RELEASED (t1) Windows Auto-Repeat: PRESSED (t0), TYPED (t0) Hence we changed the event reorder-code in NEWT to trigger NEWT-PRESSED on Windows-TYPED for printable chars, assuring key-char values on all listener callbacks. - KeyEvent.getKeyChar(): Removed disclaimer dedicated for Windows - Keyevent.isActionKey(): Completed for all NEWT non-printable action keys; Added static variant - Keyevent.isPrintableKey(): NEW: returns !isModifierKey(keyCode) && !isActionKey(keyCode) ; With static variant - Windows WindowDriver: - EVENT_KEY_PRESSED handles non-printable chars only - EVENT_KEY_TYPE handles printable chars only - Native: VK_DELETE passes keyCode - Unit tests: Wait for completion 1s -> 2s
Diffstat (limited to 'src/newt')
-rw-r--r--src/newt/classes/com/jogamp/newt/event/KeyEvent.java142
-rw-r--r--src/newt/classes/jogamp/newt/driver/windows/WindowDriver.java62
-rw-r--r--src/newt/native/WindowsWindow.c2
3 files changed, 139 insertions, 67 deletions
diff --git a/src/newt/classes/com/jogamp/newt/event/KeyEvent.java b/src/newt/classes/com/jogamp/newt/event/KeyEvent.java
index 289aa31f6..ff67b7f57 100644
--- a/src/newt/classes/com/jogamp/newt/event/KeyEvent.java
+++ b/src/newt/classes/com/jogamp/newt/event/KeyEvent.java
@@ -74,12 +74,7 @@ public class KeyEvent extends InputEvent
}
/**
- * Returns the character matching the {@link #getKeyCode() virtual key code}, if exist.
- * <p>
- * <b>Disclaimer</b>: Only valid on all platforms at {@link KeyListener#keyTyped(KeyEvent)}.
- * Precisely, on the Windows platform we currently cannot deliver the proper character
- * in case of shifted keys where no uppercase exists, e.g. 'shift + 1' doesn't produce '!'.
- * </p>
+ * Returns the character matching the {@link #getKeyCode() virtual key code}.
*/
public char getKeyChar() {
return keyChar;
@@ -111,7 +106,12 @@ public class KeyEvent extends InputEvent
}
}
- /** 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}. */
+ /**
+ * Returns true if the given <code>keyCode</code> represents a non-printable modifier key.
+ * <p>
+ * A modifier key is one of {@link #VK_SHIFT}, {@link #VK_CONTROL}, {@link #VK_ALT}, {@link #VK_ALT_GRAPH}, {@link #VK_META}.
+ * </p>
+ */
public static boolean isModifierKey(int keyCode) {
switch (keyCode) {
case VK_SHIFT:
@@ -125,58 +125,116 @@ public class KeyEvent extends InputEvent
}
}
- /** 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}. */
+ /**
+ * Returns true if {@link #getKeyCode()} represents a non-printable modifier key.
+ * <p>
+ * See {@link #isModifierKey(int)} for details.
+ * </p>
+ */
public boolean isModifierKey() {
return isModifierKey(keyCode);
}
-
- public boolean isActionKey() {
+
+ /**
+ * Returns true if the given <code>keyCode</code> represents a non-printable action key, which is not a {@link #isModifierKey(int) modifier key}.
+ * <p>
+ * An action key is one of {@link #VK_HOME}, {@link #VK_END}, {@link #VK_PAGE_UP}, {@link #VK_PAGE_DOWN}, {@link #VK_UP}, {@link #VK_PAGE_DOWN},
+ * {@link #VK_LEFT}, {@link #VK_RIGHT}, {@link #VK_F1}-{@link #VK_F24}, {@link #VK_PRINTSCREEN}, {@link #VK_CAPS_LOCK}, {@link #VK_PAUSE},
+ * {@link #VK_INSERT}, {@link #VK_HELP}, {@link #VK_WINDOWS}, etc ...
+ * </p>
+ */
+ public static boolean isActionKey(int keyCode) {
+ if( ( VK_F1 <= keyCode && keyCode <= VK_F24 ) ||
+ ( VK_ALL_CANDIDATES <= keyCode && keyCode <= VK_INPUT_METHOD_ON_OFF ) ||
+ ( VK_CUT <= keyCode && keyCode <= VK_STOP ) ) {
+ return true;
+ }
+
switch (keyCode) {
- case VK_HOME:
- case VK_END:
+ case VK_CANCEL:
+ case VK_CLEAR:
+ case VK_PAUSE:
+ case VK_CAPS_LOCK:
+ case VK_ESCAPE:
case VK_PAGE_UP:
case VK_PAGE_DOWN:
- case VK_UP:
- case VK_DOWN:
+ case VK_END:
+ case VK_HOME:
case VK_LEFT:
+ case VK_UP:
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_DOWN:
+ case VK_DELETE:
+ case VK_NUM_LOCK:
+ case VK_SCROLL_LOCK:
+
case VK_PRINTSCREEN:
- case VK_CAPS_LOCK:
- case VK_PAUSE:
case VK_INSERT:
-
case VK_HELP:
+ case VK_META:
+ case VK_KP_UP:
+ case VK_KP_DOWN:
+ case VK_KP_LEFT:
+ case VK_KP_RIGHT:
+
+ case VK_DEAD_VOICED_SOUND:
+ case VK_DEAD_SEMIVOICED_SOUND:
+
case VK_WINDOWS:
+ case VK_CONTEXT_MENU:
+ case VK_FINAL:
+
+ case VK_CONVERT:
+ case VK_NONCONVERT:
+ case VK_ACCEPT:
+ case VK_MODECHANGE:
+
+ case VK_KANA:
+ case VK_KANJI:
+
+ case VK_ALPHANUMERIC:
+ case VK_KATAKANA:
+ case VK_HIRAGANA:
+ case VK_FULL_WIDTH:
+ case VK_HALF_WIDTH:
+ case VK_ROMAN_CHARACTERS:
+
+ case VK_COMPOSE:
+ case VK_BEGIN:
+
return true;
}
return false;
}
+
+ /**
+ * Returns true if {@link #getKeyCode() keyCode} represents a non-printable action key, which is not a {@link #isModifierKey(int) modifier key}.
+ * <p>
+ * See {@link #isActionKey(int)} for details.
+ * </p>
+ */
+ public boolean isActionKey() {
+ return isActionKey(keyCode);
+ }
+
+ /**
+ * Returns true if given <code>keyKode</code> represents a printable character, which is neither a {@link #isModifierKey(int) modifier key}
+ * nor an {@link #isActionKey(int) action key}.
+ * Otherwise returns <code>false</code>.
+ */
+ public static boolean isPrintableKey(int keyCode) {
+ return !isModifierKey(keyCode) && !isActionKey(keyCode);
+ }
+ /**
+ * Returns true if {@link #getKeyCode() keyCode} represents a printable character, which is neither a {@link #isModifierKey(int) modifier key}
+ * nor an {@link #isActionKey(int) action key}.
+ * Otherwise returns <code>false</code>.
+ */
+ public boolean isPrintableKey() {
+ return isPrintableKey(keyCode);
+ }
+
private final int keyCode;
private final char keyChar;
diff --git a/src/newt/classes/jogamp/newt/driver/windows/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/windows/WindowDriver.java
index b2e518f45..650958f25 100644
--- a/src/newt/classes/jogamp/newt/driver/windows/WindowDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/windows/WindowDriver.java
@@ -273,53 +273,67 @@ public class WindowDriver extends WindowImpl {
private IntIntHashMap typedKeyCode2KeyChar = new IntIntHashMap(KeyEvent.VK_CONTEXT_MENU+1);
private final void handleKeyEvent(boolean send, boolean wait, int eventType, int modifiers, int keyCode, char keyChar) {
- 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);
+ final boolean isPrintableKey = KeyEvent.isPrintableKey(keyCode);
+ final boolean isModifierKey = 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)+", printableKey "+isPrintableKey+" [modifierKey "+isModifierKey+"] - "+System.currentTimeMillis());
- // Reorder: WINDOWS delivery order is PRESSED, TYPED and RELEASED -> NEWT order: PRESSED, RELEASED and TYPED
- // Auto-Repeat: WINDOWS delivers only PRESSED and TYPED.
+ // Reorder: WINDOWS delivery order is PRESSED (t0), TYPED (t0) and RELEASED (t1) -> NEWT order: PRESSED (t0), RELEASED (t1) and TYPED (t1)
+ // Auto-Repeat: WINDOWS delivers only PRESSED (t0) and TYPED (t0).
switch(eventType) {
case KeyEvent.EVENT_KEY_RELEASED:
+ final int keyCharTyped = typedKeyCode2KeyChar.put(keyCode, 0);
+ if( 0 != keyCharTyped ) {
+ keyChar = (char)keyCharTyped;
+ }
if( isKeyCodeTracked(keyCode) ) {
- if( keyRepeatState.put(keyCode, false) && !isModifierKeyCode ) {
+ if( keyRepeatState.put(keyCode, false) && !isModifierKey ) {
// AR out - send out missing PRESSED
emitKeyEvent(send, wait, KeyEvent.EVENT_KEY_PRESSED, modifiers | InputEvent.AUTOREPEAT_MASK, keyCode, keyChar);
}
keyPressedState.put(keyCode, false);
}
- final int keyCharTyped = typedKeyCode2KeyChar.put(keyCode, 0);
- if( 0 != keyCharTyped ) {
- keyChar = (char)keyCharTyped;
- }
emitKeyEvent(send, wait, eventType, modifiers, keyCode, keyChar);
emitKeyEvent(send, wait, KeyEvent.EVENT_KEY_TYPED, modifiers, keyCode, keyChar);
break;
case KeyEvent.EVENT_KEY_PRESSED:
- if( isKeyCodeTracked(keyCode) ) {
- if( keyPressedState.put(keyCode, true) ) {
- // key was already 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, keyChar);
+ // TYPED is delivered right after PRESSED for printable keys and contains the key-char information,
+ // hence we only deliver non printable keys (action and modifier keys) here.
+ // Modifier keys shall not AR.
+ if( !isPrintableKey ) {
+ if( !handlePressTypedAutoRepeat(isModifierKey, send, wait, modifiers, keyCode, keyChar) ) {
+ emitKeyEvent(send, wait, KeyEvent.EVENT_KEY_PRESSED, modifiers, keyCode, keyChar);
}
- } else {
- emitKeyEvent(send, wait, eventType, modifiers, keyCode, keyChar);
}
break;
case KeyEvent.EVENT_KEY_TYPED:
- if( 1 == isKeyInAutoRepeat(keyCode) ) {
- modifiers |= InputEvent.AUTOREPEAT_MASK;
- emitKeyEvent(send, wait, KeyEvent.EVENT_KEY_RELEASED, modifiers, keyCode, keyChar);
- emitKeyEvent(send, wait, eventType, modifiers, keyCode, keyChar);
- } else if( 0 != keyCode ) {
+ if( isPrintableKey ) {
typedKeyCode2KeyChar.put(keyCode, keyChar);
+ if( !handlePressTypedAutoRepeat(isModifierKey, send, wait, modifiers, keyCode, keyChar) ) {
+ emitKeyEvent(send, wait, KeyEvent.EVENT_KEY_PRESSED, modifiers, keyCode, keyChar);
+ }
}
break;
}
}
+ private final boolean handlePressTypedAutoRepeat(boolean isModifierKey, boolean send, boolean wait, int modifiers, int keyCode, char keyChar) {
+ if( isKeyCodeTracked(keyCode) && keyPressedState.put(keyCode, true) ) {
+ final boolean preKeyRepeatState = keyRepeatState.put(keyCode, true);
+ if( !isModifierKey ) {
+ // AR: Key was already pressed: Either [enter | within] AR mode
+ modifiers |= InputEvent.AUTOREPEAT_MASK;
+ if( preKeyRepeatState ) {
+ // AR: Within AR mode
+ emitKeyEvent(send, wait, KeyEvent.EVENT_KEY_PRESSED, modifiers, keyCode, keyChar);
+ } // else { AR: Enter AR mode - skip already send PRESSED ; or ALT }
+ emitKeyEvent(send, wait, KeyEvent.EVENT_KEY_RELEASED, modifiers, keyCode, keyChar);
+ emitKeyEvent(send, wait, KeyEvent.EVENT_KEY_TYPED, modifiers, keyCode, keyChar);
+ }
+ return true;
+ }
+ return false;
+ }
+
@Override
public void sendKeyEvent(int eventType, int modifiers, int keyCode, char keyChar) {
handleKeyEvent(true, false, eventType, modifiers, keyCode, keyChar);
diff --git a/src/newt/native/WindowsWindow.c b/src/newt/native/WindowsWindow.c
index 17b93cfce..24d513c68 100644
--- a/src/newt/native/WindowsWindow.c
+++ b/src/newt/native/WindowsWindow.c
@@ -605,7 +605,7 @@ static int WmKeyDown(JNIEnv *env, jobject window, UINT wkey, WORD repCnt, BYTE s
(*env)->CallVoidMethod(env, window, sendKeyEventID,
(jint) EVENT_KEY_TYPED,
modifiers,
- (jint) 0,
+ (jint) jkey,
(jchar) '\177');
}