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
26package java.awt.event;
27
28import java.awt.Event;
29import java.awt.Component;
30import java.awt.GraphicsEnvironment;
31import java.awt.Toolkit;
32import java.util.Arrays;
33
34import sun.awt.AWTAccessor;
35import sun.awt.AWTPermissions;
36import 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 */
59public 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}
586