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