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