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 physical 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 @Override 307 public void setCanAccessSystemClipboard(InputEvent event, 308 boolean canAccessSystemClipboard) { 309 event.canAccessSystemClipboard = canAccessSystemClipboard; 310 } 311 }); 312 } 313 314 /** 315 * Initialize JNI field and method IDs for fields that may be 316 accessed from C. 317 */ 318 private static native void initIDs(); 319 320 /** 321 * Constructs an InputEvent object with the specified source component, 322 * modifiers, and type. 323 * <p> This method throws an 324 * {@code IllegalArgumentException} if {@code source} 325 * is {@code null}. 326 * 327 * @param source the object where the event originated 328 * @param id the integer that identifies the event type. 329 * It is allowed to pass as parameter any value that 330 * allowed for some subclass of {@code InputEvent} class. 331 * Passing in the value different from those values result 332 * in unspecified behavior 333 * @param when a long int that gives the time the event occurred. 334 * Passing negative or zero value 335 * is not recommended 336 * @param modifiers a modifier mask describing the modifier keys and mouse 337 * buttons (for example, shift, ctrl, alt, and meta) that 338 * are down during the event. 339 * Only extended modifiers are allowed to be used as a 340 * value for this parameter (see the {@link InputEvent#getModifiersEx} 341 * class for the description of extended modifiers). 342 * Passing negative parameter 343 * is not recommended. 344 * Zero value means that no modifiers were passed 345 * @throws IllegalArgumentException if {@code source} is null 346 * @see #getSource() 347 * @see #getID() 348 * @see #getWhen() 349 * @see #getModifiers() 350 */ 351 InputEvent(Component source, int id, long when, int modifiers) { 352 super(source, id); 353 this.when = when; 354 this.modifiers = modifiers; 355 canAccessSystemClipboard = canAccessSystemClipboard(); 356 } 357 358 private boolean canAccessSystemClipboard() { 359 boolean b = false; 360 361 if (!GraphicsEnvironment.isHeadless()) { 362 SecurityManager sm = System.getSecurityManager(); 363 if (sm != null) { 364 try { 365 sm.checkPermission(AWTPermissions.ACCESS_CLIPBOARD_PERMISSION); 366 b = true; 367 } catch (SecurityException se) { 368 if (logger.isLoggable(PlatformLogger.Level.FINE)) { 369 logger.fine("InputEvent.canAccessSystemClipboard() got SecurityException ", se); 370 } 371 } 372 } else { 373 b = true; 374 } 375 } 376 377 return b; 378 } 379 380 /** 381 * Returns whether or not the Shift modifier is down on this event. 382 * @return whether or not the Shift modifier is down on this event 383 */ 384 public boolean isShiftDown() { 385 return (modifiers & SHIFT_MASK) != 0; 386 } 387 388 /** 389 * Returns whether or not the Control modifier is down on this event. 390 * @return whether or not the Control modifier is down on this event 391 */ 392 public boolean isControlDown() { 393 return (modifiers & CTRL_MASK) != 0; 394 } 395 396 /** 397 * Returns whether or not the Meta modifier is down on this event. 398 * @return whether or not the Meta modifier is down on this event 399 */ 400 public boolean isMetaDown() { 401 return (modifiers & META_MASK) != 0; 402 } 403 404 /** 405 * Returns whether or not the Alt modifier is down on this event. 406 * @return whether or not the Alt modifier is down on this event 407 */ 408 public boolean isAltDown() { 409 return (modifiers & ALT_MASK) != 0; 410 } 411 412 /** 413 * Returns whether or not the AltGraph modifier is down on this event. 414 * @return whether or not the AltGraph modifier is down on this event 415 */ 416 public boolean isAltGraphDown() { 417 return (modifiers & ALT_GRAPH_MASK) != 0; 418 } 419 420 /** 421 * Returns the difference in milliseconds between the timestamp of when this event occurred and 422 * midnight, January 1, 1970 UTC. 423 * @return the difference in milliseconds between the timestamp and midnight, January 1, 1970 UTC 424 */ 425 public long getWhen() { 426 return when; 427 } 428 429 /** 430 * Returns the modifier mask for this event. 431 * @return the modifier mask for this event 432 */ 433 public int getModifiers() { 434 return modifiers & (JDK_1_3_MODIFIERS | HIGH_MODIFIERS); 435 } 436 437 /** 438 * Returns the extended modifier mask for this event. 439 * <P> 440 * Extended modifiers are the modifiers that ends with the _DOWN_MASK suffix, 441 * such as ALT_DOWN_MASK, BUTTON1_DOWN_MASK, and others. 442 * <P> 443 * Extended modifiers represent the state of all modal keys, 444 * such as ALT, CTRL, META, and the mouse buttons just after 445 * the event occurred. 446 * <P> 447 * For example, if the user presses <b>button 1</b> followed by 448 * <b>button 2</b>, and then releases them in the same order, 449 * the following sequence of events is generated: 450 * <PRE> 451 * {@code MOUSE_PRESSED}: {@code BUTTON1_DOWN_MASK} 452 * {@code MOUSE_PRESSED}: {@code BUTTON1_DOWN_MASK | BUTTON2_DOWN_MASK} 453 * {@code MOUSE_RELEASED}: {@code BUTTON2_DOWN_MASK} 454 * {@code MOUSE_CLICKED}: {@code BUTTON2_DOWN_MASK} 455 * {@code MOUSE_RELEASED}: 456 * {@code MOUSE_CLICKED}: 457 * </PRE> 458 * <P> 459 * It is not recommended to compare the return value of this method 460 * using {@code ==} because new modifiers can be added in the future. 461 * For example, the appropriate way to check that SHIFT and BUTTON1 are 462 * down, but CTRL is up is demonstrated by the following code: 463 * <PRE> 464 * int onmask = SHIFT_DOWN_MASK | BUTTON1_DOWN_MASK; 465 * int offmask = CTRL_DOWN_MASK; 466 * if ((event.getModifiersEx() & (onmask | offmask)) == onmask) { 467 * ... 468 * } 469 * </PRE> 470 * The above code will work even if new modifiers are added. 471 * 472 * @return the extended modifier mask for this event 473 * @since 1.4 474 */ 475 public int getModifiersEx() { 476 return modifiers & ~JDK_1_3_MODIFIERS; 477 } 478 479 /** 480 * Consumes this event so that it will not be processed 481 * in the default manner by the source which originated it. 482 */ 483 public void consume() { 484 consumed = true; 485 } 486 487 /** 488 * Returns whether or not this event has been consumed. 489 * @return whether or not this event has been consumed 490 * @see #consume 491 */ 492 public boolean isConsumed() { 493 return consumed; 494 } 495 496 // state serialization compatibility with JDK 1.1 497 static final long serialVersionUID = -2482525981698309786L; 498 499 /** 500 * Returns a String describing the extended modifier keys and 501 * mouse buttons, such as "Shift", "Button1", or "Ctrl+Shift". 502 * These strings can be localized by changing the 503 * {@code awt.properties} file. 504 * <p> 505 * Note that passing negative parameter is incorrect, 506 * and will cause the returning an unspecified string. 507 * Zero parameter means that no modifiers were passed and will 508 * cause the returning an empty string. 509 * 510 * @return a String describing the extended modifier keys and 511 * mouse buttons 512 * 513 * @param modifiers a modifier mask describing the extended 514 * modifier keys and mouse buttons for the event 515 * @return a text description of the combination of extended 516 * modifier keys and mouse buttons that were held down 517 * during the event. 518 * @since 1.4 519 */ 520 public static String getModifiersExText(int modifiers) { 521 StringBuilder buf = new StringBuilder(); 522 if ((modifiers & InputEvent.META_DOWN_MASK) != 0) { 523 buf.append(Toolkit.getProperty("AWT.meta", "Meta")); 524 buf.append("+"); 525 } 526 if ((modifiers & InputEvent.CTRL_DOWN_MASK) != 0) { 527 buf.append(Toolkit.getProperty("AWT.control", "Ctrl")); 528 buf.append("+"); 529 } 530 if ((modifiers & InputEvent.ALT_DOWN_MASK) != 0) { 531 buf.append(Toolkit.getProperty("AWT.alt", "Alt")); 532 buf.append("+"); 533 } 534 if ((modifiers & InputEvent.SHIFT_DOWN_MASK) != 0) { 535 buf.append(Toolkit.getProperty("AWT.shift", "Shift")); 536 buf.append("+"); 537 } 538 if ((modifiers & InputEvent.ALT_GRAPH_DOWN_MASK) != 0) { 539 buf.append(Toolkit.getProperty("AWT.altGraph", "Alt Graph")); 540 buf.append("+"); 541 } 542 543 int buttonNumber = 1; 544 for (int mask : InputEvent.BUTTON_DOWN_MASK){ 545 if ((modifiers & mask) != 0) { 546 buf.append(Toolkit.getProperty("AWT.button"+buttonNumber, "Button"+buttonNumber)); 547 buf.append("+"); 548 } 549 buttonNumber++; 550 } 551 if (buf.length() > 0) { 552 buf.setLength(buf.length()-1); // remove trailing '+' 553 } 554 return buf.toString(); 555 } 556 }