Save This Page
Home » openjdk-7 » java » awt » [javadoc | source]
    1   /*
    2    * Copyright 1995-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   package java.awt;
   26   
   27   import java.awt.dnd.DropTarget;
   28   
   29   import java.awt.event;
   30   
   31   import java.awt.peer.ContainerPeer;
   32   import java.awt.peer.ComponentPeer;
   33   import java.awt.peer.LightweightPeer;
   34   
   35   import java.beans.PropertyChangeListener;
   36   
   37   import java.io.IOException;
   38   import java.io.ObjectInputStream;
   39   import java.io.ObjectOutputStream;
   40   import java.io.ObjectStreamField;
   41   import java.io.PrintStream;
   42   import java.io.PrintWriter;
   43   
   44   import java.util.Arrays;
   45   import java.util.EventListener;
   46   import java.util.HashSet;
   47   import java.util.Iterator;
   48   import java.util.LinkedList;
   49   import java.util.Set;
   50   
   51   import java.util.logging;
   52   
   53   import javax.accessibility;
   54   
   55   import sun.awt.AppContext;
   56   import sun.awt.CausedFocusEvent;
   57   import sun.awt.PeerEvent;
   58   import sun.awt.SunToolkit;
   59   
   60   import sun.awt.dnd.SunDropTargetEvent;
   61   
   62   import sun.java2d.pipe.Region;
   63   
   64   /**
   65    * A generic Abstract Window Toolkit(AWT) container object is a component
   66    * that can contain other AWT components.
   67    * <p>
   68    * Components added to a container are tracked in a list.  The order
   69    * of the list will define the components' front-to-back stacking order
   70    * within the container.  If no index is specified when adding a
   71    * component to a container, it will be added to the end of the list
   72    * (and hence to the bottom of the stacking order).
   73    * <p>
   74    * <b>Note</b>: For details on the focus subsystem, see
   75    * <a href="http://java.sun.com/docs/books/tutorial/uiswing/misc/focus.html">
   76    * How to Use the Focus Subsystem</a>,
   77    * a section in <em>The Java Tutorial</em>, and the
   78    * <a href="../../java/awt/doc-files/FocusSpec.html">Focus Specification</a>
   79    * for more information.
   80    *
   81    * @author      Arthur van Hoff
   82    * @author      Sami Shaio
   83    * @see       #add(java.awt.Component, int)
   84    * @see       #getComponent(int)
   85    * @see       LayoutManager
   86    * @since     JDK1.0
   87    */
   88   public class Container extends Component {
   89   
   90       private static final Logger log = Logger.getLogger("java.awt.Container");
   91       private static final Logger eventLog = Logger.getLogger("java.awt.event.Container");
   92   
   93       /**
   94        * The number of components in this container.
   95        * This value can be null.
   96        * @see #getComponent
   97        * @see #getComponents
   98        * @see #getComponentCount
   99        */
  100       int ncomponents;
  101   
  102       /**
  103        * The components in this container.
  104        * @see #add
  105        * @see #getComponents
  106        */
  107       Component component[] = new Component[0];
  108   
  109       /**
  110        * Layout manager for this container.
  111        * @see #doLayout
  112        * @see #setLayout
  113        * @see #getLayout
  114        */
  115       LayoutManager layoutMgr;
  116   
  117       /**
  118        * Event router for lightweight components.  If this container
  119        * is native, this dispatcher takes care of forwarding and
  120        * retargeting the events to lightweight components contained
  121        * (if any).
  122        */
  123       private LightweightDispatcher dispatcher;
  124   
  125       /**
  126        * The focus traversal policy that will manage keyboard traversal of this
  127        * Container's children, if this Container is a focus cycle root. If the
  128        * value is null, this Container inherits its policy from its focus-cycle-
  129        * root ancestor. If all such ancestors of this Container have null
  130        * policies, then the current KeyboardFocusManager's default policy is
  131        * used. If the value is non-null, this policy will be inherited by all
  132        * focus-cycle-root children that have no keyboard-traversal policy of
  133        * their own (as will, recursively, their focus-cycle-root children).
  134        * <p>
  135        * If this Container is not a focus cycle root, the value will be
  136        * remembered, but will not be used or inherited by this or any other
  137        * Containers until this Container is made a focus cycle root.
  138        *
  139        * @see #setFocusTraversalPolicy
  140        * @see #getFocusTraversalPolicy
  141        * @since 1.4
  142        */
  143       private transient FocusTraversalPolicy focusTraversalPolicy;
  144   
  145       /**
  146        * Indicates whether this Component is the root of a focus traversal cycle.
  147        * Once focus enters a traversal cycle, typically it cannot leave it via
  148        * focus traversal unless one of the up- or down-cycle keys is pressed.
  149        * Normal traversal is limited to this Container, and all of this
  150        * Container's descendants that are not descendants of inferior focus cycle
  151        * roots.
  152        *
  153        * @see #setFocusCycleRoot
  154        * @see #isFocusCycleRoot
  155        * @since 1.4
  156        */
  157       private boolean focusCycleRoot = false;
  158   
  159   
  160       /**
  161        * Stores the value of focusTraversalPolicyProvider property.
  162        * @since 1.5
  163        * @see #setFocusTraversalPolicyProvider
  164        */
  165       private boolean focusTraversalPolicyProvider;
  166   
  167       // keeps track of the threads that are printing this component
  168       private transient Set printingThreads;
  169       // True if there is at least one thread that's printing this component
  170       private transient boolean printing = false;
  171   
  172       transient ContainerListener containerListener;
  173   
  174       /* HierarchyListener and HierarchyBoundsListener support */
  175       transient int listeningChildren;
  176       transient int listeningBoundsChildren;
  177       transient int descendantsCount;
  178   
  179       /**
  180        * JDK 1.1 serialVersionUID
  181        */
  182       private static final long serialVersionUID = 4613797578919906343L;
  183   
  184       /**
  185        * A constant which toggles one of the controllable behaviors
  186        * of <code>getMouseEventTarget</code>. It is used to specify whether
  187        * the method can return the Container on which it is originally called
  188        * in case if none of its children are the current mouse event targets.
  189        *
  190        * @see #getMouseEventTarget(int, int, boolean, boolean, boolean)
  191        */
  192       static final boolean INCLUDE_SELF = true;
  193   
  194       /**
  195        * A constant which toggles one of the controllable behaviors
  196        * of <code>getMouseEventTarget</code>. It is used to specify whether
  197        * the method should search only lightweight components.
  198        *
  199        * @see #getMouseEventTarget(int, int, boolean, boolean, boolean)
  200        */
  201       static final boolean SEARCH_HEAVYWEIGHTS = true;
  202   
  203       /*
  204        * Number of HW or LW components in this container (including
  205        * all descendant containers).
  206        */
  207       private transient int numOfHWComponents = 0;
  208       private transient int numOfLWComponents = 0;
  209   
  210       private static final Logger mixingLog = Logger.getLogger("java.awt.mixing.Container");
  211   
  212       /**
  213        * @serialField ncomponents                     int
  214        *       The number of components in this container.
  215        *       This value can be null.
  216        * @serialField component                       Component[]
  217        *       The components in this container.
  218        * @serialField layoutMgr                       LayoutManager
  219        *       Layout manager for this container.
  220        * @serialField dispatcher                      LightweightDispatcher
  221        *       Event router for lightweight components.  If this container
  222        *       is native, this dispatcher takes care of forwarding and
  223        *       retargeting the events to lightweight components contained
  224        *       (if any).
  225        * @serialField maxSize                         Dimension
  226        *       Maximum size of this Container.
  227        * @serialField focusCycleRoot                  boolean
  228        *       Indicates whether this Component is the root of a focus traversal cycle.
  229        *       Once focus enters a traversal cycle, typically it cannot leave it via
  230        *       focus traversal unless one of the up- or down-cycle keys is pressed.
  231        *       Normal traversal is limited to this Container, and all of this
  232        *       Container's descendants that are not descendants of inferior focus cycle
  233        *       roots.
  234        * @serialField containerSerializedDataVersion  int
  235        *       Container Serial Data Version.
  236        * @serialField focusTraversalPolicyProvider    boolean
  237        *       Stores the value of focusTraversalPolicyProvider property.
  238        */
  239       private static final ObjectStreamField[] serialPersistentFields = {
  240           new ObjectStreamField("ncomponents", Integer.TYPE),
  241           new ObjectStreamField("component", Component[].class),
  242           new ObjectStreamField("layoutMgr", LayoutManager.class),
  243           new ObjectStreamField("dispatcher", LightweightDispatcher.class),
  244           new ObjectStreamField("maxSize", Dimension.class),
  245           new ObjectStreamField("focusCycleRoot", Boolean.TYPE),
  246           new ObjectStreamField("containerSerializedDataVersion", Integer.TYPE),
  247           new ObjectStreamField("focusTraversalPolicyProvider", Boolean.TYPE),
  248       };
  249   
  250       static {
  251           /* ensure that the necessary native libraries are loaded */
  252           Toolkit.loadLibraries();
  253           if (!GraphicsEnvironment.isHeadless()) {
  254               initIDs();
  255           }
  256       }
  257   
  258       /**
  259        * Initialize JNI field and method IDs for fields that may be
  260          called from C.
  261        */
  262       private static native void initIDs();
  263   
  264       /**
  265        * Constructs a new Container. Containers can be extended directly,
  266        * but are lightweight in this case and must be contained by a parent
  267        * somewhere higher up in the component tree that is native.
  268        * (such as Frame for example).
  269        */
  270       public Container() {
  271       }
  272   
  273       void initializeFocusTraversalKeys() {
  274           focusTraversalKeys = new Set[4];
  275       }
  276   
  277       /**
  278        * Gets the number of components in this panel.
  279        * @return    the number of components in this panel.
  280        * @see       #getComponent
  281        * @since     JDK1.1
  282        */
  283       public int getComponentCount() {
  284           return countComponents();
  285       }
  286   
  287       /**
  288        * @deprecated As of JDK version 1.1,
  289        * replaced by getComponentCount().
  290        */
  291       @Deprecated
  292       public int countComponents() {
  293           return ncomponents;
  294       }
  295   
  296       /**
  297        * Gets the nth component in this container.
  298        * @param      n   the index of the component to get.
  299        * @return     the n<sup>th</sup> component in this container.
  300        * @exception  ArrayIndexOutOfBoundsException
  301        *                 if the n<sup>th</sup> value does not exist.
  302        */
  303       public Component getComponent(int n) {
  304           synchronized (getTreeLock()) {
  305               if ((n < 0) || (n >= ncomponents)) {
  306                   throw new ArrayIndexOutOfBoundsException("No such child: " + n);
  307               }
  308               return component[n];
  309           }
  310       }
  311   
  312       /**
  313        * Gets all the components in this container.
  314        * @return    an array of all the components in this container.
  315        */
  316       public Component[] getComponents() {
  317           return getComponents_NoClientCode();
  318       }
  319       // NOTE: This method may be called by privileged threads.
  320       //       This functionality is implemented in a package-private method
  321       //       to insure that it cannot be overridden by client subclasses.
  322       //       DO NOT INVOKE CLIENT CODE ON THIS THREAD!
  323       final Component[] getComponents_NoClientCode() {
  324           synchronized (getTreeLock()) {
  325               return Arrays.copyOf(component, ncomponents);
  326           }
  327       } // getComponents_NoClientCode()
  328   
  329       /**
  330        * Determines the insets of this container, which indicate the size
  331        * of the container's border.
  332        * <p>
  333        * A <code>Frame</code> object, for example, has a top inset that
  334        * corresponds to the height of the frame's title bar.
  335        * @return    the insets of this container.
  336        * @see       Insets
  337        * @see       LayoutManager
  338        * @since     JDK1.1
  339        */
  340       public Insets getInsets() {
  341           return insets();
  342       }
  343   
  344       /**
  345        * @deprecated As of JDK version 1.1,
  346        * replaced by <code>getInsets()</code>.
  347        */
  348       @Deprecated
  349       public Insets insets() {
  350           ComponentPeer peer = this.peer;
  351           if (peer instanceof ContainerPeer) {
  352               ContainerPeer cpeer = (ContainerPeer)peer;
  353               return (Insets)cpeer.insets().clone();
  354           }
  355           return new Insets(0, 0, 0, 0);
  356       }
  357   
  358       /**
  359        * Appends the specified component to the end of this container.
  360        * This is a convenience method for {@link #addImpl}.
  361        * <p>
  362        * Note: If a component has been added to a container that
  363        * has been displayed, <code>validate</code> must be
  364        * called on that container to display the new component.
  365        * If multiple components are being added, you can improve
  366        * efficiency by calling <code>validate</code> only once,
  367        * after all the components have been added.
  368        *
  369        * @param     comp   the component to be added
  370        * @exception NullPointerException if {@code comp} is {@code null}
  371        * @see #addImpl
  372        * @see #validate
  373        * @see javax.swing.JComponent#revalidate()
  374        * @return    the component argument
  375        */
  376       public Component add(Component comp) {
  377           addImpl(comp, null, -1);
  378           return comp;
  379       }
  380   
  381       /**
  382        * Adds the specified component to this container.
  383        * This is a convenience method for {@link #addImpl}.
  384        * <p>
  385        * This method is obsolete as of 1.1.  Please use the
  386        * method <code>add(Component, Object)</code> instead.
  387        * @exception NullPointerException if {@code comp} is {@code null}
  388        * @see #add(Component, Object)
  389        */
  390       public Component add(String name, Component comp) {
  391           addImpl(comp, name, -1);
  392           return comp;
  393       }
  394   
  395       /**
  396        * Adds the specified component to this container at the given
  397        * position.
  398        * This is a convenience method for {@link #addImpl}.
  399        * <p>
  400        * Note: If a component has been added to a container that
  401        * has been displayed, <code>validate</code> must be
  402        * called on that container to display the new component.
  403        * If multiple components are being added, you can improve
  404        * efficiency by calling <code>validate</code> only once,
  405        * after all the components have been added.
  406        *
  407        * @param     comp   the component to be added
  408        * @param     index    the position at which to insert the component,
  409        *                   or <code>-1</code> to append the component to the end
  410        * @exception NullPointerException if {@code comp} is {@code null}
  411        * @exception IllegalArgumentException if {@code index} is invalid (see
  412        *            {@link #addImpl} for details)
  413        * @return    the component <code>comp</code>
  414        * @see #addImpl
  415        * @see #remove
  416        * @see #validate
  417        * @see javax.swing.JComponent#revalidate()
  418        */
  419       public Component add(Component comp, int index) {
  420           addImpl(comp, null, index);
  421           return comp;
  422       }
  423   
  424       /**
  425        * Checks that the component comp can be added to this container
  426        * Checks :  index in bounds of container's size,
  427        * comp is not one of this container's parents,
  428        * and comp is not a window.
  429        * Comp and container must be on the same GraphicsDevice.
  430        * if comp is container, all sub-components must be on
  431        * same GraphicsDevice.
  432        *
  433        * @since 1.5
  434        */
  435       private void checkAdding(Component comp, int index) {
  436           checkTreeLock();
  437   
  438           GraphicsConfiguration thisGC = getGraphicsConfiguration();
  439   
  440           if (index > ncomponents || index < 0) {
  441               throw new IllegalArgumentException("illegal component position");
  442           }
  443           if (comp.parent == this) {
  444               if (index == ncomponents) {
  445                   throw new IllegalArgumentException("illegal component position " +
  446                                                      index + " should be less then " + ncomponents);
  447               }
  448           }
  449           if (comp instanceof Container) {
  450               for (Container cn = this; cn != null; cn=cn.parent) {
  451                   if (cn == comp) {
  452                       throw new IllegalArgumentException("adding container's parent to itself");
  453                   }
  454               }
  455   
  456               if (comp instanceof Window) {
  457                   throw new IllegalArgumentException("adding a window to a container");
  458               }
  459           }
  460           Window thisTopLevel = getContainingWindow();
  461           Window compTopLevel = comp.getContainingWindow();
  462           if (thisTopLevel != compTopLevel) {
  463               throw new IllegalArgumentException("component and container should be in the same top-level window");
  464           }
  465           if (thisGC != null) {
  466               comp.checkGD(thisGC.getDevice().getIDstring());
  467           }
  468       }
  469   
  470       /**
  471        * Removes component comp from this container without making unneccessary changes
  472        * and generating unneccessary events. This function intended to perform optimized
  473        * remove, for example, if newParent and current parent are the same it just changes
  474        * index without calling removeNotify.
  475        * Note: Should be called while holding treeLock
  476        * Returns whether removeNotify was invoked
  477        * @since: 1.5
  478        */
  479       private boolean removeDelicately(Component comp, Container newParent, int newIndex) {
  480           checkTreeLock();
  481   
  482           int index = getComponentZOrder(comp);
  483           boolean needRemoveNotify = isRemoveNotifyNeeded(comp, this, newParent);
  484           if (needRemoveNotify) {
  485               comp.removeNotify();
  486           }
  487           if (newParent != this) {
  488               if (layoutMgr != null) {
  489                   layoutMgr.removeLayoutComponent(comp);
  490               }
  491               adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK,
  492                                       -comp.numListening(AWTEvent.HIERARCHY_EVENT_MASK));
  493               adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
  494                                       -comp.numListening(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));
  495               adjustDescendants(-(comp.countHierarchyMembers()));
  496   
  497               comp.parent = null;
  498               System.arraycopy(component, index + 1,
  499                                component, index,
  500                                ncomponents - index - 1);
  501               component[--ncomponents] = null;
  502   
  503               if (valid) {
  504                   invalidate();
  505               }
  506           } else {
  507               if (newIndex > index) { // 2->4: 012345 -> 013425, 2->5: 012345 -> 013452
  508                   if (newIndex-index > 0) {
  509                       System.arraycopy(component, index+1, component, index, newIndex-index);
  510                   }
  511               } else { // 4->2: 012345 -> 014235
  512                   if (index-newIndex > 0) {
  513                       System.arraycopy(component, newIndex, component, newIndex+1, index-newIndex);
  514                   }
  515               }
  516               component[newIndex] = comp;
  517           }
  518           if (comp.parent == null) { // was actually removed
  519               if (containerListener != null ||
  520                   (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 ||
  521                   Toolkit.enabledOnToolkit(AWTEvent.CONTAINER_EVENT_MASK)) {
  522                   ContainerEvent e = new ContainerEvent(this,
  523                                                         ContainerEvent.COMPONENT_REMOVED,
  524                                                         comp);
  525                   dispatchEvent(e);
  526   
  527               }
  528               comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, comp,
  529                                          this, HierarchyEvent.PARENT_CHANGED,
  530                                          Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK));
  531               if (peer != null && layoutMgr == null && isVisible()) {
  532                   updateCursorImmediately();
  533               }
  534           }
  535           return needRemoveNotify;
  536       }
  537   
  538       /**
  539        * Checks whether this container can contain component which is focus owner.
  540        * Verifies that container is enable and showing, and if it is focus cycle root
  541        * its FTP allows component to be focus owner
  542        * @since 1.5
  543        */
  544       boolean canContainFocusOwner(Component focusOwnerCandidate) {
  545           if (!(isEnabled() && isDisplayable()
  546                 && isVisible() && isFocusable()))
  547           {
  548               return false;
  549           }
  550           if (isFocusCycleRoot()) {
  551               FocusTraversalPolicy policy = getFocusTraversalPolicy();
  552               if (policy instanceof DefaultFocusTraversalPolicy) {
  553                   if (!((DefaultFocusTraversalPolicy)policy).accept(focusOwnerCandidate)) {
  554                       return false;
  555                   }
  556               }
  557           }
  558           synchronized(getTreeLock()) {
  559               if (parent != null) {
  560                   return parent.canContainFocusOwner(focusOwnerCandidate);
  561               }
  562           }
  563           return true;
  564       }
  565   
  566       /**
  567        * Checks whether or not this container has heavyweight children.
  568        * Note: Should be called while holding tree lock
  569        * @return true if there is at least one heavyweight children in a container, false otherwise
  570        * @since 1.5
  571        */
  572       private boolean hasHeavyweightDescendants() {
  573           checkTreeLock();
  574           return numOfHWComponents > 0;
  575       }
  576   
  577       /**
  578        * Checks whether or not this container has lightweight children.
  579        * Note: Should be called while holding tree lock
  580        * @return true if there is at least one lightweight children in a container, false otherwise
  581        * @since 1.7
  582        */
  583       private boolean hasLightweightDescendants() {
  584           checkTreeLock();
  585           return numOfLWComponents > 0;
  586       }
  587   
  588       /**
  589        * Returns closest heavyweight component to this container. If this container is heavyweight
  590        * returns this.
  591        * @since 1.5
  592        */
  593       Container getHeavyweightContainer() {
  594           checkTreeLock();
  595           if (peer != null && !(peer instanceof LightweightPeer)) {
  596               return this;
  597           } else {
  598               return getNativeContainer();
  599           }
  600       }
  601   
  602       /**
  603        * Detects whether or not remove from current parent and adding to new parent requires call of
  604        * removeNotify on the component. Since removeNotify destroys native window this might (not)
  605        * be required. For example, if new container and old containers are the same we don't need to
  606        * destroy native window.
  607        * @since: 1.5
  608        */
  609       private static boolean isRemoveNotifyNeeded(Component comp, Container oldContainer, Container newContainer) {
  610           if (oldContainer == null) { // Component didn't have parent - no removeNotify
  611               return false;
  612           }
  613           if (comp.peer == null) { // Component didn't have peer - no removeNotify
  614               return false;
  615           }
  616           if (newContainer.peer == null) {
  617               // Component has peer but new Container doesn't - call removeNotify
  618               return true;
  619           }
  620   
  621           // If component is lightweight non-Container or lightweight Container with all but heavyweight
  622           // children there is no need to call remove notify
  623           if (comp.isLightweight()) {
  624               boolean isContainer = comp instanceof Container;
  625   
  626               if (!isContainer || (isContainer && !((Container)comp).hasHeavyweightDescendants())) {
  627                   return false;
  628               }
  629           }
  630   
  631           // If this point is reached, then the comp is either a HW or a LW container with HW descendants.
  632   
  633           // All three components have peers, check for peer change
  634           Container newNativeContainer = oldContainer.getHeavyweightContainer();
  635           Container oldNativeContainer = newContainer.getHeavyweightContainer();
  636           if (newNativeContainer != oldNativeContainer) {
  637               // Native containers change - check whether or not current platform supports
  638               // changing of widget hierarchy on native level without recreation.
  639               // The current implementation forbids reparenting of LW containers with HW descendants
  640               // into another native container w/o destroying the peers. Actually such an operation
  641               // is quite rare. If we ever need to save the peers, we'll have to slightly change the
  642               // addDelicately() method in order to handle such LW containers recursively, reparenting
  643               // each HW descendant independently.
  644               return !comp.peer.isReparentSupported();
  645           } else {
  646               // if container didn't change we still might need to recreate component's window as
  647               // changes to zorder should be reflected in native window stacking order and it might
  648               // not be supported by the platform. This is important only for heavyweight child
  649               return !((ContainerPeer)(newNativeContainer.peer)).isRestackSupported();
  650           }
  651       }
  652   
  653       /**
  654        * Moves the specified component to the specified z-order index in
  655        * the container. The z-order determines the order that components
  656        * are painted; the component with the highest z-order paints first
  657        * and the component with the lowest z-order paints last.
  658        * Where components overlap, the component with the lower
  659        * z-order paints over the component with the higher z-order.
  660        * <p>
  661        * If the component is a child of some other container, it is
  662        * removed from that container before being added to this container.
  663        * The important difference between this method and
  664        * <code>java.awt.Container.add(Component, int)</code> is that this method
  665        * doesn't call <code>removeNotify</code> on the component while
  666        * removing it from its previous container unless necessary and when
  667        * allowed by the underlying native windowing system. This way, if the
  668        * component has the keyboard focus, it maintains the focus when
  669        * moved to the new position.
  670        * <p>
  671        * This property is guaranteed to apply only to lightweight
  672        * non-<code>Container</code> components.
  673        * <p>
  674        * <b>Note</b>: Not all platforms support changing the z-order of
  675        * heavyweight components from one container into another without
  676        * the call to <code>removeNotify</code>. There is no way to detect
  677        * whether a platform supports this, so developers shouldn't make
  678        * any assumptions.
  679        *
  680        * @param     comp the component to be moved
  681        * @param     index the position in the container's list to
  682        *            insert the component, where <code>getComponentCount()</code>
  683        *            appends to the end
  684        * @exception NullPointerException if <code>comp</code> is
  685        *            <code>null</code>
  686        * @exception IllegalArgumentException if <code>comp</code> is one of the
  687        *            container's parents
  688        * @exception IllegalArgumentException if <code>index</code> is not in
  689        *            the range <code>[0, getComponentCount()]</code> for moving
  690        *            between containers, or not in the range
  691        *            <code>[0, getComponentCount()-1]</code> for moving inside
  692        *            a container
  693        * @exception IllegalArgumentException if adding a container to itself
  694        * @exception IllegalArgumentException if adding a <code>Window</code>
  695        *            to a container
  696        * @see #getComponentZOrder(java.awt.Component)
  697        * @since 1.5
  698        */
  699       public void setComponentZOrder(Component comp, int index) {
  700            synchronized (getTreeLock()) {
  701                // Store parent because remove will clear it
  702                Container curParent = comp.parent;
  703                int oldZindex = getComponentZOrder(comp);
  704   
  705                if (curParent == this && index == oldZindex) {
  706                    return;
  707                }
  708                checkAdding(comp, index);
  709   
  710                boolean peerRecreated = (curParent != null) ?
  711                    curParent.removeDelicately(comp, this, index) : false;
  712   
  713                addDelicately(comp, curParent, index);
  714   
  715                // If the oldZindex == -1, the component gets inserted,
  716                // rather than it changes its z-order.
  717                if (!peerRecreated && oldZindex != -1) {
  718                    // The new 'index' cannot be == -1.
  719                    // It gets checked at the checkAdding() method.
  720                    // Therefore both oldZIndex and index denote
  721                    // some existing positions at this point and
  722                    // this is actually a Z-order changing.
  723                    comp.mixOnZOrderChanging(oldZindex, index);
  724                }
  725            }
  726       }
  727   
  728       /**
  729        * Traverses the tree of components and reparents children heavyweight component
  730        * to new heavyweight parent.
  731        * @since 1.5
  732        */
  733       private void reparentTraverse(ContainerPeer parentPeer, Container child) {
  734           checkTreeLock();
  735   
  736           for (int i = 0; i < child.getComponentCount(); i++) {
  737               Component comp = child.getComponent(i);
  738               if (comp.isLightweight()) {
  739                   // If components is lightweight check if it is container
  740                   // If it is container it might contain heavyweight children we need to reparent
  741                   if (comp instanceof Container) {
  742                       reparentTraverse(parentPeer, (Container)comp);
  743                   }
  744               } else {
  745                   // Q: Need to update NativeInLightFixer?
  746                   comp.getPeer().reparent(parentPeer);
  747               }
  748           }
  749       }
  750   
  751       /**
  752        * Reparents child component peer to this container peer.
  753        * Container must be heavyweight.
  754        * @since 1.5
  755        */
  756       private void reparentChild(Component comp) {
  757           checkTreeLock();
  758           if (comp == null) {
  759               return;
  760           }
  761           if (comp.isLightweight()) {
  762               // If component is lightweight container we need to reparent all its explicit  heavyweight children
  763               if (comp instanceof Container) {
  764                   // Traverse component's tree till depth-first until encountering heavyweight component
  765                   reparentTraverse((ContainerPeer)getPeer(), (Container)comp);
  766               }
  767           } else {
  768               comp.getPeer().reparent((ContainerPeer)getPeer());
  769           }
  770       }
  771   
  772       /**
  773        * Adds component to this container. Tries to minimize side effects of this adding -
  774        * doesn't call remove notify if it is not required.
  775        * @since 1.5
  776        */
  777       private void addDelicately(Component comp, Container curParent, int index) {
  778           checkTreeLock();
  779   
  780           // Check if moving between containers
  781           if (curParent != this) {
  782               /* Add component to list; allocate new array if necessary. */
  783               if (ncomponents == component.length) {
  784                   component = Arrays.copyOf(component, ncomponents * 2 + 1);
  785               }
  786               if (index == -1 || index == ncomponents) {
  787                   component[ncomponents++] = comp;
  788               } else {
  789                   System.arraycopy(component, index, component,
  790                                    index + 1, ncomponents - index);
  791                   component[index] = comp;
  792                   ncomponents++;
  793               }
  794               comp.parent = this;
  795   
  796               adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK,
  797                                       comp.numListening(AWTEvent.HIERARCHY_EVENT_MASK));
  798               adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
  799                                       comp.numListening(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));
  800               adjustDescendants(comp.countHierarchyMembers());
  801           } else {
  802               if (index < ncomponents) {
  803                   component[index] = comp;
  804               }
  805           }
  806   
  807           if (valid) {
  808               invalidate();
  809           }
  810           if (peer != null) {
  811               if (comp.peer == null) { // Remove notify was called or it didn't have peer - create new one
  812                   comp.addNotify();
  813                   // New created peer creates component on top of the stacking order
  814                   Container newNativeContainer = getHeavyweightContainer();
  815                   if (((ContainerPeer)newNativeContainer.getPeer()).isRestackSupported()) {
  816                       ((ContainerPeer)newNativeContainer.getPeer()).restack();
  817                   }
  818               } else { // Both container and child have peers, it means child peer should be reparented.
  819                   // In both cases we need to reparent native widgets.
  820                   Container newNativeContainer = getHeavyweightContainer();
  821                   Container oldNativeContainer = curParent.getHeavyweightContainer();
  822                   if (oldNativeContainer != newNativeContainer) {
  823                       // Native container changed - need to reparent native widgets
  824                       newNativeContainer.reparentChild(comp);
  825                   }
  826                   // If component still has a peer and it is either container or heavyweight
  827                   // and restack is supported we have to restack native windows since order might have changed
  828                   if ((!comp.isLightweight() || (comp instanceof Container))
  829                       && ((ContainerPeer)newNativeContainer.getPeer()).isRestackSupported())
  830                   {
  831                       ((ContainerPeer)newNativeContainer.getPeer()).restack();
  832                   }
  833                   if (!comp.isLightweight() && isLightweight()) {
  834                       // If component is heavyweight and one of the containers is lightweight
  835                       // the location of the component should be fixed.
  836                       comp.relocateComponent();
  837                   }
  838               }
  839           }
  840           if (curParent != this) {
  841               /* Notify the layout manager of the added component. */
  842               if (layoutMgr != null) {
  843                   if (layoutMgr instanceof LayoutManager2) {
  844                       ((LayoutManager2)layoutMgr).addLayoutComponent(comp, null);
  845                   } else {
  846                       layoutMgr.addLayoutComponent(null, comp);
  847                   }
  848               }
  849               if (containerListener != null ||
  850                   (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 ||
  851                   Toolkit.enabledOnToolkit(AWTEvent.CONTAINER_EVENT_MASK)) {
  852                   ContainerEvent e = new ContainerEvent(this,
  853                                                         ContainerEvent.COMPONENT_ADDED,
  854                                                         comp);
  855                   dispatchEvent(e);
  856               }
  857               comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, comp,
  858                                          this, HierarchyEvent.PARENT_CHANGED,
  859                                          Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK));
  860   
  861               // If component is focus owner or parent container of focus owner check that after reparenting
  862               // focus owner moved out if new container prohibit this kind of focus owner.
  863               if (comp.isFocusOwner() && !comp.canBeFocusOwner()) {
  864                   comp.transferFocus();
  865               } else if (comp instanceof Container) {
  866                   Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
  867                   if (focusOwner != null && isParentOf(focusOwner) && !focusOwner.canBeFocusOwner()) {
  868                       focusOwner.transferFocus();
  869                   }
  870               }
  871           } else {
  872               comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, comp,
  873                                          this, HierarchyEvent.HIERARCHY_CHANGED,
  874                                          Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK));
  875           }
  876   
  877           if (peer != null && layoutMgr == null && isVisible()) {
  878               updateCursorImmediately();
  879           }
  880       }
  881   
  882       /**
  883        * Returns the z-order index of the component inside the container.
  884        * The higher a component is in the z-order hierarchy, the lower
  885        * its index.  The component with the lowest z-order index is
  886        * painted last, above all other child components.
  887        *
  888        * @param comp the component being queried
  889        * @return  the z-order index of the component; otherwise
  890        *          returns -1 if the component is <code>null</code>
  891        *          or doesn't belong to the container
  892        * @see #setComponentZOrder(java.awt.Component, int)
  893        * @since 1.5
  894        */
  895       public int getComponentZOrder(Component comp) {
  896           if (comp == null) {
  897               return -1;
  898           }
  899           synchronized(getTreeLock()) {
  900               // Quick check - container should be immediate parent of the component
  901               if (comp.parent != this) {
  902                   return -1;
  903               }
  904               for (int i = 0; i < ncomponents; i++) {
  905                   if (component[i] == comp) {
  906                       return i;
  907                   }
  908               }
  909           }
  910           // To please javac
  911           return -1;
  912       }
  913   
  914       /**
  915        * Adds the specified component to the end of this container.
  916        * Also notifies the layout manager to add the component to
  917        * this container's layout using the specified constraints object.
  918        * This is a convenience method for {@link #addImpl}.
  919        * <p>
  920        * Note: If a component has been added to a container that
  921        * has been displayed, <code>validate</code> must be
  922        * called on that container to display the new component.
  923        * If multiple components are being added, you can improve
  924        * efficiency by calling <code>validate</code> only once,
  925        * after all the components have been added.
  926        *
  927        * @param     comp the component to be added
  928        * @param     constraints an object expressing
  929        *                  layout contraints for this component
  930        * @exception NullPointerException if {@code comp} is {@code null}
  931        * @see #addImpl
  932        * @see #validate
  933        * @see javax.swing.JComponent#revalidate()
  934        * @see       LayoutManager
  935        * @since     JDK1.1
  936        */
  937       public void add(Component comp, Object constraints) {
  938           addImpl(comp, constraints, -1);
  939       }
  940   
  941       /**
  942        * Adds the specified component to this container with the specified
  943        * constraints at the specified index.  Also notifies the layout
  944        * manager to add the component to the this container's layout using
  945        * the specified constraints object.
  946        * This is a convenience method for {@link #addImpl}.
  947        * <p>
  948        * Note: If a component has been added to a container that
  949        * has been displayed, <code>validate</code> must be
  950        * called on that container to display the new component.
  951        * If multiple components are being added, you can improve
  952        * efficiency by calling <code>validate</code> only once,
  953        * after all the components have been added.
  954        *
  955        * @param comp the component to be added
  956        * @param constraints an object expressing layout contraints for this
  957        * @param index the position in the container's list at which to insert
  958        * the component; <code>-1</code> means insert at the end
  959        * component
  960        * @exception NullPointerException if {@code comp} is {@code null}
  961        * @exception IllegalArgumentException if {@code index} is invalid (see
  962        *            {@link #addImpl} for details)
  963        * @see #addImpl
  964        * @see #validate
  965        * @see javax.swing.JComponent#revalidate()
  966        * @see #remove
  967        * @see LayoutManager
  968        */
  969       public void add(Component comp, Object constraints, int index) {
  970          addImpl(comp, constraints, index);
  971       }
  972   
  973       /**
  974        * Adds the specified component to this container at the specified
  975        * index. This method also notifies the layout manager to add
  976        * the component to this container's layout using the specified
  977        * constraints object via the <code>addLayoutComponent</code>
  978        * method.
  979        * <p>
  980        * The constraints are
  981        * defined by the particular layout manager being used.  For
  982        * example, the <code>BorderLayout</code> class defines five
  983        * constraints: <code>BorderLayout.NORTH</code>,
  984        * <code>BorderLayout.SOUTH</code>, <code>BorderLayout.EAST</code>,
  985        * <code>BorderLayout.WEST</code>, and <code>BorderLayout.CENTER</code>.
  986        * <p>
  987        * The <code>GridBagLayout</code> class requires a
  988        * <code>GridBagConstraints</code> object.  Failure to pass
  989        * the correct type of constraints object results in an
  990        * <code>IllegalArgumentException</code>.
  991        * <p>
  992        * If the current layout manager implements {@code LayoutManager2}, then
  993        * {@link LayoutManager2#addLayoutComponent(Component,Object)} is invoked on
  994        * it. If the current layout manager does not implement
  995        * {@code LayoutManager2}, and constraints is a {@code String}, then
  996        * {@link LayoutManager#addLayoutComponent(String,Component)} is invoked on it.
  997        * <p>
  998        * If the component is not an ancestor of this container and has a non-null
  999        * parent, it is removed from its current parent before it is added to this
 1000        * container.
 1001        * <p>
 1002        * This is the method to override if a program needs to track
 1003        * every add request to a container as all other add methods defer
 1004        * to this one. An overriding method should
 1005        * usually include a call to the superclass's version of the method:
 1006        * <p>
 1007        * <blockquote>
 1008        * <code>super.addImpl(comp, constraints, index)</code>
 1009        * </blockquote>
 1010        * <p>
 1011        * @param     comp       the component to be added
 1012        * @param     constraints an object expressing layout constraints
 1013        *                 for this component
 1014        * @param     index the position in the container's list at which to
 1015        *                 insert the component, where <code>-1</code>
 1016        *                 means append to the end
 1017        * @exception IllegalArgumentException if {@code index} is invalid;
 1018        *            if {@code comp} is a child of this container, the valid
 1019        *            range is {@code [-1, getComponentCount()-1]}; if component is
 1020        *            not a child of this container, the valid range is
 1021        *            {@code [-1, getComponentCount()]}
 1022        *
 1023        * @exception IllegalArgumentException if {@code comp} is an ancestor of
 1024        *                                     this container
 1025        * @exception IllegalArgumentException if adding a window to a container
 1026        * @exception NullPointerException if {@code comp} is {@code null}
 1027        * @see       #add(Component)
 1028        * @see       #add(Component, int)
 1029        * @see       #add(Component, java.lang.Object)
 1030        * @see       LayoutManager
 1031        * @see       LayoutManager2
 1032        * @since     JDK1.1
 1033        */
 1034       protected void addImpl(Component comp, Object constraints, int index) {
 1035           synchronized (getTreeLock()) {
 1036               /* Check for correct arguments:  index in bounds,
 1037                * comp cannot be one of this container's parents,
 1038                * and comp cannot be a window.
 1039                * comp and container must be on the same GraphicsDevice.
 1040                * if comp is container, all sub-components must be on
 1041                * same GraphicsDevice.
 1042                */
 1043               GraphicsConfiguration thisGC = this.getGraphicsConfiguration();
 1044   
 1045               if (index > ncomponents || (index < 0 && index != -1)) {
 1046                   throw new IllegalArgumentException(
 1047                             "illegal component position");
 1048               }
 1049           if (comp instanceof Container) {
 1050               for (Container cn = this; cn != null; cn=cn.parent) {
 1051                   if (cn == comp) {
 1052                   throw new IllegalArgumentException(
 1053                         "adding container's parent to itself");
 1054                   }
 1055               }
 1056               if (comp instanceof Window) {
 1057                   throw new IllegalArgumentException(
 1058                          "adding a window to a container");
 1059               }
 1060           }
 1061           if (thisGC != null) {
 1062               comp.checkGD(thisGC.getDevice().getIDstring());
 1063           }
 1064   
 1065               /* Reparent the component and tidy up the tree's state. */
 1066               if (comp.parent != null) {
 1067                   comp.parent.remove(comp);
 1068                       if (index > ncomponents) {
 1069                           throw new IllegalArgumentException("illegal component position");
 1070                       }
 1071               }
 1072   
 1073               /* Add component to list; allocate new array if necessary. */
 1074               if (ncomponents == component.length) {
 1075                   component = Arrays.copyOf(component, ncomponents * 2 + 1);
 1076               }
 1077               if (index == -1 || index == ncomponents) {
 1078                   component[ncomponents++] = comp;
 1079               } else {
 1080                   System.arraycopy(component, index, component,
 1081                                    index + 1, ncomponents - index);
 1082                   component[index] = comp;
 1083                   ncomponents++;
 1084               }
 1085               comp.parent = this;
 1086   
 1087               adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK,
 1088                   comp.numListening(AWTEvent.HIERARCHY_EVENT_MASK));
 1089               adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
 1090                   comp.numListening(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));
 1091               adjustDescendants(comp.countHierarchyMembers());
 1092   
 1093               if (valid) {
 1094                   invalidate();
 1095               }
 1096               if (peer != null) {
 1097                   comp.addNotify();
 1098               }
 1099   
 1100               /* Notify the layout manager of the added component. */
 1101               if (layoutMgr != null) {
 1102                   if (layoutMgr instanceof LayoutManager2) {
 1103                       ((LayoutManager2)layoutMgr).addLayoutComponent(comp, constraints);
 1104                   } else if (constraints instanceof String) {
 1105                       layoutMgr.addLayoutComponent((String)constraints, comp);
 1106                   }
 1107               }
 1108               if (containerListener != null ||
 1109                   (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 ||
 1110                   Toolkit.enabledOnToolkit(AWTEvent.CONTAINER_EVENT_MASK)) {
 1111                   ContainerEvent e = new ContainerEvent(this,
 1112                                        ContainerEvent.COMPONENT_ADDED,
 1113                                        comp);
 1114                   dispatchEvent(e);
 1115               }
 1116   
 1117               comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, comp,
 1118                                          this, HierarchyEvent.PARENT_CHANGED,
 1119                                          Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK));
 1120               if (peer != null && layoutMgr == null && isVisible()) {
 1121                   updateCursorImmediately();
 1122               }
 1123           }
 1124       }
 1125   
 1126       /**
 1127        * Checks that all Components that this Container contains are on
 1128        * the same GraphicsDevice as this Container.  If not, throws an
 1129        * IllegalArgumentException.
 1130        */
 1131       void checkGD(String stringID) {
 1132           Component tempComp;
 1133           for (int i = 0; i < component.length; i++) {
 1134               tempComp= component[i];
 1135               if (tempComp != null) {
 1136                   tempComp.checkGD(stringID);
 1137               }
 1138           }
 1139       }
 1140   
 1141       /**
 1142        * Removes the component, specified by <code>index</code>,
 1143        * from this container.
 1144        * This method also notifies the layout manager to remove the
 1145        * component from this container's layout via the
 1146        * <code>removeLayoutComponent</code> method.
 1147        *
 1148        * <p>
 1149        * Note: If a component has been removed from a container that
 1150        * had been displayed, {@link #validate} must be
 1151        * called on that container to reflect changes.
 1152        * If multiple components are being removed, you can improve
 1153        * efficiency by calling {@link #validate} only once,
 1154        * after all the components have been removed.
 1155        *
 1156        * @param     index   the index of the component to be removed
 1157        * @throws ArrayIndexOutOfBoundsException if {@code index} is not in
 1158        *         range {@code [0, getComponentCount()-1]}
 1159        * @see #add
 1160        * @see #validate
 1161        * @see #getComponentCount
 1162        * @since JDK1.1
 1163        */
 1164       public void remove(int index) {
 1165           synchronized (getTreeLock()) {
 1166               if (index < 0  || index >= ncomponents) {
 1167                   throw new ArrayIndexOutOfBoundsException(index);
 1168               }
 1169               Component comp = component[index];
 1170               if (peer != null) {
 1171                   comp.removeNotify();
 1172               }
 1173               if (layoutMgr != null) {
 1174                   layoutMgr.removeLayoutComponent(comp);
 1175               }
 1176   
 1177               adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK,
 1178                   -comp.numListening(AWTEvent.HIERARCHY_EVENT_MASK));
 1179               adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
 1180                   -comp.numListening(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));
 1181               adjustDescendants(-(comp.countHierarchyMembers()));
 1182   
 1183               comp.parent = null;
 1184               System.arraycopy(component, index + 1,
 1185                                component, index,
 1186                                ncomponents - index - 1);
 1187               component[--ncomponents] = null;
 1188   
 1189               if (valid) {
 1190                   invalidate();
 1191               }
 1192               if (containerListener != null ||
 1193                   (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 ||
 1194                   Toolkit.enabledOnToolkit(AWTEvent.CONTAINER_EVENT_MASK)) {
 1195                   ContainerEvent e = new ContainerEvent(this,
 1196                                        ContainerEvent.COMPONENT_REMOVED,
 1197                                        comp);
 1198                   dispatchEvent(e);
 1199               }
 1200   
 1201               comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, comp,
 1202                                          this, HierarchyEvent.PARENT_CHANGED,
 1203                                          Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK));
 1204               if (peer != null && layoutMgr == null && isVisible()) {
 1205                   updateCursorImmediately();
 1206               }
 1207           }
 1208       }
 1209   
 1210       /**
 1211        * Removes the specified component from this container.
 1212        * This method also notifies the layout manager to remove the
 1213        * component from this container's layout via the
 1214        * <code>removeLayoutComponent</code> method.
 1215        *
 1216        * <p>
 1217        * Note: If a component has been removed from a container that
 1218        * had been displayed, {@link #validate} must be
 1219        * called on that container to reflect changes.
 1220        * If multiple components are being removed, you can improve
 1221        * efficiency by calling {@link #validate} only once,
 1222        * after all the components have been removed.
 1223        *
 1224        * @param comp the component to be removed
 1225        * @see #add
 1226        * @see #validate
 1227        * @see #remove(int)
 1228        */
 1229       public void remove(Component comp) {
 1230           synchronized (getTreeLock()) {
 1231               if (comp.parent == this)  {
 1232                   /* Search backwards, expect that more recent additions
 1233                    * are more likely to be removed.
 1234                    */
 1235                   Component component[] = this.component;
 1236                   for (int i = ncomponents; --i >= 0; ) {
 1237                       if (component[i] == comp) {
 1238                           remove(i);
 1239                       }
 1240                   }
 1241               }
 1242           }
 1243       }
 1244   
 1245       /**
 1246        * Removes all the components from this container.
 1247        * This method also notifies the layout manager to remove the
 1248        * components from this container's layout via the
 1249        * <code>removeLayoutComponent</code> method.
 1250        * @see #add
 1251        * @see #remove
 1252        */
 1253       public void removeAll() {
 1254           synchronized (getTreeLock()) {
 1255               adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK,
 1256                                       -listeningChildren);
 1257               adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
 1258                                       -listeningBoundsChildren);
 1259               adjustDescendants(-descendantsCount);
 1260   
 1261               while (ncomponents > 0) {
 1262                   Component comp = component[--ncomponents];
 1263                   component[ncomponents] = null;
 1264   
 1265                   if (peer != null) {
 1266                       comp.removeNotify();
 1267                   }
 1268                   if (layoutMgr != null) {
 1269                       layoutMgr.removeLayoutComponent(comp);
 1270                   }
 1271                   comp.parent = null;
 1272                   if (containerListener != null ||
 1273                      (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 ||
 1274                       Toolkit.enabledOnToolkit(AWTEvent.CONTAINER_EVENT_MASK)) {
 1275                       ContainerEvent e = new ContainerEvent(this,
 1276                                        ContainerEvent.COMPONENT_REMOVED,
 1277                                        comp);
 1278                       dispatchEvent(e);
 1279                   }
 1280   
 1281                   comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED,
 1282                                              comp, this,
 1283                                              HierarchyEvent.PARENT_CHANGED,
 1284                                              Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK));
 1285               }
 1286               if (peer != null && layoutMgr == null && isVisible()) {
 1287                   updateCursorImmediately();
 1288               }
 1289               if (valid) {
 1290                   invalidate();
 1291               }
 1292           }
 1293       }
 1294   
 1295       // Should only be called while holding tree lock
 1296       int numListening(long mask) {
 1297           int superListening = super.numListening(mask);
 1298   
 1299           if (mask == AWTEvent.HIERARCHY_EVENT_MASK) {
 1300               if (eventLog.isLoggable(Level.FINE)) {
 1301                   // Verify listeningChildren is correct
 1302                   int sum = 0;
 1303                   for (int i = 0; i < ncomponents; i++) {
 1304                       sum += component[i].numListening(mask);
 1305                   }
 1306                   if (listeningChildren != sum) {
 1307                       eventLog.log(Level.FINE, "Assertion (listeningChildren == sum) failed");
 1308                   }
 1309               }
 1310               return listeningChildren + superListening;
 1311           } else if (mask == AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) {
 1312               if (eventLog.isLoggable(Level.FINE)) {
 1313                   // Verify listeningBoundsChildren is correct
 1314                   int sum = 0;
 1315                   for (int i = 0; i < ncomponents; i++) {
 1316                       sum += component[i].numListening(mask);
 1317                   }
 1318                   if (listeningBoundsChildren != sum) {
 1319                       eventLog.log(Level.FINE, "Assertion (listeningBoundsChildren == sum) failed");
 1320                   }
 1321               }
 1322               return listeningBoundsChildren + superListening;
 1323           } else {
 1324               // assert false;
 1325               if (eventLog.isLoggable(Level.FINE)) {
 1326                   eventLog.log(Level.FINE, "This code must never be reached");
 1327               }
 1328               return superListening;
 1329           }
 1330       }
 1331   
 1332       // Should only be called while holding tree lock
 1333       void adjustListeningChildren(long mask, int num) {
 1334           if (eventLog.isLoggable(Level.FINE)) {
 1335               boolean toAssert = (mask == AWTEvent.HIERARCHY_EVENT_MASK ||
 1336                                   mask == AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK ||
 1337                                   mask == (AWTEvent.HIERARCHY_EVENT_MASK |
 1338                                            AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));
 1339               if (!toAssert) {
 1340                   eventLog.log(Level.FINE, "Assertion failed");
 1341               }
 1342           }
 1343   
 1344           if (num == 0)
 1345               return;
 1346   
 1347           if ((mask & AWTEvent.HIERARCHY_EVENT_MASK) != 0) {
 1348               listeningChildren += num;
 1349           }
 1350           if ((mask & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) != 0) {
 1351               listeningBoundsChildren += num;
 1352           }
 1353   
 1354           adjustListeningChildrenOnParent(mask, num);
 1355       }
 1356   
 1357       // Should only be called while holding tree lock
 1358       void adjustDescendants(int num) {
 1359           if (num == 0)
 1360               return;
 1361   
 1362           descendantsCount += num;
 1363           adjustDecendantsOnParent(num);
 1364       }
 1365   
 1366       // Should only be called while holding tree lock
 1367       void adjustDecendantsOnParent(int num) {
 1368           if (parent != null) {
 1369               parent.adjustDescendants(num);
 1370           }
 1371       }
 1372   
 1373       // Should only be called while holding tree lock
 1374       int countHierarchyMembers() {
 1375           if (log.isLoggable(Level.FINE)) {
 1376               // Verify descendantsCount is correct
 1377               int sum = 0;
 1378               for (int i = 0; i < ncomponents; i++) {
 1379                   sum += component[i].countHierarchyMembers();
 1380               }
 1381               if (descendantsCount != sum) {
 1382                   log.log(Level.FINE, "Assertion (descendantsCount == sum) failed");
 1383               }
 1384           }
 1385           return descendantsCount + 1;
 1386       }
 1387   
 1388       private int getListenersCount(int id, boolean enabledOnToolkit) {
 1389           assert Thread.holdsLock(getTreeLock());
 1390           if (enabledOnToolkit) {
 1391               return descendantsCount;
 1392           }
 1393           switch (id) {
 1394             case HierarchyEvent.HIERARCHY_CHANGED:
 1395               return listeningChildren;
 1396             case HierarchyEvent.ANCESTOR_MOVED:
 1397             case HierarchyEvent.ANCESTOR_RESIZED:
 1398               return listeningBoundsChildren;
 1399             default:
 1400               return 0;
 1401           }
 1402       }
 1403   
 1404       final int createHierarchyEvents(int id, Component changed,
 1405           Container changedParent, long changeFlags, boolean enabledOnToolkit)
 1406       {
 1407           assert Thread.holdsLock(getTreeLock());
 1408           int listeners = getListenersCount(id, enabledOnToolkit);
 1409   
 1410           for (int count = listeners, i = 0; count > 0; i++) {
 1411               count -= component[i].createHierarchyEvents(id, changed,
 1412                   changedParent, changeFlags, enabledOnToolkit);
 1413           }
 1414           return listeners +
 1415               super.createHierarchyEvents(id, changed, changedParent,
 1416                                           changeFlags, enabledOnToolkit);
 1417       }
 1418   
 1419       final void createChildHierarchyEvents(int id, long changeFlags,
 1420           boolean enabledOnToolkit)
 1421       {
 1422           assert Thread.holdsLock(getTreeLock());
 1423           if (ncomponents == 0) {
 1424               return;
 1425           }
 1426           int listeners = getListenersCount(id, enabledOnToolkit);
 1427   
 1428           for (int count = listeners, i = 0; count > 0; i++) {
 1429               count -= component[i].createHierarchyEvents(id, this, parent,
 1430                   changeFlags, enabledOnToolkit);
 1431           }
 1432       }
 1433   
 1434       /**
 1435        * Gets the layout manager for this container.
 1436        * @see #doLayout
 1437        * @see #setLayout
 1438        */
 1439       public LayoutManager getLayout() {
 1440           return layoutMgr;
 1441       }
 1442   
 1443       /**
 1444        * Sets the layout manager for this container.
 1445        * @param mgr the specified layout manager
 1446        * @see #doLayout
 1447        * @see #getLayout
 1448        */
 1449       public void setLayout(LayoutManager mgr) {
 1450           layoutMgr = mgr;
 1451           if (valid) {
 1452               invalidate();
 1453           }
 1454       }
 1455   
 1456       /**
 1457        * Causes this container to lay out its components.  Most programs
 1458        * should not call this method directly, but should invoke
 1459        * the <code>validate</code> method instead.
 1460        * @see LayoutManager#layoutContainer
 1461        * @see #setLayout
 1462        * @see #validate
 1463        * @since JDK1.1
 1464        */
 1465       public void doLayout() {
 1466           layout();
 1467       }
 1468   
 1469       /**
 1470        * @deprecated As of JDK version 1.1,
 1471        * replaced by <code>doLayout()</code>.
 1472        */
 1473       @Deprecated
 1474       public void layout() {
 1475           LayoutManager layoutMgr = this.layoutMgr;
 1476           if (layoutMgr != null) {
 1477               layoutMgr.layoutContainer(this);
 1478           }
 1479       }
 1480   
 1481       /**
 1482        * Invalidates the container.  The container and all parents
 1483        * above it are marked as needing to be laid out.  This method can
 1484        * be called often, so it needs to execute quickly.
 1485        *
 1486        * <p> If the {@code LayoutManager} installed on this container is
 1487        * an instance of {@code LayoutManager2}, then
 1488        * {@link LayoutManager2#invalidateLayout(Container)} is invoked on
 1489        * it supplying this {@code Container} as the argument.
 1490        *
 1491        * @see #validate
 1492        * @see #layout
 1493        * @see LayoutManager
 1494        * @see LayoutManager2#invalidateLayout(Container)
 1495        */
 1496       public void invalidate() {
 1497           LayoutManager layoutMgr = this.layoutMgr;
 1498           if (layoutMgr instanceof LayoutManager2) {
 1499               LayoutManager2 lm = (LayoutManager2) layoutMgr;
 1500               lm.invalidateLayout(this);
 1501           }
 1502           super.invalidate();
 1503       }
 1504   
 1505       /**
 1506        * Validates this container and all of its subcomponents.
 1507        * <p>
 1508        * The <code>validate</code> method is used to cause a container
 1509        * to lay out its subcomponents again. It should be invoked when
 1510        * this container's subcomponents are modified (added to or
 1511        * removed from the container, or layout-related information
 1512        * changed) after the container has been displayed.
 1513        *
 1514        * <p>If this {@code Container} is not valid, this method invokes
 1515        * the {@code validateTree} method and marks this {@code Container}
 1516        * as valid. Otherwise, no action is performed.
 1517        *
 1518        * @see #add(java.awt.Component)
 1519        * @see Component#invalidate
 1520        * @see javax.swing.JComponent#revalidate()
 1521        * @see #validateTree
 1522        */
 1523       public void validate() {
 1524           /* Avoid grabbing lock unless really necessary. */
 1525           if (!valid) {
 1526               boolean updateCur = false;
 1527               synchronized (getTreeLock()) {
 1528                   if (!valid && peer != null) {
 1529                       ContainerPeer p = null;
 1530                       if (peer instanceof ContainerPeer) {
 1531                           p = (ContainerPeer) peer;
 1532                       }
 1533                       if (p != null) {
 1534                           p.beginValidate();
 1535                       }
 1536                       validateTree();
 1537                       valid = true;
 1538                       if (p != null) {
 1539                           p.endValidate();
 1540                           updateCur = isVisible();
 1541                       }
 1542                   }
 1543               }
 1544               if (updateCur) {
 1545                   updateCursorImmediately();
 1546               }
 1547           }
 1548       }
 1549   
 1550       /**
 1551        * Recursively descends the container tree and recomputes the
 1552        * layout for any subtrees marked as needing it (those marked as
 1553        * invalid).  Synchronization should be provided by the method
 1554        * that calls this one:  <code>validate</code>.
 1555        *
 1556        * @see #doLayout
 1557        * @see #validate
 1558        */
 1559       protected void validateTree() {
 1560           if (!valid) {
 1561               if (peer instanceof ContainerPeer) {
 1562                   ((ContainerPeer)peer).beginLayout();
 1563               }
 1564               doLayout();
 1565               Component component[] = this.component;
 1566               for (int i = 0 ; i < ncomponents ; ++i) {
 1567                   Component comp = component[i];
 1568                   if (   (comp instanceof Container)
 1569                       && !(comp instanceof Window)
 1570                       && !comp.valid) {
 1571                       ((Container)comp).validateTree();
 1572                   } else {
 1573                       comp.validate();
 1574                   }
 1575               }
 1576               if (peer instanceof ContainerPeer) {
 1577                   ((ContainerPeer)peer).endLayout();
 1578               }
 1579           }
 1580           valid = true;
 1581       }
 1582   
 1583       /**
 1584        * Recursively descends the container tree and invalidates all
 1585        * contained components.
 1586        */
 1587       void invalidateTree() {
 1588           synchronized (getTreeLock()) {
 1589               for (int i = 0; i < ncomponents; ++i) {
 1590                   Component comp = component[i];
 1591                   if (comp instanceof Container) {
 1592                       ((Container)comp).invalidateTree();
 1593                   }
 1594                   else {
 1595                       if (comp.valid) {
 1596                           comp.invalidate();
 1597                       }
 1598                   }
 1599               }
 1600               if (valid) {
 1601                   invalidate();
 1602               }
 1603           }
 1604       }
 1605   
 1606       /**
 1607        * Sets the font of this container.
 1608        * @param f The font to become this container's font.
 1609        * @see Component#getFont
 1610        * @since JDK1.0
 1611        */
 1612       public void setFont(Font f) {
 1613           boolean shouldinvalidate = false;
 1614   
 1615           Font oldfont = getFont();
 1616           super.setFont(f);
 1617           Font newfont = getFont();
 1618           if (newfont != oldfont && (oldfont == null ||
 1619                                      !oldfont.equals(newfont))) {
 1620               invalidateTree();
 1621           }
 1622       }
 1623   
 1624       /**
 1625        * Returns the preferred size of this container.  If the preferred size has
 1626        * not been set explicitly by {@link Component#setPreferredSize(Dimension)}
 1627        * and this {@code Container} has a {@code non-null} {@link LayoutManager},
 1628        * then {@link LayoutManager#preferredLayoutSize(Container)}
 1629        * is used to calculate the preferred size.
 1630        *
 1631        * <p>Note: some implementations may cache the value returned from the
 1632        * {@code LayoutManager}.  Implementations that cache need not invoke
 1633        * {@code preferredLayoutSize} on the {@code LayoutManager} every time
 1634        * this method is invoked, rather the {@code LayoutManager} will only
 1635        * be queried after the {@code Container} becomes invalid.
 1636        *
 1637        * @return    an instance of <code>Dimension</code> that represents
 1638        *                the preferred size of this container.
 1639        * @see       #getMinimumSize
 1640        * @see       #getMaximumSize
 1641        * @see       #getLayout
 1642        * @see       LayoutManager#preferredLayoutSize(Container)
 1643        * @see       Component#getPreferredSize
 1644        */
 1645       public Dimension getPreferredSize() {
 1646           return preferredSize();
 1647       }
 1648   
 1649       /**
 1650        * @deprecated As of JDK version 1.1,
 1651        * replaced by <code>getPreferredSize()</code>.
 1652        */
 1653       @Deprecated
 1654       public Dimension preferredSize() {
 1655           /* Avoid grabbing the lock if a reasonable cached size value
 1656            * is available.
 1657            */
 1658           Dimension dim = prefSize;
 1659           if (dim == null || !(isPreferredSizeSet() || isValid())) {
 1660               synchronized (getTreeLock()) {
 1661                   prefSize = (layoutMgr != null) ?
 1662                       layoutMgr.preferredLayoutSize(this) :
 1663                       super.preferredSize();
 1664                   dim = prefSize;
 1665               }
 1666           }
 1667           if (dim != null){
 1668               return new Dimension(dim);
 1669           }
 1670           else{
 1671               return dim;
 1672           }
 1673       }
 1674   
 1675       /**
 1676        * Returns the minimum size of this container.  If the minimum size has
 1677        * not been set explicitly by {@link Component#setMinimumSize(Dimension)}
 1678        * and this {@code Container} has a {@code non-null} {@link LayoutManager},
 1679        * then {@link LayoutManager#minimumLayoutSize(Container)}
 1680        * is used to calculate the minimum size.
 1681        *
 1682        * <p>Note: some implementations may cache the value returned from the
 1683        * {@code LayoutManager}.  Implementations that cache need not invoke
 1684        * {@code minimumLayoutSize} on the {@code LayoutManager} every time
 1685        * this method is invoked, rather the {@code LayoutManager} will only
 1686        * be queried after the {@code Container} becomes invalid.
 1687        *
 1688        * @return    an instance of <code>Dimension</code> that represents
 1689        *                the minimum size of this container.
 1690        * @see       #getPreferredSize
 1691        * @see       #getMaximumSize
 1692        * @see       #getLayout
 1693        * @see       LayoutManager#minimumLayoutSize(Container)
 1694        * @see       Component#getMinimumSize
 1695        * @since     JDK1.1
 1696        */
 1697       public Dimension getMinimumSize() {
 1698           return minimumSize();
 1699       }
 1700   
 1701       /**
 1702        * @deprecated As of JDK version 1.1,
 1703        * replaced by <code>getMinimumSize()</code>.
 1704        */
 1705       @Deprecated
 1706       public Dimension minimumSize() {
 1707           /* Avoid grabbing the lock if a reasonable cached size value
 1708            * is available.
 1709            */
 1710           Dimension dim = minSize;
 1711           if (dim == null || !(isMinimumSizeSet() || isValid())) {
 1712               synchronized (getTreeLock()) {
 1713                   minSize = (layoutMgr != null) ?
 1714                       layoutMgr.minimumLayoutSize(this) :
 1715                       super.minimumSize();
 1716                   dim = minSize;
 1717               }
 1718           }
 1719           if (dim != null){
 1720               return new Dimension(dim);
 1721           }
 1722           else{
 1723               return dim;
 1724           }
 1725       }
 1726   
 1727       /**
 1728        * Returns the maximum size of this container.  If the maximum size has
 1729        * not been set explicitly by {@link Component#setMaximumSize(Dimension)}
 1730        * and the {@link LayoutManager} installed on this {@code Container}
 1731        * is an instance of {@link LayoutManager2}, then
 1732        * {@link LayoutManager2#maximumLayoutSize(Container)}
 1733        * is used to calculate the maximum size.
 1734        *
 1735        * <p>Note: some implementations may cache the value returned from the
 1736        * {@code LayoutManager2}.  Implementations that cache need not invoke
 1737        * {@code maximumLayoutSize} on the {@code LayoutManager2} every time
 1738        * this method is invoked, rather the {@code LayoutManager2} will only
 1739        * be queried after the {@code Container} becomes invalid.
 1740        *
 1741        * @return    an instance of <code>Dimension</code> that represents
 1742        *                the maximum size of this container.
 1743        * @see       #getPreferredSize
 1744        * @see       #getMinimumSize
 1745        * @see       #getLayout
 1746        * @see       LayoutManager2#maximumLayoutSize(Container)
 1747        * @see       Component#getMaximumSize
 1748        */
 1749       public Dimension getMaximumSize() {
 1750           /* Avoid grabbing the lock if a reasonable cached size value
 1751            * is available.
 1752            */
 1753           Dimension dim = maxSize;
 1754           if (dim == null || !(isMaximumSizeSet() || isValid())) {
 1755               synchronized (getTreeLock()) {
 1756                  if (layoutMgr instanceof LayoutManager2) {
 1757                       LayoutManager2 lm = (LayoutManager2) layoutMgr;
 1758                       maxSize = lm.maximumLayoutSize(this);
 1759                  } else {
 1760                       maxSize = super.getMaximumSize();
 1761                  }
 1762                  dim = maxSize;
 1763               }
 1764           }
 1765           if (dim != null){
 1766               return new Dimension(dim);
 1767           }
 1768           else{
 1769               return dim;
 1770           }
 1771       }
 1772   
 1773       /**
 1774        * Returns the alignment along the x axis.  This specifies how
 1775        * the component would like to be aligned relative to other
 1776        * components.  The value should be a number between 0 and 1
 1777        * where 0 represents alignment along the origin, 1 is aligned
 1778        * the furthest away from the origin, 0.5 is centered, etc.
 1779        */
 1780       public float getAlignmentX() {
 1781           float xAlign;
 1782           if (layoutMgr instanceof LayoutManager2) {
 1783               synchronized (getTreeLock()) {
 1784                   LayoutManager2 lm = (LayoutManager2) layoutMgr;
 1785                   xAlign = lm.getLayoutAlignmentX(this);
 1786               }
 1787           } else {
 1788               xAlign = super.getAlignmentX();
 1789           }
 1790           return xAlign;
 1791       }
 1792   
 1793       /**
 1794        * Returns the alignment along the y axis.  This specifies how
 1795        * the component would like to be aligned relative to other
 1796        * components.  The value should be a number between 0 and 1
 1797        * where 0 represents alignment along the origin, 1 is aligned
 1798        * the furthest away from the origin, 0.5 is centered, etc.
 1799        */
 1800       public float getAlignmentY() {
 1801           float yAlign;
 1802           if (layoutMgr instanceof LayoutManager2) {
 1803               synchronized (getTreeLock()) {
 1804                   LayoutManager2 lm = (LayoutManager2) layoutMgr;
 1805                   yAlign = lm.getLayoutAlignmentY(this);
 1806               }
 1807           } else {
 1808               yAlign = super.getAlignmentY();
 1809           }
 1810           return yAlign;
 1811       }
 1812   
 1813       /**
 1814        * Paints the container. This forwards the paint to any lightweight
 1815        * components that are children of this container. If this method is
 1816        * reimplemented, super.paint(g) should be called so that lightweight
 1817        * components are properly rendered. If a child component is entirely
 1818        * clipped by the current clipping setting in g, paint() will not be
 1819        * forwarded to that child.
 1820        *
 1821        * @param g the specified Graphics window
 1822        * @see   Component#update(Graphics)
 1823        */
 1824       public void paint(Graphics g) {
 1825           if (isShowing()) {
 1826               synchronized (this) {
 1827                   if (printing) {
 1828                       if (printingThreads.contains(Thread.currentThread())) {
 1829                           return;
 1830                       }
 1831                   }
 1832               }
 1833   
 1834               // The container is showing on screen and
 1835               // this paint() is not called from print().
 1836               // Paint self and forward the paint to lightweight subcomponents.
 1837   
 1838               // super.paint(); -- Don't bother, since it's a NOP.
 1839   
 1840               GraphicsCallback.PaintCallback.getInstance().
 1841                   runComponents(component, g, GraphicsCallback.LIGHTWEIGHTS);
 1842           }
 1843       }
 1844   
 1845       /**
 1846        * Updates the container.  This forwards the update to any lightweight
 1847        * components that are children of this container.  If this method is
 1848        * reimplemented, super.update(g) should be called so that lightweight
 1849        * components are properly rendered.  If a child component is entirely
 1850        * clipped by the current clipping setting in g, update() will not be
 1851        * forwarded to that child.
 1852        *
 1853        * @param g the specified Graphics window
 1854        * @see   Component#update(Graphics)
 1855        */
 1856       public void update(Graphics g) {
 1857           if (isShowing()) {
 1858               if (! (peer instanceof LightweightPeer)) {
 1859                   g.clearRect(0, 0, width, height);
 1860               }
 1861               paint(g);
 1862           }
 1863       }
 1864   
 1865       /**
 1866        * Prints the container. This forwards the print to any lightweight
 1867        * components that are children of this container. If this method is
 1868        * reimplemented, super.print(g) should be called so that lightweight
 1869        * components are properly rendered. If a child component is entirely
 1870        * clipped by the current clipping setting in g, print() will not be
 1871        * forwarded to that child.
 1872        *
 1873        * @param g the specified Graphics window
 1874        * @see   Component#update(Graphics)
 1875        */
 1876       public void print(Graphics g) {
 1877           if (isShowing()) {
 1878               Thread t = Thread.currentThread();
 1879               try {
 1880                   synchronized (this) {
 1881                       if (printingThreads == null) {
 1882                           printingThreads = new HashSet();
 1883                       }
 1884                       printingThreads.add(t);
 1885                       printing = true;
 1886                   }
 1887                   super.print(g);  // By default, Component.print() calls paint()
 1888               } finally {
 1889                   synchronized (this) {
 1890                       printingThreads.remove(t);
 1891                       printing = !printingThreads.isEmpty();
 1892                   }
 1893               }
 1894   
 1895               GraphicsCallback.PrintCallback.getInstance().
 1896                   runComponents(component, g, GraphicsCallback.LIGHTWEIGHTS);
 1897           }
 1898       }
 1899   
 1900       /**
 1901        * Paints each of the components in this container.
 1902        * @param     g   the graphics context.
 1903        * @see       Component#paint
 1904        * @see       Component#paintAll
 1905        */
 1906       public void paintComponents(Graphics g) {
 1907           if (isShowing()) {
 1908               GraphicsCallback.PaintAllCallback.getInstance().
 1909                   runComponents(component, g, GraphicsCallback.TWO_PASSES);
 1910           }
 1911       }
 1912   
 1913       /**
 1914        * Simulates the peer callbacks into java.awt for printing of
 1915        * lightweight Containers.
 1916        * @param     g   the graphics context to use for printing.
 1917        * @see       Component#printAll
 1918        * @see       #printComponents
 1919        */
 1920       void lightweightPaint(Graphics g) {
 1921           super.lightweightPaint(g);
 1922           paintHeavyweightComponents(g);
 1923       }
 1924   
 1925       /**
 1926        * Prints all the heavyweight subcomponents.
 1927        */
 1928       void paintHeavyweightComponents(Graphics g) {
 1929           if (isShowing()) {
 1930               GraphicsCallback.PaintHeavyweightComponentsCallback.getInstance().
 1931                   runComponents(component, g, GraphicsCallback.LIGHTWEIGHTS |
 1932                                               GraphicsCallback.HEAVYWEIGHTS);
 1933           }
 1934       }
 1935   
 1936       /**
 1937        * Prints each of the components in this container.
 1938        * @param     g   the graphics context.
 1939        * @see       Component#print
 1940        * @see       Component#printAll
 1941        */
 1942       public void printComponents(Graphics g) {
 1943           if (isShowing()) {
 1944               GraphicsCallback.PrintAllCallback.getInstance().
 1945                   runComponents(component, g, GraphicsCallback.TWO_PASSES);
 1946           }
 1947       }
 1948   
 1949       /**
 1950        * Simulates the peer callbacks into java.awt for printing of
 1951        * lightweight Containers.
 1952        * @param     g   the graphics context to use for printing.
 1953        * @see       Component#printAll
 1954        * @see       #printComponents
 1955        */
 1956       void lightweightPrint(Graphics g) {
 1957           super.lightweightPrint(g);
 1958           printHeavyweightComponents(g);
 1959       }
 1960   
 1961       /**
 1962        * Prints all the heavyweight subcomponents.
 1963        */
 1964       void printHeavyweightComponents(Graphics g) {
 1965           if (isShowing()) {
 1966               GraphicsCallback.PrintHeavyweightComponentsCallback.getInstance().
 1967                   runComponents(component, g, GraphicsCallback.LIGHTWEIGHTS |
 1968                                               GraphicsCallback.HEAVYWEIGHTS);
 1969           }
 1970       }
 1971   
 1972       /**
 1973        * Adds the specified container listener to receive container events
 1974        * from this container.
 1975        * If l is null, no exception is thrown and no action is performed.
 1976        * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
 1977        * >AWT Threading Issues</a> for details on AWT's threading model.
 1978        *
 1979        * @param    l the container listener
 1980        *
 1981        * @see #removeContainerListener
 1982        * @see #getContainerListeners
 1983        */
 1984       public synchronized void addContainerListener(ContainerListener l) {
 1985           if (l == null) {
 1986               return;
 1987           }
 1988           containerListener = AWTEventMulticaster.add(containerListener, l);
 1989           newEventsOnly = true;
 1990       }
 1991   
 1992       /**
 1993        * Removes the specified container listener so it no longer receives
 1994        * container events from this container.
 1995        * If l is null, no exception is thrown and no action is performed.
 1996        * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
 1997        * >AWT Threading Issues</a> for details on AWT's threading model.
 1998        *
 1999        * @param   l the container listener
 2000        *
 2001        * @see #addContainerListener
 2002        * @see #getContainerListeners
 2003        */
 2004       public synchronized void removeContainerListener(ContainerListener l) {
 2005           if (l == null) {
 2006               return;
 2007           }
 2008           containerListener = AWTEventMulticaster.remove(containerListener, l);
 2009       }
 2010   
 2011       /**
 2012        * Returns an array of all the container listeners
 2013        * registered on this container.
 2014        *
 2015        * @return all of this container's <code>ContainerListener</code>s
 2016        *         or an empty array if no container
 2017        *         listeners are currently registered
 2018        *
 2019        * @see #addContainerListener
 2020        * @see #removeContainerListener
 2021        * @since 1.4
 2022        */
 2023       public synchronized ContainerListener[] getContainerListeners() {
 2024           return (ContainerListener[]) (getListeners(ContainerListener.class));
 2025       }
 2026   
 2027       /**
 2028        * Returns an array of all the objects currently registered
 2029        * as <code><em>Foo</em>Listener</code>s
 2030        * upon this <code>Container</code>.
 2031        * <code><em>Foo</em>Listener</code>s are registered using the
 2032        * <code>add<em>Foo</em>Listener</code> method.
 2033        *
 2034        * <p>
 2035        * You can specify the <code>listenerType</code> argument
 2036        * with a class literal, such as
 2037        * <code><em>Foo</em>Listener.class</code>.
 2038        * For example, you can query a
 2039        * <code>Container</code> <code>c</code>
 2040        * for its container listeners with the following code:
 2041        *
 2042        * <pre>ContainerListener[] cls = (ContainerListener[])(c.getListeners(ContainerListener.class));</pre>
 2043        *
 2044        * If no such listeners exist, this method returns an empty array.
 2045        *
 2046        * @param listenerType the type of listeners requested; this parameter
 2047        *          should specify an interface that descends from
 2048        *          <code>java.util.EventListener</code>
 2049        * @return an array of all objects registered as
 2050        *          <code><em>Foo</em>Listener</code>s on this container,
 2051        *          or an empty array if no such listeners have been added
 2052        * @exception ClassCastException if <code>listenerType</code>
 2053        *          doesn't specify a class or interface that implements
 2054        *          <code>java.util.EventListener</code>
 2055        *
 2056        * @see #getContainerListeners
 2057        *
 2058        * @since 1.3
 2059        */
 2060       public <T extends EventListener> T[] getListeners(Class<T> listenerType) {
 2061           EventListener l = null;
 2062           if  (listenerType == ContainerListener.class) {
 2063               l = containerListener;
 2064           } else {
 2065               return super.getListeners(listenerType);
 2066           }
 2067           return AWTEventMulticaster.getListeners(l, listenerType);
 2068       }
 2069   
 2070       // REMIND: remove when filtering is done at lower level
 2071       boolean eventEnabled(AWTEvent e) {
 2072           int id = e.getID();
 2073   
 2074           if (id == ContainerEvent.COMPONENT_ADDED ||
 2075               id == ContainerEvent.COMPONENT_REMOVED) {
 2076               if ((eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 ||
 2077                   containerListener != null) {
 2078                   return true;
 2079               }
 2080               return false;
 2081           }
 2082           return super.eventEnabled(e);
 2083       }
 2084   
 2085       /**
 2086        * Processes events on this container. If the event is a
 2087        * <code>ContainerEvent</code>, it invokes the
 2088        * <code>processContainerEvent</code> method, else it invokes
 2089        * its superclass's <code>processEvent</code>.
 2090        * <p>Note that if the event parameter is <code>null</code>
 2091        * the behavior is unspecified and may result in an
 2092        * exception.
 2093        *
 2094        * @param e the event
 2095        */
 2096       protected void processEvent(AWTEvent e) {
 2097           if (e instanceof ContainerEvent) {
 2098               processContainerEvent((ContainerEvent)e);
 2099               return;
 2100           }
 2101           super.processEvent(e);
 2102       }
 2103   
 2104       /**
 2105        * Processes container events occurring on this container by
 2106        * dispatching them to any registered ContainerListener objects.
 2107        * NOTE: This method will not be called unless container events
 2108        * are enabled for this component; this happens when one of the
 2109        * following occurs:
 2110        * <ul>
 2111        * <li>A ContainerListener object is registered via
 2112        *     <code>addContainerListener</code>
 2113        * <li>Container events are enabled via <code>enableEvents</code>
 2114        * </ul>
 2115        * <p>Note that if the event parameter is <code>null</code>
 2116        * the behavior is unspecified and may result in an
 2117        * exception.
 2118        *
 2119        * @param e the container event
 2120        * @see Component#enableEvents
 2121        */
 2122       protected void processContainerEvent(ContainerEvent e) {
 2123           ContainerListener listener = containerListener;
 2124           if (listener != null) {
 2125               switch(e.getID()) {
 2126                 case ContainerEvent.COMPONENT_ADDED:
 2127                   listener.componentAdded(e);
 2128                   break;
 2129                 case ContainerEvent.COMPONENT_REMOVED:
 2130                   listener.componentRemoved(e);
 2131                   break;
 2132               }
 2133           }
 2134       }
 2135   
 2136       /*
 2137        * Dispatches an event to this component or one of its sub components.
 2138        * Create ANCESTOR_RESIZED and ANCESTOR_MOVED events in response to
 2139        * COMPONENT_RESIZED and COMPONENT_MOVED events. We have to do this
 2140        * here instead of in processComponentEvent because ComponentEvents
 2141        * may not be enabled for this Container.
 2142        * @param e the event
 2143        */
 2144       void dispatchEventImpl(AWTEvent e) {
 2145           if ((dispatcher != null) && dispatcher.dispatchEvent(e)) {
 2146               // event was sent to a lightweight component.  The
 2147               // native-produced event sent to the native container
 2148               // must be properly disposed of by the peer, so it
 2149               // gets forwarded.  If the native host has been removed
 2150               // as a result of the sending the lightweight event,
 2151               // the peer reference will be null.
 2152               e.consume();
 2153               if (peer != null) {
 2154                   peer.handleEvent(e);
 2155               }
 2156               return;
 2157           }
 2158   
 2159           super.dispatchEventImpl(e);
 2160   
 2161           synchronized (getTreeLock()) {
 2162               switch (e.getID()) {
 2163                 case ComponentEvent.COMPONENT_RESIZED:
 2164                   createChildHierarchyEvents(HierarchyEvent.ANCESTOR_RESIZED, 0,
 2165                                              Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));
 2166                   break;
 2167                 case ComponentEvent.COMPONENT_MOVED:
 2168                   createChildHierarchyEvents(HierarchyEvent.ANCESTOR_MOVED, 0,
 2169                                          Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));
 2170                   break;
 2171                 default:
 2172                   break;
 2173               }
 2174           }
 2175       }
 2176   
 2177       /*
 2178        * Dispatches an event to this component, without trying to forward
 2179        * it to any subcomponents
 2180        * @param e the event
 2181        */
 2182       void dispatchEventToSelf(AWTEvent e) {
 2183           super.dispatchEventImpl(e);
 2184       }
 2185   
 2186       /**
 2187        * Fetchs the top-most (deepest) lightweight component that is interested
 2188        * in receiving mouse events.
 2189        */
 2190       Component getMouseEventTarget(int x, int y, boolean includeSelf) {
 2191           return getMouseEventTarget(x, y, includeSelf,
 2192                                      MouseEventTargetFilter.FILTER,
 2193                                      !SEARCH_HEAVYWEIGHTS);
 2194       }
 2195   
 2196       /**
 2197        * Fetches the top-most (deepest) component to receive SunDropTargetEvents.
 2198        */
 2199       Component getDropTargetEventTarget(int x, int y, boolean includeSelf) {
 2200           return getMouseEventTarget(x, y, includeSelf,
 2201                                      DropTargetEventTargetFilter.FILTER,
 2202                                      SEARCH_HEAVYWEIGHTS);
 2203       }
 2204   
 2205       /**
 2206        * A private version of getMouseEventTarget which has two additional
 2207        * controllable behaviors. This method searches for the top-most
 2208        * descendant of this container that contains the given coordinates
 2209        * and is accepted by the given filter. The search will be constrained to
 2210        * lightweight descendants if the last argument is <code>false</code>.
 2211        *
 2212        * @param filter EventTargetFilter instance to determine whether the
 2213        *        given component is a valid target for this event.
 2214        * @param searchHeavyweights if <code>false</code>, the method
 2215        *        will bypass heavyweight components during the search.
 2216        */
 2217       private Component getMouseEventTarget(int x, int y, boolean includeSelf,
 2218                                             EventTargetFilter filter,
 2219                                             boolean searchHeavyweights) {
 2220           Component comp = null;
 2221           if (searchHeavyweights) {
 2222               comp = getMouseEventTargetImpl(x, y, includeSelf, filter,
 2223                                              SEARCH_HEAVYWEIGHTS,
 2224                                              searchHeavyweights);
 2225           }
 2226   
 2227           if (comp == null || comp == this) {
 2228               comp = getMouseEventTargetImpl(x, y, includeSelf, filter,
 2229                                              !SEARCH_HEAVYWEIGHTS,
 2230                                              searchHeavyweights);
 2231           }
 2232   
 2233           return comp;
 2234       }
 2235   
 2236       /**
 2237        * A private version of getMouseEventTarget which has three additional
 2238        * controllable behaviors. This method searches for the top-most
 2239        * descendant of this container that contains the given coordinates
 2240        * and is accepted by the given filter. The search will be constrained to
 2241        * descendants of only lightweight children or only heavyweight children
 2242        * of this container depending on searchHeavyweightChildren. The search will
 2243        * be constrained to only lightweight descendants of the searched children
 2244        * of this container if searchHeavyweightDescendants is <code>false</code>.
 2245        *
 2246        * @param filter EventTargetFilter instance to determine whether the
 2247        *        selected component is a valid target for this event.
 2248        * @param searchHeavyweightChildren if <code>true</code>, the method
 2249        *        will bypass immediate lightweight children during the search.
 2250        *        If <code>false</code>, the methods will bypass immediate
 2251        *        heavyweight children during the search.
 2252        * @param searchHeavyweightDescendants if <code>false</code>, the method
 2253        *        will bypass heavyweight descendants which are not immediate
 2254        *        children during the search. If <code>true</code>, the method
 2255        *        will traverse both lightweight and heavyweight descendants during
 2256        *        the search.
 2257        */
 2258       private Component getMouseEventTargetImpl(int x, int y, boolean includeSelf,
 2259                                            EventTargetFilter filter,
 2260                                            boolean searchHeavyweightChildren,
 2261                                            boolean searchHeavyweightDescendants) {
 2262           synchronized (getTreeLock()) {
 2263               int ncomponents = this.ncomponents;
 2264               Component component[] = this.component;
 2265   
 2266               for (int i = 0 ; i < ncomponents ; i++) {
 2267                   Component comp = component[i];
 2268                   if (comp != null && comp.visible &&
 2269                       ((!searchHeavyweightChildren &&
 2270                         comp.peer instanceof LightweightPeer) ||
 2271                        (searchHeavyweightChildren &&
 2272                         !(comp.peer instanceof LightweightPeer))) &&
 2273                       comp.contains(x - comp.x, y - comp.y)) {
 2274   
 2275                       // found a component that intersects the point, see if there
 2276                       // is a deeper possibility.
 2277                       if (comp instanceof Container) {
 2278                           Container child = (Container) comp;
 2279                           Component deeper = child.getMouseEventTarget(
 2280                                   x - child.x,
 2281                                   y - child.y,
 2282                                   includeSelf,
 2283                                   filter,
 2284                                   searchHeavyweightDescendants);
 2285                           if (deeper != null) {
 2286                               return deeper;
 2287                           }
 2288                       } else {
 2289                           if (filter.accept(comp)) {
 2290                               // there isn't a deeper target, but this component
 2291                               // is a target
 2292                               return comp;
 2293                           }
 2294                       }
 2295                   }
 2296               }
 2297   
 2298               boolean isPeerOK;
 2299               boolean isMouseOverMe;
 2300   
 2301               isPeerOK = (peer instanceof LightweightPeer) || includeSelf;
 2302               isMouseOverMe = contains(x,y);
 2303   
 2304               // didn't find a child target, return this component if it's
 2305               // a possible target
 2306               if (isMouseOverMe && isPeerOK && filter.accept(this)) {
 2307                   return this;
 2308               }
 2309               // no possible target
 2310               return null;
 2311           }
 2312       }
 2313   
 2314       static interface EventTargetFilter {
 2315           boolean accept(final Component comp);
 2316       }
 2317   
 2318       static class MouseEventTargetFilter implements EventTargetFilter {
 2319           static final EventTargetFilter FILTER = new MouseEventTargetFilter();
 2320   
 2321           private MouseEventTargetFilter() {}
 2322   
 2323           public boolean accept(final Component comp) {
 2324               return (comp.eventMask & AWTEvent.MOUSE_MOTION_EVENT_MASK) != 0
 2325                   || (comp.eventMask & AWTEvent.MOUSE_EVENT_MASK) != 0
 2326                   || (comp.eventMask & AWTEvent.MOUSE_WHEEL_EVENT_MASK) != 0
 2327                   || comp.mouseListener != null
 2328                   || comp.mouseMotionListener != null
 2329                   || comp.mouseWheelListener != null;
 2330           }
 2331       }
 2332   
 2333       static class DropTargetEventTargetFilter implements EventTargetFilter {
 2334           static final EventTargetFilter FILTER = new DropTargetEventTargetFilter();
 2335   
 2336           private DropTargetEventTargetFilter() {}
 2337   
 2338           public boolean accept(final Component comp) {
 2339               DropTarget dt = comp.getDropTarget();
 2340               return dt != null && dt.isActive();
 2341           }
 2342       }
 2343   
 2344       /**
 2345        * This is called by lightweight components that want the containing
 2346        * windowed parent to enable some kind of events on their behalf.
 2347        * This is needed for events that are normally only dispatched to
 2348        * windows to be accepted so that they can be forwarded downward to
 2349        * the lightweight component that has enabled them.
 2350        */
 2351       void proxyEnableEvents(long events) {
 2352           if (peer instanceof LightweightPeer) {
 2353               // this container is lightweight.... continue sending it
 2354               // upward.
 2355               if (parent != null) {
 2356                   parent.proxyEnableEvents(events);
 2357               }
 2358           } else {
 2359               // This is a native container, so it needs to host
 2360               // one of it's children.  If this function is called before
 2361               // a peer has been created we don't yet have a dispatcher
 2362               // because it has not yet been determined if this instance
 2363               // is lightweight.
 2364               if (dispatcher != null) {
 2365                   dispatcher.enableEvents(events);
 2366               }
 2367           }
 2368       }
 2369   
 2370       /**
 2371        * @deprecated As of JDK version 1.1,
 2372        * replaced by <code>dispatchEvent(AWTEvent e)</code>
 2373        */
 2374       @Deprecated
 2375       public void deliverEvent(Event e) {
 2376           Component comp = getComponentAt(e.x, e.y);
 2377           if ((comp != null) && (comp != this)) {
 2378               e.translate(-comp.x, -comp.y);
 2379               comp.deliverEvent(e);
 2380           } else {
 2381               postEvent(e);
 2382           }
 2383       }
 2384   
 2385       /**
 2386        * Locates the component that contains the x,y position.  The
 2387        * top-most child component is returned in the case where there
 2388        * is overlap in the components.  This is determined by finding
 2389        * the component closest to the index 0 that claims to contain
 2390        * the given point via Component.contains(), except that Components
 2391        * which have native peers take precedence over those which do not
 2392        * (i.e., lightweight Components).
 2393        *
 2394        * @param x the <i>x</i> coordinate
 2395        * @param y the <i>y</i> coordinate
 2396        * @return null if the component does not contain the position.
 2397        * If there is no child component at the requested point and the
 2398        * point is within the bounds of the container the container itself
 2399        * is returned; otherwise the top-most child is returned.
 2400        * @see Component#contains
 2401        * @since JDK1.1
 2402        */
 2403       public Component getComponentAt(int x, int y) {
 2404           return locate(x, y);
 2405       }
 2406   
 2407       /**
 2408        * @deprecated As of JDK version 1.1,
 2409        * replaced by <code>getComponentAt(int, int)</code>.
 2410        */
 2411       @Deprecated
 2412       public Component locate(int x, int y) {
 2413           if (!contains(x, y)) {
 2414               return null;
 2415           }
 2416           synchronized (getTreeLock()) {
 2417               // Two passes: see comment in sun.awt.SunGraphicsCallback
 2418               for (int i = 0 ; i < ncomponents ; i++) {
 2419                   Component comp = component[i];
 2420                   if (comp != null &&
 2421                       !(comp.peer instanceof LightweightPeer)) {
 2422                       if (comp.contains(x - comp.x, y - comp.y)) {
 2423                           return comp;
 2424                       }
 2425                   }
 2426               }
 2427               for (int i = 0 ; i < ncomponents ; i++) {
 2428                   Component comp = component[i];
 2429                   if (comp != null &&
 2430                       comp.peer instanceof LightweightPeer) {
 2431                       if (comp.contains(x - comp.x, y - comp.y)) {
 2432                           return comp;
 2433                       }
 2434                   }
 2435               }
 2436           }
 2437           return this;
 2438       }
 2439   
 2440       /**
 2441        * Gets the component that contains the specified point.
 2442        * @param      p   the point.
 2443        * @return     returns the component that contains the point,
 2444        *                 or <code>null</code> if the component does
 2445        *                 not contain the point.
 2446        * @see        Component#contains
 2447        * @since      JDK1.1
 2448        */
 2449       public Component getComponentAt(Point p) {
 2450           return getComponentAt(p.x, p.y);
 2451       }
 2452   
 2453       /**
 2454        * Returns the position of the mouse pointer in this <code>Container</code>'s
 2455        * coordinate space if the <code>Container</code> is under the mouse pointer,
 2456        * otherwise returns <code>null</code>.
 2457        * This method is similar to {@link Component#getMousePosition()} with the exception
 2458        * that it can take the <code>Container</code>'s children into account.
 2459        * If <code>allowChildren</code> is <code>false</code>, this method will return
 2460        * a non-null value only if the mouse pointer is above the <code>Container</code>
 2461        * directly, not above the part obscured by children.
 2462        * If <code>allowChildren</code> is <code>true</code>, this method returns
 2463        * a non-null value if the mouse pointer is above <code>Container</code> or any
 2464        * of its descendants.
 2465        *
 2466        * @exception HeadlessException if GraphicsEnvironment.isHeadless() returns true
 2467        * @param     allowChildren true if children should be taken into account
 2468        * @see       Component#getMousePosition
 2469        * @return    mouse coordinates relative to this <code>Component</code>, or null
 2470        * @since     1.5
 2471        */
 2472       public Point getMousePosition(boolean allowChildren) throws HeadlessException {
 2473           if (GraphicsEnvironment.isHeadless()) {
 2474               throw new HeadlessException();
 2475           }
 2476           PointerInfo pi = (PointerInfo)java.security.AccessController.doPrivileged(
 2477               new java.security.PrivilegedAction() {
 2478                   public Object run() {
 2479                       return MouseInfo.getPointerInfo();
 2480                   }
 2481               }
 2482           );
 2483           synchronized (getTreeLock()) {
 2484               Component inTheSameWindow = findUnderMouseInWindow(pi);
 2485               if (isSameOrAncestorOf(inTheSameWindow, allowChildren)) {
 2486                   return  pointRelativeToComponent(pi.getLocation());
 2487               }
 2488               return null;
 2489           }
 2490       }
 2491   
 2492       boolean isSameOrAncestorOf(Component comp, boolean allowChildren) {
 2493           return this == comp || (allowChildren && isParentOf(comp));
 2494       }
 2495   
 2496       /**
 2497        * Locates the visible child component that contains the specified
 2498        * position.  The top-most child component is returned in the case
 2499        * where there is overlap in the components.  If the containing child
 2500        * component is a Container, this method will continue searching for
 2501        * the deepest nested child component.  Components which are not
 2502        * visible are ignored during the search.<p>
 2503        *
 2504        * The findComponentAt method is different from getComponentAt in
 2505        * that getComponentAt only searches the Container's immediate
 2506        * children; if the containing component is a Container,
 2507        * findComponentAt will search that child to find a nested component.
 2508        *
 2509        * @param x the <i>x</i> coordinate
 2510        * @param y the <i>y</i> coordinate
 2511        * @return null if the component does not contain the position.
 2512        * If there is no child component at the requested point and the
 2513        * point is within the bounds of the container the container itself
 2514        * is returned.
 2515        * @see Component#contains
 2516        * @see #getComponentAt
 2517        * @since 1.2
 2518        */
 2519       public Component findComponentAt(int x, int y) {
 2520           synchronized (getTreeLock()) {
 2521               return findComponentAt(x, y, true);
 2522           }
 2523       }
 2524   
 2525       /**
 2526        * Private version of findComponentAt which has a controllable
 2527        * behavior. Setting 'ignoreEnabled' to 'false' bypasses disabled
 2528        * Components during the search. This behavior is used by the
 2529        * lightweight cursor support in sun.awt.GlobalCursorManager.
 2530        * The cursor code calls this function directly via native code.
 2531        *
 2532        * The addition of this feature is temporary, pending the
 2533        * adoption of new, public API which exports this feature.
 2534        */
 2535       final Component findComponentAt(int x, int y, boolean ignoreEnabled)
 2536       {
 2537           if (isRecursivelyVisible()){
 2538               return findComponentAtImpl(x, y, ignoreEnabled);
 2539           }
 2540           return null;
 2541       }
 2542   
 2543       final Component findComponentAtImpl(int x, int y, boolean ignoreEnabled){
 2544           if (!(contains(x, y) && visible && (ignoreEnabled || enabled))) {
 2545               return null;
 2546           }
 2547           int ncomponents = this.ncomponents;
 2548           Component component[] = this.component;
 2549   
 2550           // Two passes: see comment in sun.awt.SunGraphicsCallback
 2551           for (int i = 0 ; i < ncomponents ; i++) {
 2552               Component comp = component[i];
 2553               if (comp != null &&
 2554                   !(comp.peer instanceof LightweightPeer)) {
 2555                   if (comp instanceof Container) {
 2556                       comp = ((Container)comp).findComponentAtImpl(x - comp.x,
 2557                                                                y - comp.y,
 2558                                                                ignoreEnabled);
 2559                   } else {
 2560                       comp = comp.locate(x - comp.x, y - comp.y);
 2561                   }
 2562                   if (comp != null && comp.visible &&
 2563                       (ignoreEnabled || comp.enabled))
 2564                   {
 2565                       return comp;
 2566                   }
 2567               }
 2568           }
 2569           for (int i = 0 ; i < ncomponents ; i++) {
 2570               Component comp = component[i];
 2571               if (comp != null &&
 2572                   comp.peer instanceof LightweightPeer) {
 2573                   if (comp instanceof Container) {
 2574                       comp = ((Container)comp).findComponentAtImpl(x - comp.x,
 2575                                                                y - comp.y,
 2576                                                                ignoreEnabled);
 2577                   } else {
 2578                       comp = comp.locate(x - comp.x, y - comp.y);
 2579                   }
 2580                   if (comp != null && comp.visible &&
 2581                       (ignoreEnabled || comp.enabled))
 2582                   {
 2583                       return comp;
 2584                   }
 2585               }
 2586           }
 2587           return this;
 2588       }
 2589   
 2590       /**
 2591        * Locates the visible child component that contains the specified
 2592        * point.  The top-most child component is returned in the case
 2593        * where there is overlap in the components.  If the containing child
 2594        * component is a Container, this method will continue searching for
 2595        * the deepest nested child component.  Components which are not
 2596        * visible are ignored during the search.<p>
 2597        *
 2598        * The findComponentAt method is different from getComponentAt in
 2599        * that getComponentAt only searches the Container's immediate
 2600        * children; if the containing component is a Container,
 2601        * findComponentAt will search that child to find a nested component.
 2602        *
 2603        * @param      p   the point.
 2604        * @return null if the component does not contain the position.
 2605        * If there is no child component at the requested point and the
 2606        * point is within the bounds of the container the container itself
 2607        * is returned.
 2608        * @see Component#contains
 2609        * @see #getComponentAt
 2610        * @since 1.2
 2611        */
 2612       public Component findComponentAt(Point p) {
 2613           return findComponentAt(p.x, p.y);
 2614       }
 2615   
 2616       /**
 2617        * Makes this Container displayable by connecting it to
 2618        * a native screen resource.  Making a container displayable will
 2619        * cause all of its children to be made displayable.
 2620        * This method is called internally by the toolkit and should
 2621        * not be called directly by programs.
 2622        * @see Component#isDisplayable
 2623        * @see #removeNotify
 2624        */
 2625       public void addNotify() {
 2626           synchronized (getTreeLock()) {
 2627               // addNotify() on the children may cause proxy event enabling
 2628               // on this instance, so we first call super.addNotify() and
 2629               // possibly create an lightweight event dispatcher before calling
 2630               // addNotify() on the children which may be lightweight.
 2631               super.addNotify();
 2632               if (! (peer instanceof LightweightPeer)) {
 2633                   dispatcher = new LightweightDispatcher(this);
 2634               }
 2635               int ncomponents = this.ncomponents;
 2636               Component component[] = this.component;
 2637               for (int i = 0 ; i < ncomponents ; i++) {
 2638                   component[i].addNotify();
 2639               }
 2640               // Update stacking order if native platform allows
 2641               ContainerPeer cpeer = (ContainerPeer)peer;
 2642               if (cpeer.isRestackSupported()) {
 2643                   cpeer.restack();
 2644               }
 2645   
 2646   
 2647           }
 2648       }
 2649   
 2650       /**
 2651        * Makes this Container undisplayable by removing its connection
 2652        * to its native screen resource.  Making a container undisplayable
 2653        * will cause all of its children to be made undisplayable.
 2654        * This method is called by the toolkit internally and should
 2655        * not be called directly by programs.
 2656        * @see Component#isDisplayable
 2657        * @see #addNotify
 2658        */
 2659       public void removeNotify() {
 2660           synchronized (getTreeLock()) {
 2661               int ncomponents = this.ncomponents;
 2662               Component component[] = this.component;
 2663               for (int i = ncomponents - 1; i >= 0; i--) {
 2664                   if( component[i] != null ) {
 2665                       // Fix for 6607170.
 2666                       // We want to suppress focus change on disposal
 2667                       // of the focused component. But because of focus
 2668                       // is asynchronous, we should suppress focus change
 2669                       // on every component in case it receives native focus
 2670                       // in the process of disposal.
 2671                       component[i].setAutoFocusTransferOnDisposal(false);
 2672                       component[i].removeNotify();
 2673                       component[i].setAutoFocusTransferOnDisposal(true);
 2674                   }
 2675               }
 2676               // If some of the children had focus before disposal then it still has.
 2677               // Auto-transfer focus to the next (or previous) component if auto-transfer
 2678               // is enabled.
 2679               if (containsFocus() && KeyboardFocusManager.isAutoFocusTransferEnabledFor(this)) {
 2680                   if (!transferFocus(false)) {
 2681                       transferFocusBackward(true);
 2682                   }
 2683               }
 2684               if ( dispatcher != null ) {
 2685                   dispatcher.dispose();
 2686           dispatcher = null;
 2687               }
 2688               super.removeNotify();
 2689           }
 2690       }
 2691   
 2692       /**
 2693        * Checks if the component is contained in the component hierarchy of
 2694        * this container.
 2695        * @param c the component
 2696        * @return     <code>true</code> if it is an ancestor;
 2697        *             <code>false</code> otherwise.
 2698        * @since      JDK1.1
 2699        */
 2700       public boolean isAncestorOf(Component c) {
 2701           Container p;
 2702           if (c == null || ((p = c.getParent()) == null)) {
 2703               return false;
 2704           }
 2705           while (p != null) {
 2706               if (p == this) {
 2707                   return true;
 2708               }
 2709               p = p.getParent();
 2710           }
 2711           return false;
 2712       }
 2713   
 2714       /*
 2715        * The following code was added to support modal JInternalFrames
 2716        * Unfortunately this code has to be added here so that we can get access to
 2717        * some private AWT classes like SequencedEvent.
 2718        *
 2719        * The native container of the LW component has this field set
 2720        * to tell it that it should block Mouse events for all LW
 2721        * children except for the modal component.
 2722        *
 2723        * In the case of nested Modal components, we store the previous
 2724        * modal component in the new modal components value of modalComp;
 2725        */
 2726   
 2727       transient Component modalComp;
 2728       transient AppContext modalAppContext;
 2729   
 2730       private void startLWModal() {
 2731           // Store the app context on which this component is being shown.
 2732           // Event dispatch thread of this app context will be sleeping until
 2733           // we wake it by any event from hideAndDisposeHandler().
 2734           modalAppContext = AppContext.getAppContext();
 2735   
 2736           // keep the KeyEvents from being dispatched
 2737           // until the focus has been transfered
 2738           long time = Toolkit.getEventQueue().getMostRecentEventTime();
 2739           Component predictedFocusOwner = (Component.isInstanceOf(this, "javax.swing.JInternalFrame")) ? ((javax.swing.JInternalFrame)(this)).getMostRecentFocusOwner() : null;
 2740           if (predictedFocusOwner != null) {
 2741               KeyboardFocusManager.getCurrentKeyboardFocusManager().
 2742                   enqueueKeyEvents(time, predictedFocusOwner);
 2743           }
 2744           // We have two mechanisms for blocking: 1. If we're on the
 2745           // EventDispatchThread, start a new event pump. 2. If we're
 2746           // on any other thread, call wait() on the treelock.
 2747           final Container nativeContainer;
 2748           synchronized (getTreeLock()) {
 2749               nativeContainer = getHeavyweightContainer();
 2750               if (nativeContainer.modalComp != null) {
 2751                   this.modalComp =  nativeContainer.modalComp;
 2752                   nativeContainer.modalComp = this;
 2753                   return;
 2754               }
 2755               else {
 2756                   nativeContainer.modalComp = this;
 2757               }
 2758           }
 2759   
 2760           Runnable pumpEventsForHierarchy = new Runnable() {
 2761               public void run() {
 2762                   EventDispatchThread dispatchThread =
 2763                       (EventDispatchThread)Thread.currentThread();
 2764                   dispatchThread.pumpEventsForHierarchy(
 2765                           new Conditional() {
 2766                           public boolean evaluate() {
 2767                           return ((windowClosingException == null) && (nativeContainer.modalComp != null)) ;
 2768                           }
 2769                           }, Container.this);
 2770               }
 2771           };
 2772   
 2773           if (EventQueue.isDispatchThread()) {
 2774               SequencedEvent currentSequencedEvent =
 2775                   KeyboardFocusManager.getCurrentKeyboardFocusManager().
 2776                   getCurrentSequencedEvent();
 2777               if (currentSequencedEvent != null) {
 2778                   currentSequencedEvent.dispose();
 2779               }
 2780   
 2781               pumpEventsForHierarchy.run();
 2782           } else {
 2783               synchronized (getTreeLock()) {
 2784                   Toolkit.getEventQueue().
 2785                       postEvent(new PeerEvent(this,
 2786                                   pumpEventsForHierarchy,
 2787                                   PeerEvent.PRIORITY_EVENT));
 2788                   while ((windowClosingException == null) &&
 2789                          (nativeContainer.modalComp != null))
 2790                   {
 2791                       try {
 2792                           getTreeLock().wait();
 2793                       } catch (InterruptedException e) {
 2794                           break;
 2795                       }
 2796                   }
 2797               }
 2798           }
 2799           if (windowClosingException != null) {
 2800               windowClosingException.fillInStackTrace();
 2801               throw windowClosingException;
 2802           }
 2803           if (predictedFocusOwner != null) {
 2804               KeyboardFocusManager.getCurrentKeyboardFocusManager().
 2805                   dequeueKeyEvents(time, predictedFocusOwner);
 2806           }
 2807       }
 2808   
 2809       private void stopLWModal() {
 2810           synchronized (getTreeLock()) {
 2811               if (modalAppContext != null) {
 2812                   Container nativeContainer = getHeavyweightContainer();
 2813                   if(nativeContainer != null) {
 2814                       if (this.modalComp !=  null) {
 2815                           nativeContainer.modalComp = this.modalComp;
 2816                           this.modalComp = null;
 2817                           return;
 2818                       }
 2819                       else {
 2820                           nativeContainer.modalComp = null;
 2821                       }
 2822                   }
 2823                   // Wake up event dispatch thread on which the dialog was
 2824                   // initially shown
 2825                   SunToolkit.postEvent(modalAppContext,
 2826                           new PeerEvent(this,
 2827                                   new WakingRunnable(),
 2828                                   PeerEvent.PRIORITY_EVENT));
 2829               }
 2830               EventQueue.invokeLater(new WakingRunnable());
 2831               getTreeLock().notifyAll();
 2832           }
 2833       }
 2834   
 2835       final static class WakingRunnable implements Runnable {
 2836           public void run() {
 2837           }
 2838       }
 2839   
 2840       /* End of JOptionPane support code */
 2841   
 2842       /**
 2843        * Returns a string representing the state of this <code>Container</code>.
 2844        * This method is intended to be used only for debugging purposes, and the
 2845        * content and format of the returned string may vary between
 2846        * implementations. The returned string may be empty but may not be
 2847        * <code>null</code>.
 2848        *
 2849        * @return    the parameter string of this container
 2850        */
 2851       protected String paramString() {
 2852           String str = super.paramString();
 2853           LayoutManager layoutMgr = this.layoutMgr;
 2854           if (layoutMgr != null) {
 2855               str += ",layout=" + layoutMgr.getClass().getName();
 2856           }
 2857           return str;
 2858       }
 2859   
 2860       /**
 2861        * Prints a listing of this container to the specified output
 2862        * stream. The listing starts at the specified indentation.
 2863        * <p>
 2864        * The immediate children of the container are printed with
 2865        * an indentation of <code>indent+1</code>.  The children
 2866        * of those children are printed at <code>indent+2</code>
 2867        * and so on.
 2868        *
 2869        * @param    out      a print stream
 2870        * @param    indent   the number of spaces to indent
 2871        * @see      Component#list(java.io.PrintStream, int)
 2872        * @since    JDK1.0
 2873        */
 2874       public void list(PrintStream out, int indent) {
 2875           super.list(out, indent);
 2876           int ncomponents = this.ncomponents;
 2877           Component component[] = this.component;
 2878           for (int i = 0 ; i < ncomponents ; i++) {
 2879               Component comp = component[i];
 2880               if (comp != null) {
 2881                   comp.list(out, indent+1);
 2882               }
 2883           }
 2884       }
 2885   
 2886       /**
 2887        * Prints out a list, starting at the specified indentation,
 2888        * to the specified print writer.
 2889        * <p>
 2890        * The immediate children of the container are printed with
 2891        * an indentation of <code>indent+1</code>.  The children
 2892        * of those children are printed at <code>indent+2</code>
 2893        * and so on.
 2894        *
 2895        * @param    out      a print writer
 2896        * @param    indent   the number of spaces to indent
 2897        * @see      Component#list(java.io.PrintWriter, int)
 2898        * @since    JDK1.1
 2899        */
 2900       public void list(PrintWriter out, int indent) {
 2901           super.list(out, indent);
 2902           int ncomponents = this.ncomponents;
 2903           Component component[] = this.component;
 2904           for (int i = 0 ; i < ncomponents ; i++) {
 2905               Component comp = component[i];
 2906               if (comp != null) {
 2907                   comp.list(out, indent+1);
 2908               }
 2909           }
 2910       }
 2911   
 2912       /**
 2913        * Sets the focus traversal keys for a given traversal operation for this
 2914        * Container.
 2915        * <p>
 2916        * The default values for a Container's focus traversal keys are
 2917        * implementation-dependent. Sun recommends that all implementations for a
 2918        * particular native platform use the same default values. The
 2919        * recommendations for Windows and Unix are listed below. These
 2920        * recommendations are used in the Sun AWT implementations.
 2921        *
 2922        * <table border=1 summary="Recommended default values for a Container's focus traversal keys">
 2923        * <tr>
 2924        *    <th>Identifier</th>
 2925        *    <th>Meaning</th>
 2926        *    <th>Default</th>
 2927        * </tr>
 2928        * <tr>
 2929        *    <td>KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS</td>
 2930        *    <td>Normal forward keyboard traversal</td>
 2931        *    <td>TAB on KEY_PRESSED, CTRL-TAB on KEY_PRESSED</td>
 2932        * </tr>
 2933        * <tr>
 2934        *    <td>KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS</td>
 2935        *    <td>Normal reverse keyboard traversal</td>
 2936        *    <td>SHIFT-TAB on KEY_PRESSED, CTRL-SHIFT-TAB on KEY_PRESSED</td>
 2937        * </tr>
 2938        * <tr>
 2939        *    <td>KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS</td>
 2940        *    <td>Go up one focus traversal cycle</td>
 2941        *    <td>none</td>
 2942        * </tr>
 2943        * <tr>
 2944        *    <td>KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS<td>
 2945        *    <td>Go down one focus traversal cycle</td>
 2946        *    <td>none</td>
 2947        * </tr>
 2948        * </table>
 2949        *
 2950        * To disable a traversal key, use an empty Set; Collections.EMPTY_SET is
 2951        * recommended.
 2952        * <p>
 2953        * Using the AWTKeyStroke API, client code can specify on which of two
 2954        * specific KeyEvents, KEY_PRESSED or KEY_RELEASED, the focus traversal
 2955        * operation will occur. Regardless of which KeyEvent is specified,
 2956        * however, all KeyEvents related to the focus traversal key, including the
 2957        * associated KEY_TYPED event, will be consumed, and will not be dispatched
 2958        * to any Container. It is a runtime error to specify a KEY_TYPED event as
 2959        * mapping to a focus traversal operation, or to map the same event to
 2960        * multiple default focus traversal operations.
 2961        * <p>
 2962        * If a value of null is specified for the Set, this Container inherits the
 2963        * Set from its parent. If all ancestors of this Container have null
 2964        * specified for the Set, then the current KeyboardFocusManager's default
 2965        * Set is used.
 2966        *
 2967        * @param id one of KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
 2968        *        KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
 2969        *        KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
 2970        *        KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
 2971        * @param keystrokes the Set of AWTKeyStroke for the specified operation
 2972        * @see #getFocusTraversalKeys
 2973        * @see KeyboardFocusManager#FORWARD_TRAVERSAL_KEYS
 2974        * @see KeyboardFocusManager#BACKWARD_TRAVERSAL_KEYS
 2975        * @see KeyboardFocusManager#UP_CYCLE_TRAVERSAL_KEYS
 2976        * @see KeyboardFocusManager#DOWN_CYCLE_TRAVERSAL_KEYS
 2977        * @throws IllegalArgumentException if id is not one of
 2978        *         KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
 2979        *         KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
 2980        *         KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
 2981        *         KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS, or if keystrokes
 2982        *         contains null, or if any Object in keystrokes is not an
 2983        *         AWTKeyStroke, or if any keystroke represents a KEY_TYPED event,
 2984        *         or if any keystroke already maps to another focus traversal
 2985        *         operation for this Container
 2986        * @since 1.4
 2987        * @beaninfo
 2988        *       bound: true
 2989        */
 2990       public void setFocusTraversalKeys(int id,
 2991                                         Set<? extends AWTKeyStroke> keystrokes)
 2992       {
 2993           if (id < 0 || id >= KeyboardFocusManager.TRAVERSAL_KEY_LENGTH) {
 2994               throw new IllegalArgumentException("invalid focus traversal key identifier");
 2995           }
 2996   
 2997           // Don't call super.setFocusTraversalKey. The Component parameter check
 2998           // does not allow DOWN_CYCLE_TRAVERSAL_KEYS, but we do.
 2999           setFocusTraversalKeys_NoIDCheck(id, keystrokes);
 3000       }
 3001   
 3002       /**
 3003        * Returns the Set of focus traversal keys for a given traversal operation
 3004        * for this Container. (See
 3005        * <code>setFocusTraversalKeys</code> for a full description of each key.)
 3006        * <p>
 3007        * If a Set of traversal keys has not been explicitly defined for this
 3008        * Container, then this Container's parent's Set is returned. If no Set
 3009        * has been explicitly defined for any of this Container's ancestors, then
 3010        * the current KeyboardFocusManager's default Set is returned.
 3011        *
 3012        * @param id one of KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
 3013        *        KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
 3014        *        KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
 3015        *        KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
 3016        * @return the Set of AWTKeyStrokes for the specified operation. The Set
 3017        *         will be unmodifiable, and may be empty. null will never be
 3018        *         returned.
 3019        * @see #setFocusTraversalKeys
 3020        * @see KeyboardFocusManager#FORWARD_TRAVERSAL_KEYS
 3021        * @see KeyboardFocusManager#BACKWARD_TRAVERSAL_KEYS
 3022        * @see KeyboardFocusManager#UP_CYCLE_TRAVERSAL_KEYS
 3023        * @see KeyboardFocusManager#DOWN_CYCLE_TRAVERSAL_KEYS
 3024        * @throws IllegalArgumentException if id is not one of
 3025        *         KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
 3026        *         KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
 3027        *         KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
 3028        *         KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
 3029        * @since 1.4
 3030        */
 3031       public Set<AWTKeyStroke> getFocusTraversalKeys(int id) {
 3032           if (id < 0 || id >= KeyboardFocusManager.TRAVERSAL_KEY_LENGTH) {
 3033               throw new IllegalArgumentException("invalid focus traversal key identifier");
 3034           }
 3035   
 3036           // Don't call super.getFocusTraversalKey. The Component parameter check
 3037           // does not allow DOWN_CYCLE_TRAVERSAL_KEY, but we do.
 3038           return getFocusTraversalKeys_NoIDCheck(id);
 3039       }
 3040   
 3041       /**
 3042        * Returns whether the Set of focus traversal keys for the given focus
 3043        * traversal operation has been explicitly defined for this Container. If
 3044        * this method returns <code>false</code>, this Container is inheriting the
 3045        * Set from an ancestor, or from the current KeyboardFocusManager.
 3046        *
 3047        * @param id one of KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
 3048        *        KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
 3049        *        KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
 3050        *        KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
 3051        * @return <code>true</code> if the the Set of focus traversal keys for the
 3052        *         given focus traversal operation has been explicitly defined for
 3053        *         this Component; <code>false</code> otherwise.
 3054        * @throws IllegalArgumentException if id is not one of
 3055        *         KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
 3056        *        KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
 3057        *        KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
 3058        *        KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
 3059        * @since 1.4
 3060        */
 3061       public boolean areFocusTraversalKeysSet(int id) {
 3062           if (id < 0 || id >= KeyboardFocusManager.TRAVERSAL_KEY_LENGTH) {
 3063               throw new IllegalArgumentException("invalid focus traversal key identifier");
 3064           }
 3065   
 3066           return (focusTraversalKeys != null && focusTraversalKeys[id] != null);
 3067       }
 3068   
 3069       /**
 3070        * Returns whether the specified Container is the focus cycle root of this
 3071        * Container's focus traversal cycle. Each focus traversal cycle has only
 3072        * a single focus cycle root and each Container which is not a focus cycle
 3073        * root belongs to only a single focus traversal cycle. Containers which
 3074        * are focus cycle roots belong to two cycles: one rooted at the Container
 3075        * itself, and one rooted at the Container's nearest focus-cycle-root
 3076        * ancestor. This method will return <code>true</code> for both such
 3077        * Containers in this case.
 3078        *
 3079        * @param container the Container to be tested
 3080        * @return <code>true</code> if the specified Container is a focus-cycle-
 3081        *         root of this Container; <code>false</code> otherwise
 3082        * @see #isFocusCycleRoot()
 3083        * @since 1.4
 3084        */
 3085       public boolean isFocusCycleRoot(Container container) {
 3086           if (isFocusCycleRoot() && container == this) {
 3087               return true;
 3088           } else {
 3089               return super.isFocusCycleRoot(container);
 3090           }
 3091       }
 3092   
 3093       private Container findTraversalRoot() {
 3094           // I potentially have two roots, myself and my root parent
 3095           // If I am the current root, then use me
 3096           // If none of my parents are roots, then use me
 3097           // If my root parent is the current root, then use my root parent
 3098           // If neither I nor my root parent is the current root, then
 3099           // use my root parent (a guess)
 3100   
 3101           Container currentFocusCycleRoot = KeyboardFocusManager.
 3102               getCurrentKeyboardFocusManager().getCurrentFocusCycleRoot();
 3103           Container root;
 3104   
 3105           if (currentFocusCycleRoot == this) {
 3106               root = this;
 3107           } else {
 3108               root = getFocusCycleRootAncestor();
 3109               if (root == null) {
 3110                   root = this;
 3111               }
 3112           }
 3113   
 3114           if (root != currentFocusCycleRoot) {
 3115               KeyboardFocusManager.getCurrentKeyboardFocusManager().
 3116                   setGlobalCurrentFocusCycleRoot(root);
 3117           }
 3118           return root;
 3119       }
 3120   
 3121       final boolean containsFocus() {
 3122           final Component focusOwner = KeyboardFocusManager.
 3123               getCurrentKeyboardFocusManager().getFocusOwner();
 3124           return isParentOf(focusOwner);
 3125       }
 3126   
 3127       /**
 3128        * Check if this component is the child of this container or its children.
 3129        * Note: this function acquires treeLock
 3130        * Note: this function traverses children tree only in one Window.
 3131        * @param comp a component in test, must not be null
 3132        */
 3133       private boolean isParentOf(Component comp) {
 3134           synchronized(getTreeLock()) {
 3135               while (comp != null && comp != this && !(comp instanceof Window)) {
 3136                   comp = comp.getParent();
 3137               }
 3138               return (comp == this);
 3139           }
 3140       }
 3141   
 3142       void clearMostRecentFocusOwnerOnHide() {
 3143           boolean reset = false;
 3144           Window window = null;
 3145   
 3146           synchronized (getTreeLock()) {
 3147               window = getContainingWindow();
 3148               if (window != null) {
 3149                   Component comp = KeyboardFocusManager.getMostRecentFocusOwner(window);
 3150                   reset = ((comp == this) || isParentOf(comp));
 3151                   // This synchronized should always be the second in a pair
 3152                   // (tree lock, KeyboardFocusManager.class)
 3153                   synchronized(KeyboardFocusManager.class) {
 3154                       Component storedComp = window.getTemporaryLostComponent();
 3155                       if (isParentOf(storedComp) || storedComp == this) {
 3156                           window.setTemporaryLostComponent(null);
 3157                       }
 3158                   }
 3159               }
 3160           }
 3161   
 3162           if (reset) {
 3163               KeyboardFocusManager.setMostRecentFocusOwner(window, null);
 3164           }
 3165       }
 3166   
 3167       void clearCurrentFocusCycleRootOnHide() {
 3168           KeyboardFocusManager kfm =
 3169               KeyboardFocusManager.getCurrentKeyboardFocusManager();
 3170           Container cont = kfm.getCurrentFocusCycleRoot();
 3171   
 3172           if (cont == this || isParentOf(cont)) {
 3173               kfm.setGlobalCurrentFocusCycleRoot(null);
 3174           }
 3175       }
 3176   
 3177       final Container getTraversalRoot() {
 3178           if (isFocusCycleRoot()) {
 3179               return findTraversalRoot();
 3180           }
 3181   
 3182           return super.getTraversalRoot();
 3183       }
 3184   
 3185       /**
 3186        * Sets the focus traversal policy that will manage keyboard traversal of
 3187        * this Container's children, if this Container is a focus cycle root. If
 3188        * the argument is null, this Container inherits its policy from its focus-
 3189        * cycle-root ancestor. If the argument is non-null, this policy will be
 3190        * inherited by all focus-cycle-root children that have no keyboard-
 3191        * traversal policy of their own (as will, recursively, their focus-cycle-
 3192        * root children).
 3193        * <p>
 3194        * If this Container is not a focus cycle root, the policy will be
 3195        * remembered, but will not be used or inherited by this or any other
 3196        * Containers until this Container is made a focus cycle root.
 3197        *
 3198        * @param policy the new focus traversal policy for this Container
 3199        * @see #getFocusTraversalPolicy
 3200        * @see #setFocusCycleRoot
 3201        * @see #isFocusCycleRoot
 3202        * @since 1.4
 3203        * @beaninfo
 3204        *       bound: true
 3205        */
 3206       public void setFocusTraversalPolicy(FocusTraversalPolicy policy) {
 3207           FocusTraversalPolicy oldPolicy;
 3208           synchronized (this) {
 3209               oldPolicy = this.focusTraversalPolicy;
 3210               this.focusTraversalPolicy = policy;
 3211           }
 3212           firePropertyChange("focusTraversalPolicy", oldPolicy, policy);
 3213       }
 3214   
 3215       /**
 3216        * Returns the focus traversal policy that will manage keyboard traversal
 3217        * of this Container's children, or null if this Container is not a focus
 3218        * cycle root. If no traversal policy has been explicitly set for this
 3219        * Container, then this Container's focus-cycle-root ancestor's policy is
 3220        * returned.
 3221        *
 3222        * @return this Container's focus traversal policy, or null if this
 3223        *         Container is not a focus cycle root.
 3224        * @see #setFocusTraversalPolicy
 3225        * @see #setFocusCycleRoot
 3226        * @see #isFocusCycleRoot
 3227        * @since 1.4
 3228        */
 3229       public FocusTraversalPolicy getFocusTraversalPolicy() {
 3230           if (!isFocusTraversalPolicyProvider() && !isFocusCycleRoot()) {
 3231               return null;
 3232           }
 3233   
 3234           FocusTraversalPolicy policy = this.focusTraversalPolicy;
 3235           if (policy != null) {
 3236               return policy;
 3237           }
 3238   
 3239           Container rootAncestor = getFocusCycleRootAncestor();
 3240           if (rootAncestor != null) {
 3241               return rootAncestor.getFocusTraversalPolicy();
 3242           } else {
 3243               return KeyboardFocusManager.getCurrentKeyboardFocusManager().
 3244                   getDefaultFocusTraversalPolicy();
 3245           }
 3246       }
 3247   
 3248       /**
 3249        * Returns whether the focus traversal policy has been explicitly set for
 3250        * this Container. If this method returns <code>false</code>, this
 3251        * Container will inherit its focus traversal policy from an ancestor.
 3252        *
 3253        * @return <code>true</code> if the focus traversal policy has been
 3254        *         explicitly set for this Container; <code>false</code> otherwise.
 3255        * @since 1.4
 3256        */
 3257       public boolean isFocusTraversalPolicySet() {
 3258           return (focusTraversalPolicy != null);
 3259       }
 3260   
 3261       /**
 3262        * Sets whether this Container is the root of a focus traversal cycle. Once
 3263        * focus enters a traversal cycle, typically it cannot leave it via focus
 3264        * traversal unless one of the up- or down-cycle keys is pressed. Normal
 3265        * traversal is limited to this Container, and all of this Container's
 3266        * descendants that are not descendants of inferior focus cycle roots. Note
 3267        * that a FocusTraversalPolicy may bend these restrictions, however. For
 3268        * example, ContainerOrderFocusTraversalPolicy supports implicit down-cycle
 3269        * traversal.
 3270        * <p>
 3271        * The alternative way to specify the traversal order of this Container's
 3272        * children is to make this Container a
 3273        * <a href="doc-files/FocusSpec.html#FocusTraversalPolicyProviders">focus traversal policy provider</a>.
 3274        *
 3275        * @param focusCycleRoot indicates whether this Container is the root of a
 3276        *        focus traversal cycle
 3277        * @see #isFocusCycleRoot()
 3278        * @see #setFocusTraversalPolicy
 3279        * @see #getFocusTraversalPolicy
 3280        * @see ContainerOrderFocusTraversalPolicy
 3281        * @see #setFocusTraversalPolicyProvider
 3282        * @since 1.4
 3283        * @beaninfo
 3284        *       bound: true
 3285        */
 3286       public void setFocusCycleRoot(boolean focusCycleRoot) {
 3287           boolean oldFocusCycleRoot;
 3288           synchronized (this) {
 3289               oldFocusCycleRoot = this.focusCycleRoot;
 3290               this.focusCycleRoot = focusCycleRoot;
 3291           }
 3292           firePropertyChange("focusCycleRoot", oldFocusCycleRoot,
 3293                              focusCycleRoot);
 3294       }
 3295   
 3296       /**
 3297        * Returns whether this Container is the root of a focus traversal cycle.
 3298        * Once focus enters a traversal cycle, typically it cannot leave it via
 3299        * focus traversal unless one of the up- or down-cycle keys is pressed.
 3300        * Normal traversal is limited to this Container, and all of this
 3301        * Container's descendants that are not descendants of inferior focus
 3302        * cycle roots. Note that a FocusTraversalPolicy may bend these
 3303        * restrictions, however. For example, ContainerOrderFocusTraversalPolicy
 3304        * supports implicit down-cycle traversal.
 3305        *
 3306        * @return whether this Container is the root of a focus traversal cycle
 3307        * @see #setFocusCycleRoot
 3308        * @see #setFocusTraversalPolicy
 3309        * @see #getFocusTraversalPolicy
 3310        * @see ContainerOrderFocusTraversalPolicy
 3311        * @since 1.4
 3312        */
 3313       public boolean isFocusCycleRoot() {
 3314           return focusCycleRoot;
 3315       }
 3316   
 3317       /**
 3318        * Sets whether this container will be used to provide focus
 3319        * traversal policy. Container with this property as
 3320        * <code>true</code> will be used to acquire focus traversal policy
 3321        * instead of closest focus cycle root ancestor.
 3322        * @param provider indicates whether this container will be used to
 3323        *                provide focus traversal policy
 3324        * @see #setFocusTraversalPolicy
 3325        * @see #getFocusTraversalPolicy
 3326        * @see #isFocusTraversalPolicyProvider
 3327        * @since 1.5
 3328        * @beaninfo
 3329        *        bound: true
 3330        */
 3331       public final void setFocusTraversalPolicyProvider(boolean provider) {
 3332           boolean oldProvider;
 3333           synchronized(this) {
 3334               oldProvider = focusTraversalPolicyProvider;
 3335               focusTraversalPolicyProvider = provider;
 3336           }
 3337           firePropertyChange("focusTraversalPolicyProvider", oldProvider, provider);
 3338       }
 3339   
 3340       /**
 3341        * Returns whether this container provides focus traversal
 3342        * policy. If this property is set to <code>true</code> then when
 3343        * keyboard focus manager searches container hierarchy for focus
 3344        * traversal policy and encounters this container before any other
 3345        * container with this property as true or focus cycle roots then
 3346        * its focus traversal policy will be used instead of focus cycle
 3347        * root's policy.
 3348        * @see #setFocusTraversalPolicy
 3349        * @see #getFocusTraversalPolicy
 3350        * @see #setFocusCycleRoot
 3351        * @see #setFocusTraversalPolicyProvider
 3352        * @return <code>true</code> if this container provides focus traversal
 3353        *         policy, <code>false</code> otherwise
 3354        * @since 1.5
 3355        * @beaninfo
 3356        *        bound: true
 3357        */
 3358       public final boolean isFocusTraversalPolicyProvider() {
 3359           return focusTraversalPolicyProvider;
 3360       }
 3361   
 3362       /**
 3363        * Transfers the focus down one focus traversal cycle. If this Container is
 3364        * a focus cycle root, then the focus owner is set to this Container's
 3365        * default Component to focus, and the current focus cycle root is set to
 3366        * this Container. If this Container is not a focus cycle root, then no
 3367        * focus traversal operation occurs.
 3368        *
 3369        * @see       Component#requestFocus()
 3370        * @see       #isFocusCycleRoot
 3371        * @see       #setFocusCycleRoot
 3372        * @since     1.4
 3373        */
 3374       public void transferFocusDownCycle() {
 3375           if (isFocusCycleRoot()) {
 3376               KeyboardFocusManager.getCurrentKeyboardFocusManager().
 3377                   setGlobalCurrentFocusCycleRoot(this);
 3378               Component toFocus = getFocusTraversalPolicy().
 3379                   getDefaultComponent(this);
 3380               if (toFocus != null) {
 3381                   toFocus.requestFocus(CausedFocusEvent.Cause.TRAVERSAL_DOWN);
 3382               }
 3383           }
 3384       }
 3385   
 3386       void preProcessKeyEvent(KeyEvent e) {
 3387           Container parent = this.parent;
 3388           if (parent != null) {
 3389               parent.preProcessKeyEvent(e);
 3390           }
 3391       }
 3392   
 3393       void postProcessKeyEvent(KeyEvent e) {
 3394           Container parent = this.parent;
 3395           if (parent != null) {
 3396               parent.postProcessKeyEvent(e);
 3397           }
 3398       }
 3399   
 3400       boolean postsOldMouseEvents() {
 3401           return true;
 3402       }
 3403   
 3404       /**
 3405        * Sets the <code>ComponentOrientation</code> property of this container
 3406        * and all components contained within it.
 3407        *
 3408        * @param o the new component orientation of this container and
 3409        *        the components contained within it.
 3410        * @exception NullPointerException if <code>orientation</code> is null.
 3411        * @see Component#setComponentOrientation
 3412        * @see Component#getComponentOrientation
 3413        * @since 1.4
 3414        */
 3415       public void applyComponentOrientation(ComponentOrientation o) {
 3416           super.applyComponentOrientation(o);
 3417   
 3418           for (int i = 0 ; i < ncomponents ; ++i) {
 3419                component[i].applyComponentOrientation(o);
 3420           }
 3421       }
 3422   
 3423       /**
 3424        * Adds a PropertyChangeListener to the listener list. The listener is
 3425        * registered for all bound properties of this class, including the
 3426        * following:
 3427        * <ul>
 3428        *    <li>this Container's font ("font")</li>
 3429        *    <li>this Container's background color ("background")</li>
 3430        *    <li>this Container's foreground color ("foreground")</li>
 3431        *    <li>this Container's focusability ("focusable")</li>
 3432        *    <li>this Container's focus traversal keys enabled state
 3433        *        ("focusTraversalKeysEnabled")</li>
 3434        *    <li>this Container's Set of FORWARD_TRAVERSAL_KEYS
 3435        *        ("forwardFocusTraversalKeys")</li>
 3436        *    <li>this Container's Set of BACKWARD_TRAVERSAL_KEYS
 3437        *        ("backwardFocusTraversalKeys")</li>
 3438        *    <li>this Container's Set of UP_CYCLE_TRAVERSAL_KEYS
 3439        *        ("upCycleFocusTraversalKeys")</li>
 3440        *    <li>this Container's Set of DOWN_CYCLE_TRAVERSAL_KEYS
 3441        *        ("downCycleFocusTraversalKeys")</li>
 3442        *    <li>this Container's focus traversal policy ("focusTraversalPolicy")
 3443        *        </li>
 3444        *    <li>this Container's focus-cycle-root state ("focusCycleRoot")</li>
 3445        * </ul>
 3446        * Note that if this Container is inheriting a bound property, then no
 3447        * event will be fired in response to a change in the inherited property.
 3448        * <p>
 3449        * If listener is null, no exception is thrown and no action is performed.
 3450        *
 3451        * @param    listener  the PropertyChangeListener to be added
 3452        *
 3453        * @see Component#removePropertyChangeListener
 3454        * @see #addPropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
 3455        */
 3456       public void addPropertyChangeListener(PropertyChangeListener listener) {
 3457           super.addPropertyChangeListener(listener);
 3458       }
 3459   
 3460       /**
 3461        * Adds a PropertyChangeListener to the listener list for a specific
 3462        * property. The specified property may be user-defined, or one of the
 3463        * following defaults:
 3464        * <ul>
 3465        *    <li>this Container's font ("font")</li>
 3466        *    <li>this Container's background color ("background")</li>
 3467        *    <li>this Container's foreground color ("foreground")</li>
 3468        *    <li>this Container's focusability ("focusable")</li>
 3469        *    <li>this Container's focus traversal keys enabled state
 3470        *        ("focusTraversalKeysEnabled")</li>
 3471        *    <li>this Container's Set of FORWARD_TRAVERSAL_KEYS
 3472        *        ("forwardFocusTraversalKeys")</li>
 3473        *    <li>this Container's Set of BACKWARD_TRAVERSAL_KEYS
 3474        *        ("backwardFocusTraversalKeys")</li>
 3475        *    <li>this Container's Set of UP_CYCLE_TRAVERSAL_KEYS
 3476        *        ("upCycleFocusTraversalKeys")</li>
 3477        *    <li>this Container's Set of DOWN_CYCLE_TRAVERSAL_KEYS
 3478        *        ("downCycleFocusTraversalKeys")</li>
 3479        *    <li>this Container's focus traversal policy ("focusTraversalPolicy")
 3480        *        </li>
 3481        *    <li>this Container's focus-cycle-root state ("focusCycleRoot")</li>
 3482        *    <li>this Container's focus-traversal-policy-provider state("focusTraversalPolicyProvider")</li>
 3483        *    <li>this Container's focus-traversal-policy-provider state("focusTraversalPolicyProvider")</li>
 3484        * </ul>
 3485        * Note that if this Container is inheriting a bound property, then no
 3486        * event will be fired in response to a change in the inherited property.
 3487        * <p>
 3488        * If listener is null, no exception is thrown and no action is performed.
 3489        *
 3490        * @param propertyName one of the property names listed above
 3491        * @param listener the PropertyChangeListener to be added
 3492        *
 3493        * @see #addPropertyChangeListener(java.beans.PropertyChangeListener)
 3494        * @see Component#removePropertyChangeListener
 3495        */
 3496       public void addPropertyChangeListener(String propertyName,
 3497                                             PropertyChangeListener listener) {
 3498           super.addPropertyChangeListener(propertyName, listener);
 3499       }
 3500   
 3501       // Serialization support. A Container is responsible for restoring the
 3502       // parent fields of its component children.
 3503   
 3504       /**
 3505        * Container Serial Data Version.
 3506        */
 3507       private int containerSerializedDataVersion = 1;
 3508   
 3509       /**
 3510        * Serializes this <code>Container</code> to the specified
 3511        * <code>ObjectOutputStream</code>.
 3512        * <ul>
 3513        *    <li>Writes default serializable fields to the stream.</li>
 3514        *    <li>Writes a list of serializable ContainerListener(s) as optional
 3515        *        data. The non-serializable ContainerListner(s) are detected and
 3516        *        no attempt is made to serialize them.</li>
 3517        *    <li>Write this Container's FocusTraversalPolicy if and only if it
 3518        *        is Serializable; otherwise, <code>null</code> is written.</li>
 3519        * </ul>
 3520        *
 3521        * @param s the <code>ObjectOutputStream</code> to write
 3522        * @serialData <code>null</code> terminated sequence of 0 or more pairs;
 3523        *   the pair consists of a <code>String</code> and <code>Object</code>;
 3524        *   the <code>String</code> indicates the type of object and
 3525        *   is one of the following:
 3526        *   <code>containerListenerK</code> indicating an
 3527        *     <code>ContainerListener</code> object;
 3528        *   the <code>Container</code>'s <code>FocusTraversalPolicy</code>,
 3529        *     or <code>null</code>
 3530        *
 3531        * @see AWTEventMulticaster#save(java.io.ObjectOutputStream, java.lang.String, java.util.EventListener)
 3532        * @see Container#containerListenerK
 3533        * @see #readObject(ObjectInputStream)
 3534        */
 3535       private void writeObject(ObjectOutputStream s) throws IOException {
 3536           ObjectOutputStream.PutField f = s.putFields();
 3537           f.put("ncomponents", ncomponents);
 3538           f.put("component", component);
 3539           f.put("layoutMgr", layoutMgr);
 3540           f.put("dispatcher", dispatcher);
 3541           f.put("maxSize", maxSize);
 3542           f.put("focusCycleRoot", focusCycleRoot);
 3543           f.put("containerSerializedDataVersion", containerSerializedDataVersion);
 3544           f.put("focusTraversalPolicyProvider", focusTraversalPolicyProvider);
 3545           s.writeFields();
 3546   
 3547           AWTEventMulticaster.save(s, containerListenerK, containerListener);
 3548           s.writeObject(null);
 3549   
 3550           if (focusTraversalPolicy instanceof java.io.Serializable) {
 3551               s.writeObject(focusTraversalPolicy);
 3552           } else {
 3553               s.writeObject(null);
 3554           }
 3555       }
 3556   
 3557       /**
 3558        * Deserializes this <code>Container</code> from the specified
 3559        * <code>ObjectInputStream</code>.
 3560        * <ul>
 3561        *    <li>Reads default serializable fields from the stream.</li>
 3562        *    <li>Reads a list of serializable ContainerListener(s) as optional
 3563        *        data. If the list is null, no Listeners are installed.</li>
 3564        *    <li>Reads this Container's FocusTraversalPolicy, which may be null,
 3565        *        as optional data.</li>
 3566        * </ul>
 3567        *
 3568        * @param s the <code>ObjectInputStream</code> to read
 3569        * @serial
 3570        * @see #addContainerListener
 3571        * @see #writeObject(ObjectOutputStream)
 3572        */
 3573       private void readObject(ObjectInputStream s)
 3574           throws ClassNotFoundException, IOException
 3575       {
 3576           ObjectInputStream.GetField f = s.readFields();
 3577           ncomponents = f.get("ncomponents", 0);
 3578           component = (Component[])f.get("component", new Component[0]);
 3579           layoutMgr = (LayoutManager)f.get("layoutMgr", null);
 3580           dispatcher = (LightweightDispatcher)f.get("dispatcher", null);
 3581           // Old stream. Doesn't contain maxSize among Component's fields.
 3582           if (maxSize == null) {
 3583               maxSize = (Dimension)f.get("maxSize", null);
 3584           }
 3585           focusCycleRoot = f.get("focusCycleRoot", false);
 3586           containerSerializedDataVersion = f.get("containerSerializedDataVersion", 1);
 3587           focusTraversalPolicyProvider = f.get("focusTraversalPolicyProvider", false);
 3588   
 3589           Component component[] = this.component;
 3590           for(int i = 0; i < ncomponents; i++) {
 3591               component[i].parent = this;
 3592               adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK,
 3593                   component[i].numListening(AWTEvent.HIERARCHY_EVENT_MASK));
 3594               adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
 3595                   component[i].numListening(
 3596                       AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));
 3597               adjustDescendants(component[i].countHierarchyMembers());
 3598           }
 3599   
 3600           Object keyOrNull;
 3601           while(null != (keyOrNull = s.readObject())) {
 3602               String key = ((String)keyOrNull).intern();
 3603   
 3604               if (containerListenerK == key) {
 3605                   addContainerListener((ContainerListener)(s.readObject()));
 3606               } else {
 3607                   // skip value for unrecognized key
 3608                   s.readObject();
 3609               }
 3610           }
 3611   
 3612           try {
 3613               Object policy = s.readObject();
 3614               if (policy instanceof FocusTraversalPolicy) {
 3615                   focusTraversalPolicy = (FocusTraversalPolicy)policy;
 3616               }
 3617           } catch (java.io.OptionalDataException e) {
 3618               // JDK 1.1/1.2/1.3 instances will not have this optional data.
 3619               // e.eof will be true to indicate that there is no more data
 3620               // available for this object. If e.eof is not true, throw the
 3621               // exception as it might have been caused by reasons unrelated to
 3622               // focusTraversalPolicy.
 3623   
 3624               if (!e.eof) {
 3625                   throw e;
 3626               }
 3627           }
 3628       }
 3629   
 3630       /*
 3631        * --- Accessibility Support ---
 3632        */
 3633   
 3634       /**
 3635        * Inner class of Container used to provide default support for
 3636        * accessibility.  This class is not meant to be used directly by
 3637        * application developers, but is instead meant only to be
 3638        * subclassed by container developers.
 3639        * <p>
 3640        * The class used to obtain the accessible role for this object,
 3641        * as well as implementing many of the methods in the
 3642        * AccessibleContainer interface.
 3643        * @since 1.3
 3644        */
 3645       protected class AccessibleAWTContainer extends AccessibleAWTComponent {
 3646   
 3647           /**
 3648            * JDK1.3 serialVersionUID
 3649            */
 3650           private static final long serialVersionUID = 5081320404842566097L;
 3651   
 3652           /**
 3653            * Returns the number of accessible children in the object.  If all
 3654            * of the children of this object implement <code>Accessible</code>,
 3655            * then this method should return the number of children of this object.
 3656            *
 3657            * @return the number of accessible children in the object
 3658            */
 3659           public int getAccessibleChildrenCount() {
 3660               return Container.this.getAccessibleChildrenCount();
 3661           }
 3662   
 3663           /**
 3664            * Returns the nth <code>Accessible</code> child of the object.
 3665            *
 3666            * @param i zero-based index of child
 3667            * @return the nth <code>Accessible</code> child of the object
 3668            */
 3669           public Accessible getAccessibleChild(int i) {
 3670               return Container.this.getAccessibleChild(i);
 3671           }
 3672   
 3673           /**
 3674            * Returns the <code>Accessible</code> child, if one exists,
 3675            * contained at the local coordinate <code>Point</code>.
 3676            *
 3677            * @param p the point defining the top-left corner of the
 3678            *    <code>Accessible</code>, given in the coordinate space
 3679            *    of the object's parent
 3680            * @return the <code>Accessible</code>, if it exists,
 3681            *    at the specified location; else <code>null</code>
 3682            */
 3683           public Accessible getAccessibleAt(Point p) {
 3684               return Container.this.getAccessibleAt(p);
 3685           }
 3686   
 3687           protected ContainerListener accessibleContainerHandler = null;
 3688   
 3689           /**
 3690            * Fire <code>PropertyChange</code> listener, if one is registered,
 3691            * when children are added or removed.
 3692            * @since 1.3
 3693            */
 3694           protected class AccessibleContainerHandler
 3695               implements ContainerListener {
 3696               public void componentAdded(ContainerEvent e) {
 3697                   Component c = e.getChild();
 3698                   if (c != null && c instanceof Accessible) {
 3699                       AccessibleAWTContainer.this.firePropertyChange(
 3700                           AccessibleContext.ACCESSIBLE_CHILD_PROPERTY,
 3701                           null, ((Accessible) c).getAccessibleContext());
 3702                   }
 3703               }
 3704               public void componentRemoved(ContainerEvent e) {
 3705                   Component c = e.getChild();
 3706                   if (c != null && c instanceof Accessible) {
 3707                       AccessibleAWTContainer.this.firePropertyChange(
 3708                           AccessibleContext.ACCESSIBLE_CHILD_PROPERTY,
 3709                           ((Accessible) c).getAccessibleContext(), null);
 3710                   }
 3711               }
 3712           }
 3713   
 3714           /**
 3715            * Adds a PropertyChangeListener to the listener list.
 3716            *
 3717            * @param listener  the PropertyChangeListener to be added
 3718            */
 3719           public void addPropertyChangeListener(PropertyChangeListener listener) {
 3720               if (accessibleContainerHandler == null) {
 3721                   accessibleContainerHandler = new AccessibleContainerHandler();
 3722                   Container.this.addContainerListener(accessibleContainerHandler);
 3723               }
 3724               super.addPropertyChangeListener(listener);
 3725           }
 3726   
 3727       } // inner class AccessibleAWTContainer
 3728   
 3729       /**
 3730        * Returns the <code>Accessible</code> child contained at the local
 3731        * coordinate <code>Point</code>, if one exists.  Otherwise
 3732        * returns <code>null</code>.
 3733        *
 3734        * @param p the point defining the top-left corner of the
 3735        *    <code>Accessible</code>, given in the coordinate space
 3736        *    of the object's parent
 3737        * @return the <code>Accessible</code> at the specified location,
 3738        *    if it exists; otherwise <code>null</code>
 3739        */
 3740       Accessible getAccessibleAt(Point p) {
 3741           synchronized (getTreeLock()) {
 3742               if (this instanceof Accessible) {
 3743                   Accessible a = (Accessible)this;
 3744                   AccessibleContext ac = a.getAccessibleContext();
 3745                   if (ac != null) {
 3746                       AccessibleComponent acmp;
 3747                       Point location;
 3748                       int nchildren = ac.getAccessibleChildrenCount();
 3749                       for (int i=0; i < nchildren; i++) {
 3750                           a = ac.getAccessibleChild(i);
 3751                           if ((a != null)) {
 3752                               ac = a.getAccessibleContext();
 3753                               if (ac != null) {
 3754                                   acmp = ac.getAccessibleComponent();
 3755                                   if ((acmp != null) && (acmp.isShowing())) {
 3756                                       location = acmp.getLocation();
 3757                                       Point np = new Point(p.x-location.x,
 3758                                                            p.y-location.y);
 3759                                       if (acmp.contains(np)){
 3760                                           return a;
 3761                                       }
 3762                                   }
 3763                               }
 3764                           }
 3765                       }
 3766                   }
 3767                   return (Accessible)this;
 3768               } else {
 3769                   Component ret = this;
 3770                   if (!this.contains(p.x,p.y)) {
 3771                       ret = null;
 3772                   } else {
 3773                       int ncomponents = this.getComponentCount();
 3774                       for (int i=0; i < ncomponents; i++) {
 3775                           Component comp = this.getComponent(i);
 3776                           if ((comp != null) && comp.isShowing()) {
 3777                               Point location = comp.getLocation();
 3778                               if (comp.contains(p.x-location.x,p.y-location.y)) {
 3779                                   ret = comp;
 3780                               }
 3781                           }
 3782                       }
 3783                   }
 3784                   if (ret instanceof Accessible) {
 3785                       return (Accessible) ret;
 3786                   }
 3787               }
 3788               return null;
 3789           }
 3790       }
 3791   
 3792       /**
 3793        * Returns the number of accessible children in the object.  If all
 3794        * of the children of this object implement <code>Accessible</code>,
 3795        * then this method should return the number of children of this object.
 3796        *
 3797        * @return the number of accessible children in the object
 3798        */
 3799       int getAccessibleChildrenCount() {
 3800           synchronized (getTreeLock()) {
 3801               int count = 0;
 3802               Component[] children = this.getComponents();
 3803               for (int i = 0; i < children.length; i++) {
 3804                   if (children[i] instanceof Accessible) {
 3805                       count++;
 3806                   }
 3807               }
 3808               return count;
 3809           }
 3810       }
 3811   
 3812       /**
 3813        * Returns the nth <code>Accessible</code> child of the object.
 3814        *
 3815        * @param i zero-based index of child
 3816        * @return the nth <code>Accessible</code> child of the object
 3817        */
 3818       Accessible getAccessibleChild(int i) {
 3819           synchronized (getTreeLock()) {
 3820               Component[] children = this.getComponents();
 3821               int count = 0;
 3822               for (int j = 0; j < children.length; j++) {
 3823                   if (children[j] instanceof Accessible) {
 3824                       if (count == i) {
 3825                           return (Accessible) children[j];
 3826                       } else {
 3827                           count++;
 3828                       }
 3829                   }
 3830               }
 3831               return null;
 3832           }
 3833       }
 3834   
 3835       // ************************** MIXING CODE *******************************
 3836   
 3837       final void increaseComponentCount(Component c) {
 3838           synchronized (getTreeLock()) {
 3839               if (!c.isDisplayable()) {
 3840                   throw new IllegalStateException(
 3841                       "Peer does not exist while invoking the increaseComponentCount() method"
 3842                   );
 3843               }
 3844   
 3845               int addHW = 0;
 3846               int addLW = 0;
 3847   
 3848               if (c instanceof Container) {
 3849                   addLW = ((Container)c).numOfLWComponents;
 3850                   addHW = ((Container)c).numOfHWComponents;
 3851               }
 3852               if (c.isLightweight()) {
 3853                   addLW++;
 3854               } else {
 3855                   addHW++;
 3856               }
 3857   
 3858               for (Container cont = this; cont != null; cont = cont.getContainer()) {
 3859                   cont.numOfLWComponents += addLW;
 3860                   cont.numOfHWComponents += addHW;
 3861               }
 3862           }
 3863       }
 3864   
 3865       final void decreaseComponentCount(Component c) {
 3866           synchronized (getTreeLock()) {
 3867               if (!c.isDisplayable()) {
 3868                   throw new IllegalStateException(
 3869                       "Peer does not exist while invoking the decreaseComponentCount() method"
 3870                   );
 3871               }
 3872   
 3873               int subHW = 0;
 3874               int subLW = 0;
 3875   
 3876               if (c instanceof Container) {
 3877                   subLW = ((Container)c).numOfLWComponents;
 3878                   subHW = ((Container)c).numOfHWComponents;
 3879               }
 3880               if (c.isLightweight()) {
 3881                   subLW++;
 3882               } else {
 3883                   subHW++;
 3884               }
 3885   
 3886               for (Container cont = this; cont != null; cont = cont.getContainer()) {
 3887                   cont.numOfLWComponents -= subLW;
 3888                   cont.numOfHWComponents -= subHW;
 3889               }
 3890           }
 3891       }
 3892   
 3893       private int getTopmostComponentIndex() {
 3894           checkTreeLock();
 3895           if (getComponentCount() > 0) {
 3896               return 0;
 3897           }
 3898           return -1;
 3899       }
 3900   
 3901       private int getBottommostComponentIndex() {
 3902           checkTreeLock();
 3903           if (getComponentCount() > 0) {
 3904               return getComponentCount() - 1;
 3905           }
 3906           return -1;
 3907       }
 3908   
 3909       final void recursiveSubtractAndApplyShape(Region shape) {
 3910           recursiveSubtractAndApplyShape(shape, getTopmostComponentIndex(), getBottommostComponentIndex());
 3911       }
 3912   
 3913       final void recursiveSubtractAndApplyShape(Region shape, int fromZorder) {
 3914           recursiveSubtractAndApplyShape(shape, fromZorder, getBottommostComponentIndex());
 3915       }
 3916   
 3917       final void recursiveSubtractAndApplyShape(Region shape, int fromZorder, int toZorder) {
 3918           checkTreeLock();
 3919           if (mixingLog.isLoggable(Level.FINE)) {
 3920               mixingLog.fine("this = " + this +
 3921                   "; shape=" + shape + "; fromZ=" + fromZorder + "; toZ=" + toZorder);
 3922           }
 3923           if (fromZorder == -1) {
 3924               return;
 3925           }
 3926           for (int index = fromZorder; index <= toZorder; index++) {
 3927               Component comp = getComponent(index);
 3928               if (!comp.isLightweight()) {
 3929                   comp.subtractAndApplyShape(shape);
 3930               } else if (comp instanceof Container &&
 3931                       ((Container)comp).hasHeavyweightDescendants() && comp.isShowing()) {
 3932                   ((Container)comp).recursiveSubtractAndApplyShape(shape);
 3933               }
 3934           }
 3935       }
 3936   
 3937       final void recursiveApplyCurrentShape() {
 3938           recursiveApplyCurrentShape(getTopmostComponentIndex(), getBottommostComponentIndex());
 3939       }
 3940   
 3941       final void recursiveApplyCurrentShape(int fromZorder) {
 3942           recursiveApplyCurrentShape(fromZorder, getBottommostComponentIndex());
 3943       }
 3944   
 3945       final void recursiveApplyCurrentShape(int fromZorder, int toZorder) {
 3946           checkTreeLock();
 3947           if (mixingLog.isLoggable(Level.FINE)) {
 3948               mixingLog.fine("this = " + this +
 3949                   "; fromZ=" + fromZorder + "; toZ=" + toZorder);
 3950           }
 3951           if (fromZorder == -1) {
 3952               return;
 3953           }
 3954           for (int index = fromZorder; index <= toZorder; index++) {
 3955               Component comp = getComponent(index);
 3956               if (!comp.isLightweight()) {
 3957                   comp.applyCurrentShape();
 3958               } else if (comp instanceof Container &&
 3959                       ((Container)comp).hasHeavyweightDescendants()) {
 3960                   ((Container)comp).recursiveApplyCurrentShape();
 3961               }
 3962           }
 3963       }
 3964   
 3965       private void recursiveShowHeavyweightChildren() {
 3966           if (!hasHeavyweightDescendants() || !isVisible()) {
 3967               return;
 3968           }
 3969           for (int index = 0; index < getComponentCount(); index++) {
 3970               Component comp = getComponent(index);
 3971               if (comp.isLightweight()) {
 3972                   if  (comp instanceof Container) {
 3973                       ((Container)comp).recursiveShowHeavyweightChildren();
 3974                   }
 3975               } else {
 3976                   if (comp.isVisible()) {
 3977                       ComponentPeer peer = comp.getPeer();
 3978                       if (peer != null) {
 3979                           peer.show();
 3980                       }
 3981                   }
 3982               }
 3983           }
 3984       }
 3985   
 3986       private void recursiveHideHeavyweightChildren() {
 3987           if (!hasHeavyweightDescendants()) {
 3988               return;
 3989           }
 3990           for (int index = 0; index < getComponentCount(); index++) {
 3991               Component comp = getComponent(index);
 3992               if (comp.isLightweight()) {
 3993                   if  (comp instanceof Container) {
 3994                       ((Container)comp).recursiveHideHeavyweightChildren();
 3995                   }
 3996               } else {
 3997                   if (comp.isVisible()) {
 3998                       ComponentPeer peer = comp.getPeer();
 3999                       if (peer != null) {
 4000                           peer.hide();
 4001                       }
 4002                   }
 4003               }
 4004           }
 4005       }
 4006   
 4007       private void recursiveRelocateHeavyweightChildren(Point origin) {
 4008           for (int index = 0; index < getComponentCount(); index++) {
 4009               Component comp = getComponent(index);
 4010               if (comp.isLightweight()) {
 4011                   if  (comp instanceof Container &&
 4012                           ((Container)comp).hasHeavyweightDescendants())
 4013                   {
 4014                       final Point newOrigin = new Point(origin);
 4015                       newOrigin.translate(comp.getX(), comp.getY());
 4016                       ((Container)comp).recursiveRelocateHeavyweightChildren(newOrigin);
 4017                   }
 4018               } else {
 4019                   ComponentPeer peer = comp.getPeer();
 4020                   if (peer != null) {
 4021                       peer.setBounds(origin.x + comp.getX(), origin.y + comp.getY(),
 4022                               comp.getWidth(), comp.getHeight(),
 4023                               ComponentPeer.SET_LOCATION);
 4024                   }
 4025               }
 4026           }
 4027       }
 4028   
 4029       /*
 4030        * Consider the heavyweight container hides or shows the HW descendants
 4031        * automatically. Therefore we care of LW containers' visibility only.
 4032        */
 4033       private boolean isRecursivelyVisibleUpToHeavyweightContainer() {
 4034           if (!isLightweight()) {
 4035               return true;
 4036           }
 4037           return isVisible() && (getContainer() == null ||
 4038                getContainer().isRecursivelyVisibleUpToHeavyweightContainer());
 4039       }
 4040   
 4041       @Override
 4042       void mixOnShowing() {
 4043           synchronized (getTreeLock()) {
 4044               if (mixingLog.isLoggable(Level.FINE)) {
 4045                   mixingLog.fine("this = " + this);
 4046               }
 4047   
 4048               boolean isLightweight = isLightweight();
 4049   
 4050               if (isLightweight && isRecursivelyVisibleUpToHeavyweightContainer()) {
 4051                   recursiveShowHeavyweightChildren();
 4052               }
 4053   
 4054               if (!isLightweight || (isLightweight && hasHeavyweightDescendants())) {
 4055                   recursiveApplyCurrentShape();
 4056               }
 4057   
 4058               super.mixOnShowing();
 4059           }
 4060       }
 4061   
 4062       @Override
 4063       void mixOnHiding(boolean isLightweight) {
 4064           synchronized (getTreeLock()) {
 4065               if (mixingLog.isLoggable(Level.FINE)) {
 4066                   mixingLog.fine("this = " + this +
 4067                           "; isLightweight=" + isLightweight);
 4068               }
 4069               if (isLightweight) {
 4070                   recursiveHideHeavyweightChildren();
 4071               }
 4072               super.mixOnHiding(isLightweight);
 4073           }
 4074       }
 4075   
 4076       @Override
 4077       void mixOnReshaping() {
 4078           synchronized (getTreeLock()) {
 4079               if (mixingLog.isLoggable(Level.FINE)) {
 4080                   mixingLog.fine("this = " + this);
 4081               }
 4082               if (isLightweight() && hasHeavyweightDescendants()) {
 4083                   final Point origin = new Point(getX(), getY());
 4084                   for (Container cont = getContainer();
 4085                           cont != null && cont.isLightweight();
 4086                           cont = cont.getContainer())
 4087                   {
 4088                       origin.translate(cont.getX(), cont.getY());
 4089                   }
 4090   
 4091                   recursiveRelocateHeavyweightChildren(origin);
 4092               }
 4093               super.mixOnReshaping();
 4094           }
 4095       }
 4096   
 4097       @Override
 4098       void mixOnZOrderChanging(int oldZorder, int newZorder) {
 4099           synchronized (getTreeLock()) {
 4100               if (mixingLog.isLoggable(Level.FINE)) {
 4101                   mixingLog.fine("this = " + this +
 4102                       "; oldZ=" + oldZorder + "; newZ=" + newZorder);
 4103               }
 4104   
 4105               boolean becameHigher = newZorder < oldZorder;
 4106   
 4107               if (becameHigher && isLightweight() && hasHeavyweightDescendants()) {
 4108                   recursiveApplyCurrentShape();
 4109               }
 4110               super.mixOnZOrderChanging(oldZorder, newZorder);
 4111           }
 4112       }
 4113   
 4114       // ****************** END OF MIXING CODE ********************************
 4115   }
 4116   
 4117   
 4118   /**
 4119    * Class to manage the dispatching of MouseEvents to the lightweight descendants
 4120    * and SunDropTargetEvents to both lightweight and heavyweight descendants
 4121    * contained by a native container.
 4122    *
 4123    * NOTE: the class name is not appropriate anymore, but we cannot change it
 4124    * because we must keep serialization compatibility.
 4125    *
 4126    * @author Timothy Prinzing
 4127    */
 4128   class LightweightDispatcher implements java.io.Serializable, AWTEventListener {
 4129   
 4130       /*
 4131        * JDK 1.1 serialVersionUID
 4132        */
 4133       private static final long serialVersionUID = 5184291520170872969L;
 4134       /*
 4135        * Our own mouse event for when we're dragged over from another hw
 4136        * container
 4137        */
 4138       private static final int  LWD_MOUSE_DRAGGED_OVER = 1500;
 4139   
 4140       private static final Logger eventLog = Logger.getLogger("java.awt.event.LightweightDispatcher");
 4141   
 4142       LightweightDispatcher(Container nativeContainer) {
 4143           this.nativeContainer = nativeContainer;
 4144           mouseEventTarget = null;
 4145           eventMask = 0;
 4146       }
 4147   
 4148       /*
 4149        * Clean up any resources allocated when dispatcher was created;
 4150        * should be called from Container.removeNotify
 4151        */
 4152       void dispose() {
 4153           //System.out.println("Disposing lw dispatcher");
 4154           stopListeningForOtherDrags();
 4155           mouseEventTarget = null;
 4156       }
 4157   
 4158       /**
 4159        * Enables events to subcomponents.
 4160        */
 4161       void enableEvents(long events) {
 4162           eventMask |= events;
 4163       }
 4164   
 4165       /**
 4166        * Dispatches an event to a sub-component if necessary, and
 4167        * returns whether or not the event was forwarded to a
 4168        * sub-component.
 4169        *
 4170        * @param e the event
 4171        */
 4172       boolean dispatchEvent(AWTEvent e) {
 4173           boolean ret = false;
 4174   
 4175           /*
 4176            * Fix for BugTraq Id 4389284.
 4177            * Dispatch SunDropTargetEvents regardless of eventMask value.
 4178            * Do not update cursor on dispatching SunDropTargetEvents.
 4179            */
 4180           if (e instanceof SunDropTargetEvent) {
 4181   
 4182               SunDropTargetEvent sdde = (SunDropTargetEvent) e;
 4183               ret = processDropTargetEvent(sdde);
 4184   
 4185           } else {
 4186               if (e instanceof MouseEvent && (eventMask & MOUSE_MASK) != 0) {
 4187                   MouseEvent me = (MouseEvent) e;
 4188                   ret = processMouseEvent(me);
 4189               }
 4190   
 4191               if (e.getID() == MouseEvent.MOUSE_MOVED) {
 4192                   nativeContainer.updateCursorImmediately();
 4193               }
 4194           }
 4195   
 4196           return ret;
 4197       }
 4198   
 4199       /* This method effectively returns whether or not a mouse button was down
 4200        * just BEFORE the event happened.  A better method name might be
 4201        * wasAMouseButtonDownBeforeThisEvent().
 4202        */
 4203       private boolean isMouseGrab(MouseEvent e) {
 4204           int modifiers = e.getModifiersEx();
 4205   
 4206           if(e.getID() == MouseEvent.MOUSE_PRESSED
 4207               || e.getID() == MouseEvent.MOUSE_RELEASED)
 4208           {
 4209               switch (e.getButton()) {
 4210               case MouseEvent.BUTTON1:
 4211                   modifiers ^= InputEvent.BUTTON1_DOWN_MASK;
 4212                   break;
 4213               case MouseEvent.BUTTON2:
 4214                   modifiers ^= InputEvent.BUTTON2_DOWN_MASK;
 4215                   break;
 4216               case MouseEvent.BUTTON3:
 4217                   modifiers ^= InputEvent.BUTTON3_DOWN_MASK;
 4218                   break;
 4219               }
 4220           }
 4221           /* modifiers now as just before event */
 4222           return ((modifiers & (InputEvent.BUTTON1_DOWN_MASK
 4223                                 | InputEvent.BUTTON2_DOWN_MASK
 4224                                 | InputEvent.BUTTON3_DOWN_MASK)) != 0);
 4225       }
 4226   
 4227       /**
 4228        * This method attempts to distribute a mouse event to a lightweight
 4229        * component.  It tries to avoid doing any unnecessary probes down
 4230        * into the component tree to minimize the overhead of determining
 4231        * where to route the event, since mouse movement events tend to
 4232        * come in large and frequent amounts.
 4233        */
 4234       private boolean processMouseEvent(MouseEvent e) {
 4235           int id = e.getID();
 4236           Component mouseOver =   // sensitive to mouse events
 4237               nativeContainer.getMouseEventTarget(e.getX(), e.getY(),
 4238                                                   Container.INCLUDE_SELF);
 4239   
 4240           trackMouseEnterExit(mouseOver, e);
 4241   
 4242       // 4508327 : MOUSE_CLICKED should only go to the recipient of
 4243       // the accompanying MOUSE_PRESSED, so don't reset mouseEventTarget on a
 4244       // MOUSE_CLICKED.
 4245       if (!isMouseGrab(e) && id != MouseEvent.MOUSE_CLICKED) {
 4246               mouseEventTarget = (mouseOver != nativeContainer) ? mouseOver: null;
 4247           }
 4248   
 4249           if (mouseEventTarget != null) {
 4250               switch (id) {
 4251               case MouseEvent.MOUSE_ENTERED:
 4252               case MouseEvent.MOUSE_EXITED:
 4253                   break;
 4254               case MouseEvent.MOUSE_PRESSED:
 4255                   retargetMouseEvent(mouseEventTarget, id, e);
 4256                   break;
 4257           case MouseEvent.MOUSE_RELEASED:
 4258               retargetMouseEvent(mouseEventTarget, id, e);
 4259           break;
 4260           case MouseEvent.MOUSE_CLICKED:
 4261           // 4508327: MOUSE_CLICKED should never be dispatched to a Component
 4262           // other than that which received the MOUSE_PRESSED event.  If the
 4263           // mouse is now over a different Component, don't dispatch the event.
 4264           // The previous fix for a similar problem was associated with bug
 4265           // 4155217.
 4266           if (mouseOver == mouseEventTarget) {
 4267               retargetMouseEvent(mouseOver, id, e);
 4268           }
 4269           break;
 4270               case MouseEvent.MOUSE_MOVED:
 4271                   retargetMouseEvent(mouseEventTarget, id, e);
 4272                   break;
 4273           case MouseEvent.MOUSE_DRAGGED:
 4274               if (isMouseGrab(e)) {
 4275                   retargetMouseEvent(mouseEventTarget, id, e);
 4276               }
 4277                   break;
 4278           case MouseEvent.MOUSE_WHEEL:
 4279               // This may send it somewhere that doesn't have MouseWheelEvents
 4280               // enabled.  In this case, Component.dispatchEventImpl() will
 4281               // retarget the event to a parent that DOES have the events enabled.
 4282               if (eventLog.isLoggable(Level.FINEST) && (mouseOver != null)) {
 4283                   eventLog.log(Level.FINEST, "retargeting mouse wheel to " +
 4284                                mouseOver.getName() + ", " +
 4285                                mouseOver.getClass());
 4286               }
 4287               retargetMouseEvent(mouseOver, id, e);
 4288           break;
 4289               }
 4290               e.consume();
 4291       }
 4292       return e.isConsumed();
 4293       }
 4294   
 4295       private boolean processDropTargetEvent(SunDropTargetEvent e) {
 4296           int id = e.getID();
 4297           int x = e.getX();
 4298           int y = e.getY();
 4299   
 4300           /*
 4301            * Fix for BugTraq ID 4395290.
 4302            * It is possible that SunDropTargetEvent's Point is outside of the
 4303            * native container bounds. In this case we truncate coordinates.
 4304            */
 4305           if (!nativeContainer.contains(x, y)) {
 4306               final Dimension d = nativeContainer.getSize();
 4307               if (d.width <= x) {
 4308                   x = d.width - 1;
 4309               } else if (x < 0) {
 4310                   x = 0;
 4311               }
 4312               if (d.height <= y) {
 4313                   y = d.height - 1;
 4314               } else if (y < 0) {
 4315                   y = 0;
 4316               }
 4317           }
 4318           Component mouseOver =   // not necessarily sensitive to mouse events
 4319               nativeContainer.getDropTargetEventTarget(x, y,
 4320                                                        Container.INCLUDE_SELF);
 4321           trackMouseEnterExit(mouseOver, e);
 4322   
 4323           if (mouseOver != nativeContainer && mouseOver != null) {
 4324               switch (id) {
 4325               case SunDropTargetEvent.MOUSE_ENTERED:
 4326               case SunDropTargetEvent.MOUSE_EXITED:
 4327                   break;
 4328               default:
 4329                   retargetMouseEvent(mouseOver, id, e);
 4330                   e.consume();
 4331                   break;
 4332               }
 4333           }
 4334           return e.isConsumed();
 4335       }
 4336   
 4337       /*
 4338        * Generates enter/exit events as mouse moves over lw components
 4339        * @param targetOver        Target mouse is over (including native container)
 4340        * @param e                 Mouse event in native container
 4341        */
 4342       private void trackMouseEnterExit(Component targetOver, MouseEvent e) {
 4343           Component       targetEnter = null;
 4344           int             id = e.getID();
 4345   
 4346           if (e instanceof SunDropTargetEvent &&
 4347               id == MouseEvent.MOUSE_ENTERED &&
 4348               isMouseInNativeContainer == true) {
 4349               // This can happen if a lightweight component which initiated the
 4350               // drag has an associated drop target. MOUSE_ENTERED comes when the
 4351               // mouse is in the native container already. To propagate this event
 4352               // properly we should null out targetLastEntered.
 4353               targetLastEntered = null;
 4354           } else if ( id != MouseEvent.MOUSE_EXITED &&
 4355                id != MouseEvent.MOUSE_DRAGGED &&
 4356                id != LWD_MOUSE_DRAGGED_OVER &&
 4357                isMouseInNativeContainer == false ) {
 4358               // any event but an exit or drag means we're in the native container
 4359               isMouseInNativeContainer = true;
 4360               startListeningForOtherDrags();
 4361           } else if ( id == MouseEvent.MOUSE_EXITED ) {
 4362               isMouseInNativeContainer = false;
 4363               stopListeningForOtherDrags();
 4364           }
 4365   
 4366           if (isMouseInNativeContainer) {
 4367               targetEnter = targetOver;
 4368           }
 4369   
 4370           if (targetLastEntered == targetEnter) {
 4371                   return;
 4372           }
 4373   
 4374           if (targetLastEntered != null) {
 4375               retargetMouseEvent(targetLastEntered, MouseEvent.MOUSE_EXITED, e);
 4376           }
 4377           if (id == MouseEvent.MOUSE_EXITED) {
 4378               // consume native exit event if we generate one
 4379               e.consume();
 4380           }
 4381   
 4382           if (targetEnter != null) {
 4383               retargetMouseEvent(targetEnter, MouseEvent.MOUSE_ENTERED, e);
 4384           }
 4385           if (id == MouseEvent.MOUSE_ENTERED) {
 4386               // consume native enter event if we generate one
 4387               e.consume();
 4388           }
 4389   
 4390           targetLastEntered = targetEnter;
 4391       }
 4392   
 4393       /*
 4394        * Listens to global mouse drag events so even drags originating
 4395        * from other heavyweight containers will generate enter/exit
 4396        * events in this container
 4397        */
 4398       private void startListeningForOtherDrags() {
 4399           //System.out.println("Adding AWTEventListener");
 4400           java.security.AccessController.doPrivileged(
 4401               new java.security.PrivilegedAction() {
 4402                   public Object run() {
 4403                       nativeContainer.getToolkit().addAWTEventListener(
 4404                           LightweightDispatcher.this,
 4405                           AWTEvent.MOUSE_EVENT_MASK |
 4406                           AWTEvent.MOUSE_MOTION_EVENT_MASK);
 4407                       return null;
 4408                   }
 4409               }
 4410           );
 4411       }
 4412   
 4413       private void stopListeningForOtherDrags() {
 4414           //System.out.println("Removing AWTEventListener");
 4415           java.security.AccessController.doPrivileged(
 4416               new java.security.PrivilegedAction() {
 4417                   public Object run() {
 4418                       nativeContainer.getToolkit().removeAWTEventListener(LightweightDispatcher.this);
 4419                       return null;
 4420                   }
 4421               }
 4422           );
 4423       }
 4424   
 4425       /*
 4426        * (Implementation of AWTEventListener)
 4427        * Listen for drag events posted in other hw components so we can
 4428        * track enter/exit regardless of where a drag originated
 4429        */
 4430       public void eventDispatched(AWTEvent e) {
 4431           boolean isForeignDrag = (e instanceof MouseEvent) &&
 4432                                   !(e instanceof SunDropTargetEvent) &&
 4433                                   (e.id == MouseEvent.MOUSE_DRAGGED) &&
 4434                                   (e.getSource() != nativeContainer);
 4435   
 4436           if (!isForeignDrag) {
 4437               // only interested in drags from other hw components
 4438               return;
 4439           }
 4440   
 4441           MouseEvent      srcEvent = (MouseEvent)e;
 4442           MouseEvent      me;
 4443   
 4444           synchronized (nativeContainer.getTreeLock()) {
 4445               Component srcComponent = srcEvent.getComponent();
 4446   
 4447               // component may have disappeared since drag event posted
 4448               // (i.e. Swing hierarchical menus)
 4449               if ( !srcComponent.isShowing() ) {
 4450                   return;
 4451               }
 4452   
 4453               // see 5083555
 4454               // check if srcComponent is in any modal blocked window
 4455               Component c = nativeContainer;
 4456               while ((c != null) && !(c instanceof Window)) {
 4457                   c = c.getParent_NoClientCode();
 4458               }
 4459               if ((c == null) || ((Window)c).isModalBlocked()) {
 4460                   return;
 4461               }
 4462   
 4463               //
 4464               // create an internal 'dragged-over' event indicating
 4465               // we are being dragged over from another hw component
 4466               //
 4467               me = new MouseEvent(nativeContainer,
 4468                                  LWD_MOUSE_DRAGGED_OVER,
 4469                                  srcEvent.getWhen(),
 4470                                  srcEvent.getModifiersEx() | srcEvent.getModifiers(),
 4471                                  srcEvent.getX(),
 4472                                  srcEvent.getY(),
 4473                                  srcEvent.getXOnScreen(),
 4474                                  srcEvent.getYOnScreen(),
 4475                                  srcEvent.getClickCount(),
 4476                                  srcEvent.isPopupTrigger(),
 4477                                  srcEvent.getButton());
 4478               ((AWTEvent)srcEvent).copyPrivateDataInto(me);
 4479               // translate coordinates to this native container
 4480               final Point ptSrcOrigin = srcComponent.getLocationOnScreen();
 4481   
 4482               if (AppContext.getAppContext() != nativeContainer.appContext) {
 4483                   final MouseEvent mouseEvent = me;
 4484                   Runnable r = new Runnable() {
 4485                           public void run() {
 4486                               if (!nativeContainer.isShowing() ) {
 4487                                   return;
 4488                               }
 4489   
 4490                               Point       ptDstOrigin = nativeContainer.getLocationOnScreen();
 4491                               mouseEvent.translatePoint(ptSrcOrigin.x - ptDstOrigin.x,
 4492                                                 ptSrcOrigin.y - ptDstOrigin.y );
 4493                               Component targetOver =
 4494                                   nativeContainer.getMouseEventTarget(mouseEvent.getX(),
 4495                                                                       mouseEvent.getY(),
 4496                                                                       Container.INCLUDE_SELF);
 4497                               trackMouseEnterExit(targetOver, mouseEvent);
 4498                           }
 4499                       };
 4500                   SunToolkit.executeOnEventHandlerThread(nativeContainer, r);
 4501                   return;
 4502               } else {
 4503                   if (!nativeContainer.isShowing() ) {
 4504                       return;
 4505                   }
 4506   
 4507                   Point   ptDstOrigin = nativeContainer.getLocationOnScreen();
 4508                   me.translatePoint( ptSrcOrigin.x - ptDstOrigin.x, ptSrcOrigin.y - ptDstOrigin.y );
 4509               }
 4510           }
 4511           //System.out.println("Track event: " + me);
 4512           // feed the 'dragged-over' event directly to the enter/exit
 4513           // code (not a real event so don't pass it to dispatchEvent)
 4514           Component targetOver =
 4515               nativeContainer.getMouseEventTarget(me.getX(), me.getY(),
 4516                                                   Container.INCLUDE_SELF);
 4517           trackMouseEnterExit(targetOver, me);
 4518       }
 4519   
 4520       /**
 4521        * Sends a mouse event to the current mouse event recipient using
 4522        * the given event (sent to the windowed host) as a srcEvent.  If
 4523        * the mouse event target is still in the component tree, the
 4524        * coordinates of the event are translated to those of the target.
 4525        * If the target has been removed, we don't bother to send the
 4526        * message.
 4527        */
 4528       void retargetMouseEvent(Component target, int id, MouseEvent e) {
 4529           if (target == null) {
 4530               return; // mouse is over another hw component or target is disabled
 4531           }
 4532   
 4533           int x = e.getX(), y = e.getY();
 4534           Component component;
 4535   
 4536           for(component = target;
 4537               component != null && component != nativeContainer;
 4538               component = component.getParent()) {
 4539               x -= component.x;
 4540               y -= component.y;
 4541           }
 4542           MouseEvent retargeted;
 4543           if (component != null) {
 4544               if (e instanceof SunDropTargetEvent) {
 4545                   retargeted = new SunDropTargetEvent(target,
 4546                                                       id,
 4547                                                       x,
 4548                                                       y,
 4549                                                       ((SunDropTargetEvent)e).getDispatcher());
 4550               } else if (id == MouseEvent.MOUSE_WHEEL) {
 4551                   retargeted = new MouseWheelEvent(target,
 4552                                         id,
 4553                                          e.getWhen(),
 4554                                          e.getModifiersEx() | e.getModifiers(),
 4555                                          x,
 4556                                          y,
 4557                                          e.getXOnScreen(),
 4558                                          e.getYOnScreen(),
 4559                                          e.getClickCount(),
 4560                                          e.isPopupTrigger(),
 4561                                          ((MouseWheelEvent)e).getScrollType(),
 4562                                          ((MouseWheelEvent)e).getScrollAmount(),
 4563                                          ((MouseWheelEvent)e).getWheelRotation(),
 4564                                          ((MouseWheelEvent)e).getPreciseWheelRotation());
 4565               }
 4566               else {
 4567                   retargeted = new MouseEvent(target,
 4568                                               id,
 4569                                               e.getWhen(),
 4570                                               e.getModifiersEx() | e.getModifiers(),
 4571                                               x,
 4572                                               y,
 4573                                               e.getXOnScreen(),
 4574                                               e.getYOnScreen(),
 4575                                               e.getClickCount(),
 4576                                               e.isPopupTrigger(),
 4577                                               e.getButton());
 4578               }
 4579   
 4580               ((AWTEvent)e).copyPrivateDataInto(retargeted);
 4581   
 4582               if (target == nativeContainer) {
 4583                   // avoid recursively calling LightweightDispatcher...
 4584                   ((Container)target).dispatchEventToSelf(retargeted);
 4585               } else {
 4586                   assert AppContext.getAppContext() == target.appContext;
 4587   
 4588                   if (nativeContainer.modalComp != null) {
 4589                       if (((Container)nativeContainer.modalComp).isAncestorOf(target)) {
 4590                           target.dispatchEvent(retargeted);
 4591                       } else {
 4592                           e.consume();
 4593                       }
 4594                   } else {
 4595                       target.dispatchEvent(retargeted);
 4596                   }
 4597               }
 4598           }
 4599       }
 4600   
 4601       // --- member variables -------------------------------
 4602   
 4603       /**
 4604        * The windowed container that might be hosting events for
 4605        * subcomponents.
 4606        */
 4607       private Container nativeContainer;
 4608   
 4609       /**
 4610        * This variable is not used, but kept for serialization compatibility
 4611        */
 4612       private Component focus;
 4613   
 4614       /**
 4615        * The current subcomponent being hosted by this windowed
 4616        * component that has events being forwarded to it.  If this
 4617        * is null, there are currently no events being forwarded to
 4618        * a subcomponent.
 4619        */
 4620       private transient Component mouseEventTarget;
 4621   
 4622       /**
 4623        * The last component entered
 4624        */
 4625       private transient Component targetLastEntered;
 4626   
 4627       /**
 4628        * Is the mouse over the native container
 4629        */
 4630       private transient boolean isMouseInNativeContainer = false;
 4631   
 4632       /**
 4633        * This variable is not used, but kept for serialization compatibility
 4634        */
 4635       private Cursor nativeCursor;
 4636   
 4637       /**
 4638        * The event mask for contained lightweight components.  Lightweight
 4639        * components need a windowed container to host window-related
 4640        * events.  This separate mask indicates events that have been
 4641        * requested by contained lightweight components without effecting
 4642        * the mask of the windowed component itself.
 4643        */
 4644       private long eventMask;
 4645   
 4646       /**
 4647        * The kind of events routed to lightweight components from windowed
 4648        * hosts.
 4649        */
 4650       private static final long PROXY_EVENT_MASK =
 4651           AWTEvent.FOCUS_EVENT_MASK |
 4652           AWTEvent.KEY_EVENT_MASK |
 4653           AWTEvent.MOUSE_EVENT_MASK |
 4654           AWTEvent.MOUSE_MOTION_EVENT_MASK |
 4655           AWTEvent.MOUSE_WHEEL_EVENT_MASK;
 4656   
 4657       private static final long MOUSE_MASK =
 4658           AWTEvent.MOUSE_EVENT_MASK |
 4659           AWTEvent.MOUSE_MOTION_EVENT_MASK |
 4660           AWTEvent.MOUSE_WHEEL_EVENT_MASK;
 4661   }

Save This Page
Home » openjdk-7 » java » awt » [javadoc | source]