jdk/src/share/classes/java/awt/AWTEvent.java
changeset 2 90ce3da70b43
child 3084 67ca55732362
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/awt/AWTEvent.java	Sat Dec 01 00:00:00 2007 +0000
@@ -0,0 +1,567 @@
+/*
+ * Copyright 1996-2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package java.awt;
+
+import java.util.EventObject;
+import java.awt.event.*;
+import java.awt.peer.ComponentPeer;
+import java.awt.peer.LightweightPeer;
+import java.lang.reflect.Field;
+import java.util.logging.Logger;
+import java.util.logging.Level;
+
+/**
+ * The root event class for all AWT events.
+ * This class and its subclasses supercede the original
+ * java.awt.Event class.
+ * Subclasses of this root AWTEvent class defined outside of the
+ * java.awt.event package should define event ID values greater than
+ * the value defined by RESERVED_ID_MAX.
+ * <p>
+ * The event masks defined in this class are needed by Component subclasses
+ * which are using Component.enableEvents() to select for event types not
+ * selected by registered listeners. If a listener is registered on a
+ * component, the appropriate event mask is already set internally by the
+ * component.
+ * <p>
+ * The masks are also used to specify to which types of events an
+ * AWTEventListener should listen. The masks are bitwise-ORed together
+ * and passed to Toolkit.addAWTEventListener.
+ *
+ * @see Component#enableEvents
+ * @see Toolkit#addAWTEventListener
+ *
+ * @see java.awt.event.ActionEvent
+ * @see java.awt.event.AdjustmentEvent
+ * @see java.awt.event.ComponentEvent
+ * @see java.awt.event.ContainerEvent
+ * @see java.awt.event.FocusEvent
+ * @see java.awt.event.InputMethodEvent
+ * @see java.awt.event.InvocationEvent
+ * @see java.awt.event.ItemEvent
+ * @see java.awt.event.HierarchyEvent
+ * @see java.awt.event.KeyEvent
+ * @see java.awt.event.MouseEvent
+ * @see java.awt.event.MouseWheelEvent
+ * @see java.awt.event.PaintEvent
+ * @see java.awt.event.TextEvent
+ * @see java.awt.event.WindowEvent
+ *
+ * @author Carl Quinn
+ * @author Amy Fowler
+ * @since 1.1
+ */
+public abstract class AWTEvent extends EventObject {
+    private static final Logger log = Logger.getLogger("java.awt.AWTEvent");
+    private byte bdata[];
+
+    /**
+     * The event's id.
+     * @serial
+     * @see #getID()
+     * @see #AWTEvent
+     */
+    protected int id;
+
+    /**
+     * Controls whether or not the event is sent back down to the peer once the
+     * source has processed it - false means it's sent to the peer; true means
+     * it's not. Semantic events always have a 'true' value since they were
+     * generated by the peer in response to a low-level event.
+     * @serial
+     * @see #consume
+     * @see #isConsumed
+     */
+    protected boolean consumed = false;
+
+    transient boolean focusManagerIsDispatching = false;
+    transient boolean isPosted;
+
+    /**
+     * The event mask for selecting component events.
+     */
+    public final static long COMPONENT_EVENT_MASK = 0x01;
+
+    /**
+     * The event mask for selecting container events.
+     */
+    public final static long CONTAINER_EVENT_MASK = 0x02;
+
+    /**
+     * The event mask for selecting focus events.
+     */
+    public final static long FOCUS_EVENT_MASK = 0x04;
+
+    /**
+     * The event mask for selecting key events.
+     */
+    public final static long KEY_EVENT_MASK = 0x08;
+
+    /**
+     * The event mask for selecting mouse events.
+     */
+    public final static long MOUSE_EVENT_MASK = 0x10;
+
+    /**
+     * The event mask for selecting mouse motion events.
+     */
+    public final static long MOUSE_MOTION_EVENT_MASK = 0x20;
+
+    /**
+     * The event mask for selecting window events.
+     */
+    public final static long WINDOW_EVENT_MASK = 0x40;
+
+    /**
+     * The event mask for selecting action events.
+     */
+    public final static long ACTION_EVENT_MASK = 0x80;
+
+    /**
+     * The event mask for selecting adjustment events.
+     */
+    public final static long ADJUSTMENT_EVENT_MASK = 0x100;
+
+    /**
+     * The event mask for selecting item events.
+     */
+    public final static long ITEM_EVENT_MASK = 0x200;
+
+    /**
+     * The event mask for selecting text events.
+     */
+    public final static long TEXT_EVENT_MASK = 0x400;
+
+    /**
+     * The event mask for selecting input method events.
+     */
+    public final static long INPUT_METHOD_EVENT_MASK = 0x800;
+
+    /**
+     * The pseudo event mask for enabling input methods.
+     * We're using one bit in the eventMask so we don't need
+     * a separate field inputMethodsEnabled.
+     */
+    final static long INPUT_METHODS_ENABLED_MASK = 0x1000;
+
+    /**
+     * The event mask for selecting paint events.
+     */
+    public final static long PAINT_EVENT_MASK = 0x2000;
+
+    /**
+     * The event mask for selecting invocation events.
+     */
+    public final static long INVOCATION_EVENT_MASK = 0x4000;
+
+    /**
+     * The event mask for selecting hierarchy events.
+     */
+    public final static long HIERARCHY_EVENT_MASK = 0x8000;
+
+    /**
+     * The event mask for selecting hierarchy bounds events.
+     */
+    public final static long HIERARCHY_BOUNDS_EVENT_MASK = 0x10000;
+
+    /**
+     * The event mask for selecting mouse wheel events.
+     * @since 1.4
+     */
+    public final static long MOUSE_WHEEL_EVENT_MASK = 0x20000;
+
+    /**
+     * The event mask for selecting window state events.
+     * @since 1.4
+     */
+    public final static long WINDOW_STATE_EVENT_MASK = 0x40000;
+
+    /**
+     * The event mask for selecting window focus events.
+     * @since 1.4
+     */
+    public final static long WINDOW_FOCUS_EVENT_MASK = 0x80000;
+
+    /**
+     * WARNING: there are more mask defined privately.  See
+     * SunToolkit.GRAB_EVENT_MASK.
+     */
+
+    /**
+     * The maximum value for reserved AWT event IDs. Programs defining
+     * their own event IDs should use IDs greater than this value.
+     */
+    public final static int RESERVED_ID_MAX = 1999;
+
+    // security stuff
+    private static Field inputEvent_CanAccessSystemClipboard_Field = null;
+
+    /*
+     * JDK 1.1 serialVersionUID
+     */
+    private static final long serialVersionUID = -1825314779160409405L;
+
+    static {
+        /* ensure that the necessary native libraries are loaded */
+        Toolkit.loadLibraries();
+        if (!GraphicsEnvironment.isHeadless()) {
+            initIDs();
+        }
+    }
+
+    private static synchronized Field get_InputEvent_CanAccessSystemClipboard() {
+        if (inputEvent_CanAccessSystemClipboard_Field == null) {
+            inputEvent_CanAccessSystemClipboard_Field =
+                (Field)java.security.AccessController.doPrivileged(
+                    new java.security.PrivilegedAction() {
+                            public Object run() {
+                                Field field = null;
+                                try {
+                                    field = InputEvent.class.
+                                        getDeclaredField("canAccessSystemClipboard");
+                                    field.setAccessible(true);
+                                    return field;
+                                } catch (SecurityException e) {
+                                    if (log.isLoggable(Level.FINE)) {
+                                        log.log(Level.FINE, "AWTEvent.get_InputEvent_CanAccessSystemClipboard() got SecurityException ", e);
+                                    }
+                                } catch (NoSuchFieldException e) {
+                                    if (log.isLoggable(Level.FINE)) {
+                                        log.log(Level.FINE, "AWTEvent.get_InputEvent_CanAccessSystemClipboard() got NoSuchFieldException ", e);
+                                    }
+                                }
+                                return null;
+                            }
+                        });
+        }
+
+        return inputEvent_CanAccessSystemClipboard_Field;
+    }
+
+    /**
+     * Initialize JNI field and method IDs for fields that may be
+     * accessed from C.
+     */
+    private static native void initIDs();
+
+    /**
+     * Constructs an AWTEvent object from the parameters of a 1.0-style event.
+     * @param event the old-style event
+     */
+    public AWTEvent(Event event) {
+        this(event.target, event.id);
+    }
+
+    /**
+     * Constructs an AWTEvent object with the specified source object and type.
+     *
+     * @param source the object where the event originated
+     * @param id the event type
+     */
+    public AWTEvent(Object source, int id) {
+        super(source);
+        this.id = id;
+        switch(id) {
+          case ActionEvent.ACTION_PERFORMED:
+          case ItemEvent.ITEM_STATE_CHANGED:
+          case AdjustmentEvent.ADJUSTMENT_VALUE_CHANGED:
+          case TextEvent.TEXT_VALUE_CHANGED:
+            consumed = true;
+            break;
+          default:
+        }
+    }
+
+    /**
+     * Retargets an event to a new source. This method is typically used to
+     * retarget an event to a lightweight child Component of the original
+     * heavyweight source.
+     * <p>
+     * This method is intended to be used only by event targeting subsystems,
+     * such as client-defined KeyboardFocusManagers. It is not for general
+     * client use.
+     *
+     * @param newSource the new Object to which the event should be dispatched
+     * @since 1.4
+     */
+    public void setSource(Object newSource) {
+        if (source == newSource) {
+            return;
+        }
+
+        Component comp = null;
+        if (newSource instanceof Component) {
+            comp = (Component)newSource;
+            while (comp != null && comp.peer != null &&
+                   (comp.peer instanceof LightweightPeer)) {
+                comp = comp.parent;
+            }
+        }
+
+        synchronized (this) {
+            source = newSource;
+            if (comp != null) {
+                ComponentPeer peer = comp.peer;
+                if (peer != null) {
+                    nativeSetSource(peer);
+                }
+            }
+        }
+    }
+
+    private native void nativeSetSource(ComponentPeer peer);
+
+    /**
+     * Returns the event type.
+     */
+    public int getID() {
+        return id;
+    }
+
+    /**
+     * Returns a String representation of this object.
+     */
+    public String toString() {
+        String srcName = null;
+        if (source instanceof Component) {
+            srcName = ((Component)source).getName();
+        } else if (source instanceof MenuComponent) {
+            srcName = ((MenuComponent)source).getName();
+        }
+        return getClass().getName() + "[" + paramString() + "] on " +
+            (srcName != null? srcName : source);
+    }
+
+    /**
+     * Returns a string representing the state of this <code>Event</code>.
+     * This method is intended to be used only for debugging purposes, and the
+     * content and format of the returned string may vary between
+     * implementations. The returned string may be empty but may not be
+     * <code>null</code>.
+     *
+     * @return  a string representation of this event
+     */
+    public String paramString() {
+        return "";
+    }
+
+    /**
+     * Consumes this event, if this event can be consumed. Only low-level,
+     * system events can be consumed
+     */
+    protected void consume() {
+        switch(id) {
+          case KeyEvent.KEY_PRESSED:
+          case KeyEvent.KEY_RELEASED:
+          case MouseEvent.MOUSE_PRESSED:
+          case MouseEvent.MOUSE_RELEASED:
+          case MouseEvent.MOUSE_MOVED:
+          case MouseEvent.MOUSE_DRAGGED:
+          case MouseEvent.MOUSE_ENTERED:
+          case MouseEvent.MOUSE_EXITED:
+          case MouseEvent.MOUSE_WHEEL:
+          case InputMethodEvent.INPUT_METHOD_TEXT_CHANGED:
+          case InputMethodEvent.CARET_POSITION_CHANGED:
+              consumed = true;
+              break;
+          default:
+              // event type cannot be consumed
+        }
+    }
+
+    /**
+     * Returns whether this event has been consumed.
+     */
+    protected boolean isConsumed() {
+        return consumed;
+    }
+
+    /**
+     * Converts a new event to an old one (used for compatibility).
+     * If the new event cannot be converted (because no old equivalent
+     * exists) then this returns null.
+     *
+     * Note: this method is here instead of in each individual new
+     * event class in java.awt.event because we don't want to make
+     * it public and it needs to be called from java.awt.
+     */
+    Event convertToOld() {
+        Object src = getSource();
+        int newid = id;
+
+        switch(id) {
+          case KeyEvent.KEY_PRESSED:
+          case KeyEvent.KEY_RELEASED:
+              KeyEvent ke = (KeyEvent)this;
+              if (ke.isActionKey()) {
+                  newid = (id == KeyEvent.KEY_PRESSED?
+                           Event.KEY_ACTION : Event.KEY_ACTION_RELEASE);
+              }
+              int keyCode = ke.getKeyCode();
+              if (keyCode == KeyEvent.VK_SHIFT ||
+                  keyCode == KeyEvent.VK_CONTROL ||
+                  keyCode == KeyEvent.VK_ALT) {
+                  return null;  // suppress modifier keys in old event model.
+              }
+              // no mask for button1 existed in old Event - strip it out
+              return new Event(src, ke.getWhen(), newid, 0, 0,
+                               Event.getOldEventKey(ke),
+                               (ke.getModifiers() & ~InputEvent.BUTTON1_MASK));
+
+          case MouseEvent.MOUSE_PRESSED:
+          case MouseEvent.MOUSE_RELEASED:
+          case MouseEvent.MOUSE_MOVED:
+          case MouseEvent.MOUSE_DRAGGED:
+          case MouseEvent.MOUSE_ENTERED:
+          case MouseEvent.MOUSE_EXITED:
+              MouseEvent me = (MouseEvent)this;
+              // no mask for button1 existed in old Event - strip it out
+              Event olde = new Event(src, me.getWhen(), newid,
+                               me.getX(), me.getY(), 0,
+                               (me.getModifiers() & ~InputEvent.BUTTON1_MASK));
+              olde.clickCount = me.getClickCount();
+              return olde;
+
+          case FocusEvent.FOCUS_GAINED:
+              return new Event(src, Event.GOT_FOCUS, null);
+
+          case FocusEvent.FOCUS_LOST:
+              return new Event(src, Event.LOST_FOCUS, null);
+
+          case WindowEvent.WINDOW_CLOSING:
+          case WindowEvent.WINDOW_ICONIFIED:
+          case WindowEvent.WINDOW_DEICONIFIED:
+              return new Event(src, newid, null);
+
+          case ComponentEvent.COMPONENT_MOVED:
+              if (src instanceof Frame || src instanceof Dialog) {
+                  Point p = ((Component)src).getLocation();
+                  return new Event(src, 0, Event.WINDOW_MOVED, p.x, p.y, 0, 0);
+              }
+              break;
+
+          case ActionEvent.ACTION_PERFORMED:
+              ActionEvent ae = (ActionEvent)this;
+              String cmd;
+              if (src instanceof Button) {
+                  cmd = ((Button)src).getLabel();
+              } else if (src instanceof MenuItem) {
+                  cmd = ((MenuItem)src).getLabel();
+              } else {
+                  cmd = ae.getActionCommand();
+              }
+              return new Event(src, 0, newid, 0, 0, 0, ae.getModifiers(), cmd);
+
+          case ItemEvent.ITEM_STATE_CHANGED:
+              ItemEvent ie = (ItemEvent)this;
+              Object arg;
+              if (src instanceof List) {
+                  newid = (ie.getStateChange() == ItemEvent.SELECTED?
+                           Event.LIST_SELECT : Event.LIST_DESELECT);
+                  arg = ie.getItem();
+              } else {
+                  newid = Event.ACTION_EVENT;
+                  if (src instanceof Choice) {
+                      arg = ie.getItem();
+
+                  } else { // Checkbox
+                      arg = Boolean.valueOf(ie.getStateChange() == ItemEvent.SELECTED);
+                  }
+              }
+              return new Event(src, newid, arg);
+
+          case AdjustmentEvent.ADJUSTMENT_VALUE_CHANGED:
+              AdjustmentEvent aje = (AdjustmentEvent)this;
+              switch(aje.getAdjustmentType()) {
+                case AdjustmentEvent.UNIT_INCREMENT:
+                  newid = Event.SCROLL_LINE_DOWN;
+                  break;
+                case AdjustmentEvent.UNIT_DECREMENT:
+                  newid = Event.SCROLL_LINE_UP;
+                  break;
+                case AdjustmentEvent.BLOCK_INCREMENT:
+                  newid = Event.SCROLL_PAGE_DOWN;
+                  break;
+                case AdjustmentEvent.BLOCK_DECREMENT:
+                  newid = Event.SCROLL_PAGE_UP;
+                  break;
+                case AdjustmentEvent.TRACK:
+                  if (aje.getValueIsAdjusting()) {
+                      newid = Event.SCROLL_ABSOLUTE;
+                  }
+                  else {
+                      newid = Event.SCROLL_END;
+                  }
+                  break;
+                default:
+                  return null;
+              }
+              return new Event(src, newid, Integer.valueOf(aje.getValue()));
+
+          default:
+        }
+        return null;
+    }
+
+    /**
+     * Copies all private data from this event into that.
+     * Space is allocated for the copied data that will be
+     * freed when the that is finalized. Upon completion,
+     * this event is not changed.
+     */
+    void copyPrivateDataInto(AWTEvent that) {
+        that.bdata = this.bdata;
+        // Copy canAccessSystemClipboard value from this into that.
+        if (this instanceof InputEvent && that instanceof InputEvent) {
+            Field field = get_InputEvent_CanAccessSystemClipboard();
+            if (field != null) {
+                try {
+                    boolean b = field.getBoolean(this);
+                    field.setBoolean(that, b);
+                } catch(IllegalAccessException e) {
+                    if (log.isLoggable(Level.FINE)) {
+                        log.log(Level.FINE, "AWTEvent.copyPrivateDataInto() got IllegalAccessException ", e);
+                    }
+                }
+            }
+        }
+    }
+
+    void dispatched() {
+        if (this instanceof InputEvent) {
+            Field field = get_InputEvent_CanAccessSystemClipboard();
+            if (field != null) {
+                try {
+                    field.setBoolean(this, false);
+                } catch(IllegalAccessException e) {
+                    if (log.isLoggable(Level.FINE)) {
+                        log.log(Level.FINE, "AWTEvent.dispatched() got IllegalAccessException ", e);
+                    }
+                }
+            }
+        }
+    }
+} // class AWTEvent