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;
27
28 import java.util.EventObject;
29 import java.awt.event;
30 import java.awt.peer.ComponentPeer;
31 import java.awt.peer.LightweightPeer;
32 import java.lang.reflect.Field;
33 import java.util.logging.Logger;
34 import java.util.logging.Level;
35
36 /**
37 * The root event class for all AWT events.
38 * This class and its subclasses supercede the original
39 * java.awt.Event class.
40 * Subclasses of this root AWTEvent class defined outside of the
41 * java.awt.event package should define event ID values greater than
42 * the value defined by RESERVED_ID_MAX.
43 * <p>
44 * The event masks defined in this class are needed by Component subclasses
45 * which are using Component.enableEvents() to select for event types not
46 * selected by registered listeners. If a listener is registered on a
47 * component, the appropriate event mask is already set internally by the
48 * component.
49 * <p>
50 * The masks are also used to specify to which types of events an
51 * AWTEventListener should listen. The masks are bitwise-ORed together
52 * and passed to Toolkit.addAWTEventListener.
53 *
54 * @see Component#enableEvents
55 * @see Toolkit#addAWTEventListener
56 *
57 * @see java.awt.event.ActionEvent
58 * @see java.awt.event.AdjustmentEvent
59 * @see java.awt.event.ComponentEvent
60 * @see java.awt.event.ContainerEvent
61 * @see java.awt.event.FocusEvent
62 * @see java.awt.event.InputMethodEvent
63 * @see java.awt.event.InvocationEvent
64 * @see java.awt.event.ItemEvent
65 * @see java.awt.event.HierarchyEvent
66 * @see java.awt.event.KeyEvent
67 * @see java.awt.event.MouseEvent
68 * @see java.awt.event.MouseWheelEvent
69 * @see java.awt.event.PaintEvent
70 * @see java.awt.event.TextEvent
71 * @see java.awt.event.WindowEvent
72 *
73 * @author Carl Quinn
74 * @author Amy Fowler
75 * @since 1.1
76 */
77 public abstract class AWTEvent extends EventObject {
78 private static final Logger log = Logger.getLogger("java.awt.AWTEvent");
79 private byte bdata[];
80
81 /**
82 * The event's id.
83 * @serial
84 * @see #getID()
85 * @see #AWTEvent
86 */
87 protected int id;
88
89 /**
90 * Controls whether or not the event is sent back down to the peer once the
91 * source has processed it - false means it's sent to the peer; true means
92 * it's not. Semantic events always have a 'true' value since they were
93 * generated by the peer in response to a low-level event.
94 * @serial
95 * @see #consume
96 * @see #isConsumed
97 */
98 protected boolean consumed = false;
99
100 transient boolean focusManagerIsDispatching = false;
101 transient boolean isPosted;
102
103 /**
104 * The event mask for selecting component events.
105 */
106 public final static long COMPONENT_EVENT_MASK = 0x01;
107
108 /**
109 * The event mask for selecting container events.
110 */
111 public final static long CONTAINER_EVENT_MASK = 0x02;
112
113 /**
114 * The event mask for selecting focus events.
115 */
116 public final static long FOCUS_EVENT_MASK = 0x04;
117
118 /**
119 * The event mask for selecting key events.
120 */
121 public final static long KEY_EVENT_MASK = 0x08;
122
123 /**
124 * The event mask for selecting mouse events.
125 */
126 public final static long MOUSE_EVENT_MASK = 0x10;
127
128 /**
129 * The event mask for selecting mouse motion events.
130 */
131 public final static long MOUSE_MOTION_EVENT_MASK = 0x20;
132
133 /**
134 * The event mask for selecting window events.
135 */
136 public final static long WINDOW_EVENT_MASK = 0x40;
137
138 /**
139 * The event mask for selecting action events.
140 */
141 public final static long ACTION_EVENT_MASK = 0x80;
142
143 /**
144 * The event mask for selecting adjustment events.
145 */
146 public final static long ADJUSTMENT_EVENT_MASK = 0x100;
147
148 /**
149 * The event mask for selecting item events.
150 */
151 public final static long ITEM_EVENT_MASK = 0x200;
152
153 /**
154 * The event mask for selecting text events.
155 */
156 public final static long TEXT_EVENT_MASK = 0x400;
157
158 /**
159 * The event mask for selecting input method events.
160 */
161 public final static long INPUT_METHOD_EVENT_MASK = 0x800;
162
163 /**
164 * The pseudo event mask for enabling input methods.
165 * We're using one bit in the eventMask so we don't need
166 * a separate field inputMethodsEnabled.
167 */
168 final static long INPUT_METHODS_ENABLED_MASK = 0x1000;
169
170 /**
171 * The event mask for selecting paint events.
172 */
173 public final static long PAINT_EVENT_MASK = 0x2000;
174
175 /**
176 * The event mask for selecting invocation events.
177 */
178 public final static long INVOCATION_EVENT_MASK = 0x4000;
179
180 /**
181 * The event mask for selecting hierarchy events.
182 */
183 public final static long HIERARCHY_EVENT_MASK = 0x8000;
184
185 /**
186 * The event mask for selecting hierarchy bounds events.
187 */
188 public final static long HIERARCHY_BOUNDS_EVENT_MASK = 0x10000;
189
190 /**
191 * The event mask for selecting mouse wheel events.
192 * @since 1.4
193 */
194 public final static long MOUSE_WHEEL_EVENT_MASK = 0x20000;
195
196 /**
197 * The event mask for selecting window state events.
198 * @since 1.4
199 */
200 public final static long WINDOW_STATE_EVENT_MASK = 0x40000;
201
202 /**
203 * The event mask for selecting window focus events.
204 * @since 1.4
205 */
206 public final static long WINDOW_FOCUS_EVENT_MASK = 0x80000;
207
208 /**
209 * WARNING: there are more mask defined privately. See
210 * SunToolkit.GRAB_EVENT_MASK.
211 */
212
213 /**
214 * The maximum value for reserved AWT event IDs. Programs defining
215 * their own event IDs should use IDs greater than this value.
216 */
217 public final static int RESERVED_ID_MAX = 1999;
218
219 // security stuff
220 private static Field inputEvent_CanAccessSystemClipboard_Field = null;
221
222 /*
223 * JDK 1.1 serialVersionUID
224 */
225 private static final long serialVersionUID = -1825314779160409405L;
226
227 static {
228 /* ensure that the necessary native libraries are loaded */
229 Toolkit.loadLibraries();
230 if (!GraphicsEnvironment.isHeadless()) {
231 initIDs();
232 }
233 }
234
235 private static synchronized Field get_InputEvent_CanAccessSystemClipboard() {
236 if (inputEvent_CanAccessSystemClipboard_Field == null) {
237 inputEvent_CanAccessSystemClipboard_Field =
238 (Field)java.security.AccessController.doPrivileged(
239 new java.security.PrivilegedAction() {
240 public Object run() {
241 Field field = null;
242 try {
243 field = InputEvent.class.
244 getDeclaredField("canAccessSystemClipboard");
245 field.setAccessible(true);
246 return field;
247 } catch (SecurityException e) {
248 if (log.isLoggable(Level.FINE)) {
249 log.log(Level.FINE, "AWTEvent.get_InputEvent_CanAccessSystemClipboard() got SecurityException ", e);
250 }
251 } catch (NoSuchFieldException e) {
252 if (log.isLoggable(Level.FINE)) {
253 log.log(Level.FINE, "AWTEvent.get_InputEvent_CanAccessSystemClipboard() got NoSuchFieldException ", e);
254 }
255 }
256 return null;
257 }
258 });
259 }
260
261 return inputEvent_CanAccessSystemClipboard_Field;
262 }
263
264 /**
265 * Initialize JNI field and method IDs for fields that may be
266 * accessed from C.
267 */
268 private static native void initIDs();
269
270 /**
271 * Constructs an AWTEvent object from the parameters of a 1.0-style event.
272 * @param event the old-style event
273 */
274 public AWTEvent(Event event) {
275 this(event.target, event.id);
276 }
277
278 /**
279 * Constructs an AWTEvent object with the specified source object and type.
280 *
281 * @param source the object where the event originated
282 * @param id the event type
283 */
284 public AWTEvent(Object source, int id) {
285 super(source);
286 this.id = id;
287 switch(id) {
288 case ActionEvent.ACTION_PERFORMED:
289 case ItemEvent.ITEM_STATE_CHANGED:
290 case AdjustmentEvent.ADJUSTMENT_VALUE_CHANGED:
291 case TextEvent.TEXT_VALUE_CHANGED:
292 consumed = true;
293 break;
294 default:
295 }
296 }
297
298 /**
299 * Retargets an event to a new source. This method is typically used to
300 * retarget an event to a lightweight child Component of the original
301 * heavyweight source.
302 * <p>
303 * This method is intended to be used only by event targeting subsystems,
304 * such as client-defined KeyboardFocusManagers. It is not for general
305 * client use.
306 *
307 * @param newSource the new Object to which the event should be dispatched
308 * @since 1.4
309 */
310 public void setSource(Object newSource) {
311 if (source == newSource) {
312 return;
313 }
314
315 Component comp = null;
316 if (newSource instanceof Component) {
317 comp = (Component)newSource;
318 while (comp != null && comp.peer != null &&
319 (comp.peer instanceof LightweightPeer)) {
320 comp = comp.parent;
321 }
322 }
323
324 synchronized (this) {
325 source = newSource;
326 if (comp != null) {
327 ComponentPeer peer = comp.peer;
328 if (peer != null) {
329 nativeSetSource(peer);
330 }
331 }
332 }
333 }
334
335 private native void nativeSetSource(ComponentPeer peer);
336
337 /**
338 * Returns the event type.
339 */
340 public int getID() {
341 return id;
342 }
343
344 /**
345 * Returns a String representation of this object.
346 */
347 public String toString() {
348 String srcName = null;
349 if (source instanceof Component) {
350 srcName = ((Component)source).getName();
351 } else if (source instanceof MenuComponent) {
352 srcName = ((MenuComponent)source).getName();
353 }
354 return getClass().getName() + "[" + paramString() + "] on " +
355 (srcName != null? srcName : source);
356 }
357
358 /**
359 * Returns a string representing the state of this <code>Event</code>.
360 * This method is intended to be used only for debugging purposes, and the
361 * content and format of the returned string may vary between
362 * implementations. The returned string may be empty but may not be
363 * <code>null</code>.
364 *
365 * @return a string representation of this event
366 */
367 public String paramString() {
368 return "";
369 }
370
371 /**
372 * Consumes this event, if this event can be consumed. Only low-level,
373 * system events can be consumed
374 */
375 protected void consume() {
376 switch(id) {
377 case KeyEvent.KEY_PRESSED:
378 case KeyEvent.KEY_RELEASED:
379 case MouseEvent.MOUSE_PRESSED:
380 case MouseEvent.MOUSE_RELEASED:
381 case MouseEvent.MOUSE_MOVED:
382 case MouseEvent.MOUSE_DRAGGED:
383 case MouseEvent.MOUSE_ENTERED:
384 case MouseEvent.MOUSE_EXITED:
385 case MouseEvent.MOUSE_WHEEL:
386 case InputMethodEvent.INPUT_METHOD_TEXT_CHANGED:
387 case InputMethodEvent.CARET_POSITION_CHANGED:
388 consumed = true;
389 break;
390 default:
391 // event type cannot be consumed
392 }
393 }
394
395 /**
396 * Returns whether this event has been consumed.
397 */
398 protected boolean isConsumed() {
399 return consumed;
400 }
401
402 /**
403 * Converts a new event to an old one (used for compatibility).
404 * If the new event cannot be converted (because no old equivalent
405 * exists) then this returns null.
406 *
407 * Note: this method is here instead of in each individual new
408 * event class in java.awt.event because we don't want to make
409 * it public and it needs to be called from java.awt.
410 */
411 Event convertToOld() {
412 Object src = getSource();
413 int newid = id;
414
415 switch(id) {
416 case KeyEvent.KEY_PRESSED:
417 case KeyEvent.KEY_RELEASED:
418 KeyEvent ke = (KeyEvent)this;
419 if (ke.isActionKey()) {
420 newid = (id == KeyEvent.KEY_PRESSED?
421 Event.KEY_ACTION : Event.KEY_ACTION_RELEASE);
422 }
423 int keyCode = ke.getKeyCode();
424 if (keyCode == KeyEvent.VK_SHIFT ||
425 keyCode == KeyEvent.VK_CONTROL ||
426 keyCode == KeyEvent.VK_ALT) {
427 return null; // suppress modifier keys in old event model.
428 }
429 // no mask for button1 existed in old Event - strip it out
430 return new Event(src, ke.getWhen(), newid, 0, 0,
431 Event.getOldEventKey(ke),
432 (ke.getModifiers() & ~InputEvent.BUTTON1_MASK));
433
434 case MouseEvent.MOUSE_PRESSED:
435 case MouseEvent.MOUSE_RELEASED:
436 case MouseEvent.MOUSE_MOVED:
437 case MouseEvent.MOUSE_DRAGGED:
438 case MouseEvent.MOUSE_ENTERED:
439 case MouseEvent.MOUSE_EXITED:
440 MouseEvent me = (MouseEvent)this;
441 // no mask for button1 existed in old Event - strip it out
442 Event olde = new Event(src, me.getWhen(), newid,
443 me.getX(), me.getY(), 0,
444 (me.getModifiers() & ~InputEvent.BUTTON1_MASK));
445 olde.clickCount = me.getClickCount();
446 return olde;
447
448 case FocusEvent.FOCUS_GAINED:
449 return new Event(src, Event.GOT_FOCUS, null);
450
451 case FocusEvent.FOCUS_LOST:
452 return new Event(src, Event.LOST_FOCUS, null);
453
454 case WindowEvent.WINDOW_CLOSING:
455 case WindowEvent.WINDOW_ICONIFIED:
456 case WindowEvent.WINDOW_DEICONIFIED:
457 return new Event(src, newid, null);
458
459 case ComponentEvent.COMPONENT_MOVED:
460 if (src instanceof Frame || src instanceof Dialog) {
461 Point p = ((Component)src).getLocation();
462 return new Event(src, 0, Event.WINDOW_MOVED, p.x, p.y, 0, 0);
463 }
464 break;
465
466 case ActionEvent.ACTION_PERFORMED:
467 ActionEvent ae = (ActionEvent)this;
468 String cmd;
469 if (src instanceof Button) {
470 cmd = ((Button)src).getLabel();
471 } else if (src instanceof MenuItem) {
472 cmd = ((MenuItem)src).getLabel();
473 } else {
474 cmd = ae.getActionCommand();
475 }
476 return new Event(src, 0, newid, 0, 0, 0, ae.getModifiers(), cmd);
477
478 case ItemEvent.ITEM_STATE_CHANGED:
479 ItemEvent ie = (ItemEvent)this;
480 Object arg;
481 if (src instanceof List) {
482 newid = (ie.getStateChange() == ItemEvent.SELECTED?
483 Event.LIST_SELECT : Event.LIST_DESELECT);
484 arg = ie.getItem();
485 } else {
486 newid = Event.ACTION_EVENT;
487 if (src instanceof Choice) {
488 arg = ie.getItem();
489
490 } else { // Checkbox
491 arg = Boolean.valueOf(ie.getStateChange() == ItemEvent.SELECTED);
492 }
493 }
494 return new Event(src, newid, arg);
495
496 case AdjustmentEvent.ADJUSTMENT_VALUE_CHANGED:
497 AdjustmentEvent aje = (AdjustmentEvent)this;
498 switch(aje.getAdjustmentType()) {
499 case AdjustmentEvent.UNIT_INCREMENT:
500 newid = Event.SCROLL_LINE_DOWN;
501 break;
502 case AdjustmentEvent.UNIT_DECREMENT:
503 newid = Event.SCROLL_LINE_UP;
504 break;
505 case AdjustmentEvent.BLOCK_INCREMENT:
506 newid = Event.SCROLL_PAGE_DOWN;
507 break;
508 case AdjustmentEvent.BLOCK_DECREMENT:
509 newid = Event.SCROLL_PAGE_UP;
510 break;
511 case AdjustmentEvent.TRACK:
512 if (aje.getValueIsAdjusting()) {
513 newid = Event.SCROLL_ABSOLUTE;
514 }
515 else {
516 newid = Event.SCROLL_END;
517 }
518 break;
519 default:
520 return null;
521 }
522 return new Event(src, newid, Integer.valueOf(aje.getValue()));
523
524 default:
525 }
526 return null;
527 }
528
529 /**
530 * Copies all private data from this event into that.
531 * Space is allocated for the copied data that will be
532 * freed when the that is finalized. Upon completion,
533 * this event is not changed.
534 */
535 void copyPrivateDataInto(AWTEvent that) {
536 that.bdata = this.bdata;
537 // Copy canAccessSystemClipboard value from this into that.
538 if (this instanceof InputEvent && that instanceof InputEvent) {
539 Field field = get_InputEvent_CanAccessSystemClipboard();
540 if (field != null) {
541 try {
542 boolean b = field.getBoolean(this);
543 field.setBoolean(that, b);
544 } catch(IllegalAccessException e) {
545 if (log.isLoggable(Level.FINE)) {
546 log.log(Level.FINE, "AWTEvent.copyPrivateDataInto() got IllegalAccessException ", e);
547 }
548 }
549 }
550 }
551 }
552
553 void dispatched() {
554 if (this instanceof InputEvent) {
555 Field field = get_InputEvent_CanAccessSystemClipboard();
556 if (field != null) {
557 try {
558 field.setBoolean(this, false);
559 } catch(IllegalAccessException e) {
560 if (log.isLoggable(Level.FINE)) {
561 log.log(Level.FINE, "AWTEvent.dispatched() got IllegalAccessException ", e);
562 }
563 }
564 }
565 }
566 }
567 } // class AWTEvent