1 /* 2 * Copyright (c) 2002-2008 LWJGL Project 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: 8 * 9 * * Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * * Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * * Neither the name of 'LWJGL' nor the names of 17 * its contributors may be used to endorse or promote products derived 18 * from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 package org.lwjgl.input; 33 34 import java.lang.reflect.Field; 35 import java.lang.reflect.Modifier; 36 import java.nio.ByteBuffer; 37 import java.util.HashMap; 38 import java.util.Map; 39 40 import org.lwjgl.BufferUtils; 41 import org.lwjgl.LWJGLException; 42 import org.lwjgl.Sys; 43 import org.lwjgl.opengl.Display; 44 import org.lwjgl.opengl.InputImplementation; 45 46 /** 47 * <br> 48 * A raw Keyboard interface. This can be used to poll the current state of the 49 * keys, or read all the keyboard presses / releases since the last read. 50 * 51 * @author cix_foo <cix_foo@users.sourceforge.net> 52 * @author elias_naur <elias_naur@users.sourceforge.net> 53 * @author Brian Matzon <brian@matzon.dk> 54 * @version $Revision$ 55 * $Id$ 56 */ 57 public class Keyboard { 58 /** Internal use - event size in bytes */ 59 public static final int EVENT_SIZE = 4 + 1 + 4 + 8 + 1; 60 61 /** 62 * The special character meaning that no 63 * character was translated for the event. 64 */ 65 public static final int CHAR_NONE = '\0'; 66 67 /** 68 * The special keycode meaning that only the 69 * translated character is valid. 70 */ 71 public static final int KEY_NONE = 0x00; 72 73 public static final int KEY_ESCAPE = 0x01; 74 public static final int KEY_1 = 0x02; 75 public static final int KEY_2 = 0x03; 76 public static final int KEY_3 = 0x04; 77 public static final int KEY_4 = 0x05; 78 public static final int KEY_5 = 0x06; 79 public static final int KEY_6 = 0x07; 80 public static final int KEY_7 = 0x08; 81 public static final int KEY_8 = 0x09; 82 public static final int KEY_9 = 0x0A; 83 public static final int KEY_0 = 0x0B; 84 public static final int KEY_MINUS = 0x0C; /* - on main keyboard */ 85 public static final int KEY_EQUALS = 0x0D; 86 public static final int KEY_BACK = 0x0E; /* backspace */ 87 public static final int KEY_TAB = 0x0F; 88 public static final int KEY_Q = 0x10; 89 public static final int KEY_W = 0x11; 90 public static final int KEY_E = 0x12; 91 public static final int KEY_R = 0x13; 92 public static final int KEY_T = 0x14; 93 public static final int KEY_Y = 0x15; 94 public static final int KEY_U = 0x16; 95 public static final int KEY_I = 0x17; 96 public static final int KEY_O = 0x18; 97 public static final int KEY_P = 0x19; 98 public static final int KEY_LBRACKET = 0x1A; 99 public static final int KEY_RBRACKET = 0x1B; 100 public static final int KEY_RETURN = 0x1C; /* Enter on main keyboard */ 101 public static final int KEY_LCONTROL = 0x1D; 102 public static final int KEY_A = 0x1E; 103 public static final int KEY_S = 0x1F; 104 public static final int KEY_D = 0x20; 105 public static final int KEY_F = 0x21; 106 public static final int KEY_G = 0x22; 107 public static final int KEY_H = 0x23; 108 public static final int KEY_J = 0x24; 109 public static final int KEY_K = 0x25; 110 public static final int KEY_L = 0x26; 111 public static final int KEY_SEMICOLON = 0x27; 112 public static final int KEY_APOSTROPHE = 0x28; 113 public static final int KEY_GRAVE = 0x29; /* accent grave */ 114 public static final int KEY_LSHIFT = 0x2A; 115 public static final int KEY_BACKSLASH = 0x2B; 116 public static final int KEY_Z = 0x2C; 117 public static final int KEY_X = 0x2D; 118 public static final int KEY_C = 0x2E; 119 public static final int KEY_V = 0x2F; 120 public static final int KEY_B = 0x30; 121 public static final int KEY_N = 0x31; 122 public static final int KEY_M = 0x32; 123 public static final int KEY_COMMA = 0x33; 124 public static final int KEY_PERIOD = 0x34; /* . on main keyboard */ 125 public static final int KEY_SLASH = 0x35; /* / on main keyboard */ 126 public static final int KEY_RSHIFT = 0x36; 127 public static final int KEY_MULTIPLY = 0x37; /* * on numeric keypad */ 128 public static final int KEY_LMENU = 0x38; /* left Alt */ 129 public static final int KEY_SPACE = 0x39; 130 public static final int KEY_CAPITAL = 0x3A; 131 public static final int KEY_F1 = 0x3B; 132 public static final int KEY_F2 = 0x3C; 133 public static final int KEY_F3 = 0x3D; 134 public static final int KEY_F4 = 0x3E; 135 public static final int KEY_F5 = 0x3F; 136 public static final int KEY_F6 = 0x40; 137 public static final int KEY_F7 = 0x41; 138 public static final int KEY_F8 = 0x42; 139 public static final int KEY_F9 = 0x43; 140 public static final int KEY_F10 = 0x44; 141 public static final int KEY_NUMLOCK = 0x45; 142 public static final int KEY_SCROLL = 0x46; /* Scroll Lock */ 143 public static final int KEY_NUMPAD7 = 0x47; 144 public static final int KEY_NUMPAD8 = 0x48; 145 public static final int KEY_NUMPAD9 = 0x49; 146 public static final int KEY_SUBTRACT = 0x4A; /* - on numeric keypad */ 147 public static final int KEY_NUMPAD4 = 0x4B; 148 public static final int KEY_NUMPAD5 = 0x4C; 149 public static final int KEY_NUMPAD6 = 0x4D; 150 public static final int KEY_ADD = 0x4E; /* + on numeric keypad */ 151 public static final int KEY_NUMPAD1 = 0x4F; 152 public static final int KEY_NUMPAD2 = 0x50; 153 public static final int KEY_NUMPAD3 = 0x51; 154 public static final int KEY_NUMPAD0 = 0x52; 155 public static final int KEY_DECIMAL = 0x53; /* . on numeric keypad */ 156 public static final int KEY_F11 = 0x57; 157 public static final int KEY_F12 = 0x58; 158 public static final int KEY_F13 = 0x64; /* (NEC PC98) */ 159 public static final int KEY_F14 = 0x65; /* (NEC PC98) */ 160 public static final int KEY_F15 = 0x66; /* (NEC PC98) */ 161 public static final int KEY_F16 = 0x67; /* Extended Function keys - (Mac) */ 162 public static final int KEY_F17 = 0x68; 163 public static final int KEY_F18 = 0x69; 164 public static final int KEY_KANA = 0x70; /* (Japanese keyboard) */ 165 public static final int KEY_F19 = 0x71; /* Extended Function keys - (Mac) */ 166 public static final int KEY_CONVERT = 0x79; /* (Japanese keyboard) */ 167 public static final int KEY_NOCONVERT = 0x7B; /* (Japanese keyboard) */ 168 public static final int KEY_YEN = 0x7D; /* (Japanese keyboard) */ 169 public static final int KEY_NUMPADEQUALS = 0x8D; /* = on numeric keypad (NEC PC98) */ 170 public static final int KEY_CIRCUMFLEX = 0x90; /* (Japanese keyboard) */ 171 public static final int KEY_AT = 0x91; /* (NEC PC98) */ 172 public static final int KEY_COLON = 0x92; /* (NEC PC98) */ 173 public static final int KEY_UNDERLINE = 0x93; /* (NEC PC98) */ 174 public static final int KEY_KANJI = 0x94; /* (Japanese keyboard) */ 175 public static final int KEY_STOP = 0x95; /* (NEC PC98) */ 176 public static final int KEY_AX = 0x96; /* (Japan AX) */ 177 public static final int KEY_UNLABELED = 0x97; /* (J3100) */ 178 public static final int KEY_NUMPADENTER = 0x9C; /* Enter on numeric keypad */ 179 public static final int KEY_RCONTROL = 0x9D; 180 public static final int KEY_SECTION = 0xA7; /* Section symbol (Mac) */ 181 public static final int KEY_NUMPADCOMMA = 0xB3; /* , on numeric keypad (NEC PC98) */ 182 public static final int KEY_DIVIDE = 0xB5; /* / on numeric keypad */ 183 public static final int KEY_SYSRQ = 0xB7; 184 public static final int KEY_RMENU = 0xB8; /* right Alt */ 185 public static final int KEY_FUNCTION = 0xC4; /* Function (Mac) */ 186 public static final int KEY_PAUSE = 0xC5; /* Pause */ 187 public static final int KEY_HOME = 0xC7; /* Home on arrow keypad */ 188 public static final int KEY_UP = 0xC8; /* UpArrow on arrow keypad */ 189 public static final int KEY_PRIOR = 0xC9; /* PgUp on arrow keypad */ 190 public static final int KEY_LEFT = 0xCB; /* LeftArrow on arrow keypad */ 191 public static final int KEY_RIGHT = 0xCD; /* RightArrow on arrow keypad */ 192 public static final int KEY_END = 0xCF; /* End on arrow keypad */ 193 public static final int KEY_DOWN = 0xD0; /* DownArrow on arrow keypad */ 194 public static final int KEY_NEXT = 0xD1; /* PgDn on arrow keypad */ 195 public static final int KEY_INSERT = 0xD2; /* Insert on arrow keypad */ 196 public static final int KEY_DELETE = 0xD3; /* Delete on arrow keypad */ 197 public static final int KEY_CLEAR = 0xDA; /* Clear key (Mac) */ 198 public static final int KEY_LMETA = 0xDB; /* Left Windows/Option key */ 199 /** 200 * The left windows key, mapped to KEY_LMETA 201 * 202 * @deprecated Use KEY_LMETA instead 203 */ 204 public static final int KEY_LWIN = KEY_LMETA; /* Left Windows key */ 205 public static final int KEY_RMETA = 0xDC; /* Right Windows/Option key */ 206 /** 207 * The right windows key, mapped to KEY_RMETA 208 * 209 * @deprecated Use KEY_RMETA instead 210 */ 211 public static final int KEY_RWIN = KEY_RMETA; /* Right Windows key */ 212 public static final int KEY_APPS = 0xDD; /* AppMenu key */ 213 public static final int KEY_POWER = 0xDE; 214 public static final int KEY_SLEEP = 0xDF; 215 216 /* public static final int STATE_ON = 0; 217 public static final int STATE_OFF = 1; 218 public static final int STATE_UNKNOWN = 2; 219 */ 220 public static final int KEYBOARD_SIZE = 256; 221 222 /** Buffer size in events */ 223 private static final int BUFFER_SIZE = 50; 224 225 /** Key names */ 226 private static final String[] keyName = new String[KEYBOARD_SIZE]; 227 private static final Map<String, Integer> keyMap = new HashMap<String, Integer>(253); 228 private static int counter; 229 230 static { 231 // Use reflection to find out key names 232 Field[] fields = Keyboard.class.getFields(); 233 try { 234 for ( Field field : fields ) { 235 if ( Modifier.isStatic(field.getModifiers()) 236 && Modifier.isPublic(field.getModifiers()) 237 && Modifier.isFinal(field.getModifiers()) 238 && field.getType().equals(int.class) 239 && field.getName().startsWith("KEY_") 240 && !field.getName().endsWith("WIN") ) { /* Don't use deprecated names */ 241 242 int key = field.getInt(null); 243 String name = field.getName().substring(4); 244 keyName[key] = name; keyMap.put(name, key)245 keyMap.put(name, key); 246 counter++; 247 } 248 249 } 250 } catch (Exception e) { 251 } 252 253 } 254 255 /** The number of keys supported */ 256 private static final int keyCount = counter; 257 258 /** Has the keyboard been created? */ 259 private static boolean created; 260 261 /** Are repeat events enabled? */ 262 private static boolean repeat_enabled; 263 264 /** The keys status from the last poll */ 265 private static final ByteBuffer keyDownBuffer = BufferUtils.createByteBuffer(KEYBOARD_SIZE); 266 267 /** 268 * The key events from the last read: a sequence of pairs of key number, 269 * followed by state. The state is followed by 270 * a 4 byte code point representing the translated character. 271 */ 272 private static ByteBuffer readBuffer; 273 274 /** current event */ 275 private static KeyEvent current_event = new KeyEvent(); 276 277 /** scratch event */ 278 private static KeyEvent tmp_event = new KeyEvent(); 279 280 /** One time initialization */ 281 private static boolean initialized; 282 283 private static InputImplementation implementation; 284 285 /** 286 * Keyboard cannot be constructed. 287 */ Keyboard()288 private Keyboard() { 289 } 290 291 /** 292 * Static initialization 293 */ initialize()294 private static void initialize() { 295 if (initialized) 296 return; 297 Sys.initialize(); 298 initialized = true; 299 } 300 301 /** 302 * "Create" the keyboard with the given implementation. This is used 303 * reflectively from AWTInputAdapter. 304 * 305 * @throws LWJGLException if the keyboard could not be created for any reason 306 */ create(InputImplementation impl)307 private static void create(InputImplementation impl) throws LWJGLException { 308 if (created) 309 return; 310 if (!initialized) 311 initialize(); 312 implementation = impl; 313 implementation.createKeyboard(); 314 created = true; 315 readBuffer = ByteBuffer.allocate(EVENT_SIZE*BUFFER_SIZE); 316 reset(); 317 } 318 319 /** 320 * "Create" the keyboard. The display must first have been created. The 321 * reason for this is so the keyboard has a window to "focus" in. 322 * 323 * @throws LWJGLException if the keyboard could not be created for any reason 324 */ create()325 public static void create() throws LWJGLException { 326 synchronized (OpenGLPackageAccess.global_lock) { 327 if (!Display.isCreated()) throw new IllegalStateException("Display must be created."); 328 329 create(OpenGLPackageAccess.createImplementation()); 330 } 331 } 332 reset()333 private static void reset() { 334 readBuffer.limit(0); 335 for (int i = 0; i < keyDownBuffer.remaining(); i++) 336 keyDownBuffer.put(i, (byte)0); 337 current_event.reset(); 338 } 339 340 /** 341 * @return true if the keyboard has been created 342 */ isCreated()343 public static boolean isCreated() { 344 synchronized (OpenGLPackageAccess.global_lock) { 345 return created; 346 } 347 } 348 349 /** 350 * "Destroy" the keyboard 351 */ destroy()352 public static void destroy() { 353 synchronized (OpenGLPackageAccess.global_lock) { 354 if (!created) 355 return; 356 created = false; 357 implementation.destroyKeyboard(); 358 reset(); 359 } 360 } 361 362 /** 363 * Polls the keyboard for its current state. Access the polled values using the 364 * <code>isKeyDown</code> method. 365 * By using this method, it is possible to "miss" keyboard keys if you don't 366 * poll fast enough. 367 * 368 * To use buffered values, you have to call <code>next</code> for each event you 369 * want to read. You can query which key caused the event by using 370 * <code>getEventKey</code>. To get the state of that key, for that event, use 371 * <code>getEventKeyState</code> - finally use <code>getEventCharacter</code> to get the 372 * character for that event. 373 * 374 * NOTE: This method does not query the operating system for new events. To do that, 375 * Display.processMessages() (or Display.update()) must be called first. 376 * 377 * @see org.lwjgl.input.Keyboard#isKeyDown(int key) 378 * @see org.lwjgl.input.Keyboard#next() 379 * @see org.lwjgl.input.Keyboard#getEventKey() 380 * @see org.lwjgl.input.Keyboard#getEventKeyState() 381 * @see org.lwjgl.input.Keyboard#getEventCharacter() 382 */ poll()383 public static void poll() { 384 synchronized (OpenGLPackageAccess.global_lock) { 385 if (!created) 386 throw new IllegalStateException("Keyboard must be created before you can poll the device"); 387 implementation.pollKeyboard(keyDownBuffer); 388 read(); 389 } 390 } 391 read()392 private static void read() { 393 readBuffer.compact(); 394 implementation.readKeyboard(readBuffer); 395 readBuffer.flip(); 396 } 397 398 /** 399 * Checks to see if a key is down. 400 * @param key Keycode to check 401 * @return true if the key is down according to the last poll() 402 */ isKeyDown(int key)403 public static boolean isKeyDown(int key) { 404 synchronized (OpenGLPackageAccess.global_lock) { 405 if (!created) 406 throw new IllegalStateException("Keyboard must be created before you can query key state"); 407 return keyDownBuffer.get(key) != 0; 408 } 409 } 410 411 /** 412 * Checks whether one of the state keys are "active" 413 * 414 * @param key State key to test (KEY_CAPITAL | KEY_NUMLOCK | KEY_SYSRQ) 415 * @return STATE_ON if on, STATE_OFF if off and STATE_UNKNOWN if the state is unknown 416 */ 417 /* public static int isStateKeySet(int key) { 418 if (!created) 419 throw new IllegalStateException("Keyboard must be created before you can query key state"); 420 return implementation.isStateKeySet(key); 421 } 422 */ 423 /** 424 * Gets a key's name 425 * @param key The key 426 * @return a String with the key's human readable name in it or null if the key is unnamed 427 */ getKeyName(int key)428 public static synchronized String getKeyName(int key) { 429 return keyName[key]; 430 } 431 432 /** 433 * Get's a key's index. If the key is unrecognised then KEY_NONE is returned. 434 * @param keyName The key name 435 */ getKeyIndex(String keyName)436 public static synchronized int getKeyIndex(String keyName) { 437 Integer ret = keyMap.get(keyName); 438 if (ret == null) 439 return KEY_NONE; 440 else 441 return ret; 442 } 443 444 /** 445 * Gets the number of keyboard events waiting after doing a buffer enabled poll(). 446 * @return the number of keyboard events 447 */ getNumKeyboardEvents()448 public static int getNumKeyboardEvents() { 449 synchronized (OpenGLPackageAccess.global_lock) { 450 if (!created) 451 throw new IllegalStateException("Keyboard must be created before you can read events"); 452 int old_position = readBuffer.position(); 453 int num_events = 0; 454 while (readNext(tmp_event) && (!tmp_event.repeat || repeat_enabled)) 455 num_events++; 456 readBuffer.position(old_position); 457 return num_events; 458 } 459 } 460 461 /** 462 * Gets the next keyboard event. You can query which key caused the event by using 463 * <code>getEventKey</code>. To get the state of that key, for that event, use 464 * <code>getEventKeyState</code> - finally use <code>getEventCharacter</code> to get the 465 * character for that event. 466 * 467 * @see org.lwjgl.input.Keyboard#getEventKey() 468 * @see org.lwjgl.input.Keyboard#getEventKeyState() 469 * @see org.lwjgl.input.Keyboard#getEventCharacter() 470 * @return true if a keyboard event was read, false otherwise 471 */ next()472 public static boolean next() { 473 synchronized (OpenGLPackageAccess.global_lock) { 474 if (!created) 475 throw new IllegalStateException("Keyboard must be created before you can read events"); 476 477 boolean result; 478 while ((result = readNext(current_event)) && current_event.repeat && !repeat_enabled) 479 ; 480 return result; 481 } 482 } 483 484 /** 485 * Controls whether repeat events are reported or not. If repeat events 486 * are enabled, key down events are reported when a key is pressed and held for 487 * a OS dependent amount of time. To distinguish a repeat event from a normal event, 488 * use isRepeatEvent(). 489 * 490 * @see org.lwjgl.input.Keyboard#getEventKey() 491 */ enableRepeatEvents(boolean enable)492 public static void enableRepeatEvents(boolean enable) { 493 synchronized (OpenGLPackageAccess.global_lock) { 494 repeat_enabled = enable; 495 } 496 } 497 498 /** 499 * Check whether repeat events are currently reported or not. 500 * 501 * @return true is repeat events are reported, false if not. 502 * @see org.lwjgl.input.Keyboard#getEventKey() 503 */ areRepeatEventsEnabled()504 public static boolean areRepeatEventsEnabled() { 505 synchronized (OpenGLPackageAccess.global_lock) { 506 return repeat_enabled; 507 } 508 } 509 readNext(KeyEvent event)510 private static boolean readNext(KeyEvent event) { 511 if (readBuffer.hasRemaining()) { 512 event.key = readBuffer.getInt() & 0xFF; 513 event.state = readBuffer.get() != 0; 514 event.character = readBuffer.getInt(); 515 event.nanos = readBuffer.getLong(); 516 event.repeat = readBuffer.get() == 1; 517 return true; 518 } else 519 return false; 520 } 521 522 /** 523 * @return Number of keys on this keyboard 524 */ getKeyCount()525 public static int getKeyCount() { 526 return keyCount; 527 } 528 529 /** 530 * @return The character from the current event 531 */ getEventCharacter()532 public static char getEventCharacter() { 533 synchronized (OpenGLPackageAccess.global_lock) { 534 return (char)current_event.character; 535 } 536 } 537 538 /** 539 * Please note that the key code returned is NOT valid against the 540 * current keyboard layout. To get the actual character pressed call 541 * getEventCharacter 542 * 543 * @return The key from the current event 544 */ getEventKey()545 public static int getEventKey() { 546 synchronized (OpenGLPackageAccess.global_lock) { 547 return current_event.key; 548 } 549 } 550 551 /** 552 * Gets the state of the key that generated the 553 * current event 554 * 555 * @return True if key was down, or false if released 556 */ getEventKeyState()557 public static boolean getEventKeyState() { 558 synchronized (OpenGLPackageAccess.global_lock) { 559 return current_event.state; 560 } 561 } 562 563 /** 564 * Gets the time in nanoseconds of the current event. 565 * Only useful for relative comparisons with other 566 * Keyboard events, as the absolute time has no defined 567 * origin. 568 * @return The time in nanoseconds of the current event 569 */ getEventNanoseconds()570 public static long getEventNanoseconds() { 571 synchronized (OpenGLPackageAccess.global_lock) { 572 return current_event.nanos; 573 } 574 } 575 576 /** 577 * @see org.lwjgl.input.Keyboard#enableRepeatEvents(boolean) 578 * @return true if the current event is a repeat event, false if 579 * the current event is not a repeat even or if repeat events are disabled. 580 */ isRepeatEvent()581 public static boolean isRepeatEvent() { 582 synchronized (OpenGLPackageAccess.global_lock) { 583 return current_event.repeat; 584 } 585 } 586 587 private static final class KeyEvent { 588 /** The current keyboard character being examined */ 589 private int character; 590 591 /** The current keyboard event key being examined */ 592 private int key; 593 594 /** The current state of the key being examined in the event queue */ 595 private boolean state; 596 597 /** The current event time */ 598 private long nanos; 599 600 /** Is the current event a repeated event? */ 601 private boolean repeat; 602 reset()603 private void reset() { 604 character = 0; 605 key = 0; 606 state = false; 607 repeat = false; 608 } 609 } 610 } 611