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