1 /*
   2  * Copyright (c) 1996, 2008, 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 }