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