1 /* 2 * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package javafx.scene.input; 27 28 import com.sun.javafx.tk.Toolkit; 29 import javafx.beans.NamedArg; 30 import javafx.event.EventTarget; 31 import javafx.event.EventType; 32 33 import com.sun.javafx.robot.impl.FXRobotHelper; 34 import com.sun.javafx.robot.impl.FXRobotHelper.FXRobotInputAccessor; 35 import com.sun.javafx.scene.input.KeyCodeMap; 36 import javafx.event.Event; 37 import javafx.scene.input.ScrollEvent.HorizontalTextScrollUnits; 38 import javafx.scene.input.ScrollEvent.VerticalTextScrollUnits; 39 40 /** 41 * An event which indicates that a keystroke occurred in a {@link javafx.scene.Node}. 42 * <p> 43 * This event is generated when a key is pressed, released, or typed. 44 * Depending on the type of the event it is passed 45 * to {@link javafx.scene.Node#onKeyPressedProperty onKeyPressed}, {@link javafx.scene.Node#onKeyTypedProperty onKeyTyped} 46 * or {@link javafx.scene.Node#onKeyReleasedProperty onKeyReleased} function. 47 * 48 * <p> 49 * <em>"Key typed" events</em> are higher-level and generally do not depend on 50 * the platform or keyboard layout. They are generated when a Unicode character 51 * is entered, and are the preferred way to find out about character input. 52 * In the simplest case, a key typed event is produced by a single key press 53 * (e.g., 'a'). Often, however, characters are produced by series of key 54 * presses (e.g., SHIFT + 'a'), and the mapping from key pressed events to 55 * key typed events may be many-to-one or many-to-many. Key releases are not 56 * usually necessary to generate a key typed event, but there are some cases 57 * where the key typed event is not generated until a key is released (e.g., 58 * entering ASCII sequences via the Alt-Numpad method in Windows). 59 * No key typed events are generated for keys that don't generate Unicode 60 * characters (e.g., action keys, modifier keys, etc.). 61 * 62 * <p> 63 * The {@code character} variable always contains a valid Unicode character(s) 64 * or CHAR_UNDEFINED. Character input is reported by key typed events; 65 * key pressed and key released events are not necessarily associated 66 * with character input. Therefore, the {@code character} variable 67 * is guaranteed to be meaningful only for key typed events. 68 * 69 * <p> 70 * For key pressed and key released events, the {@code code} variable contains 71 * the event's key code. For key typed events, the {@code code} variable 72 * always contains {@code KeyCode.UNDEFINED}. 73 * 74 * <p> 75 * <em>"Key pressed" and "key released" events</em> are lower-level and depend 76 * on the platform and keyboard layout. They are generated whenever a key is 77 * pressed or released, and are the only way to find out about keys that don't 78 * generate character input (e.g., action keys, modifier keys, etc.). The key 79 * being pressed or released is indicated by the code variable, which contains 80 * a virtual key code. 81 * 82 * <p> 83 * For triggering context menus see the {@link ContextMenuEvent}. 84 * @since JavaFX 2.0 85 */ 86 public final class KeyEvent extends InputEvent { 87 88 private static final long serialVersionUID = 20121107L; 89 90 /** 91 * Common supertype for all key event types. 92 */ 93 public static final EventType<KeyEvent> ANY = 94 new EventType<KeyEvent>(InputEvent.ANY, "KEY"); 95 96 /** 97 * This event occurs when a key has been pressed. 98 */ 99 public static final EventType<KeyEvent> KEY_PRESSED = 100 new EventType<KeyEvent>(KeyEvent.ANY, "KEY_PRESSED"); 101 102 /** 103 * This event occurs when a key has been released. 104 */ 105 public static final EventType<KeyEvent> KEY_RELEASED = 106 new EventType<KeyEvent>(KeyEvent.ANY, "KEY_RELEASED"); 107 108 /** 109 * This event occurs when a character-generating key was typed 110 * (pressed and released). The event contains the {@code character} 111 * field containing the typed string, the {@code code} and {@code text} 112 * fields are not used. 113 */ 114 public static final EventType<KeyEvent> KEY_TYPED = 115 new EventType<KeyEvent>(KeyEvent.ANY, "KEY_TYPED"); 116 117 static { 118 FXRobotInputAccessor a = new FXRobotInputAccessor() { 119 @Override public int getCodeForKeyCode(KeyCode keyCode) { 120 return keyCode.code; 121 } 122 @Override public KeyCode getKeyCodeForCode(int code) { 123 return KeyCodeMap.valueOf(code); 124 } 125 @Override public KeyEvent createKeyEvent( 126 EventType<? extends KeyEvent> eventType, 127 KeyCode code, String character, String text, 128 boolean shiftDown, boolean controlDown, 129 boolean altDown, boolean metaDown) 130 { 131 return new KeyEvent((EventType<KeyEvent>)eventType, character, text, code, 132 shiftDown, controlDown, altDown, metaDown); 133 } 134 @Override public MouseEvent createMouseEvent( 135 EventType<? extends MouseEvent> eventType, 136 int x, int y, int screenX, int screenY, 137 MouseButton button, int clickCount, boolean shiftDown, 138 boolean controlDown, boolean altDown, boolean metaDown, 139 boolean popupTrigger, boolean primaryButtonDown, 140 boolean middleButtonDown, boolean secondaryButtonDown) 141 { 142 return new MouseEvent(eventType, x, y, 143 screenX, screenY, 144 button, clickCount, 145 shiftDown, 146 controlDown, 147 altDown, 148 metaDown, 149 primaryButtonDown, 150 middleButtonDown, 151 secondaryButtonDown, 152 false, 153 popupTrigger, 154 false, 155 null 156 ); 157 } 158 159 @Override 160 public ScrollEvent createScrollEvent( 161 EventType<? extends ScrollEvent> eventType, 162 int scrollX, int scrollY, 163 HorizontalTextScrollUnits xTextUnits, int xText, 164 VerticalTextScrollUnits yTextUnits, int yText, 165 int x, int y, int screenX, int screenY, 166 boolean shiftDown, boolean controlDown, 167 boolean altDown, boolean metaDown) { 168 return new ScrollEvent(ScrollEvent.SCROLL, 169 x, y, screenX, screenY, 170 shiftDown, controlDown, altDown, metaDown, false, false, 171 scrollX, scrollY, 0, 0, 172 xTextUnits, xText, yTextUnits, yText, 173 0, null); 174 } 175 }; 176 FXRobotHelper.setInputAccessor(a); 177 } 178 179 /** 180 * Constructs new KeyEvent event with null source and target and KeyCode object directly specified. 181 * @param source the source of the event. Can be null. 182 * @param target the target of the event. Can be null. 183 * @param eventType The type of the event. 184 * @param character The character or sequence of characters associated with the event 185 * @param text A String describing the key code 186 * @param code The integer key code 187 * @param shiftDown true if shift modifier was pressed. 188 * @param controlDown true if control modifier was pressed. 189 * @param altDown true if alt modifier was pressed. 190 * @param metaDown true if meta modifier was pressed. 191 * @since JavaFX 8.0 192 */ 193 public KeyEvent(@NamedArg("source") Object source, @NamedArg("target") EventTarget target, @NamedArg("eventType") EventType<KeyEvent> eventType, @NamedArg("character") String character, 194 @NamedArg("text") String text, @NamedArg("code") KeyCode code, @NamedArg("shiftDown") boolean shiftDown, @NamedArg("controlDown") boolean controlDown, 195 @NamedArg("altDown") boolean altDown, @NamedArg("metaDown") boolean metaDown) { 196 super(source, target, eventType); 197 boolean isKeyTyped = eventType == KEY_TYPED; 198 199 this.character = isKeyTyped ? character : KeyEvent.CHAR_UNDEFINED; 200 this.text = isKeyTyped ? "" : text; 201 this.code = isKeyTyped ? KeyCode.UNDEFINED : code; 202 this.shiftDown = shiftDown; 203 this.controlDown = controlDown; 204 this.altDown = altDown; 205 this.metaDown = metaDown; 206 } 207 208 /** 209 * Constructs new KeyEvent event with null source and target and KeyCode object directly specified. 210 * @param eventType The type of the event. 211 * @param character The character or sequence of characters associated with the event 212 * @param text A String describing the key code 213 * @param code The integer key code 214 * @param shiftDown true if shift modifier was pressed. 215 * @param controlDown true if control modifier was pressed. 216 * @param altDown true if alt modifier was pressed. 217 * @param metaDown true if meta modifier was pressed. 218 * @since JavaFX 8.0 219 */ 220 public KeyEvent(@NamedArg("eventType") EventType<KeyEvent> eventType, @NamedArg("character") String character, 221 @NamedArg("text") String text, @NamedArg("code") KeyCode code, @NamedArg("shiftDown") boolean shiftDown, @NamedArg("controlDown") boolean controlDown, 222 @NamedArg("altDown") boolean altDown, @NamedArg("metaDown") boolean metaDown) { 223 super(eventType); 224 boolean isKeyTyped = eventType == KEY_TYPED; 225 226 this.character = isKeyTyped ? character : KeyEvent.CHAR_UNDEFINED; 227 this.text = isKeyTyped ? "" : text; 228 this.code = isKeyTyped ? KeyCode.UNDEFINED : code; 229 this.shiftDown = shiftDown; 230 this.controlDown = controlDown; 231 this.altDown = altDown; 232 this.metaDown = metaDown; 233 } 234 235 /** 236 * KEY_PRESSED and KEY_RELEASED events which do not map to a valid Unicode 237 * character use this for the keyChar value. 238 */ 239 public static final String CHAR_UNDEFINED = KeyCode.UNDEFINED.ch; 240 241 /** 242 * The Unicode character or sequence of characters associated with the key 243 * typed event. Contains multiple elements if the key produced a single 244 * Unicode character from outside of the Basic Multilingual Plane which 245 * needs to be encoded by the corresponding surrogate pair in Java or if 246 * the key produced multiple Unicode characters itself. 247 * <p/> 248 * For example, {@code character} will have the value "A" for a key typed 249 * event generated by pressing SHIFT + 'a'. 250 * For key pressed and key released events, {@code character} is always 251 * {@code CHAR_UNDEFINED}. 252 */ 253 private final String character; 254 255 /** 256 * The Unicode character or sequence of characters associated with the key 257 * typed event. Contains multiple elements if the key produced a single 258 * Unicode character from outside of the Basic Multilingual Plane which 259 * needs to be encoded by the corresponding surrogate pair in Java or if 260 * the key produced multiple Unicode characters itself. 261 * <p/> 262 * For example, {@code character} will have the value "A" for a key typed 263 * event generated by pressing SHIFT + 'a'. 264 * For key pressed and key released events, {@code character} is always 265 * {@code CHAR_UNDEFINED}. 266 * 267 * @return The Unicode character(s) associated with the key typed event 268 */ 269 public final String getCharacter() { 270 return character; 271 } 272 273 /** 274 * A String describing the key code, such as "HOME", "F1" or "A", 275 * for key pressed and key released events. 276 * For key typed events, {@code text} is always the empty string. 277 */ 278 private final String text; 279 280 /** 281 * A String describing the key code, such as "HOME", "F1" or "A", 282 * for key pressed and key released events. 283 * For key typed events, {@code text} is always the empty string. 284 * 285 * @return A String describing the key code 286 */ 287 public final String getText() { 288 return text; 289 } 290 291 /** 292 * The integer key code associated with the key in this key 293 * pressed or key released event. 294 * For key typed events, {@code code} is always {@code KeyCode.UNDEFINED}. 295 */ 296 private final KeyCode code; 297 298 /** 299 * The key code associated with the key in this key pressed or key released 300 * event. For key typed events, {@code code} is always {@code KeyCode.UNDEFINED}. 301 * 302 * @return The key code associated with the key in this event, 303 * {@code KeyCode.UNDEFINED} for key typed event 304 */ 305 public final KeyCode getCode() { 306 return code; 307 } 308 309 /** 310 * Returns whether or not the Shift modifier is down on this event. 311 */ 312 private final boolean shiftDown; 313 314 /** 315 * Returns whether or not the Shift modifier is down on this event. 316 * @return whether or not the Shift modifier is down on this event. 317 */ 318 public final boolean isShiftDown() { 319 return shiftDown; 320 } 321 322 /** 323 * Returns whether or not the Control modifier is down on this event. 324 */ 325 private final boolean controlDown; 326 327 /** 328 * Returns whether or not the Control modifier is down on this event. 329 * @return whether or not the Control modifier is down on this event. 330 */ 331 public final boolean isControlDown() { 332 return controlDown; 333 } 334 335 /** 336 * Returns whether or not the Alt modifier is down on this event. 337 */ 338 private final boolean altDown; 339 340 /** 341 * Returns whether or not the Alt modifier is down on this event. 342 * @return whether or not the Alt modifier is down on this event. 343 */ 344 public final boolean isAltDown() { 345 return altDown; 346 } 347 348 /** 349 * Returns whether or not the Meta modifier is down on this event. 350 */ 351 private final boolean metaDown; 352 353 /** 354 * Returns whether or not the Meta modifier is down on this event. 355 * @return whether or not the Meta modifier is down on this event. 356 */ 357 public final boolean isMetaDown() { 358 return metaDown; 359 } 360 361 362 /** 363 * Returns whether or not the host platform common shortcut modifier is 364 * down on this event. This common shortcut modifier is a modifier key which 365 * is used commonly in shortcuts on the host platform. It is for example 366 * {@code control} on Windows and {@code meta} (command key) on Mac. 367 * 368 * @return {@code true} if the shortcut modifier is down, {@code false} 369 * otherwise 370 */ 371 public final boolean isShortcutDown() { 372 switch (Toolkit.getToolkit().getPlatformShortcutKey()) { 373 case SHIFT: 374 return shiftDown; 375 376 case CONTROL: 377 return controlDown; 378 379 case ALT: 380 return altDown; 381 382 case META: 383 return metaDown; 384 385 default: 386 return false; 387 } 388 } 389 390 /** 391 * Returns a string representation of this {@code KeyEvent} object. 392 * @return a string representation of this {@code KeyEvent} object. 393 */ 394 @Override public String toString() { 395 final StringBuilder sb = new StringBuilder("KeyEvent ["); 396 397 sb.append("source = ").append(getSource()); 398 sb.append(", target = ").append(getTarget()); 399 sb.append(", eventType = ").append(getEventType()); 400 sb.append(", consumed = ").append(isConsumed()); 401 402 sb.append(", character = ").append(getCharacter()); 403 sb.append(", text = ").append(getText()); 404 sb.append(", code = ").append(getCode()); 405 406 if (isShiftDown()) { 407 sb.append(", shiftDown"); 408 } 409 if (isControlDown()) { 410 sb.append(", controlDown"); 411 } 412 if (isAltDown()) { 413 sb.append(", altDown"); 414 } 415 if (isMetaDown()) { 416 sb.append(", metaDown"); 417 } 418 if (isShortcutDown()) { 419 sb.append(", shortcutDown"); 420 } 421 422 return sb.append("]").toString(); 423 } 424 425 @Override 426 public KeyEvent copyFor(Object newSource, EventTarget newTarget) { 427 return (KeyEvent) super.copyFor(newSource, newTarget); 428 } 429 430 /** 431 * Creates a copy of the given event with the given fields substituted. 432 * @param source the new source of the copied event 433 * @param target the new target of the copied event 434 * @param type the new event type. 435 * @return the event copy with the fields substituted 436 * @since JavaFX 8.0 437 */ 438 public KeyEvent copyFor(Object source, EventTarget target, EventType<KeyEvent> type) { 439 KeyEvent e = copyFor(source, target); 440 e.eventType = type; 441 return e; 442 } 443 444 @Override 445 public EventType<KeyEvent> getEventType() { 446 return (EventType<KeyEvent>) super.getEventType(); 447 } 448 449 450 451 }