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