Implemented Keyboard.enableRepeatEvents(), Keyboard.areRepeatEventsEnabled() and Keyboard.isEventRepeat() to control repeat event reporting. Added repeat key test to KeyboardTest

This commit is contained in:
Elias Naur 2007-05-13 22:01:48 +00:00
parent eef220a10f
commit fc759e6192
6 changed files with 129 additions and 58 deletions

View file

@ -57,7 +57,7 @@ import org.lwjgl.opengl.InputImplementation;
*/
public class Keyboard {
/** Internal use - event size in bytes */
public static final int EVENT_SIZE = 4 + 1 + 4 + 8;
public static final int EVENT_SIZE = 4 + 1 + 4 + 8 + 1;
/**
* The special character meaning that no
@ -239,6 +239,9 @@ public class Keyboard {
/** Has the keyboard been created? */
private static boolean created;
/** Are repeat events enabled? */
private static boolean repeat_enabled;
/** The keys status from the last poll */
private static final ByteBuffer keyDownBuffer = BufferUtils.createByteBuffer(KEYBOARD_SIZE);
@ -249,17 +252,11 @@ public class Keyboard {
*/
private static ByteBuffer readBuffer;
/** The current keyboard character being examined */
private static int eventCharacter;
/** current event */
private static KeyEvent current_event = new KeyEvent();
/** The current keyboard event key being examined */
private static int eventKey;
/** The current state of the key being examined in the event queue */
private static boolean eventState;
/** The current event time */
private static long eventNanos;
/** scratch event */
private static KeyEvent tmp_event = new KeyEvent();
/** One time initialization */
private static boolean initialized;
@ -318,9 +315,7 @@ public class Keyboard {
readBuffer.limit(0);
for (int i = 0; i < keyDownBuffer.remaining(); i++)
keyDownBuffer.put(i, (byte)0);
eventCharacter = 0;
eventKey = 0;
eventState = false;
current_event.reset();
}
/**
@ -432,7 +427,12 @@ public class Keyboard {
synchronized (OpenGLPackageAccess.global_lock) {
if (!created)
throw new IllegalStateException("Keyboard must be created before you can read events");
return readBuffer.remaining()/EVENT_SIZE;
int old_position = readBuffer.position();
int num_events = 0;
while (readNext(tmp_event) && (!tmp_event.repeat || repeat_enabled))
num_events++;
readBuffer.position(old_position);
return num_events;
}
}
@ -452,18 +452,47 @@ public class Keyboard {
if (!created)
throw new IllegalStateException("Keyboard must be created before you can read events");
if (readBuffer.hasRemaining()) {
eventKey = readBuffer.getInt() & 0xFF;
eventState = readBuffer.get() != 0;
eventCharacter = readBuffer.getInt();
eventNanos = readBuffer.getLong();
return true;
} else {
return false;
}
boolean result;
while ((result = readNext(current_event)) && current_event.repeat && !repeat_enabled)
;
return result;
}
}
/**
* Controls whether repeat events are reported or not. If repeat events
* are enabled, key down events are reported when a key is pressed and held for
* a OS dependent amount of time. To distinguish a repeat event from a normal event,
* use isRepeatEvent().
*
* @see org.lwjgl.input.Keyboard#getEventKey()
*/
public static synchronized void enableRepeatEvents(boolean enable) {
repeat_enabled = enable;
}
/**
* Check whether repeat events are currently reported or not.
*
* @return true is repeat events are reported, false if not.
* @see org.lwjgl.input.Keyboard#getEventKey()
*/
public static synchronized boolean areRepeatEventsEnabled() {
return repeat_enabled;
}
private static boolean readNext(KeyEvent event) {
if (readBuffer.hasRemaining()) {
event.key = readBuffer.getInt() & 0xFF;
event.state = readBuffer.get() != 0;
event.character = readBuffer.getInt();
event.nanos = readBuffer.getLong();
event.repeat = readBuffer.get() == 1;
return true;
} else
return false;
}
/**
* @return Number of keys on this keyboard
*/
@ -478,7 +507,7 @@ public class Keyboard {
*/
public static synchronized char getEventCharacter() {
synchronized (OpenGLPackageAccess.global_lock) {
return (char)eventCharacter;
return (char)current_event.character;
}
}
@ -491,7 +520,7 @@ public class Keyboard {
*/
public static synchronized int getEventKey() {
synchronized (OpenGLPackageAccess.global_lock) {
return eventKey;
return current_event.key;
}
}
@ -503,7 +532,7 @@ public class Keyboard {
*/
public static synchronized boolean getEventKeyState() {
synchronized (OpenGLPackageAccess.global_lock) {
return eventState;
return current_event.state;
}
}
@ -516,7 +545,42 @@ public class Keyboard {
*/
public static synchronized long getEventNanoseconds() {
synchronized (OpenGLPackageAccess.global_lock) {
return eventNanos;
return current_event.nanos;
}
}
/**
* @see org.lwjgl.input.Keyboard#enableRepeatEvents()
* @return true if the current event is a repeat event, false if
* the current event is not a repeat even or if repeat events are disabled.
*/
public static synchronized boolean isRepeatEvent() {
synchronized (OpenGLPackageAccess.global_lock) {
return current_event.repeat;
}
}
private final static class KeyEvent {
/** The current keyboard character being examined */
private int character;
/** The current keyboard event key being examined */
private int key;
/** The current state of the key being examined in the event queue */
private boolean state;
/** The current event time */
private long nanos;
/** Is the current event a repeated event? */
private boolean repeat;
private void reset() {
character = 0;
key = 0;
state = false;
repeat = false;
}
}
}

View file

@ -264,9 +264,9 @@ final class KeyboardEventQueue extends EventQueue implements KeyListener {
//component.removeKeyListener(this);
}
private void putKeyboardEvent(int key_code, byte state, int character, long nanos) {
private void putKeyboardEvent(int key_code, byte state, int character, long nanos, boolean repeat) {
event.clear();
event.putInt(key_code).put(state).putInt(character).putLong(nanos);
event.putInt(key_code).put(state).putInt(character).putLong(nanos).put(repeat ? (byte)1 : (byte)0);
event.flip();
putEvent(event);
}
@ -287,15 +287,16 @@ final class KeyboardEventQueue extends EventQueue implements KeyListener {
if (character == KeyEvent.CHAR_UNDEFINED)
character = Keyboard.CHAR_NONE;
if (state == 1) {
boolean repeat = false;
if (has_deferred_event) {
if ((nanos == deferred_nanos && deferred_key_code == key_code &&
deferred_key_location == key_location)) {
has_deferred_event = false;
return; // Ignore repeated key down, key up event pair
}
flushDeferredEvent();
repeat = true; // Repeat event
} else
flushDeferredEvent();
}
putKeyEvent(key_code, key_location, state, character, nanos);
putKeyEvent(key_code, key_location, state, character, nanos, repeat);
} else {
flushDeferredEvent();
has_deferred_event = true;
@ -309,19 +310,19 @@ final class KeyboardEventQueue extends EventQueue implements KeyListener {
private void flushDeferredEvent() {
if (has_deferred_event) {
putKeyEvent(deferred_key_code, deferred_key_location, deferred_key_state, deferred_character, deferred_nanos);
putKeyEvent(deferred_key_code, deferred_key_location, deferred_key_state, deferred_character, deferred_nanos, false);
has_deferred_event = false;
}
}
private void putKeyEvent(int key_code, int key_location, byte state, int character, long nanos) {
private void putKeyEvent(int key_code, int key_location, byte state, int character, long nanos, boolean repeat) {
int key_code_mapped = getMappedKeyCode(key_code, key_location);
/* Ignore repeating presses */
if ( key_states[key_code_mapped] == state )
return;
repeat = true;
key_states[key_code_mapped] = state;
int key_int_char = character & 0xffff;
putKeyboardEvent(key_code_mapped, state, key_int_char, nanos);
putKeyboardEvent(key_code_mapped, state, key_int_char, nanos, repeat);
}
private int getMappedKeyCode(int key_code, int position) {

View file

@ -75,7 +75,7 @@ final class LinuxKeyboard {
private final CharBuffer char_buffer = CharBuffer.allocate(KEYBOARD_BUFFER_SIZE);
// Deferred key released event, to detect key repeat
private boolean has_deferred_event = true;
private boolean has_deferred_event;
private int deferred_keycode;
private int deferred_event_keycode;
private long deferred_nanos;
@ -169,9 +169,9 @@ final class LinuxKeyboard {
keyDownBuffer.position(old_position);
}
private void putKeyboardEvent(int keycode, byte state, int ch, long nanos) {
private void putKeyboardEvent(int keycode, byte state, int ch, long nanos, boolean repeat) {
tmp_event.clear();
tmp_event.putInt(keycode).put(state).putInt(ch).putLong(nanos);
tmp_event.putInt(keycode).put(state).putInt(ch).putLong(nanos).put(repeat ? (byte)1 : (byte)0);
tmp_event.flip();
event_queue.putEvent(tmp_event);
}
@ -211,20 +211,20 @@ final class LinuxKeyboard {
return lookupStringISO88591(event_ptr, translation_buffer);
}
private void translateEvent(long event_ptr, int keycode, byte key_state, long nanos) {
private void translateEvent(long event_ptr, int keycode, byte key_state, long nanos, boolean repeat) {
int num_chars, i;
int ch;
num_chars = lookupString(event_ptr, temp_translation_buffer);
if (num_chars > 0) {
ch = temp_translation_buffer[0];
putKeyboardEvent(keycode, key_state, ch, nanos);
putKeyboardEvent(keycode, key_state, ch, nanos, repeat);
for (i = 1; i < num_chars; i++) {
ch = temp_translation_buffer[i];
putKeyboardEvent(0, (byte)0, ch, nanos);
putKeyboardEvent(0, (byte)0, ch, nanos, repeat);
}
} else {
putKeyboardEvent(keycode, key_state, 0, nanos);
putKeyboardEvent(keycode, key_state, 0, nanos, repeat);
}
}
@ -305,14 +305,15 @@ final class LinuxKeyboard {
key_down_buffer[keycode] = key_state;
long nanos = millis*1000000;
if (event_type == LinuxEvent.KeyPress) {
boolean repeat = false;
if (has_deferred_event) {
if (nanos == deferred_nanos && event_keycode == deferred_event_keycode) {
has_deferred_event = false;
return; // Repeated event, ignore it
}
flushDeferredEvent();
repeat = true; // Repeated event
} else
flushDeferredEvent();
}
translateEvent(event_ptr, keycode, key_state, nanos);
translateEvent(event_ptr, keycode, key_state, nanos, repeat);
} else {
flushDeferredEvent();
has_deferred_event = true;
@ -325,7 +326,7 @@ final class LinuxKeyboard {
private void flushDeferredEvent() {
if (has_deferred_event) {
putKeyboardEvent(deferred_keycode, deferred_key_state, 0, deferred_nanos);
putKeyboardEvent(deferred_keycode, deferred_key_state, 0, deferred_nanos, false);
has_deferred_event = false;
}
}

View file

@ -608,12 +608,11 @@ final class WindowsDisplay implements DisplayImplementation {
private void handleKeyButton(long wParam, long lParam, long millis) {
byte previous_state = (byte)((lParam >>> 30) & 0x1);
byte state = (byte)(1 - ((lParam >>> 31) & 0x1));
if (state == previous_state)
return; // Auto-repeat message
boolean repeat = state == previous_state; // Repeat message
byte extended = (byte)((lParam >>> 24) & 0x1);
int scan_code = (int)((lParam >>> 16) & 0xFF);
if (keyboard != null)
keyboard.handleKey((int)wParam, scan_code, extended != 0, state, millis);
keyboard.handleKey((int)wParam, scan_code, extended != 0, state, millis, repeat);
}
private static int transformY(long hwnd, int y) {

View file

@ -63,6 +63,7 @@ final class WindowsKeyboard {
private byte retained_state;
private int retained_char;
private long retained_millis;
private boolean retained_repeat;
public WindowsKeyboard(long hwnd) throws LWJGLException {
this.hwnd = hwnd;
@ -97,9 +98,9 @@ final class WindowsKeyboard {
private static native int GetKeyboardState(ByteBuffer lpKeyState);
private static native int GetKeyState(int virt_key);
private void putEvent(int keycode, byte state, int ch, long millis) {
private void putEvent(int keycode, byte state, int ch, long millis, boolean repeat) {
tmp_event.clear();
tmp_event.putInt(keycode).put(state).putInt(ch).putLong(millis*1000000);
tmp_event.putInt(keycode).put(state).putInt(ch).putLong(millis*1000000).put(repeat ? (byte)1 : (byte)0);
tmp_event.flip();
event_queue.putEvent(tmp_event);
}
@ -144,11 +145,11 @@ final class WindowsKeyboard {
private void flushRetained() {
if (has_retained_event) {
has_retained_event = false;
putEvent(retained_key_code, retained_state, retained_char, retained_millis);
putEvent(retained_key_code, retained_state, retained_char, retained_millis, retained_repeat);
}
}
public void handleKey(int virt_key, int scan_code, boolean extended, byte event_state, long millis) {
public void handleKey(int virt_key, int scan_code, boolean extended, byte event_state, long millis, boolean repeat) {
virt_key = translateExtended(virt_key, scan_code, event_state, extended);
flushRetained();
has_retained_event = true;
@ -159,12 +160,13 @@ final class WindowsKeyboard {
retained_state = event_state;
retained_millis = millis;
retained_char = 0;
retained_repeat = repeat;
// translate(virt_key, event_state, millis*1000000);
}
public void handleChar(int event_char, long millis) {
if (!has_retained_event) {
putEvent(0, (byte)0, event_char, millis);
putEvent(0, (byte)0, event_char, millis, false);
} else
retained_char = event_char;
}

View file

@ -152,7 +152,11 @@ public class KeyboardTest {
System.out.println("Pressed:" + Keyboard.getEventKeyState());
System.out.println("Key character code: " + character_code);
System.out.println("Key character: " + Keyboard.getEventCharacter());
System.out.println("Repeat event: " + Keyboard.isRepeatEvent());
if (Keyboard.getEventKey() == Keyboard.KEY_R && Keyboard.getEventKeyState()) {
Keyboard.enableRepeatEvents(!Keyboard.areRepeatEventsEnabled());
}
if (Keyboard.getEventKey() == Keyboard.KEY_ESCAPE) {
return;
}