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