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