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      */
getButtonDownMasks()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      */
getMaskForButton(int button)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 */
NativeLibLoader.loadLibraries()317         NativeLibLoader.loadLibraries();
318         if (!GraphicsEnvironment.isHeadless()) {
initIDs()319             initIDs();
320         }
AWTAccessor.setInputEventAccessor( new AWTAccessor.InputEventAccessor() { public int[] getButtonDownMasks() { return InputEvent.getButtonDownMasks(); } public boolean canAccessSystemClipboard(InputEvent event) { return event.canAccessSystemClipboard; } @Override public void setCanAccessSystemClipboard(InputEvent event, boolean canAccessSystemClipboard) { event.canAccessSystemClipboard = canAccessSystemClipboard; } })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      */
initIDs()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      */
InputEvent(Component source, int id, long when, int modifiers)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 
canAccessSystemClipboard()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      */
isShiftDown()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      */
isControlDown()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      */
isMetaDown()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      */
isAltDown()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      */
isAltGraphDown()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      */
getWhen()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")
getModifiers()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      */
getModifiersEx()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      */
consume()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      */
isConsumed()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      */
getModifiersExText(int modifiers)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 }
586