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