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