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