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