1 /* 2 * Copyright (c) 1996, 2016, 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 java.awt.event; 27 28 import java.awt.Event; 29 import java.awt.Component; 30 import java.awt.GraphicsEnvironment; 31 import java.awt.Toolkit; 32 import java.util.Arrays; 33 34 import sun.awt.AWTAccessor; 35 import sun.awt.AWTPermissions; 36 import sun.util.logging.PlatformLogger; 37 38 /** 39 * The root event class for all component-level input events. 40 * 41 * Input events are delivered to listeners before they are 42 * processed normally by the source where they originated. 43 * This allows listeners and component subclasses to "consume" 44 * the event so that the source will not process them in their 45 * default manner. For example, consuming mousePressed events 46 * on a Button component will prevent the Button from being 47 * activated. 48 * 49 * @author Carl Quinn 50 * 51 * @see KeyEvent 52 * @see KeyAdapter 53 * @see MouseEvent 54 * @see MouseAdapter 55 * @see MouseMotionAdapter 56 * 57 * @since 1.1 58 */ 59 public abstract class InputEvent extends ComponentEvent { 60 61 private static final PlatformLogger logger = PlatformLogger.getLogger("java.awt.event.InputEvent"); 62 63 /** 64 * The Shift key modifier constant. 65 * 66 * @deprecated It is recommended that SHIFT_DOWN_MASK be used instead 67 */ 68 @Deprecated(since = "9") 69 public static final int SHIFT_MASK = Event.SHIFT_MASK; 70 71 /** 72 * The Control key modifier constant. 73 * 74 * @deprecated It is recommended that CTRL_DOWN_MASK be used instead 75 */ 76 @Deprecated(since = "9") 77 public static final int CTRL_MASK = Event.CTRL_MASK; 78 79 /** 80 * The Meta key modifier constant. 81 * 82 * @deprecated It is recommended that META_DOWN_MASK be used instead 83 */ 84 @Deprecated(since = "9") 85 public static final int META_MASK = Event.META_MASK; 86 87 /** 88 * The Alt key modifier constant. 89 * 90 * @deprecated It is recommended that ALT_DOWN_MASK be used instead 91 */ 92 @Deprecated(since = "9") 93 public static final int ALT_MASK = Event.ALT_MASK; 94 95 /** 96 * The AltGraph key modifier constant. 97 * 98 * @deprecated It is recommended that ALT_GRAPH_DOWN_MASK be used instead 99 */ 100 @Deprecated(since = "9") 101 public static final int ALT_GRAPH_MASK = 1 << 5; 102 103 /** 104 * The Mouse Button1 modifier constant. 105 * 106 * @deprecated It is recommended that BUTTON1_DOWN_MASK be used instead 107 */ 108 @Deprecated(since = "9") 109 public static final int BUTTON1_MASK = 1 << 4; 110 111 /** 112 * The Mouse Button2 modifier constant. 113 * 114 * @deprecated It is recommended that BUTTON2_DOWN_MASK be used instead. 115 * Note that BUTTON2_MASK has the same value as ALT_MASK. 116 */ 117 @Deprecated(since = "9") 118 public static final int BUTTON2_MASK = Event.ALT_MASK; 119 120 /** 121 * The Mouse Button3 modifier constant. 122 * 123 * @deprecated It is recommended that BUTTON3_DOWN_MASK be used instead. 124 * Note that BUTTON3_MASK has the same value as META_MASK. 125 */ 126 @Deprecated(since = "9") 127 public static final int BUTTON3_MASK = Event.META_MASK; 128 129 /** 130 * The Shift key extended modifier constant. 131 * @since 1.4 132 */ 133 public static final int SHIFT_DOWN_MASK = 1 << 6; 134 135 /** 136 * The Control key extended modifier constant. 137 * @since 1.4 138 */ 139 public static final int CTRL_DOWN_MASK = 1 << 7; 140 141 /** 142 * The Meta key extended modifier constant. 143 * @since 1.4 144 */ 145 public static final int META_DOWN_MASK = 1 << 8; 146 147 /** 148 * The Alt key extended modifier constant. 149 * @since 1.4 150 */ 151 public static final int ALT_DOWN_MASK = 1 << 9; 152 153 /** 154 * The Mouse Button1 extended modifier constant. 155 * @since 1.4 156 */ 157 public static final int BUTTON1_DOWN_MASK = 1 << 10; 158 159 /** 160 * The Mouse Button2 extended modifier constant. 161 * @since 1.4 162 */ 163 public static final int BUTTON2_DOWN_MASK = 1 << 11; 164 165 /** 166 * The Mouse Button3 extended modifier constant. 167 * @since 1.4 168 */ 169 public static final int BUTTON3_DOWN_MASK = 1 << 12; 170 171 /** 172 * The AltGraph key extended modifier constant. 173 * @since 1.4 174 */ 175 public static final int ALT_GRAPH_DOWN_MASK = 1 << 13; 176 177 /** 178 * An array of extended modifiers for additional buttons. 179 * @see #getButtonDownMasks() 180 * There are twenty buttons fit into 4byte space. 181 * one more bit is reserved for FIRST_HIGH_BIT. 182 * @since 1.7 183 */ 184 private static final int [] BUTTON_DOWN_MASK = new int [] { BUTTON1_DOWN_MASK, 185 BUTTON2_DOWN_MASK, 186 BUTTON3_DOWN_MASK, 187 1<<14, //4th physical button (this is not a wheel!) 188 1<<15, //(this is not a wheel!) 189 1<<16, 190 1<<17, 191 1<<18, 192 1<<19, 193 1<<20, 194 1<<21, 195 1<<22, 196 1<<23, 197 1<<24, 198 1<<25, 199 1<<26, 200 1<<27, 201 1<<28, 202 1<<29, 203 1<<30}; 204 205 /** 206 * A method to access an array of extended modifiers for additional buttons. 207 * @since 1.7 208 */ 209 private static int [] getButtonDownMasks(){ 210 return Arrays.copyOf(BUTTON_DOWN_MASK, BUTTON_DOWN_MASK.length); 211 } 212 213 214 /** 215 * A method to obtain a mask for any existing mouse button. 216 * The returned mask may be used for different purposes. Following are some of them: 217 * <ul> 218 * <li> {@link java.awt.Robot#mousePress(int) mousePress(buttons)} and 219 * {@link java.awt.Robot#mouseRelease(int) mouseRelease(buttons)} 220 * <li> as a {@code modifiers} parameter when creating a new {@link MouseEvent} instance 221 * <li> to check {@link MouseEvent#getModifiersEx() modifiersEx} of existing {@code MouseEvent} 222 * </ul> 223 * @param button is a number to represent a button starting from 1. 224 * For example, 225 * <pre> 226 * int button = InputEvent.getMaskForButton(1); 227 * </pre> 228 * will have the same meaning as 229 * <pre> 230 * int button = InputEvent.getMaskForButton(MouseEvent.BUTTON1); 231 * </pre> 232 * because {@link MouseEvent#BUTTON1 MouseEvent.BUTTON1} equals to 1. 233 * If a mouse has three enabled buttons(see {@link java.awt.MouseInfo#getNumberOfButtons() MouseInfo.getNumberOfButtons()}) 234 * then the values from the left column passed into the method will return 235 * corresponding values from the right column: 236 * <PRE> 237 * <b>button </b> <b>returned mask</b> 238 * {@link MouseEvent#BUTTON1 BUTTON1} {@link MouseEvent#BUTTON1_DOWN_MASK BUTTON1_DOWN_MASK} 239 * {@link MouseEvent#BUTTON2 BUTTON2} {@link MouseEvent#BUTTON2_DOWN_MASK BUTTON2_DOWN_MASK} 240 * {@link MouseEvent#BUTTON3 BUTTON3} {@link MouseEvent#BUTTON3_DOWN_MASK BUTTON3_DOWN_MASK} 241 * </PRE> 242 * If a mouse has more than three enabled buttons then more values 243 * are admissible (4, 5, etc.). There is no assigned constants for these extended buttons. 244 * The button masks for the extra buttons returned by this method have no assigned names like the 245 * first three button masks. 246 * <p> 247 * This method has the following implementation restriction. 248 * It returns masks for a limited number of buttons only. The maximum number is 249 * implementation dependent and may vary. 250 * This limit is defined by the relevant number 251 * of buttons that may hypothetically exist on the mouse but it is greater than the 252 * {@link java.awt.MouseInfo#getNumberOfButtons() MouseInfo.getNumberOfButtons()}. 253 * 254 * @return a mask for an existing mouse button. 255 * @throws IllegalArgumentException if {@code button} is less than zero or greater than the number 256 * of button masks reserved for buttons 257 * @since 1.7 258 * @see java.awt.MouseInfo#getNumberOfButtons() 259 * @see Toolkit#areExtraMouseButtonsEnabled() 260 * @see MouseEvent#getModifiers() 261 * @see MouseEvent#getModifiersEx() 262 */ 263 public static int getMaskForButton(int button) { 264 if (button <= 0 || button > BUTTON_DOWN_MASK.length) { 265 throw new IllegalArgumentException("button doesn't exist " + button); 266 } 267 return BUTTON_DOWN_MASK[button - 1]; 268 } 269 270 // the constant below MUST be updated if any extra modifier 271 // bits are to be added! 272 // in fact, it is undesirable to add modifier bits 273 // to the same field as this may break applications 274 // see bug# 5066958 275 static final int FIRST_HIGH_BIT = 1 << 31; 276 277 static final int JDK_1_3_MODIFIERS = SHIFT_DOWN_MASK - 1; 278 static final int HIGH_MODIFIERS = ~( FIRST_HIGH_BIT - 1 ); 279 280 /** 281 * The input event's Time stamp in UTC format. The time stamp 282 * indicates when the input event was created. 283 * 284 * @serial 285 * @see #getWhen() 286 */ 287 long when; 288 289 /** 290 * The state of the modifier mask at the time the input 291 * event was fired. 292 * 293 * @serial 294 * @see #getModifiers() 295 * @see #getModifiersEx() 296 * @see java.awt.event.KeyEvent 297 * @see java.awt.event.MouseEvent 298 */ 299 int modifiers; 300 301 /* 302 * A flag that indicates that this instance can be used to access 303 * the system clipboard. 304 */ 305 private transient boolean canAccessSystemClipboard; 306 307 static { 308 /* ensure that the necessary native libraries are loaded */ 309 NativeLibLoader.loadLibraries(); 310 if (!GraphicsEnvironment.isHeadless()) { 311 initIDs(); 312 } 313 AWTAccessor.setInputEventAccessor( 314 new AWTAccessor.InputEventAccessor() { 315 public int[] getButtonDownMasks() { 316 return InputEvent.getButtonDownMasks(); 317 } 318 319 public boolean canAccessSystemClipboard(InputEvent event) { 320 return event.canAccessSystemClipboard; 321 } 322 323 @Override 324 public void setCanAccessSystemClipboard(InputEvent event, 325 boolean canAccessSystemClipboard) { 326 event.canAccessSystemClipboard = canAccessSystemClipboard; 327 } 328 }); 329 } 330 331 /** 332 * Initialize JNI field and method IDs for fields that may be 333 accessed from C. 334 */ 335 private static native void initIDs(); 336 337 /** 338 * Constructs an InputEvent object with the specified source component, 339 * modifiers, and type. 340 * <p> This method throws an 341 * {@code IllegalArgumentException} if {@code source} 342 * is {@code null}. 343 * 344 * @param source the object where the event originated 345 * @param id the integer that identifies the event type. 346 * It is allowed to pass as parameter any value that 347 * allowed for some subclass of {@code InputEvent} class. 348 * Passing in the value different from those values result 349 * in unspecified behavior 350 * @param when a long int that gives the time the event occurred. 351 * Passing negative or zero value 352 * is not recommended 353 * @param modifiers a modifier mask describing the modifier keys and mouse 354 * buttons (for example, shift, ctrl, alt, and meta) that 355 * are down during the event. 356 * Only extended modifiers are allowed to be used as a 357 * value for this parameter (see the {@link InputEvent#getModifiersEx} 358 * class for the description of extended modifiers). 359 * Passing negative parameter 360 * is not recommended. 361 * Zero value means that no modifiers were passed 362 * @throws IllegalArgumentException if {@code source} is null 363 * @see #getSource() 364 * @see #getID() 365 * @see #getWhen() 366 * @see #getModifiers() 367 */ 368 InputEvent(Component source, int id, long when, int modifiers) { 369 super(source, id); 370 this.when = when; 371 this.modifiers = modifiers; 372 canAccessSystemClipboard = canAccessSystemClipboard(); 373 } 374 375 private boolean canAccessSystemClipboard() { 376 boolean b = false; 377 378 if (!GraphicsEnvironment.isHeadless()) { 379 SecurityManager sm = System.getSecurityManager(); 380 if (sm != null) { 381 try { 382 sm.checkPermission(AWTPermissions.ACCESS_CLIPBOARD_PERMISSION); 383 b = true; 384 } catch (SecurityException se) { 385 if (logger.isLoggable(PlatformLogger.Level.FINE)) { 386 logger.fine("InputEvent.canAccessSystemClipboard() got SecurityException ", se); 387 } 388 } 389 } else { 390 b = true; 391 } 392 } 393 394 return b; 395 } 396 397 /** 398 * Returns whether or not the Shift modifier is down on this event. 399 * @return whether or not the Shift modifier is down on this event 400 */ 401 public boolean isShiftDown() { 402 return (modifiers & SHIFT_DOWN_MASK) != 0; 403 } 404 405 /** 406 * Returns whether or not the Control modifier is down on this event. 407 * @return whether or not the Control modifier is down on this event 408 */ 409 public boolean isControlDown() { 410 return (modifiers & CTRL_DOWN_MASK) != 0; 411 } 412 413 /** 414 * Returns whether or not the Meta modifier is down on this event. 415 * @return whether or not the Meta modifier is down on this event 416 */ 417 public boolean isMetaDown() { 418 return (modifiers & META_DOWN_MASK) != 0; 419 } 420 421 /** 422 * Returns whether or not the Alt modifier is down on this event. 423 * @return whether or not the Alt modifier is down on this event 424 */ 425 public boolean isAltDown() { 426 return (modifiers & ALT_DOWN_MASK) != 0; 427 } 428 429 /** 430 * Returns whether or not the AltGraph modifier is down on this event. 431 * @return whether or not the AltGraph modifier is down on this event 432 */ 433 public boolean isAltGraphDown() { 434 return (modifiers & ALT_GRAPH_DOWN_MASK) != 0; 435 } 436 437 /** 438 * Returns the difference in milliseconds between the timestamp of when this event occurred and 439 * midnight, January 1, 1970 UTC. 440 * @return the difference in milliseconds between the timestamp and midnight, January 1, 1970 UTC 441 */ 442 public long getWhen() { 443 return when; 444 } 445 446 /** 447 * Returns the modifier mask for this event. 448 * 449 * @return the modifier mask for this event 450 * @deprecated It is recommended that {@link #getModifiersEx()} be used 451 * instead 452 */ 453 @Deprecated(since = "9") 454 public int getModifiers() { 455 return modifiers & (JDK_1_3_MODIFIERS | HIGH_MODIFIERS); 456 } 457 458 /** 459 * Returns the extended modifier mask for this event. 460 * <P> 461 * Extended modifiers are the modifiers that ends with the _DOWN_MASK suffix, 462 * such as ALT_DOWN_MASK, BUTTON1_DOWN_MASK, and others. 463 * <P> 464 * Extended modifiers represent the state of all modal keys, 465 * such as ALT, CTRL, META, and the mouse buttons just after 466 * the event occurred. 467 * <P> 468 * For example, if the user presses <b>button 1</b> followed by 469 * <b>button 2</b>, and then releases them in the same order, 470 * the following sequence of events is generated: 471 * <PRE> 472 * {@code MOUSE_PRESSED}: {@code BUTTON1_DOWN_MASK} 473 * {@code MOUSE_PRESSED}: {@code BUTTON1_DOWN_MASK | BUTTON2_DOWN_MASK} 474 * {@code MOUSE_RELEASED}: {@code BUTTON2_DOWN_MASK} 475 * {@code MOUSE_CLICKED}: {@code BUTTON2_DOWN_MASK} 476 * {@code MOUSE_RELEASED}: 477 * {@code MOUSE_CLICKED}: 478 * </PRE> 479 * <P> 480 * It is not recommended to compare the return value of this method 481 * using {@code ==} because new modifiers can be added in the future. 482 * For example, the appropriate way to check that SHIFT and BUTTON1 are 483 * down, but CTRL is up is demonstrated by the following code: 484 * <PRE> 485 * int onmask = SHIFT_DOWN_MASK | BUTTON1_DOWN_MASK; 486 * int offmask = CTRL_DOWN_MASK; 487 * if ((event.getModifiersEx() & (onmask | offmask)) == onmask) { 488 * ... 489 * } 490 * </PRE> 491 * The above code will work even if new modifiers are added. 492 * 493 * @return the extended modifier mask for this event 494 * @since 1.4 495 */ 496 public int getModifiersEx() { 497 return modifiers & ~JDK_1_3_MODIFIERS; 498 } 499 500 /** 501 * Consumes this event so that it will not be processed 502 * in the default manner by the source which originated it. 503 */ 504 public void consume() { 505 consumed = true; 506 } 507 508 /** 509 * Returns whether or not this event has been consumed. 510 * @return whether or not this event has been consumed 511 * @see #consume 512 */ 513 public boolean isConsumed() { 514 return consumed; 515 } 516 517 // state serialization compatibility with JDK 1.1 518 static final long serialVersionUID = -2482525981698309786L; 519 520 /** 521 * Returns a String describing the extended modifier keys and 522 * mouse buttons, such as "Shift", "Button1", or "Ctrl+Shift". 523 * These strings can be localized by changing the 524 * {@code awt.properties} file. 525 * <p> 526 * Note that passing negative parameter is incorrect, 527 * and will cause the returning an unspecified string. 528 * Zero parameter means that no modifiers were passed and will 529 * cause the returning an empty string. 530 * 531 * @return a String describing the extended modifier keys and 532 * mouse buttons 533 * 534 * @param modifiers a modifier mask describing the extended 535 * modifier keys and mouse buttons for the event 536 * @return a text description of the combination of extended 537 * modifier keys and mouse buttons that were held down 538 * during the event. 539 * @since 1.4 540 */ 541 public static String getModifiersExText(int modifiers) { 542 StringBuilder buf = new StringBuilder(); 543 if ((modifiers & InputEvent.META_DOWN_MASK) != 0) { 544 buf.append(Toolkit.getProperty("AWT.meta", "Meta")); 545 buf.append("+"); 546 } 547 if ((modifiers & InputEvent.CTRL_DOWN_MASK) != 0) { 548 buf.append(Toolkit.getProperty("AWT.control", "Ctrl")); 549 buf.append("+"); 550 } 551 if ((modifiers & InputEvent.ALT_DOWN_MASK) != 0) { 552 buf.append(Toolkit.getProperty("AWT.alt", "Alt")); 553 buf.append("+"); 554 } 555 if ((modifiers & InputEvent.SHIFT_DOWN_MASK) != 0) { 556 buf.append(Toolkit.getProperty("AWT.shift", "Shift")); 557 buf.append("+"); 558 } 559 if ((modifiers & InputEvent.ALT_GRAPH_DOWN_MASK) != 0) { 560 buf.append(Toolkit.getProperty("AWT.altGraph", "Alt Graph")); 561 buf.append("+"); 562 } 563 564 int buttonNumber = 1; 565 for (int mask : InputEvent.BUTTON_DOWN_MASK){ 566 if ((modifiers & mask) != 0) { 567 buf.append(Toolkit.getProperty("AWT.button"+buttonNumber, "Button"+buttonNumber)); 568 buf.append("+"); 569 } 570 buttonNumber++; 571 } 572 if (buf.length() > 0) { 573 buf.setLength(buf.length()-1); // remove trailing '+' 574 } 575 return buf.toString(); 576 } 577 }