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