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