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