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