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