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