297 lines
13 KiB
Java
297 lines
13 KiB
Java
/*
|
|
* Copyright (c) 2002-2008 LWJGL Project
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are
|
|
* met:
|
|
*
|
|
* * Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
*
|
|
* * 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.
|
|
*
|
|
* * Neither the name of 'LWJGL' nor the names of
|
|
* its contributors may be used to endorse or promote products derived
|
|
* from this software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
* "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 THE COPYRIGHT OWNER 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.
|
|
*/
|
|
package org.lwjgl.opengl;
|
|
|
|
/**
|
|
* A native implementation of a LWJGL compatible Keyboard event queue.
|
|
* @author elias_naur
|
|
* @author mojang
|
|
*/
|
|
|
|
import java.awt.event.KeyEvent;
|
|
import java.util.HashMap;
|
|
import java.nio.ByteBuffer;
|
|
|
|
import org.lwjgl.input.Keyboard;
|
|
|
|
final class MacOSXNativeKeyboard extends EventQueue {
|
|
private final byte[] key_states = new byte[Keyboard.KEYBOARD_SIZE];
|
|
|
|
/** Event scratch array */
|
|
private final ByteBuffer event = ByteBuffer.allocate(Keyboard.EVENT_SIZE);
|
|
|
|
private ByteBuffer window_handle;
|
|
|
|
private boolean has_deferred_event;
|
|
private long deferred_nanos;
|
|
private int deferred_key_code;
|
|
private byte deferred_key_state;
|
|
private int deferred_character;
|
|
|
|
private HashMap<Short, Integer> nativeToLwjglMap;
|
|
|
|
MacOSXNativeKeyboard(ByteBuffer window_handle) {
|
|
super(Keyboard.EVENT_SIZE);
|
|
nativeToLwjglMap = new HashMap<Short, Integer>();
|
|
initKeyboardMappings();
|
|
this.window_handle = window_handle;
|
|
}
|
|
|
|
private native void nRegisterKeyListener(ByteBuffer window_handle);
|
|
|
|
private native void nUnregisterKeyListener(ByteBuffer window_handle);
|
|
|
|
// These are from: <HIToolbox/Events.h>
|
|
private void initKeyboardMappings() {
|
|
nativeToLwjglMap.put((short)0x1D, Keyboard.KEY_0);
|
|
nativeToLwjglMap.put((short)0x12, Keyboard.KEY_1);
|
|
nativeToLwjglMap.put((short)0x13, Keyboard.KEY_2);
|
|
nativeToLwjglMap.put((short)0x14, Keyboard.KEY_3);
|
|
nativeToLwjglMap.put((short)0x15, Keyboard.KEY_4);
|
|
nativeToLwjglMap.put((short)0x17, Keyboard.KEY_5);
|
|
nativeToLwjglMap.put((short)0x16, Keyboard.KEY_6);
|
|
nativeToLwjglMap.put((short)0x1A, Keyboard.KEY_7);
|
|
nativeToLwjglMap.put((short)0x1C, Keyboard.KEY_8);
|
|
nativeToLwjglMap.put((short)0x19, Keyboard.KEY_9);
|
|
nativeToLwjglMap.put((short)0x00, Keyboard.KEY_A);
|
|
nativeToLwjglMap.put((short)0x0B, Keyboard.KEY_B);
|
|
nativeToLwjglMap.put((short)0x08, Keyboard.KEY_C);
|
|
nativeToLwjglMap.put((short)0x02, Keyboard.KEY_D);
|
|
nativeToLwjglMap.put((short)0x0E, Keyboard.KEY_E);
|
|
nativeToLwjglMap.put((short)0x03, Keyboard.KEY_F);
|
|
nativeToLwjglMap.put((short)0x05, Keyboard.KEY_G);
|
|
nativeToLwjglMap.put((short)0x04, Keyboard.KEY_H);
|
|
nativeToLwjglMap.put((short)0x22, Keyboard.KEY_I);
|
|
nativeToLwjglMap.put((short)0x26, Keyboard.KEY_J);
|
|
nativeToLwjglMap.put((short)0x28, Keyboard.KEY_K);
|
|
nativeToLwjglMap.put((short)0x25, Keyboard.KEY_L);
|
|
nativeToLwjglMap.put((short)0x2E, Keyboard.KEY_M);
|
|
nativeToLwjglMap.put((short)0x2D, Keyboard.KEY_N);
|
|
nativeToLwjglMap.put((short)0x1F, Keyboard.KEY_O);
|
|
nativeToLwjglMap.put((short)0x23, Keyboard.KEY_P);
|
|
nativeToLwjglMap.put((short)0x0C, Keyboard.KEY_Q);
|
|
nativeToLwjglMap.put((short)0x0F, Keyboard.KEY_R);
|
|
nativeToLwjglMap.put((short)0x01, Keyboard.KEY_S);
|
|
nativeToLwjglMap.put((short)0x11, Keyboard.KEY_T);
|
|
nativeToLwjglMap.put((short)0x20, Keyboard.KEY_U);
|
|
nativeToLwjglMap.put((short)0x09, Keyboard.KEY_V);
|
|
nativeToLwjglMap.put((short)0x0D, Keyboard.KEY_W);
|
|
nativeToLwjglMap.put((short)0x07, Keyboard.KEY_X);
|
|
nativeToLwjglMap.put((short)0x10, Keyboard.KEY_Y);
|
|
nativeToLwjglMap.put((short)0x06, Keyboard.KEY_Z);
|
|
|
|
nativeToLwjglMap.put((short)0x2A, Keyboard.KEY_BACKSLASH);
|
|
nativeToLwjglMap.put((short)0x2B, Keyboard.KEY_COMMA);
|
|
nativeToLwjglMap.put((short)0x18, Keyboard.KEY_EQUALS);
|
|
nativeToLwjglMap.put((short)0x21, Keyboard.KEY_LBRACKET);
|
|
nativeToLwjglMap.put((short)0x1B, Keyboard.KEY_MINUS);
|
|
nativeToLwjglMap.put((short)0x27, Keyboard.KEY_APOSTROPHE);
|
|
nativeToLwjglMap.put((short)0x1E, Keyboard.KEY_RBRACKET);
|
|
nativeToLwjglMap.put((short)0x29, Keyboard.KEY_SEMICOLON);
|
|
nativeToLwjglMap.put((short)0x2C, Keyboard.KEY_SLASH);
|
|
nativeToLwjglMap.put((short)0x2F, Keyboard.KEY_PERIOD);
|
|
nativeToLwjglMap.put((short)0x32, Keyboard.KEY_GRAVE);
|
|
|
|
nativeToLwjglMap.put((short)0x41, Keyboard.KEY_DECIMAL);
|
|
nativeToLwjglMap.put((short)0x43, Keyboard.KEY_MULTIPLY);
|
|
nativeToLwjglMap.put((short)0x45, Keyboard.KEY_ADD);
|
|
nativeToLwjglMap.put((short)0x47, Keyboard.KEY_CLEAR);
|
|
nativeToLwjglMap.put((short)0x4B, Keyboard.KEY_DIVIDE);
|
|
nativeToLwjglMap.put((short)0x4C, Keyboard.KEY_NUMPADENTER);
|
|
nativeToLwjglMap.put((short)0x4E, Keyboard.KEY_SUBTRACT);
|
|
nativeToLwjglMap.put((short)0x51, Keyboard.KEY_NUMPADEQUALS);
|
|
|
|
nativeToLwjglMap.put((short)0x52, Keyboard.KEY_NUMPAD0);
|
|
nativeToLwjglMap.put((short)0x53, Keyboard.KEY_NUMPAD1);
|
|
nativeToLwjglMap.put((short)0x54, Keyboard.KEY_NUMPAD2);
|
|
nativeToLwjglMap.put((short)0x55, Keyboard.KEY_NUMPAD3);
|
|
nativeToLwjglMap.put((short)0x56, Keyboard.KEY_NUMPAD4);
|
|
nativeToLwjglMap.put((short)0x57, Keyboard.KEY_NUMPAD5);
|
|
nativeToLwjglMap.put((short)0x58, Keyboard.KEY_NUMPAD6);
|
|
nativeToLwjglMap.put((short)0x59, Keyboard.KEY_NUMPAD7);
|
|
nativeToLwjglMap.put((short)0x5B, Keyboard.KEY_NUMPAD8);
|
|
nativeToLwjglMap.put((short)0x5C, Keyboard.KEY_NUMPAD9);
|
|
|
|
|
|
nativeToLwjglMap.put((short)0x24, Keyboard.KEY_RETURN);
|
|
nativeToLwjglMap.put((short)0x30, Keyboard.KEY_TAB);
|
|
nativeToLwjglMap.put((short)0x31, Keyboard.KEY_SPACE);
|
|
nativeToLwjglMap.put((short)0x33, Keyboard.KEY_BACK);
|
|
nativeToLwjglMap.put((short)0x35, Keyboard.KEY_ESCAPE);
|
|
nativeToLwjglMap.put((short)0x36, Keyboard.KEY_RMETA); // not in Events.h - works on MBP
|
|
nativeToLwjglMap.put((short)0x37, Keyboard.KEY_LMETA);
|
|
nativeToLwjglMap.put((short)0x38, Keyboard.KEY_LSHIFT);
|
|
nativeToLwjglMap.put((short)0x39, Keyboard.KEY_CAPITAL);
|
|
nativeToLwjglMap.put((short)0x3A, Keyboard.KEY_LMENU);
|
|
nativeToLwjglMap.put((short)0x3B, Keyboard.KEY_LCONTROL);
|
|
nativeToLwjglMap.put((short)0x3C, Keyboard.KEY_RSHIFT);
|
|
nativeToLwjglMap.put((short)0x3D, Keyboard.KEY_RMENU);
|
|
nativeToLwjglMap.put((short)0x3E, Keyboard.KEY_RCONTROL);
|
|
|
|
nativeToLwjglMap.put((short)0x3F, Keyboard.KEY_FUNCTION);
|
|
nativeToLwjglMap.put((short)0x77, Keyboard.KEY_END);
|
|
|
|
nativeToLwjglMap.put((short)0x7A, Keyboard.KEY_F1);
|
|
nativeToLwjglMap.put((short)0x78, Keyboard.KEY_F2);
|
|
nativeToLwjglMap.put((short)0x63, Keyboard.KEY_F3);
|
|
nativeToLwjglMap.put((short)0x76, Keyboard.KEY_F4);
|
|
nativeToLwjglMap.put((short)0x60, Keyboard.KEY_F5);
|
|
nativeToLwjglMap.put((short)0x61, Keyboard.KEY_F6);
|
|
nativeToLwjglMap.put((short)0x62, Keyboard.KEY_F7);
|
|
nativeToLwjglMap.put((short)0x64, Keyboard.KEY_F8);
|
|
nativeToLwjglMap.put((short)0x65, Keyboard.KEY_F9);
|
|
nativeToLwjglMap.put((short)0x6D, Keyboard.KEY_F10);
|
|
nativeToLwjglMap.put((short)0x67, Keyboard.KEY_F11);
|
|
nativeToLwjglMap.put((short)0x6F, Keyboard.KEY_F12);
|
|
nativeToLwjglMap.put((short)0x69, Keyboard.KEY_F13);
|
|
nativeToLwjglMap.put((short)0x6B, Keyboard.KEY_F14);
|
|
nativeToLwjglMap.put((short)0x71, Keyboard.KEY_F15);
|
|
nativeToLwjglMap.put((short)0x6A, Keyboard.KEY_F16);
|
|
nativeToLwjglMap.put((short)0x40, Keyboard.KEY_F17);
|
|
nativeToLwjglMap.put((short)0x4F, Keyboard.KEY_F18);
|
|
nativeToLwjglMap.put((short)0x50, Keyboard.KEY_F19);
|
|
// nativeToLwjglMap.put((short)0x5A, Keyboard.KEY_F20);
|
|
|
|
nativeToLwjglMap.put((short)0x75, Keyboard.KEY_DELETE);
|
|
nativeToLwjglMap.put((short)0x72, Keyboard.KEY_INSERT); // 'Help' in Events.h
|
|
nativeToLwjglMap.put((short)0x73, Keyboard.KEY_HOME);
|
|
// nativeToLwjglMap.put((short)0xA4, Keyboard.KEY_MUTE);
|
|
nativeToLwjglMap.put((short)0x79, Keyboard.KEY_NEXT);
|
|
nativeToLwjglMap.put((short)0x74, Keyboard.KEY_PRIOR);
|
|
// nativeToLwjglMap.put((short)0x49, Keyboard.KEY_VOLUMEDOWN);
|
|
// nativeToLwjglMap.put((short)0x48, Keyboard.KEY_VOLUMEUP);
|
|
nativeToLwjglMap.put((short)0x7B, Keyboard.KEY_LEFT);
|
|
nativeToLwjglMap.put((short)0x7C, Keyboard.KEY_RIGHT);
|
|
nativeToLwjglMap.put((short)0x7D, Keyboard.KEY_DOWN);
|
|
nativeToLwjglMap.put((short)0x7E, Keyboard.KEY_UP);
|
|
|
|
nativeToLwjglMap.put((short)0x0A, Keyboard.KEY_SECTION);
|
|
|
|
nativeToLwjglMap.put((short)0x6E, Keyboard.KEY_APPS); // not in Events.h
|
|
nativeToLwjglMap.put((short)0x129, Keyboard.KEY_COLON); // not in Events.h -- do we need it?
|
|
}
|
|
|
|
public void register() {
|
|
nRegisterKeyListener(window_handle);
|
|
}
|
|
|
|
public void unregister() {
|
|
nUnregisterKeyListener(window_handle);
|
|
}
|
|
|
|
public 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).put(repeat ? (byte)1 : (byte)0);
|
|
event.flip();
|
|
putEvent(event);
|
|
}
|
|
|
|
public synchronized void poll(ByteBuffer key_down_buffer) {
|
|
flushDeferredEvent();
|
|
int old_position = key_down_buffer.position();
|
|
key_down_buffer.put(key_states);
|
|
key_down_buffer.position(old_position);
|
|
}
|
|
|
|
public synchronized void copyEvents(ByteBuffer dest) {
|
|
flushDeferredEvent();
|
|
super.copyEvents(dest);
|
|
}
|
|
|
|
private synchronized void handleKey(int key_code, byte state, int character, long nanos) {
|
|
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)) {
|
|
has_deferred_event = false;
|
|
repeat = true; // Repeat event
|
|
} else
|
|
flushDeferredEvent();
|
|
}
|
|
putKeyEvent(key_code, state, character, nanos, repeat);
|
|
} else {
|
|
flushDeferredEvent();
|
|
has_deferred_event = true;
|
|
deferred_nanos = nanos;
|
|
deferred_key_code = key_code;
|
|
deferred_key_state = state;
|
|
deferred_character = character;
|
|
}
|
|
}
|
|
|
|
private void flushDeferredEvent() {
|
|
if (has_deferred_event) {
|
|
putKeyEvent(deferred_key_code, deferred_key_state, deferred_character, deferred_nanos, false);
|
|
has_deferred_event = false;
|
|
}
|
|
}
|
|
|
|
public void putKeyEvent(int key_code, byte state, int character, long nanos, boolean repeat) {
|
|
/* Ignore repeating presses */
|
|
int mapped_code = getMappedKeyCode((short)key_code);
|
|
if (mapped_code < 0) {
|
|
System.out.println("Unrecognized keycode: " + key_code);
|
|
/* Unrecognized / unmapped code, do nothing */
|
|
return;
|
|
}
|
|
if ( key_states[mapped_code] == state )
|
|
repeat = true;
|
|
key_states[mapped_code] = state;
|
|
int key_int_char = character & 0xffff;
|
|
putKeyboardEvent(mapped_code, state, key_int_char, nanos, repeat);
|
|
}
|
|
|
|
private int getMappedKeyCode(short key_code) {
|
|
if (nativeToLwjglMap.containsKey(key_code)) {
|
|
return nativeToLwjglMap.get(key_code);
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
public void keyPressed(int key_code, String chars, long nanos) {
|
|
// use only first character of chars returned for key press
|
|
int character = (chars == null || chars.length() == 0) ? 0 : (int)chars.charAt(0);
|
|
handleKey(key_code, (byte)1, character, nanos);
|
|
}
|
|
|
|
public void keyReleased(int key_code, String chars, long nanos) {
|
|
// use only first character of chars returned for key release
|
|
int character = (chars == null || chars.length() == 0) ? 0 : (int)chars.charAt(0);
|
|
handleKey(key_code, (byte)0, character, nanos);
|
|
}
|
|
|
|
public void keyTyped(KeyEvent e) {
|
|
}
|
|
}
|