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