1 /*
   2  * Copyright (c) 1995, 2013, 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<Thread> 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     @SuppressWarnings({"unchecked","rawtypes"})
 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.Level.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.Level.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.Level.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.Level.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.Level.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 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 = java.security.AccessController.doPrivileged(
2603             new java.security.PrivilegedAction<PointerInfo>() {
2604                 public PointerInfo 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.getComponentAt(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.getComponentAt(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().getMostRecentKeyEventTime();
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      * <p>
3097      * This method may throw a {@code ClassCastException} if any {@code Object}
3098      * in {@code keystrokes} is not an {@code AWTKeyStroke}.
3099      *
3100      * @param id one of KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
3101      *        KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
3102      *        KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
3103      *        KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
3104      * @param keystrokes the Set of AWTKeyStroke for the specified operation
3105      * @see #getFocusTraversalKeys
3106      * @see KeyboardFocusManager#FORWARD_TRAVERSAL_KEYS
3107      * @see KeyboardFocusManager#BACKWARD_TRAVERSAL_KEYS
3108      * @see KeyboardFocusManager#UP_CYCLE_TRAVERSAL_KEYS
3109      * @see KeyboardFocusManager#DOWN_CYCLE_TRAVERSAL_KEYS
3110      * @throws IllegalArgumentException if id is not one of
3111      *         KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
3112      *         KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
3113      *         KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
3114      *         KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS, or if keystrokes
3115      *         contains null, or if any keystroke represents a KEY_TYPED event,
3116      *         or if any keystroke already maps to another focus traversal
3117      *         operation for this Container
3118      * @since 1.4
3119      * @beaninfo
3120      *       bound: true
3121      */
3122     public void setFocusTraversalKeys(int id,
3123                                       Set<? extends AWTKeyStroke> keystrokes)
3124     {
3125         if (id < 0 || id >= KeyboardFocusManager.TRAVERSAL_KEY_LENGTH) {
3126             throw new IllegalArgumentException("invalid focus traversal key identifier");
3127         }
3128 
3129         // Don't call super.setFocusTraversalKey. The Component parameter check
3130         // does not allow DOWN_CYCLE_TRAVERSAL_KEYS, but we do.
3131         setFocusTraversalKeys_NoIDCheck(id, keystrokes);
3132     }
3133 
3134     /**
3135      * Returns the Set of focus traversal keys for a given traversal operation
3136      * for this Container. (See
3137      * <code>setFocusTraversalKeys</code> for a full description of each key.)
3138      * <p>
3139      * If a Set of traversal keys has not been explicitly defined for this
3140      * Container, then this Container's parent's Set is returned. If no Set
3141      * has been explicitly defined for any of this Container's ancestors, then
3142      * the current KeyboardFocusManager's default Set is returned.
3143      *
3144      * @param id one of KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
3145      *        KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
3146      *        KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
3147      *        KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
3148      * @return the Set of AWTKeyStrokes for the specified operation. The Set
3149      *         will be unmodifiable, and may be empty. null will never be
3150      *         returned.
3151      * @see #setFocusTraversalKeys
3152      * @see KeyboardFocusManager#FORWARD_TRAVERSAL_KEYS
3153      * @see KeyboardFocusManager#BACKWARD_TRAVERSAL_KEYS
3154      * @see KeyboardFocusManager#UP_CYCLE_TRAVERSAL_KEYS
3155      * @see KeyboardFocusManager#DOWN_CYCLE_TRAVERSAL_KEYS
3156      * @throws IllegalArgumentException if id is not one of
3157      *         KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
3158      *         KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
3159      *         KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
3160      *         KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
3161      * @since 1.4
3162      */
3163     public Set<AWTKeyStroke> getFocusTraversalKeys(int id) {
3164         if (id < 0 || id >= KeyboardFocusManager.TRAVERSAL_KEY_LENGTH) {
3165             throw new IllegalArgumentException("invalid focus traversal key identifier");
3166         }
3167 
3168         // Don't call super.getFocusTraversalKey. The Component parameter check
3169         // does not allow DOWN_CYCLE_TRAVERSAL_KEY, but we do.
3170         return getFocusTraversalKeys_NoIDCheck(id);
3171     }
3172 
3173     /**
3174      * Returns whether the Set of focus traversal keys for the given focus
3175      * traversal operation has been explicitly defined for this Container. If
3176      * this method returns <code>false</code>, this Container is inheriting the
3177      * Set from an ancestor, or from the current KeyboardFocusManager.
3178      *
3179      * @param id one of KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
3180      *        KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
3181      *        KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
3182      *        KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
3183      * @return <code>true</code> if the the Set of focus traversal keys for the
3184      *         given focus traversal operation has been explicitly defined for
3185      *         this Component; <code>false</code> otherwise.
3186      * @throws IllegalArgumentException if id is not one of
3187      *         KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
3188      *        KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
3189      *        KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
3190      *        KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
3191      * @since 1.4
3192      */
3193     public boolean areFocusTraversalKeysSet(int id) {
3194         if (id < 0 || id >= KeyboardFocusManager.TRAVERSAL_KEY_LENGTH) {
3195             throw new IllegalArgumentException("invalid focus traversal key identifier");
3196         }
3197 
3198         return (focusTraversalKeys != null && focusTraversalKeys[id] != null);
3199     }
3200 
3201     /**
3202      * Returns whether the specified Container is the focus cycle root of this
3203      * Container's focus traversal cycle. Each focus traversal cycle has only
3204      * a single focus cycle root and each Container which is not a focus cycle
3205      * root belongs to only a single focus traversal cycle. Containers which
3206      * are focus cycle roots belong to two cycles: one rooted at the Container
3207      * itself, and one rooted at the Container's nearest focus-cycle-root
3208      * ancestor. This method will return <code>true</code> for both such
3209      * Containers in this case.
3210      *
3211      * @param container the Container to be tested
3212      * @return <code>true</code> if the specified Container is a focus-cycle-
3213      *         root of this Container; <code>false</code> otherwise
3214      * @see #isFocusCycleRoot()
3215      * @since 1.4
3216      */
3217     public boolean isFocusCycleRoot(Container container) {
3218         if (isFocusCycleRoot() && container == this) {
3219             return true;
3220         } else {
3221             return super.isFocusCycleRoot(container);
3222         }
3223     }
3224 
3225     private Container findTraversalRoot() {
3226         // I potentially have two roots, myself and my root parent
3227         // If I am the current root, then use me
3228         // If none of my parents are roots, then use me
3229         // If my root parent is the current root, then use my root parent
3230         // If neither I nor my root parent is the current root, then
3231         // use my root parent (a guess)
3232 
3233         Container currentFocusCycleRoot = KeyboardFocusManager.
3234             getCurrentKeyboardFocusManager().getCurrentFocusCycleRoot();
3235         Container root;
3236 
3237         if (currentFocusCycleRoot == this) {
3238             root = this;
3239         } else {
3240             root = getFocusCycleRootAncestor();
3241             if (root == null) {
3242                 root = this;
3243             }
3244         }
3245 
3246         if (root != currentFocusCycleRoot) {
3247             KeyboardFocusManager.getCurrentKeyboardFocusManager().
3248                 setGlobalCurrentFocusCycleRootPriv(root);
3249         }
3250         return root;
3251     }
3252 
3253     final boolean containsFocus() {
3254         final Component focusOwner = KeyboardFocusManager.
3255             getCurrentKeyboardFocusManager().getFocusOwner();
3256         return isParentOf(focusOwner);
3257     }
3258 
3259     /**
3260      * Check if this component is the child of this container or its children.
3261      * Note: this function acquires treeLock
3262      * Note: this function traverses children tree only in one Window.
3263      * @param comp a component in test, must not be null
3264      */
3265     private boolean isParentOf(Component comp) {
3266         synchronized(getTreeLock()) {
3267             while (comp != null && comp != this && !(comp instanceof Window)) {
3268                 comp = comp.getParent();
3269             }
3270             return (comp == this);
3271         }
3272     }
3273 
3274     void clearMostRecentFocusOwnerOnHide() {
3275         boolean reset = false;
3276         Window window = null;
3277 
3278         synchronized (getTreeLock()) {
3279             window = getContainingWindow();
3280             if (window != null) {
3281                 Component comp = KeyboardFocusManager.getMostRecentFocusOwner(window);
3282                 reset = ((comp == this) || isParentOf(comp));
3283                 // This synchronized should always be the second in a pair
3284                 // (tree lock, KeyboardFocusManager.class)
3285                 synchronized(KeyboardFocusManager.class) {
3286                     Component storedComp = window.getTemporaryLostComponent();
3287                     if (isParentOf(storedComp) || storedComp == this) {
3288                         window.setTemporaryLostComponent(null);
3289                     }
3290                 }
3291             }
3292         }
3293 
3294         if (reset) {
3295             KeyboardFocusManager.setMostRecentFocusOwner(window, null);
3296         }
3297     }
3298 
3299     void clearCurrentFocusCycleRootOnHide() {
3300         KeyboardFocusManager kfm =
3301             KeyboardFocusManager.getCurrentKeyboardFocusManager();
3302         Container cont = kfm.getCurrentFocusCycleRoot();
3303 
3304         if (cont == this || isParentOf(cont)) {
3305             kfm.setGlobalCurrentFocusCycleRootPriv(null);
3306         }
3307     }
3308 
3309     @Override
3310     void clearLightweightDispatcherOnRemove(Component removedComponent) {
3311         if (dispatcher != null) {
3312             dispatcher.removeReferences(removedComponent);
3313         } else {
3314             //It is a Lightweight Container, should clear parent`s Dispatcher
3315             super.clearLightweightDispatcherOnRemove(removedComponent);
3316         }
3317     }
3318 
3319     final Container getTraversalRoot() {
3320         if (isFocusCycleRoot()) {
3321             return findTraversalRoot();
3322         }
3323 
3324         return super.getTraversalRoot();
3325     }
3326 
3327     /**
3328      * Sets the focus traversal policy that will manage keyboard traversal of
3329      * this Container's children, if this Container is a focus cycle root. If
3330      * the argument is null, this Container inherits its policy from its focus-
3331      * cycle-root ancestor. If the argument is non-null, this policy will be
3332      * inherited by all focus-cycle-root children that have no keyboard-
3333      * traversal policy of their own (as will, recursively, their focus-cycle-
3334      * root children).
3335      * <p>
3336      * If this Container is not a focus cycle root, the policy will be
3337      * remembered, but will not be used or inherited by this or any other
3338      * Containers until this Container is made a focus cycle root.
3339      *
3340      * @param policy the new focus traversal policy for this Container
3341      * @see #getFocusTraversalPolicy
3342      * @see #setFocusCycleRoot
3343      * @see #isFocusCycleRoot
3344      * @since 1.4
3345      * @beaninfo
3346      *       bound: true
3347      */
3348     public void setFocusTraversalPolicy(FocusTraversalPolicy policy) {
3349         FocusTraversalPolicy oldPolicy;
3350         synchronized (this) {
3351             oldPolicy = this.focusTraversalPolicy;
3352             this.focusTraversalPolicy = policy;
3353         }
3354         firePropertyChange("focusTraversalPolicy", oldPolicy, policy);
3355     }
3356 
3357     /**
3358      * Returns the focus traversal policy that will manage keyboard traversal
3359      * of this Container's children, or null if this Container is not a focus
3360      * cycle root. If no traversal policy has been explicitly set for this
3361      * Container, then this Container's focus-cycle-root ancestor's policy is
3362      * returned.
3363      *
3364      * @return this Container's focus traversal policy, or null if this
3365      *         Container is not a focus cycle root.
3366      * @see #setFocusTraversalPolicy
3367      * @see #setFocusCycleRoot
3368      * @see #isFocusCycleRoot
3369      * @since 1.4
3370      */
3371     public FocusTraversalPolicy getFocusTraversalPolicy() {
3372         if (!isFocusTraversalPolicyProvider() && !isFocusCycleRoot()) {
3373             return null;
3374         }
3375 
3376         FocusTraversalPolicy policy = this.focusTraversalPolicy;
3377         if (policy != null) {
3378             return policy;
3379         }
3380 
3381         Container rootAncestor = getFocusCycleRootAncestor();
3382         if (rootAncestor != null) {
3383             return rootAncestor.getFocusTraversalPolicy();
3384         } else {
3385             return KeyboardFocusManager.getCurrentKeyboardFocusManager().
3386                 getDefaultFocusTraversalPolicy();
3387         }
3388     }
3389 
3390     /**
3391      * Returns whether the focus traversal policy has been explicitly set for
3392      * this Container. If this method returns <code>false</code>, this
3393      * Container will inherit its focus traversal policy from an ancestor.
3394      *
3395      * @return <code>true</code> if the focus traversal policy has been
3396      *         explicitly set for this Container; <code>false</code> otherwise.
3397      * @since 1.4
3398      */
3399     public boolean isFocusTraversalPolicySet() {
3400         return (focusTraversalPolicy != null);
3401     }
3402 
3403     /**
3404      * Sets whether this Container is the root of a focus traversal cycle. Once
3405      * focus enters a traversal cycle, typically it cannot leave it via focus
3406      * traversal unless one of the up- or down-cycle keys is pressed. Normal
3407      * traversal is limited to this Container, and all of this Container's
3408      * descendants that are not descendants of inferior focus cycle roots. Note
3409      * that a FocusTraversalPolicy may bend these restrictions, however. For
3410      * example, ContainerOrderFocusTraversalPolicy supports implicit down-cycle
3411      * traversal.
3412      * <p>
3413      * The alternative way to specify the traversal order of this Container's
3414      * children is to make this Container a
3415      * <a href="doc-files/FocusSpec.html#FocusTraversalPolicyProviders">focus traversal policy provider</a>.
3416      *
3417      * @param focusCycleRoot indicates whether this Container is the root of a
3418      *        focus traversal cycle
3419      * @see #isFocusCycleRoot()
3420      * @see #setFocusTraversalPolicy
3421      * @see #getFocusTraversalPolicy
3422      * @see ContainerOrderFocusTraversalPolicy
3423      * @see #setFocusTraversalPolicyProvider
3424      * @since 1.4
3425      * @beaninfo
3426      *       bound: true
3427      */
3428     public void setFocusCycleRoot(boolean focusCycleRoot) {
3429         boolean oldFocusCycleRoot;
3430         synchronized (this) {
3431             oldFocusCycleRoot = this.focusCycleRoot;
3432             this.focusCycleRoot = focusCycleRoot;
3433         }
3434         firePropertyChange("focusCycleRoot", oldFocusCycleRoot,
3435                            focusCycleRoot);
3436     }
3437 
3438     /**
3439      * Returns whether this Container is the root of a focus traversal cycle.
3440      * Once focus enters a traversal cycle, typically it cannot leave it via
3441      * focus traversal unless one of the up- or down-cycle keys is pressed.
3442      * Normal traversal is limited to this Container, and all of this
3443      * Container's descendants that are not descendants of inferior focus
3444      * cycle roots. Note that a FocusTraversalPolicy may bend these
3445      * restrictions, however. For example, ContainerOrderFocusTraversalPolicy
3446      * supports implicit down-cycle traversal.
3447      *
3448      * @return whether this Container is the root of a focus traversal cycle
3449      * @see #setFocusCycleRoot
3450      * @see #setFocusTraversalPolicy
3451      * @see #getFocusTraversalPolicy
3452      * @see ContainerOrderFocusTraversalPolicy
3453      * @since 1.4
3454      */
3455     public boolean isFocusCycleRoot() {
3456         return focusCycleRoot;
3457     }
3458 
3459     /**
3460      * Sets whether this container will be used to provide focus
3461      * traversal policy. Container with this property as
3462      * <code>true</code> will be used to acquire focus traversal policy
3463      * instead of closest focus cycle root ancestor.
3464      * @param provider indicates whether this container will be used to
3465      *                provide focus traversal policy
3466      * @see #setFocusTraversalPolicy
3467      * @see #getFocusTraversalPolicy
3468      * @see #isFocusTraversalPolicyProvider
3469      * @since 1.5
3470      * @beaninfo
3471      *        bound: true
3472      */
3473     public final void setFocusTraversalPolicyProvider(boolean provider) {
3474         boolean oldProvider;
3475         synchronized(this) {
3476             oldProvider = focusTraversalPolicyProvider;
3477             focusTraversalPolicyProvider = provider;
3478         }
3479         firePropertyChange("focusTraversalPolicyProvider", oldProvider, provider);
3480     }
3481 
3482     /**
3483      * Returns whether this container provides focus traversal
3484      * policy. If this property is set to <code>true</code> then when
3485      * keyboard focus manager searches container hierarchy for focus
3486      * traversal policy and encounters this container before any other
3487      * container with this property as true or focus cycle roots then
3488      * its focus traversal policy will be used instead of focus cycle
3489      * root's policy.
3490      * @see #setFocusTraversalPolicy
3491      * @see #getFocusTraversalPolicy
3492      * @see #setFocusCycleRoot
3493      * @see #setFocusTraversalPolicyProvider
3494      * @return <code>true</code> if this container provides focus traversal
3495      *         policy, <code>false</code> otherwise
3496      * @since 1.5
3497      * @beaninfo
3498      *        bound: true
3499      */
3500     public final boolean isFocusTraversalPolicyProvider() {
3501         return focusTraversalPolicyProvider;
3502     }
3503 
3504     /**
3505      * Transfers the focus down one focus traversal cycle. If this Container is
3506      * a focus cycle root, then the focus owner is set to this Container's
3507      * default Component to focus, and the current focus cycle root is set to
3508      * this Container. If this Container is not a focus cycle root, then no
3509      * focus traversal operation occurs.
3510      *
3511      * @see       Component#requestFocus()
3512      * @see       #isFocusCycleRoot
3513      * @see       #setFocusCycleRoot
3514      * @since     1.4
3515      */
3516     public void transferFocusDownCycle() {
3517         if (isFocusCycleRoot()) {
3518             KeyboardFocusManager.getCurrentKeyboardFocusManager().
3519                 setGlobalCurrentFocusCycleRootPriv(this);
3520             Component toFocus = getFocusTraversalPolicy().
3521                 getDefaultComponent(this);
3522             if (toFocus != null) {
3523                 toFocus.requestFocus(CausedFocusEvent.Cause.TRAVERSAL_DOWN);
3524             }
3525         }
3526     }
3527 
3528     void preProcessKeyEvent(KeyEvent e) {
3529         Container parent = this.parent;
3530         if (parent != null) {
3531             parent.preProcessKeyEvent(e);
3532         }
3533     }
3534 
3535     void postProcessKeyEvent(KeyEvent e) {
3536         Container parent = this.parent;
3537         if (parent != null) {
3538             parent.postProcessKeyEvent(e);
3539         }
3540     }
3541 
3542     boolean postsOldMouseEvents() {
3543         return true;
3544     }
3545 
3546     /**
3547      * Sets the <code>ComponentOrientation</code> property of this container
3548      * and all components contained within it.
3549      * <p>
3550      * This method changes layout-related information, and therefore,
3551      * invalidates the component hierarchy.
3552      *
3553      * @param o the new component orientation of this container and
3554      *        the components contained within it.
3555      * @exception NullPointerException if <code>orientation</code> is null.
3556      * @see Component#setComponentOrientation
3557      * @see Component#getComponentOrientation
3558      * @see #invalidate
3559      * @since 1.4
3560      */
3561     public void applyComponentOrientation(ComponentOrientation o) {
3562         super.applyComponentOrientation(o);
3563         synchronized (getTreeLock()) {
3564             for (int i = 0; i < component.size(); i++) {
3565                 Component comp = component.get(i);
3566                 comp.applyComponentOrientation(o);
3567             }
3568         }
3569     }
3570 
3571     /**
3572      * Adds a PropertyChangeListener to the listener list. The listener is
3573      * registered for all bound properties of this class, including the
3574      * following:
3575      * <ul>
3576      *    <li>this Container's font ("font")</li>
3577      *    <li>this Container's background color ("background")</li>
3578      *    <li>this Container's foreground color ("foreground")</li>
3579      *    <li>this Container's focusability ("focusable")</li>
3580      *    <li>this Container's focus traversal keys enabled state
3581      *        ("focusTraversalKeysEnabled")</li>
3582      *    <li>this Container's Set of FORWARD_TRAVERSAL_KEYS
3583      *        ("forwardFocusTraversalKeys")</li>
3584      *    <li>this Container's Set of BACKWARD_TRAVERSAL_KEYS
3585      *        ("backwardFocusTraversalKeys")</li>
3586      *    <li>this Container's Set of UP_CYCLE_TRAVERSAL_KEYS
3587      *        ("upCycleFocusTraversalKeys")</li>
3588      *    <li>this Container's Set of DOWN_CYCLE_TRAVERSAL_KEYS
3589      *        ("downCycleFocusTraversalKeys")</li>
3590      *    <li>this Container's focus traversal policy ("focusTraversalPolicy")
3591      *        </li>
3592      *    <li>this Container's focus-cycle-root state ("focusCycleRoot")</li>
3593      * </ul>
3594      * Note that if this Container is inheriting a bound property, then no
3595      * event will be fired in response to a change in the inherited property.
3596      * <p>
3597      * If listener is null, no exception is thrown and no action is performed.
3598      *
3599      * @param    listener  the PropertyChangeListener to be added
3600      *
3601      * @see Component#removePropertyChangeListener
3602      * @see #addPropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
3603      */
3604     public void addPropertyChangeListener(PropertyChangeListener listener) {
3605         super.addPropertyChangeListener(listener);
3606     }
3607 
3608     /**
3609      * Adds a PropertyChangeListener to the listener list for a specific
3610      * property. The specified property may be user-defined, or one of the
3611      * following defaults:
3612      * <ul>
3613      *    <li>this Container's font ("font")</li>
3614      *    <li>this Container's background color ("background")</li>
3615      *    <li>this Container's foreground color ("foreground")</li>
3616      *    <li>this Container's focusability ("focusable")</li>
3617      *    <li>this Container's focus traversal keys enabled state
3618      *        ("focusTraversalKeysEnabled")</li>
3619      *    <li>this Container's Set of FORWARD_TRAVERSAL_KEYS
3620      *        ("forwardFocusTraversalKeys")</li>
3621      *    <li>this Container's Set of BACKWARD_TRAVERSAL_KEYS
3622      *        ("backwardFocusTraversalKeys")</li>
3623      *    <li>this Container's Set of UP_CYCLE_TRAVERSAL_KEYS
3624      *        ("upCycleFocusTraversalKeys")</li>
3625      *    <li>this Container's Set of DOWN_CYCLE_TRAVERSAL_KEYS
3626      *        ("downCycleFocusTraversalKeys")</li>
3627      *    <li>this Container's focus traversal policy ("focusTraversalPolicy")
3628      *        </li>
3629      *    <li>this Container's focus-cycle-root state ("focusCycleRoot")</li>
3630      *    <li>this Container's focus-traversal-policy-provider state("focusTraversalPolicyProvider")</li>
3631      *    <li>this Container's focus-traversal-policy-provider state("focusTraversalPolicyProvider")</li>
3632      * </ul>
3633      * Note that if this Container is inheriting a bound property, then no
3634      * event will be fired in response to a change in the inherited property.
3635      * <p>
3636      * If listener is null, no exception is thrown and no action is performed.
3637      *
3638      * @param propertyName one of the property names listed above
3639      * @param listener the PropertyChangeListener to be added
3640      *
3641      * @see #addPropertyChangeListener(java.beans.PropertyChangeListener)
3642      * @see Component#removePropertyChangeListener
3643      */
3644     public void addPropertyChangeListener(String propertyName,
3645                                           PropertyChangeListener listener) {
3646         super.addPropertyChangeListener(propertyName, listener);
3647     }
3648 
3649     // Serialization support. A Container is responsible for restoring the
3650     // parent fields of its component children.
3651 
3652     /**
3653      * Container Serial Data Version.
3654      */
3655     private int containerSerializedDataVersion = 1;
3656 
3657     /**
3658      * Serializes this <code>Container</code> to the specified
3659      * <code>ObjectOutputStream</code>.
3660      * <ul>
3661      *    <li>Writes default serializable fields to the stream.</li>
3662      *    <li>Writes a list of serializable ContainerListener(s) as optional
3663      *        data. The non-serializable ContainerListner(s) are detected and
3664      *        no attempt is made to serialize them.</li>
3665      *    <li>Write this Container's FocusTraversalPolicy if and only if it
3666      *        is Serializable; otherwise, <code>null</code> is written.</li>
3667      * </ul>
3668      *
3669      * @param s the <code>ObjectOutputStream</code> to write
3670      * @serialData <code>null</code> terminated sequence of 0 or more pairs;
3671      *   the pair consists of a <code>String</code> and <code>Object</code>;
3672      *   the <code>String</code> indicates the type of object and
3673      *   is one of the following:
3674      *   <code>containerListenerK</code> indicating an
3675      *     <code>ContainerListener</code> object;
3676      *   the <code>Container</code>'s <code>FocusTraversalPolicy</code>,
3677      *     or <code>null</code>
3678      *
3679      * @see AWTEventMulticaster#save(java.io.ObjectOutputStream, java.lang.String, java.util.EventListener)
3680      * @see Container#containerListenerK
3681      * @see #readObject(ObjectInputStream)
3682      */
3683     private void writeObject(ObjectOutputStream s) throws IOException {
3684         ObjectOutputStream.PutField f = s.putFields();
3685         f.put("ncomponents", component.size());
3686         f.put("component", getComponentsSync());
3687         f.put("layoutMgr", layoutMgr);
3688         f.put("dispatcher", dispatcher);
3689         f.put("maxSize", maxSize);
3690         f.put("focusCycleRoot", focusCycleRoot);
3691         f.put("containerSerializedDataVersion", containerSerializedDataVersion);
3692         f.put("focusTraversalPolicyProvider", focusTraversalPolicyProvider);
3693         s.writeFields();
3694 
3695         AWTEventMulticaster.save(s, containerListenerK, containerListener);
3696         s.writeObject(null);
3697 
3698         if (focusTraversalPolicy instanceof java.io.Serializable) {
3699             s.writeObject(focusTraversalPolicy);
3700         } else {
3701             s.writeObject(null);
3702         }
3703     }
3704 
3705     /**
3706      * Deserializes this <code>Container</code> from the specified
3707      * <code>ObjectInputStream</code>.
3708      * <ul>
3709      *    <li>Reads default serializable fields from the stream.</li>
3710      *    <li>Reads a list of serializable ContainerListener(s) as optional
3711      *        data. If the list is null, no Listeners are installed.</li>
3712      *    <li>Reads this Container's FocusTraversalPolicy, which may be null,
3713      *        as optional data.</li>
3714      * </ul>
3715      *
3716      * @param s the <code>ObjectInputStream</code> to read
3717      * @serial
3718      * @see #addContainerListener
3719      * @see #writeObject(ObjectOutputStream)
3720      */
3721     private void readObject(ObjectInputStream s)
3722         throws ClassNotFoundException, IOException
3723     {
3724         ObjectInputStream.GetField f = s.readFields();
3725         Component [] tmpComponent = (Component[])f.get("component", EMPTY_ARRAY);
3726         int ncomponents = (Integer) f.get("ncomponents", 0);
3727         component = new java.util.ArrayList<Component>(ncomponents);
3728         for (int i = 0; i < ncomponents; ++i) {
3729             component.add(tmpComponent[i]);
3730         }
3731         layoutMgr = (LayoutManager)f.get("layoutMgr", null);
3732         dispatcher = (LightweightDispatcher)f.get("dispatcher", null);
3733         // Old stream. Doesn't contain maxSize among Component's fields.
3734         if (maxSize == null) {
3735             maxSize = (Dimension)f.get("maxSize", null);
3736         }
3737         focusCycleRoot = f.get("focusCycleRoot", false);
3738         containerSerializedDataVersion = f.get("containerSerializedDataVersion", 1);
3739         focusTraversalPolicyProvider = f.get("focusTraversalPolicyProvider", false);
3740         java.util.List<Component> component = this.component;
3741         for(Component comp : component) {
3742             comp.parent = this;
3743             adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK,
3744                                     comp.numListening(AWTEvent.HIERARCHY_EVENT_MASK));
3745             adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
3746                                     comp.numListening(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));
3747             adjustDescendants(comp.countHierarchyMembers());
3748         }
3749 
3750         Object keyOrNull;
3751         while(null != (keyOrNull = s.readObject())) {
3752             String key = ((String)keyOrNull).intern();
3753 
3754             if (containerListenerK == key) {
3755                 addContainerListener((ContainerListener)(s.readObject()));
3756             } else {
3757                 // skip value for unrecognized key
3758                 s.readObject();
3759             }
3760         }
3761 
3762         try {
3763             Object policy = s.readObject();
3764             if (policy instanceof FocusTraversalPolicy) {
3765                 focusTraversalPolicy = (FocusTraversalPolicy)policy;
3766             }
3767         } catch (java.io.OptionalDataException e) {
3768             // JDK 1.1/1.2/1.3 instances will not have this optional data.
3769             // e.eof will be true to indicate that there is no more data
3770             // available for this object. If e.eof is not true, throw the
3771             // exception as it might have been caused by reasons unrelated to
3772             // focusTraversalPolicy.
3773 
3774             if (!e.eof) {
3775                 throw e;
3776             }
3777         }
3778     }
3779 
3780     /*
3781      * --- Accessibility Support ---
3782      */
3783 
3784     /**
3785      * Inner class of Container used to provide default support for
3786      * accessibility.  This class is not meant to be used directly by
3787      * application developers, but is instead meant only to be
3788      * subclassed by container developers.
3789      * <p>
3790      * The class used to obtain the accessible role for this object,
3791      * as well as implementing many of the methods in the
3792      * AccessibleContainer interface.
3793      * @since 1.3
3794      */
3795     protected class AccessibleAWTContainer extends AccessibleAWTComponent {
3796 
3797         /**
3798          * JDK1.3 serialVersionUID
3799          */
3800         private static final long serialVersionUID = 5081320404842566097L;
3801 
3802         /**
3803          * Returns the number of accessible children in the object.  If all
3804          * of the children of this object implement <code>Accessible</code>,
3805          * then this method should return the number of children of this object.
3806          *
3807          * @return the number of accessible children in the object
3808          */
3809         public int getAccessibleChildrenCount() {
3810             return Container.this.getAccessibleChildrenCount();
3811         }
3812 
3813         /**
3814          * Returns the nth <code>Accessible</code> child of the object.
3815          *
3816          * @param i zero-based index of child
3817          * @return the nth <code>Accessible</code> child of the object
3818          */
3819         public Accessible getAccessibleChild(int i) {
3820             return Container.this.getAccessibleChild(i);
3821         }
3822 
3823         /**
3824          * Returns the <code>Accessible</code> child, if one exists,
3825          * contained at the local coordinate <code>Point</code>.
3826          *
3827          * @param p the point defining the top-left corner of the
3828          *    <code>Accessible</code>, given in the coordinate space
3829          *    of the object's parent
3830          * @return the <code>Accessible</code>, if it exists,
3831          *    at the specified location; else <code>null</code>
3832          */
3833         public Accessible getAccessibleAt(Point p) {
3834             return Container.this.getAccessibleAt(p);
3835         }
3836 
3837         /**
3838          * Number of PropertyChangeListener objects registered. It's used
3839          * to add/remove ContainerListener to track target Container's state.
3840          */
3841         private volatile transient int propertyListenersCount = 0;
3842 
3843         protected ContainerListener accessibleContainerHandler = null;
3844 
3845         /**
3846          * Fire <code>PropertyChange</code> listener, if one is registered,
3847          * when children are added or removed.
3848          * @since 1.3
3849          */
3850         protected class AccessibleContainerHandler
3851             implements ContainerListener {
3852             public void componentAdded(ContainerEvent e) {
3853                 Component c = e.getChild();
3854                 if (c != null && c instanceof Accessible) {
3855                     AccessibleAWTContainer.this.firePropertyChange(
3856                         AccessibleContext.ACCESSIBLE_CHILD_PROPERTY,
3857                         null, ((Accessible) c).getAccessibleContext());
3858                 }
3859             }
3860             public void componentRemoved(ContainerEvent e) {
3861                 Component c = e.getChild();
3862                 if (c != null && c instanceof Accessible) {
3863                     AccessibleAWTContainer.this.firePropertyChange(
3864                         AccessibleContext.ACCESSIBLE_CHILD_PROPERTY,
3865                         ((Accessible) c).getAccessibleContext(), null);
3866                 }
3867             }
3868         }
3869 
3870         /**
3871          * Adds a PropertyChangeListener to the listener list.
3872          *
3873          * @param listener  the PropertyChangeListener to be added
3874          */
3875         public void addPropertyChangeListener(PropertyChangeListener listener) {
3876             if (accessibleContainerHandler == null) {
3877                 accessibleContainerHandler = new AccessibleContainerHandler();
3878             }
3879             if (propertyListenersCount++ == 0) {
3880                 Container.this.addContainerListener(accessibleContainerHandler);
3881             }
3882             super.addPropertyChangeListener(listener);
3883         }
3884 
3885         /**
3886          * Remove a PropertyChangeListener from the listener list.
3887          * This removes a PropertyChangeListener that was registered
3888          * for all properties.
3889          *
3890          * @param listener the PropertyChangeListener to be removed
3891          */
3892         public void removePropertyChangeListener(PropertyChangeListener listener) {
3893             if (--propertyListenersCount == 0) {
3894                 Container.this.removeContainerListener(accessibleContainerHandler);
3895             }
3896             super.removePropertyChangeListener(listener);
3897         }
3898 
3899     } // inner class AccessibleAWTContainer
3900 
3901     /**
3902      * Returns the <code>Accessible</code> child contained at the local
3903      * coordinate <code>Point</code>, if one exists.  Otherwise
3904      * returns <code>null</code>.
3905      *
3906      * @param p the point defining the top-left corner of the
3907      *    <code>Accessible</code>, given in the coordinate space
3908      *    of the object's parent
3909      * @return the <code>Accessible</code> at the specified location,
3910      *    if it exists; otherwise <code>null</code>
3911      */
3912     Accessible getAccessibleAt(Point p) {
3913         synchronized (getTreeLock()) {
3914             if (this instanceof Accessible) {
3915                 Accessible a = (Accessible)this;
3916                 AccessibleContext ac = a.getAccessibleContext();
3917                 if (ac != null) {
3918                     AccessibleComponent acmp;
3919                     Point location;
3920                     int nchildren = ac.getAccessibleChildrenCount();
3921                     for (int i=0; i < nchildren; i++) {
3922                         a = ac.getAccessibleChild(i);
3923                         if ((a != null)) {
3924                             ac = a.getAccessibleContext();
3925                             if (ac != null) {
3926                                 acmp = ac.getAccessibleComponent();
3927                                 if ((acmp != null) && (acmp.isShowing())) {
3928                                     location = acmp.getLocation();
3929                                     Point np = new Point(p.x-location.x,
3930                                                          p.y-location.y);
3931                                     if (acmp.contains(np)){
3932                                         return a;
3933                                     }
3934                                 }
3935                             }
3936                         }
3937                     }
3938                 }
3939                 return (Accessible)this;
3940             } else {
3941                 Component ret = this;
3942                 if (!this.contains(p.x,p.y)) {
3943                     ret = null;
3944                 } else {
3945                     int ncomponents = this.getComponentCount();
3946                     for (int i=0; i < ncomponents; i++) {
3947                         Component comp = this.getComponent(i);
3948                         if ((comp != null) && comp.isShowing()) {
3949                             Point location = comp.getLocation();
3950                             if (comp.contains(p.x-location.x,p.y-location.y)) {
3951                                 ret = comp;
3952                             }
3953                         }
3954                     }
3955                 }
3956                 if (ret instanceof Accessible) {
3957                     return (Accessible) ret;
3958                 }
3959             }
3960             return null;
3961         }
3962     }
3963 
3964     /**
3965      * Returns the number of accessible children in the object.  If all
3966      * of the children of this object implement <code>Accessible</code>,
3967      * then this method should return the number of children of this object.
3968      *
3969      * @return the number of accessible children in the object
3970      */
3971     int getAccessibleChildrenCount() {
3972         synchronized (getTreeLock()) {
3973             int count = 0;
3974             Component[] children = this.getComponents();
3975             for (int i = 0; i < children.length; i++) {
3976                 if (children[i] instanceof Accessible) {
3977                     count++;
3978                 }
3979             }
3980             return count;
3981         }
3982     }
3983 
3984     /**
3985      * Returns the nth <code>Accessible</code> child of the object.
3986      *
3987      * @param i zero-based index of child
3988      * @return the nth <code>Accessible</code> child of the object
3989      */
3990     Accessible getAccessibleChild(int i) {
3991         synchronized (getTreeLock()) {
3992             Component[] children = this.getComponents();
3993             int count = 0;
3994             for (int j = 0; j < children.length; j++) {
3995                 if (children[j] instanceof Accessible) {
3996                     if (count == i) {
3997                         return (Accessible) children[j];
3998                     } else {
3999                         count++;
4000                     }
4001                 }
4002             }
4003             return null;
4004         }
4005     }
4006 
4007     // ************************** MIXING CODE *******************************
4008 
4009     final void increaseComponentCount(Component c) {
4010         synchronized (getTreeLock()) {
4011             if (!c.isDisplayable()) {
4012                 throw new IllegalStateException(
4013                     "Peer does not exist while invoking the increaseComponentCount() method"
4014                 );
4015             }
4016 
4017             int addHW = 0;
4018             int addLW = 0;
4019 
4020             if (c instanceof Container) {
4021                 addLW = ((Container)c).numOfLWComponents;
4022                 addHW = ((Container)c).numOfHWComponents;
4023             }
4024             if (c.isLightweight()) {
4025                 addLW++;
4026             } else {
4027                 addHW++;
4028             }
4029 
4030             for (Container cont = this; cont != null; cont = cont.getContainer()) {
4031                 cont.numOfLWComponents += addLW;
4032                 cont.numOfHWComponents += addHW;
4033             }
4034         }
4035     }
4036 
4037     final void decreaseComponentCount(Component c) {
4038         synchronized (getTreeLock()) {
4039             if (!c.isDisplayable()) {
4040                 throw new IllegalStateException(
4041                     "Peer does not exist while invoking the decreaseComponentCount() method"
4042                 );
4043             }
4044 
4045             int subHW = 0;
4046             int subLW = 0;
4047 
4048             if (c instanceof Container) {
4049                 subLW = ((Container)c).numOfLWComponents;
4050                 subHW = ((Container)c).numOfHWComponents;
4051             }
4052             if (c.isLightweight()) {
4053                 subLW++;
4054             } else {
4055                 subHW++;
4056             }
4057 
4058             for (Container cont = this; cont != null; cont = cont.getContainer()) {
4059                 cont.numOfLWComponents -= subLW;
4060                 cont.numOfHWComponents -= subHW;
4061             }
4062         }
4063     }
4064 
4065     private int getTopmostComponentIndex() {
4066         checkTreeLock();
4067         if (getComponentCount() > 0) {
4068             return 0;
4069         }
4070         return -1;
4071     }
4072 
4073     private int getBottommostComponentIndex() {
4074         checkTreeLock();
4075         if (getComponentCount() > 0) {
4076             return getComponentCount() - 1;
4077         }
4078         return -1;
4079     }
4080 
4081     /*
4082      * This method is overriden to handle opaque children in non-opaque
4083      * containers.
4084      */
4085     @Override
4086     final Region getOpaqueShape() {
4087         checkTreeLock();
4088         if (isLightweight() && isNonOpaqueForMixing()
4089                 && hasLightweightDescendants())
4090         {
4091             Region s = Region.EMPTY_REGION;
4092             for (int index = 0; index < getComponentCount(); index++) {
4093                 Component c = getComponent(index);
4094                 if (c.isLightweight() && c.isShowing()) {
4095                     s = s.getUnion(c.getOpaqueShape());
4096                 }
4097             }
4098             return s.getIntersection(getNormalShape());
4099         }
4100         return super.getOpaqueShape();
4101     }
4102 
4103     final void recursiveSubtractAndApplyShape(Region shape) {
4104         recursiveSubtractAndApplyShape(shape, getTopmostComponentIndex(), getBottommostComponentIndex());
4105     }
4106 
4107     final void recursiveSubtractAndApplyShape(Region shape, int fromZorder) {
4108         recursiveSubtractAndApplyShape(shape, fromZorder, getBottommostComponentIndex());
4109     }
4110 
4111     final void recursiveSubtractAndApplyShape(Region shape, int fromZorder, int toZorder) {
4112         checkTreeLock();
4113         if (mixingLog.isLoggable(PlatformLogger.Level.FINE)) {
4114             mixingLog.fine("this = " + this +
4115                 "; shape=" + shape + "; fromZ=" + fromZorder + "; toZ=" + toZorder);
4116         }
4117         if (fromZorder == -1) {
4118             return;
4119         }
4120         if (shape.isEmpty()) {
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.subtractAndApplyShape(shape);
4133             } else if (comp instanceof Container &&
4134                     ((Container)comp).hasHeavyweightDescendants() && comp.isShowing()) {
4135                 ((Container)comp).recursiveSubtractAndApplyShape(shape);
4136             }
4137         }
4138     }
4139 
4140     final void recursiveApplyCurrentShape() {
4141         recursiveApplyCurrentShape(getTopmostComponentIndex(), getBottommostComponentIndex());
4142     }
4143 
4144     final void recursiveApplyCurrentShape(int fromZorder) {
4145         recursiveApplyCurrentShape(fromZorder, getBottommostComponentIndex());
4146     }
4147 
4148     final void recursiveApplyCurrentShape(int fromZorder, int toZorder) {
4149         checkTreeLock();
4150         if (mixingLog.isLoggable(PlatformLogger.Level.FINE)) {
4151             mixingLog.fine("this = " + this +
4152                 "; fromZ=" + fromZorder + "; toZ=" + toZorder);
4153         }
4154         if (fromZorder == -1) {
4155             return;
4156         }
4157         // An invalid container with not-null layout should be ignored
4158         // by the mixing code, the container will be validated later
4159         // and the mixing code will be executed later.
4160         if (getLayout() != null && !isValid()) {
4161             return;
4162         }
4163         for (int index = fromZorder; index <= toZorder; index++) {
4164             Component comp = getComponent(index);
4165             if (!comp.isLightweight()) {
4166                 comp.applyCurrentShape();
4167             }
4168             if (comp instanceof Container &&
4169                     ((Container)comp).hasHeavyweightDescendants()) {
4170                 ((Container)comp).recursiveApplyCurrentShape();
4171             }
4172         }
4173     }
4174 
4175     private void recursiveShowHeavyweightChildren() {
4176         if (!hasHeavyweightDescendants() || !isVisible()) {
4177             return;
4178         }
4179         for (int index = 0; index < getComponentCount(); index++) {
4180             Component comp = getComponent(index);
4181             if (comp.isLightweight()) {
4182                 if  (comp instanceof Container) {
4183                     ((Container)comp).recursiveShowHeavyweightChildren();
4184                 }
4185             } else {
4186                 if (comp.isVisible()) {
4187                     ComponentPeer peer = comp.getPeer();
4188                     if (peer != null) {
4189                         peer.setVisible(true);
4190                     }
4191                 }
4192             }
4193         }
4194     }
4195 
4196     private void recursiveHideHeavyweightChildren() {
4197         if (!hasHeavyweightDescendants()) {
4198             return;
4199         }
4200         for (int index = 0; index < getComponentCount(); index++) {
4201             Component comp = getComponent(index);
4202             if (comp.isLightweight()) {
4203                 if  (comp instanceof Container) {
4204                     ((Container)comp).recursiveHideHeavyweightChildren();
4205                 }
4206             } else {
4207                 if (comp.isVisible()) {
4208                     ComponentPeer peer = comp.getPeer();
4209                     if (peer != null) {
4210                         peer.setVisible(false);
4211                     }
4212                 }
4213             }
4214         }
4215     }
4216 
4217     private void recursiveRelocateHeavyweightChildren(Point origin) {
4218         for (int index = 0; index < getComponentCount(); index++) {
4219             Component comp = getComponent(index);
4220             if (comp.isLightweight()) {
4221                 if  (comp instanceof Container &&
4222                         ((Container)comp).hasHeavyweightDescendants())
4223                 {
4224                     final Point newOrigin = new Point(origin);
4225                     newOrigin.translate(comp.getX(), comp.getY());
4226                     ((Container)comp).recursiveRelocateHeavyweightChildren(newOrigin);
4227                 }
4228             } else {
4229                 ComponentPeer peer = comp.getPeer();
4230                 if (peer != null) {
4231                     peer.setBounds(origin.x + comp.getX(), origin.y + comp.getY(),
4232                             comp.getWidth(), comp.getHeight(),
4233                             ComponentPeer.SET_LOCATION);
4234                 }
4235             }
4236         }
4237     }
4238 
4239     /**
4240      * Checks if the container and its direct lightweight containers are
4241      * visible.
4242      *
4243      * Consider the heavyweight container hides or shows the HW descendants
4244      * automatically. Therefore we care of LW containers' visibility only.
4245      *
4246      * This method MUST be invoked under the TreeLock.
4247      */
4248     final boolean isRecursivelyVisibleUpToHeavyweightContainer() {
4249         if (!isLightweight()) {
4250             return true;
4251         }
4252 
4253         for (Container cont = this;
4254                 cont != null && cont.isLightweight();
4255                 cont = cont.getContainer())
4256         {
4257             if (!cont.isVisible()) {
4258                 return false;
4259             }
4260         }
4261         return true;
4262     }
4263 
4264     @Override
4265     void mixOnShowing() {
4266         synchronized (getTreeLock()) {
4267             if (mixingLog.isLoggable(PlatformLogger.Level.FINE)) {
4268                 mixingLog.fine("this = " + this);
4269             }
4270 
4271             boolean isLightweight = isLightweight();
4272 
4273             if (isLightweight && isRecursivelyVisibleUpToHeavyweightContainer()) {
4274                 recursiveShowHeavyweightChildren();
4275             }
4276 
4277             if (!isMixingNeeded()) {
4278                 return;
4279             }
4280 
4281             if (!isLightweight || (isLightweight && hasHeavyweightDescendants())) {
4282                 recursiveApplyCurrentShape();
4283             }
4284 
4285             super.mixOnShowing();
4286         }
4287     }
4288 
4289     @Override
4290     void mixOnHiding(boolean isLightweight) {
4291         synchronized (getTreeLock()) {
4292             if (mixingLog.isLoggable(PlatformLogger.Level.FINE)) {
4293                 mixingLog.fine("this = " + this +
4294                         "; isLightweight=" + isLightweight);
4295             }
4296             if (isLightweight) {
4297                 recursiveHideHeavyweightChildren();
4298             }
4299             super.mixOnHiding(isLightweight);
4300         }
4301     }
4302 
4303     @Override
4304     void mixOnReshaping() {
4305         synchronized (getTreeLock()) {
4306             if (mixingLog.isLoggable(PlatformLogger.Level.FINE)) {
4307                 mixingLog.fine("this = " + this);
4308             }
4309 
4310             boolean isMixingNeeded = isMixingNeeded();
4311 
4312             if (isLightweight() && hasHeavyweightDescendants()) {
4313                 final Point origin = new Point(getX(), getY());
4314                 for (Container cont = getContainer();
4315                         cont != null && cont.isLightweight();
4316                         cont = cont.getContainer())
4317                 {
4318                     origin.translate(cont.getX(), cont.getY());
4319                 }
4320 
4321                 recursiveRelocateHeavyweightChildren(origin);
4322 
4323                 if (!isMixingNeeded) {
4324                     return;
4325                 }
4326 
4327                 recursiveApplyCurrentShape();
4328             }
4329 
4330             if (!isMixingNeeded) {
4331                 return;
4332             }
4333 
4334             super.mixOnReshaping();
4335         }
4336     }
4337 
4338     @Override
4339     void mixOnZOrderChanging(int oldZorder, int newZorder) {
4340         synchronized (getTreeLock()) {
4341             if (mixingLog.isLoggable(PlatformLogger.Level.FINE)) {
4342                 mixingLog.fine("this = " + this +
4343                     "; oldZ=" + oldZorder + "; newZ=" + newZorder);
4344             }
4345 
4346             if (!isMixingNeeded()) {
4347                 return;
4348             }
4349 
4350             boolean becameHigher = newZorder < oldZorder;
4351 
4352             if (becameHigher && isLightweight() && hasHeavyweightDescendants()) {
4353                 recursiveApplyCurrentShape();
4354             }
4355             super.mixOnZOrderChanging(oldZorder, newZorder);
4356         }
4357     }
4358 
4359     @Override
4360     void mixOnValidating() {
4361         synchronized (getTreeLock()) {
4362             if (mixingLog.isLoggable(PlatformLogger.Level.FINE)) {
4363                 mixingLog.fine("this = " + this);
4364             }
4365 
4366             if (!isMixingNeeded()) {
4367                 return;
4368             }
4369 
4370             if (hasHeavyweightDescendants()) {
4371                 recursiveApplyCurrentShape();
4372             }
4373 
4374             if (isLightweight() && isNonOpaqueForMixing()) {
4375                 subtractAndApplyShapeBelowMe();
4376             }
4377 
4378             super.mixOnValidating();
4379         }
4380     }
4381 
4382     // ****************** END OF MIXING CODE ********************************
4383 }
4384 
4385 
4386 /**
4387  * Class to manage the dispatching of MouseEvents to the lightweight descendants
4388  * and SunDropTargetEvents to both lightweight and heavyweight descendants
4389  * contained by a native container.
4390  *
4391  * NOTE: the class name is not appropriate anymore, but we cannot change it
4392  * because we must keep serialization compatibility.
4393  *
4394  * @author Timothy Prinzing
4395  */
4396 class LightweightDispatcher implements java.io.Serializable, AWTEventListener {
4397 
4398     /*
4399      * JDK 1.1 serialVersionUID
4400      */
4401     private static final long serialVersionUID = 5184291520170872969L;
4402     /*
4403      * Our own mouse event for when we're dragged over from another hw
4404      * container
4405      */
4406     private static final int  LWD_MOUSE_DRAGGED_OVER = 1500;
4407 
4408     private static final PlatformLogger eventLog = PlatformLogger.getLogger("java.awt.event.LightweightDispatcher");
4409 
4410     LightweightDispatcher(Container nativeContainer) {
4411         this.nativeContainer = nativeContainer;
4412         mouseEventTarget = null;
4413         eventMask = 0;
4414     }
4415 
4416     /*
4417      * Clean up any resources allocated when dispatcher was created;
4418      * should be called from Container.removeNotify
4419      */
4420     void dispose() {
4421         //System.out.println("Disposing lw dispatcher");
4422         stopListeningForOtherDrags();
4423         mouseEventTarget = null;
4424         targetLastEntered = null;
4425     }
4426 
4427     /**
4428      * Enables events to subcomponents.
4429      */
4430     void enableEvents(long events) {
4431         eventMask |= events;
4432     }
4433 
4434     /**
4435      * Dispatches an event to a sub-component if necessary, and
4436      * returns whether or not the event was forwarded to a
4437      * sub-component.
4438      *
4439      * @param e the event
4440      */
4441     boolean dispatchEvent(AWTEvent e) {
4442         boolean ret = false;
4443 
4444         /*
4445          * Fix for BugTraq Id 4389284.
4446          * Dispatch SunDropTargetEvents regardless of eventMask value.
4447          * Do not update cursor on dispatching SunDropTargetEvents.
4448          */
4449         if (e instanceof SunDropTargetEvent) {
4450 
4451             SunDropTargetEvent sdde = (SunDropTargetEvent) e;
4452             ret = processDropTargetEvent(sdde);
4453 
4454         } else {
4455             if (e instanceof MouseEvent && (eventMask & MOUSE_MASK) != 0) {
4456                 MouseEvent me = (MouseEvent) e;
4457                 ret = processMouseEvent(me);
4458             }
4459 
4460             if (e.getID() == MouseEvent.MOUSE_MOVED) {
4461                 nativeContainer.updateCursorImmediately();
4462             }
4463         }
4464 
4465         return ret;
4466     }
4467 
4468     /* This method effectively returns whether or not a mouse button was down
4469      * just BEFORE the event happened.  A better method name might be
4470      * wasAMouseButtonDownBeforeThisEvent().
4471      */
4472     private boolean isMouseGrab(MouseEvent e) {
4473         int modifiers = e.getModifiersEx();
4474 
4475         if(e.getID() == MouseEvent.MOUSE_PRESSED
4476             || e.getID() == MouseEvent.MOUSE_RELEASED)
4477         {
4478             switch (e.getButton()) {
4479             case MouseEvent.BUTTON1:
4480                 modifiers ^= InputEvent.BUTTON1_DOWN_MASK;
4481                 break;
4482             case MouseEvent.BUTTON2:
4483                 modifiers ^= InputEvent.BUTTON2_DOWN_MASK;
4484                 break;
4485             case MouseEvent.BUTTON3:
4486                 modifiers ^= InputEvent.BUTTON3_DOWN_MASK;
4487                 break;
4488             }
4489         }
4490         /* modifiers now as just before event */
4491         return ((modifiers & (InputEvent.BUTTON1_DOWN_MASK
4492                               | InputEvent.BUTTON2_DOWN_MASK
4493                               | InputEvent.BUTTON3_DOWN_MASK)) != 0);
4494     }
4495 
4496     /**
4497      * This method attempts to distribute a mouse event to a lightweight
4498      * component.  It tries to avoid doing any unnecessary probes down
4499      * into the component tree to minimize the overhead of determining
4500      * where to route the event, since mouse movement events tend to
4501      * come in large and frequent amounts.
4502      */
4503     private boolean processMouseEvent(MouseEvent e) {
4504         int id = e.getID();
4505         Component mouseOver =   // sensitive to mouse events
4506             nativeContainer.getMouseEventTarget(e.getX(), e.getY(),
4507                                                 Container.INCLUDE_SELF);
4508 
4509         trackMouseEnterExit(mouseOver, e);
4510 
4511     // 4508327 : MOUSE_CLICKED should only go to the recipient of
4512     // the accompanying MOUSE_PRESSED, so don't reset mouseEventTarget on a
4513     // MOUSE_CLICKED.
4514     if (!isMouseGrab(e) && id != MouseEvent.MOUSE_CLICKED) {
4515             mouseEventTarget = (mouseOver != nativeContainer) ? mouseOver: null;
4516             isCleaned = false;
4517         }
4518 
4519         if (mouseEventTarget != null) {
4520             switch (id) {
4521             case MouseEvent.MOUSE_ENTERED:
4522             case MouseEvent.MOUSE_EXITED:
4523                 break;
4524             case MouseEvent.MOUSE_PRESSED:
4525                 retargetMouseEvent(mouseEventTarget, id, e);
4526                 break;
4527         case MouseEvent.MOUSE_RELEASED:
4528             retargetMouseEvent(mouseEventTarget, id, e);
4529         break;
4530         case MouseEvent.MOUSE_CLICKED:
4531         // 4508327: MOUSE_CLICKED should never be dispatched to a Component
4532         // other than that which received the MOUSE_PRESSED event.  If the
4533         // mouse is now over a different Component, don't dispatch the event.
4534         // The previous fix for a similar problem was associated with bug
4535         // 4155217.
4536         if (mouseOver == mouseEventTarget) {
4537             retargetMouseEvent(mouseOver, id, e);
4538         }
4539         break;
4540             case MouseEvent.MOUSE_MOVED:
4541                 retargetMouseEvent(mouseEventTarget, id, e);
4542                 break;
4543         case MouseEvent.MOUSE_DRAGGED:
4544             if (isMouseGrab(e)) {
4545                 retargetMouseEvent(mouseEventTarget, id, e);
4546             }
4547                 break;
4548         case MouseEvent.MOUSE_WHEEL:
4549             // This may send it somewhere that doesn't have MouseWheelEvents
4550             // enabled.  In this case, Component.dispatchEventImpl() will
4551             // retarget the event to a parent that DOES have the events enabled.
4552             if (eventLog.isLoggable(PlatformLogger.Level.FINEST) && (mouseOver != null)) {
4553                 eventLog.finest("retargeting mouse wheel to " +
4554                                 mouseOver.getName() + ", " +
4555                                 mouseOver.getClass());
4556             }
4557             retargetMouseEvent(mouseOver, id, e);
4558         break;
4559             }
4560         //Consuming of wheel events is implemented in "retargetMouseEvent".
4561         if (id != MouseEvent.MOUSE_WHEEL) {
4562             e.consume();
4563         }
4564     } else if (isCleaned && id != MouseEvent.MOUSE_WHEEL) {
4565         //After mouseEventTarget was removed and cleaned should consume all events
4566         //until new mouseEventTarget is found
4567         e.consume();
4568     }
4569     return e.isConsumed();
4570     }
4571 
4572     private boolean processDropTargetEvent(SunDropTargetEvent e) {
4573         int id = e.getID();
4574         int x = e.getX();
4575         int y = e.getY();
4576 
4577         /*
4578          * Fix for BugTraq ID 4395290.
4579          * It is possible that SunDropTargetEvent's Point is outside of the
4580          * native container bounds. In this case we truncate coordinates.
4581          */
4582         if (!nativeContainer.contains(x, y)) {
4583             final Dimension d = nativeContainer.getSize();
4584             if (d.width <= x) {
4585                 x = d.width - 1;
4586             } else if (x < 0) {
4587                 x = 0;
4588             }
4589             if (d.height <= y) {
4590                 y = d.height - 1;
4591             } else if (y < 0) {
4592                 y = 0;
4593             }
4594         }
4595         Component mouseOver =   // not necessarily sensitive to mouse events
4596             nativeContainer.getDropTargetEventTarget(x, y,
4597                                                      Container.INCLUDE_SELF);
4598         trackMouseEnterExit(mouseOver, e);
4599 
4600         if (mouseOver != nativeContainer && mouseOver != null) {
4601             switch (id) {
4602             case SunDropTargetEvent.MOUSE_ENTERED:
4603             case SunDropTargetEvent.MOUSE_EXITED:
4604                 break;
4605             default:
4606                 retargetMouseEvent(mouseOver, id, e);
4607                 e.consume();
4608                 break;
4609             }
4610         }
4611         return e.isConsumed();
4612     }
4613 
4614     /*
4615      * Generates enter/exit events as mouse moves over lw components
4616      * @param targetOver        Target mouse is over (including native container)
4617      * @param e                 Mouse event in native container
4618      */
4619     private void trackMouseEnterExit(Component targetOver, MouseEvent e) {
4620         Component       targetEnter = null;
4621         int             id = e.getID();
4622 
4623         if (e instanceof SunDropTargetEvent &&
4624             id == MouseEvent.MOUSE_ENTERED &&
4625             isMouseInNativeContainer == true) {
4626             // This can happen if a lightweight component which initiated the
4627             // drag has an associated drop target. MOUSE_ENTERED comes when the
4628             // mouse is in the native container already. To propagate this event
4629             // properly we should null out targetLastEntered.
4630             targetLastEntered = null;
4631         } else if ( id != MouseEvent.MOUSE_EXITED &&
4632              id != MouseEvent.MOUSE_DRAGGED &&
4633              id != LWD_MOUSE_DRAGGED_OVER &&
4634              isMouseInNativeContainer == false ) {
4635             // any event but an exit or drag means we're in the native container
4636             isMouseInNativeContainer = true;
4637             startListeningForOtherDrags();
4638         } else if ( id == MouseEvent.MOUSE_EXITED ) {
4639             isMouseInNativeContainer = false;
4640             stopListeningForOtherDrags();
4641         }
4642 
4643         if (isMouseInNativeContainer) {
4644             targetEnter = targetOver;
4645         }
4646 
4647         if (targetLastEntered == targetEnter) {
4648                 return;
4649         }
4650 
4651         if (targetLastEntered != null) {
4652             retargetMouseEvent(targetLastEntered, MouseEvent.MOUSE_EXITED, e);
4653         }
4654         if (id == MouseEvent.MOUSE_EXITED) {
4655             // consume native exit event if we generate one
4656             e.consume();
4657         }
4658 
4659         if (targetEnter != null) {
4660             retargetMouseEvent(targetEnter, MouseEvent.MOUSE_ENTERED, e);
4661         }
4662         if (id == MouseEvent.MOUSE_ENTERED) {
4663             // consume native enter event if we generate one
4664             e.consume();
4665         }
4666 
4667         targetLastEntered = targetEnter;
4668     }
4669 
4670     /*
4671      * Listens to global mouse drag events so even drags originating
4672      * from other heavyweight containers will generate enter/exit
4673      * events in this container
4674      */
4675     private void startListeningForOtherDrags() {
4676         //System.out.println("Adding AWTEventListener");
4677         java.security.AccessController.doPrivileged(
4678             new java.security.PrivilegedAction<Object>() {
4679                 public Object run() {
4680                     nativeContainer.getToolkit().addAWTEventListener(
4681                         LightweightDispatcher.this,
4682                         AWTEvent.MOUSE_EVENT_MASK |
4683                         AWTEvent.MOUSE_MOTION_EVENT_MASK);
4684                     return null;
4685                 }
4686             }
4687         );
4688     }
4689 
4690     private void stopListeningForOtherDrags() {
4691         //System.out.println("Removing AWTEventListener");
4692         java.security.AccessController.doPrivileged(
4693             new java.security.PrivilegedAction<Object>() {
4694                 public Object run() {
4695                     nativeContainer.getToolkit().removeAWTEventListener(LightweightDispatcher.this);
4696                     return null;
4697                 }
4698             }
4699         );
4700     }
4701 
4702     /*
4703      * (Implementation of AWTEventListener)
4704      * Listen for drag events posted in other hw components so we can
4705      * track enter/exit regardless of where a drag originated
4706      */
4707     public void eventDispatched(AWTEvent e) {
4708         boolean isForeignDrag = (e instanceof MouseEvent) &&
4709                                 !(e instanceof SunDropTargetEvent) &&
4710                                 (e.id == MouseEvent.MOUSE_DRAGGED) &&
4711                                 (e.getSource() != nativeContainer);
4712 
4713         if (!isForeignDrag) {
4714             // only interested in drags from other hw components
4715             return;
4716         }
4717 
4718         MouseEvent      srcEvent = (MouseEvent)e;
4719         MouseEvent      me;
4720 
4721         synchronized (nativeContainer.getTreeLock()) {
4722             Component srcComponent = srcEvent.getComponent();
4723 
4724             // component may have disappeared since drag event posted
4725             // (i.e. Swing hierarchical menus)
4726             if ( !srcComponent.isShowing() ) {
4727                 return;
4728             }
4729 
4730             // see 5083555
4731             // check if srcComponent is in any modal blocked window
4732             Component c = nativeContainer;
4733             while ((c != null) && !(c instanceof Window)) {
4734                 c = c.getParent_NoClientCode();
4735             }
4736             if ((c == null) || ((Window)c).isModalBlocked()) {
4737                 return;
4738             }
4739 
4740             //
4741             // create an internal 'dragged-over' event indicating
4742             // we are being dragged over from another hw component
4743             //
4744             me = new MouseEvent(nativeContainer,
4745                                LWD_MOUSE_DRAGGED_OVER,
4746                                srcEvent.getWhen(),
4747                                srcEvent.getModifiersEx() | srcEvent.getModifiers(),
4748                                srcEvent.getX(),
4749                                srcEvent.getY(),
4750                                srcEvent.getXOnScreen(),
4751                                srcEvent.getYOnScreen(),
4752                                srcEvent.getClickCount(),
4753                                srcEvent.isPopupTrigger(),
4754                                srcEvent.getButton());
4755             ((AWTEvent)srcEvent).copyPrivateDataInto(me);
4756             // translate coordinates to this native container
4757             final Point ptSrcOrigin = srcComponent.getLocationOnScreen();
4758 
4759             if (AppContext.getAppContext() != nativeContainer.appContext) {
4760                 final MouseEvent mouseEvent = me;
4761                 Runnable r = new Runnable() {
4762                         public void run() {
4763                             if (!nativeContainer.isShowing() ) {
4764                                 return;
4765                             }
4766 
4767                             Point       ptDstOrigin = nativeContainer.getLocationOnScreen();
4768                             mouseEvent.translatePoint(ptSrcOrigin.x - ptDstOrigin.x,
4769                                               ptSrcOrigin.y - ptDstOrigin.y );
4770                             Component targetOver =
4771                                 nativeContainer.getMouseEventTarget(mouseEvent.getX(),
4772                                                                     mouseEvent.getY(),
4773                                                                     Container.INCLUDE_SELF);
4774                             trackMouseEnterExit(targetOver, mouseEvent);
4775                         }
4776                     };
4777                 SunToolkit.executeOnEventHandlerThread(nativeContainer, r);
4778                 return;
4779             } else {
4780                 if (!nativeContainer.isShowing() ) {
4781                     return;
4782                 }
4783 
4784                 Point   ptDstOrigin = nativeContainer.getLocationOnScreen();
4785                 me.translatePoint( ptSrcOrigin.x - ptDstOrigin.x, ptSrcOrigin.y - ptDstOrigin.y );
4786             }
4787         }
4788         //System.out.println("Track event: " + me);
4789         // feed the 'dragged-over' event directly to the enter/exit
4790         // code (not a real event so don't pass it to dispatchEvent)
4791         Component targetOver =
4792             nativeContainer.getMouseEventTarget(me.getX(), me.getY(),
4793                                                 Container.INCLUDE_SELF);
4794         trackMouseEnterExit(targetOver, me);
4795     }
4796 
4797     /**
4798      * Sends a mouse event to the current mouse event recipient using
4799      * the given event (sent to the windowed host) as a srcEvent.  If
4800      * the mouse event target is still in the component tree, the
4801      * coordinates of the event are translated to those of the target.
4802      * If the target has been removed, we don't bother to send the
4803      * message.
4804      */
4805     void retargetMouseEvent(Component target, int id, MouseEvent e) {
4806         if (target == null) {
4807             return; // mouse is over another hw component or target is disabled
4808         }
4809 
4810         int x = e.getX(), y = e.getY();
4811         Component component;
4812 
4813         for(component = target;
4814             component != null && component != nativeContainer;
4815             component = component.getParent()) {
4816             x -= component.x;
4817             y -= component.y;
4818         }
4819         MouseEvent retargeted;
4820         if (component != null) {
4821             if (e instanceof SunDropTargetEvent) {
4822                 retargeted = new SunDropTargetEvent(target,
4823                                                     id,
4824                                                     x,
4825                                                     y,
4826                                                     ((SunDropTargetEvent)e).getDispatcher());
4827             } else if (id == MouseEvent.MOUSE_WHEEL) {
4828                 retargeted = new MouseWheelEvent(target,
4829                                       id,
4830                                        e.getWhen(),
4831                                        e.getModifiersEx() | e.getModifiers(),
4832                                        x,
4833                                        y,
4834                                        e.getXOnScreen(),
4835                                        e.getYOnScreen(),
4836                                        e.getClickCount(),
4837                                        e.isPopupTrigger(),
4838                                        ((MouseWheelEvent)e).getScrollType(),
4839                                        ((MouseWheelEvent)e).getScrollAmount(),
4840                                        ((MouseWheelEvent)e).getWheelRotation(),
4841                                        ((MouseWheelEvent)e).getPreciseWheelRotation());
4842             }
4843             else {
4844                 retargeted = new MouseEvent(target,
4845                                             id,
4846                                             e.getWhen(),
4847                                             e.getModifiersEx() | e.getModifiers(),
4848                                             x,
4849                                             y,
4850                                             e.getXOnScreen(),
4851                                             e.getYOnScreen(),
4852                                             e.getClickCount(),
4853                                             e.isPopupTrigger(),
4854                                             e.getButton());
4855             }
4856 
4857             ((AWTEvent)e).copyPrivateDataInto(retargeted);
4858 
4859             if (target == nativeContainer) {
4860                 // avoid recursively calling LightweightDispatcher...
4861                 ((Container)target).dispatchEventToSelf(retargeted);
4862             } else {
4863                 assert AppContext.getAppContext() == target.appContext;
4864 
4865                 if (nativeContainer.modalComp != null) {
4866                     if (((Container)nativeContainer.modalComp).isAncestorOf(target)) {
4867                         target.dispatchEvent(retargeted);
4868                     } else {
4869                         e.consume();
4870                     }
4871                 } else {
4872                     target.dispatchEvent(retargeted);
4873                 }
4874             }
4875             if (id == MouseEvent.MOUSE_WHEEL && retargeted.isConsumed()) {
4876                 //An exception for wheel bubbling to the native system.
4877                 //In "processMouseEvent" total event consuming for wheel events is skipped.
4878                 //Protection from bubbling of Java-accepted wheel events.
4879                 e.consume();
4880             }
4881         }
4882     }
4883 
4884     // --- member variables -------------------------------
4885 
4886     /**
4887      * The windowed container that might be hosting events for
4888      * subcomponents.
4889      */
4890     private Container nativeContainer;
4891 
4892     /**
4893      * This variable is not used, but kept for serialization compatibility
4894      */
4895     private Component focus;
4896 
4897     /**
4898      * The current subcomponent being hosted by this windowed
4899      * component that has events being forwarded to it.  If this
4900      * is null, there are currently no events being forwarded to
4901      * a subcomponent.
4902      */
4903     private transient Component mouseEventTarget;
4904 
4905     /**
4906      * The last component entered
4907      */
4908     private transient Component targetLastEntered;
4909 
4910     /**
4911      * Indicates whether {@code mouseEventTarget} was removed and nulled
4912      */
4913     private transient boolean isCleaned;
4914 
4915     /**
4916      * Is the mouse over the native container
4917      */
4918     private transient boolean isMouseInNativeContainer = false;
4919 
4920     /**
4921      * This variable is not used, but kept for serialization compatibility
4922      */
4923     private Cursor nativeCursor;
4924 
4925     /**
4926      * The event mask for contained lightweight components.  Lightweight
4927      * components need a windowed container to host window-related
4928      * events.  This separate mask indicates events that have been
4929      * requested by contained lightweight components without effecting
4930      * the mask of the windowed component itself.
4931      */
4932     private long eventMask;
4933 
4934     /**
4935      * The kind of events routed to lightweight components from windowed
4936      * hosts.
4937      */
4938     private static final long PROXY_EVENT_MASK =
4939         AWTEvent.FOCUS_EVENT_MASK |
4940         AWTEvent.KEY_EVENT_MASK |
4941         AWTEvent.MOUSE_EVENT_MASK |
4942         AWTEvent.MOUSE_MOTION_EVENT_MASK |
4943         AWTEvent.MOUSE_WHEEL_EVENT_MASK;
4944 
4945     private static final long MOUSE_MASK =
4946         AWTEvent.MOUSE_EVENT_MASK |
4947         AWTEvent.MOUSE_MOTION_EVENT_MASK |
4948         AWTEvent.MOUSE_WHEEL_EVENT_MASK;
4949 
4950     void removeReferences(Component removedComponent) {
4951         if (mouseEventTarget == removedComponent) {
4952             isCleaned = true;
4953             mouseEventTarget = null;
4954         }
4955         if (targetLastEntered == removedComponent) {
4956             targetLastEntered = null;
4957         }
4958     }
4959 }