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