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