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