View Javadoc
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.util.logging.PlatformLogger;
36  import sun.security.util.SecurityConstants;
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 7.0
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 phisical 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 7.0
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      * <p>
237      * @throws IllegalArgumentException if {@code button} is less than zero or greater than the number
238      *         of button masks reserved for buttons
239      * @since 7.0
240      * @see java.awt.MouseInfo#getNumberOfButtons()
241      * @see Toolkit#areExtraMouseButtonsEnabled()
242      * @see MouseEvent#getModifiers()
243      * @see MouseEvent#getModifiersEx()
244      */
245     public static int getMaskForButton(int button) {
246         if (button <= 0 || button > BUTTON_DOWN_MASK.length) {
247             throw new IllegalArgumentException("button doesn\'t exist " + button);
248         }
249         return BUTTON_DOWN_MASK[button - 1];
250     }
251 
252     // the constant below MUST be updated if any extra modifier
253     // bits are to be added!
254     // in fact, it is undesirable to add modifier bits
255     // to the same field as this may break applications
256     // see bug# 5066958
257     static final int FIRST_HIGH_BIT = 1 << 31;
258 
259     static final int JDK_1_3_MODIFIERS = SHIFT_DOWN_MASK - 1;
260     static final int HIGH_MODIFIERS = ~( FIRST_HIGH_BIT - 1 );
261 
262     /**
263      * The input event's Time stamp in UTC format.  The time stamp
264      * indicates when the input event was created.
265      *
266      * @serial
267      * @see #getWhen()
268      */
269     long when;
270 
271     /**
272      * The state of the modifier mask at the time the input
273      * event was fired.
274      *
275      * @serial
276      * @see #getModifiers()
277      * @see #getModifiersEx()
278      * @see java.awt.event.KeyEvent
279      * @see java.awt.event.MouseEvent
280      */
281     int modifiers;
282 
283     /*
284      * A flag that indicates that this instance can be used to access
285      * the system clipboard.
286      */
287     private transient boolean canAccessSystemClipboard;
288 
289     static {
290         /* ensure that the necessary native libraries are loaded */
291         NativeLibLoader.loadLibraries();
292         if (!GraphicsEnvironment.isHeadless()) {
293             initIDs();
294         }
295         AWTAccessor.setInputEventAccessor(
296             new AWTAccessor.InputEventAccessor() {
297                 public int[] getButtonDownMasks() {
298                     return InputEvent.getButtonDownMasks();
299                 }
300             });
301     }
302 
303     /**
304      * Initialize JNI field and method IDs for fields that may be
305        accessed from C.
306      */
307     private static native void initIDs();
308 
309     /**
310      * Constructs an InputEvent object with the specified source component,
311      * modifiers, and type.
312      * <p> This method throws an
313      * <code>IllegalArgumentException</code> if <code>source</code>
314      * is <code>null</code>.
315      *
316      * @param source the object where the event originated
317      * @param id           the integer that identifies the event type.
318      *                     It is allowed to pass as parameter any value that
319      *                     allowed for some subclass of {@code InputEvent} class.
320      *                     Passing in the value different from those values result
321      *                     in unspecified behavior
322      * @param when         a long int that gives the time the event occurred.
323      *                     Passing negative or zero value
324      *                     is not recommended
325      * @param modifiers    a modifier mask describing the modifier keys and mouse
326      *                     buttons (for example, shift, ctrl, alt, and meta) that
327      *                     are down during the event.
328      *                     Only extended modifiers are allowed to be used as a
329      *                     value for this parameter (see the {@link InputEvent#getModifiersEx}
330      *                     class for the description of extended modifiers).
331      *                     Passing negative parameter
332      *                     is not recommended.
333      *                     Zero value means that no modifiers were passed
334      * @throws IllegalArgumentException if <code>source</code> is null
335      * @see #getSource()
336      * @see #getID()
337      * @see #getWhen()
338      * @see #getModifiers()
339      */
340     InputEvent(Component source, int id, long when, int modifiers) {
341         super(source, id);
342         this.when = when;
343         this.modifiers = modifiers;
344         canAccessSystemClipboard = canAccessSystemClipboard();
345     }
346 
347     private boolean canAccessSystemClipboard() {
348         boolean b = false;
349 
350         if (!GraphicsEnvironment.isHeadless()) {
351             SecurityManager sm = System.getSecurityManager();
352             if (sm != null) {
353                 try {
354                     sm.checkPermission(SecurityConstants.AWT.ACCESS_CLIPBOARD_PERMISSION);
355                     b = true;
356                 } catch (SecurityException se) {
357                     if (logger.isLoggable(PlatformLogger.Level.FINE)) {
358                         logger.fine("InputEvent.canAccessSystemClipboard() got SecurityException ", se);
359                     }
360                 }
361             } else {
362                 b = true;
363             }
364         }
365 
366         return b;
367     }
368 
369     /**
370      * Returns whether or not the Shift modifier is down on this event.
371      */
372     public boolean isShiftDown() {
373         return (modifiers & SHIFT_MASK) != 0;
374     }
375 
376     /**
377      * Returns whether or not the Control modifier is down on this event.
378      */
379     public boolean isControlDown() {
380         return (modifiers & CTRL_MASK) != 0;
381     }
382 
383     /**
384      * Returns whether or not the Meta modifier is down on this event.
385      */
386     public boolean isMetaDown() {
387         return (modifiers & META_MASK) != 0;
388     }
389 
390     /**
391      * Returns whether or not the Alt modifier is down on this event.
392      */
393     public boolean isAltDown() {
394         return (modifiers & ALT_MASK) != 0;
395     }
396 
397     /**
398      * Returns whether or not the AltGraph modifier is down on this event.
399      */
400     public boolean isAltGraphDown() {
401         return (modifiers & ALT_GRAPH_MASK) != 0;
402     }
403 
404     /**
405      * Returns the difference in milliseconds between the timestamp of when this event occurred and
406      * midnight, January 1, 1970 UTC.
407      */
408     public long getWhen() {
409         return when;
410     }
411 
412     /**
413      * Returns the modifier mask for this event.
414      */
415     public int getModifiers() {
416         return modifiers & (JDK_1_3_MODIFIERS | HIGH_MODIFIERS);
417     }
418 
419     /**
420      * Returns the extended modifier mask for this event.
421      * <P>
422      * Extended modifiers are the modifiers that ends with the _DOWN_MASK suffix,
423      * such as ALT_DOWN_MASK, BUTTON1_DOWN_MASK, and others.
424      * <P>
425      * Extended modifiers represent the state of all modal keys,
426      * such as ALT, CTRL, META, and the mouse buttons just after
427      * the event occurred.
428      * <P>
429      * For example, if the user presses <b>button 1</b> followed by
430      * <b>button 2</b>, and then releases them in the same order,
431      * the following sequence of events is generated:
432      * <PRE>
433      *    <code>MOUSE_PRESSED</code>:  <code>BUTTON1_DOWN_MASK</code>
434      *    <code>MOUSE_PRESSED</code>:  <code>BUTTON1_DOWN_MASK | BUTTON2_DOWN_MASK</code>
435      *    <code>MOUSE_RELEASED</code>: <code>BUTTON2_DOWN_MASK</code>
436      *    <code>MOUSE_CLICKED</code>:  <code>BUTTON2_DOWN_MASK</code>
437      *    <code>MOUSE_RELEASED</code>:
438      *    <code>MOUSE_CLICKED</code>:
439      * </PRE>
440      * <P>
441      * It is not recommended to compare the return value of this method
442      * using <code>==</code> because new modifiers can be added in the future.
443      * For example, the appropriate way to check that SHIFT and BUTTON1 are
444      * down, but CTRL is up is demonstrated by the following code:
445      * <PRE>
446      *    int onmask = SHIFT_DOWN_MASK | BUTTON1_DOWN_MASK;
447      *    int offmask = CTRL_DOWN_MASK;
448      *    if ((event.getModifiersEx() &amp; (onmask | offmask)) == onmask) {
449      *        ...
450      *    }
451      * </PRE>
452      * The above code will work even if new modifiers are added.
453      *
454      * @since 1.4
455      */
456     public int getModifiersEx() {
457         return modifiers & ~JDK_1_3_MODIFIERS;
458     }
459 
460     /**
461      * Consumes this event so that it will not be processed
462      * in the default manner by the source which originated it.
463      */
464     public void consume() {
465         consumed = true;
466     }
467 
468     /**
469      * Returns whether or not this event has been consumed.
470      * @see #consume
471      */
472     public boolean isConsumed() {
473         return consumed;
474     }
475 
476     // state serialization compatibility with JDK 1.1
477     static final long serialVersionUID = -2482525981698309786L;
478 
479     /**
480      * Returns a String describing the extended modifier keys and
481      * mouse buttons, such as "Shift", "Button1", or "Ctrl+Shift".
482      * These strings can be localized by changing the
483      * <code>awt.properties</code> file.
484      * <p>
485      * Note that passing negative parameter is incorrect,
486      * and will cause the returning an unspecified string.
487      * Zero parameter means that no modifiers were passed and will
488      * cause the returning an empty string.
489      *
490      * @param modifiers a modifier mask describing the extended
491      *                modifier keys and mouse buttons for the event
492      * @return a text description of the combination of extended
493      *         modifier keys and mouse buttons that were held down
494      *         during the event.
495      * @since 1.4
496      */
497     public static String getModifiersExText(int modifiers) {
498         StringBuilder buf = new StringBuilder();
499         if ((modifiers & InputEvent.META_DOWN_MASK) != 0) {
500             buf.append(Toolkit.getProperty("AWT.meta", "Meta"));
501             buf.append("+");
502         }
503         if ((modifiers & InputEvent.CTRL_DOWN_MASK) != 0) {
504             buf.append(Toolkit.getProperty("AWT.control", "Ctrl"));
505             buf.append("+");
506         }
507         if ((modifiers & InputEvent.ALT_DOWN_MASK) != 0) {
508             buf.append(Toolkit.getProperty("AWT.alt", "Alt"));
509             buf.append("+");
510         }
511         if ((modifiers & InputEvent.SHIFT_DOWN_MASK) != 0) {
512             buf.append(Toolkit.getProperty("AWT.shift", "Shift"));
513             buf.append("+");
514         }
515         if ((modifiers & InputEvent.ALT_GRAPH_DOWN_MASK) != 0) {
516             buf.append(Toolkit.getProperty("AWT.altGraph", "Alt Graph"));
517             buf.append("+");
518         }
519 
520         int buttonNumber = 1;
521         for (int mask : InputEvent.BUTTON_DOWN_MASK){
522             if ((modifiers & mask) != 0) {
523                 buf.append(Toolkit.getProperty("AWT.button"+buttonNumber, "Button"+buttonNumber));
524                 buf.append("+");
525             }
526             buttonNumber++;
527         }
528         if (buf.length() > 0) {
529             buf.setLength(buf.length()-1); // remove trailing '+'
530         }
531         return buf.toString();
532     }
533 }