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