1 /*
2 * Copyright 1996-2007 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any 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.logging.Logger;
33 import java.util.logging.Level;
34
35 /**
36 * The root event class for all component-level input events.
37 *
38 * Input events are delivered to listeners before they are
39 * processed normally by the source where they originated.
40 * This allows listeners and component subclasses to "consume"
41 * the event so that the source will not process them in their
42 * default manner. For example, consuming mousePressed events
43 * on a Button component will prevent the Button from being
44 * activated.
45 *
46 * @author Carl Quinn
47 *
48 * @see KeyEvent
49 * @see KeyAdapter
50 * @see MouseEvent
51 * @see MouseAdapter
52 * @see MouseMotionAdapter
53 *
54 * @since 1.1
55 */
56 public abstract class InputEvent extends ComponentEvent {
57 private static final Logger log = Logger.getLogger("java.awt.event.InputEvent");
58
59 /**
60 * The Shift key modifier constant.
61 * It is recommended that SHIFT_DOWN_MASK be used instead.
62 */
63 public static final int SHIFT_MASK = Event.SHIFT_MASK;
64
65 /**
66 * The Control key modifier constant.
67 * It is recommended that CTRL_DOWN_MASK be used instead.
68 */
69 public static final int CTRL_MASK = Event.CTRL_MASK;
70
71 /**
72 * The Meta key modifier constant.
73 * It is recommended that META_DOWN_MASK be used instead.
74 */
75 public static final int META_MASK = Event.META_MASK;
76
77 /**
78 * The Alt key modifier constant.
79 * It is recommended that ALT_DOWN_MASK be used instead.
80 */
81 public static final int ALT_MASK = Event.ALT_MASK;
82
83 /**
84 * The AltGraph key modifier constant.
85 */
86 public static final int ALT_GRAPH_MASK = 1 << 5;
87
88 /**
89 * The Mouse Button1 modifier constant.
90 * It is recommended that BUTTON1_DOWN_MASK be used instead.
91 */
92 public static final int BUTTON1_MASK = 1 << 4;
93
94 /**
95 * The Mouse Button2 modifier constant.
96 * It is recommended that BUTTON2_DOWN_MASK be used instead.
97 * Note that BUTTON2_MASK has the same value as ALT_MASK.
98 */
99 public static final int BUTTON2_MASK = Event.ALT_MASK;
100
101 /**
102 * The Mouse Button3 modifier constant.
103 * It is recommended that BUTTON3_DOWN_MASK be used instead.
104 * Note that BUTTON3_MASK has the same value as META_MASK.
105 */
106 public static final int BUTTON3_MASK = Event.META_MASK;
107
108 /**
109 * The Shift key extended modifier constant.
110 * @since 1.4
111 */
112 public static final int SHIFT_DOWN_MASK = 1 << 6;
113
114 /**
115 * The Control key extended modifier constant.
116 * @since 1.4
117 */
118 public static final int CTRL_DOWN_MASK = 1 << 7;
119
120 /**
121 * The Meta key extended modifier constant.
122 * @since 1.4
123 */
124 public static final int META_DOWN_MASK = 1 << 8;
125
126 /**
127 * The Alt key extended modifier constant.
128 * @since 1.4
129 */
130 public static final int ALT_DOWN_MASK = 1 << 9;
131
132 /**
133 * The Mouse Button1 extended modifier constant.
134 * @since 1.4
135 */
136 public static final int BUTTON1_DOWN_MASK = 1 << 10;
137
138 /**
139 * The Mouse Button2 extended modifier constant.
140 * @since 1.4
141 */
142 public static final int BUTTON2_DOWN_MASK = 1 << 11;
143
144 /**
145 * The Mouse Button3 extended modifier constant.
146 * @since 1.4
147 */
148 public static final int BUTTON3_DOWN_MASK = 1 << 12;
149
150 /**
151 * The AltGraph key extended modifier constant.
152 * @since 1.4
153 */
154 public static final int ALT_GRAPH_DOWN_MASK = 1 << 13;
155
156 // the constant below MUST be updated if any extra modifier
157 // bits are to be added!
158 // in fact, it is undesirable to add modifier bits
159 // to the same field as this may break applications
160 // see bug# 5066958
161
162 static final int FIRST_HIGH_BIT = 1 << 14;
163
164 static final int JDK_1_3_MODIFIERS = SHIFT_DOWN_MASK - 1;
165 static final int HIGH_MODIFIERS = ~( FIRST_HIGH_BIT - 1 );
166
167 /**
168 * The input event's Time stamp in UTC format. The time stamp
169 * indicates when the input event was created.
170 *
171 * @serial
172 * @see #getWhen()
173 */
174 long when;
175
176 /**
177 * The state of the modifier mask at the time the input
178 * event was fired.
179 *
180 * @serial
181 * @see #getModifiers()
182 * @see #getModifiersEx()
183 * @see java.awt.event.KeyEvent
184 * @see java.awt.event.MouseEvent
185 */
186 int modifiers;
187
188 /*
189 * A flag that indicates that this instance can be used to access
190 * the system clipboard.
191 */
192 private transient boolean canAccessSystemClipboard;
193
194 static {
195 /* ensure that the necessary native libraries are loaded */
196 NativeLibLoader.loadLibraries();
197 if (!GraphicsEnvironment.isHeadless()) {
198 initIDs();
199 }
200 }
201
202 /**
203 * Initialize JNI field and method IDs for fields that may be
204 accessed from C.
205 */
206 private static native void initIDs();
207
208 /**
209 * Constructs an InputEvent object with the specified source component,
210 * modifiers, and type.
211 * <p> This method throws an
212 * <code>IllegalArgumentException</code> if <code>source</code>
213 * is <code>null</code>.
214 *
215 * @param source the object where the event originated
216 * @param id the integer that identifies the event type.
217 * It is allowed to pass as parameter any value that
218 * allowed for some subclass of {@code InputEvent} class.
219 * Passing in the value different from those values result
220 * in unspecified behavior
221 * @param when a long int that gives the time the event occurred.
222 * Passing negative or zero value
223 * is not recommended
224 * @param modifiers the modifier keys down during event (e.g. shift, ctrl,
225 * alt, meta)
226 * Passing negative parameter is not recommended.
227 * Zero value means no modifiers.
228 * Either extended _DOWN_MASK or old _MASK modifiers
229 * should be used, but both models should not be mixed
230 * in one event. Use of the extended modifiers is
231 * preferred
232 * @throws IllegalArgumentException if <code>source</code> is null
233 * @see #getSource()
234 * @see #getID()
235 * @see #getWhen()
236 * @see #getModifiers()
237 */
238 InputEvent(Component source, int id, long when, int modifiers) {
239 super(source, id);
240 this.when = when;
241 this.modifiers = modifiers;
242 canAccessSystemClipboard = canAccessSystemClipboard();
243 }
244
245 private boolean canAccessSystemClipboard() {
246 boolean b = false;
247
248 if (!GraphicsEnvironment.isHeadless()) {
249 SecurityManager sm = System.getSecurityManager();
250 if (sm != null) {
251 try {
252 sm.checkSystemClipboardAccess();
253 b = true;
254 } catch (SecurityException se) {
255 if (log.isLoggable(Level.FINE)) {
256 log.log(Level.FINE, "InputEvent.canAccessSystemClipboard() got SecurityException ", se);
257 }
258 }
259 } else {
260 b = true;
261 }
262 }
263
264 return b;
265 }
266
267 /**
268 * Returns whether or not the Shift modifier is down on this event.
269 */
270 public boolean isShiftDown() {
271 return (modifiers & SHIFT_MASK) != 0;
272 }
273
274 /**
275 * Returns whether or not the Control modifier is down on this event.
276 */
277 public boolean isControlDown() {
278 return (modifiers & CTRL_MASK) != 0;
279 }
280
281 /**
282 * Returns whether or not the Meta modifier is down on this event.
283 */
284 public boolean isMetaDown() {
285 return (modifiers & META_MASK) != 0;
286 }
287
288 /**
289 * Returns whether or not the Alt modifier is down on this event.
290 */
291 public boolean isAltDown() {
292 return (modifiers & ALT_MASK) != 0;
293 }
294
295 /**
296 * Returns whether or not the AltGraph modifier is down on this event.
297 */
298 public boolean isAltGraphDown() {
299 return (modifiers & ALT_GRAPH_MASK) != 0;
300 }
301
302 /**
303 * Returns the difference in milliseconds between the timestamp of when this event occurred and
304 * midnight, January 1, 1970 UTC.
305 */
306 public long getWhen() {
307 return when;
308 }
309
310 /**
311 * Returns the modifier mask for this event.
312 */
313 public int getModifiers() {
314 return modifiers & (JDK_1_3_MODIFIERS | HIGH_MODIFIERS);
315 }
316
317 /**
318 * Returns the extended modifier mask for this event.
319 * Extended modifiers represent the state of all modal keys,
320 * such as ALT, CTRL, META, and the mouse buttons just after
321 * the event occurred
322 * <P>
323 * For example, if the user presses <b>button 1</b> followed by
324 * <b>button 2</b>, and then releases them in the same order,
325 * the following sequence of events is generated:
326 * <PRE>
327 * <code>MOUSE_PRESSED</code>: <code>BUTTON1_DOWN_MASK</code>
328 * <code>MOUSE_PRESSED</code>: <code>BUTTON1_DOWN_MASK | BUTTON2_DOWN_MASK</code>
329 * <code>MOUSE_RELEASED</code>: <code>BUTTON2_DOWN_MASK</code>
330 * <code>MOUSE_CLICKED</code>: <code>BUTTON2_DOWN_MASK</code>
331 * <code>MOUSE_RELEASED</code>:
332 * <code>MOUSE_CLICKED</code>:
333 * </PRE>
334 * <P>
335 * It is not recommended to compare the return value of this method
336 * using <code>==</code> because new modifiers can be added in the future.
337 * For example, the appropriate way to check that SHIFT and BUTTON1 are
338 * down, but CTRL is up is demonstrated by the following code:
339 * <PRE>
340 * int onmask = SHIFT_DOWN_MASK | BUTTON1_DOWN_MASK;
341 * int offmask = CTRL_DOWN_MASK;
342 * if ((event.getModifiersEx() & (onmask | offmask)) == onmask) {
343 * ...
344 * }
345 * </PRE>
346 * The above code will work even if new modifiers are added.
347 *
348 * @since 1.4
349 */
350 public int getModifiersEx() {
351 return modifiers & ~JDK_1_3_MODIFIERS;
352 }
353
354 /**
355 * Consumes this event so that it will not be processed
356 * in the default manner by the source which originated it.
357 */
358 public void consume() {
359 consumed = true;
360 }
361
362 /**
363 * Returns whether or not this event has been consumed.
364 * @see #consume
365 */
366 public boolean isConsumed() {
367 return consumed;
368 }
369
370 // state serialization compatibility with JDK 1.1
371 static final long serialVersionUID = -2482525981698309786L;
372
373 /**
374 * Returns a String describing the extended modifier keys and
375 * mouse buttons, such as "Shift", "Button1", or "Ctrl+Shift".
376 * These strings can be localized by changing the
377 * <code>awt.properties</code> file.
378 * <p>
379 * Note that passing negative parameter is incorrect,
380 * and will cause the returning an unspecified string.
381 * Zero parameter means that no modifiers were passed and will
382 * cause the returning an empty string.
383 *
384 * @param modifiers a modifier mask describing the extended
385 * modifier keys and mouse buttons for the event
386 * @return a text description of the combination of extended
387 * modifier keys and mouse buttons that were held down
388 * during the event.
389 * @since 1.4
390 */
391 public static String getModifiersExText(int modifiers) {
392 StringBuilder buf = new StringBuilder();
393 if ((modifiers & InputEvent.META_DOWN_MASK) != 0) {
394 buf.append(Toolkit.getProperty("AWT.meta", "Meta"));
395 buf.append("+");
396 }
397 if ((modifiers & InputEvent.CTRL_DOWN_MASK) != 0) {
398 buf.append(Toolkit.getProperty("AWT.control", "Ctrl"));
399 buf.append("+");
400 }
401 if ((modifiers & InputEvent.ALT_DOWN_MASK) != 0) {
402 buf.append(Toolkit.getProperty("AWT.alt", "Alt"));
403 buf.append("+");
404 }
405 if ((modifiers & InputEvent.SHIFT_DOWN_MASK) != 0) {
406 buf.append(Toolkit.getProperty("AWT.shift", "Shift"));
407 buf.append("+");
408 }
409 if ((modifiers & InputEvent.ALT_GRAPH_DOWN_MASK) != 0) {
410 buf.append(Toolkit.getProperty("AWT.altGraph", "Alt Graph"));
411 buf.append("+");
412 }
413 if ((modifiers & InputEvent.BUTTON1_DOWN_MASK) != 0) {
414 buf.append(Toolkit.getProperty("AWT.button1", "Button1"));
415 buf.append("+");
416 }
417 if ((modifiers & InputEvent.BUTTON2_DOWN_MASK) != 0) {
418 buf.append(Toolkit.getProperty("AWT.button2", "Button2"));
419 buf.append("+");
420 }
421 if ((modifiers & InputEvent.BUTTON3_DOWN_MASK) != 0) {
422 buf.append(Toolkit.getProperty("AWT.button3", "Button3"));
423 buf.append("+");
424 }
425 if (buf.length() > 0) {
426 buf.setLength(buf.length()-1); // remove trailing '+'
427 }
428 return buf.toString();
429 }
430 }