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() &amp; (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 }