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