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