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