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