1 /*
   2  * Copyright (c) 1995, 2017, 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.PeerEvent;
  60 import sun.awt.SunToolkit;
  61 
  62 import sun.awt.dnd.SunDropTargetEvent;
  63 
  64 import sun.java2d.pipe.Region;
  65 
  66 import sun.security.action.GetBooleanAction;
  67 
  68 /**
  69  * A generic Abstract Window Toolkit(AWT) container object is a component
  70  * that can contain other AWT components.
  71  * <p>
  72  * Components added to a container are tracked in a list.  The order
  73  * of the list will define the components' front-to-back stacking order
  74  * within the container.  If no index is specified when adding a
  75  * component to a container, it will be added to the end of the list
  76  * (and hence to the bottom of the stacking order).
  77  * <p>
  78  * <b>Note</b>: For details on the focus subsystem, see
  79  * <a href="http://docs.oracle.com/javase/tutorial/uiswing/misc/focus.html">
  80  * How to Use the Focus Subsystem</a>,
  81  * a section in <em>The Java Tutorial</em>, and the
  82  * <a href="../../java/awt/doc-files/FocusSpec.html">Focus Specification</a>
  83  * for more information.
  84  *
  85  * @author      Arthur van Hoff
  86  * @author      Sami Shaio
  87  * @see       #add(java.awt.Component, int)
  88  * @see       #getComponent(int)
  89  * @see       LayoutManager
  90  * @since     1.0
  91  */
  92 public class Container extends Component {
  93 
  94     private static final PlatformLogger log = PlatformLogger.getLogger("java.awt.Container");
  95     private static final PlatformLogger eventLog = PlatformLogger.getLogger("java.awt.event.Container");
  96 
  97     private static final Component[] EMPTY_ARRAY = new Component[0];
  98 
  99     /**
 100      * The components in this container.
 101      * @see #add
 102      * @see #getComponents
 103      */
 104     private java.util.List<Component> component = new ArrayList<>();
 105 
 106     /**
 107      * Layout manager for this container.
 108      * @see #doLayout
 109      * @see #setLayout
 110      * @see #getLayout
 111      */
 112     LayoutManager layoutMgr;
 113 
 114     /**
 115      * Event router for lightweight components.  If this container
 116      * is native, this dispatcher takes care of forwarding and
 117      * retargeting the events to lightweight components contained
 118      * (if any).
 119      */
 120     private LightweightDispatcher dispatcher;
 121 
 122     /**
 123      * The focus traversal policy that will manage keyboard traversal of this
 124      * Container's children, if this Container is a focus cycle root. If the
 125      * value is null, this Container inherits its policy from its focus-cycle-
 126      * root ancestor. If all such ancestors of this Container have null
 127      * policies, then the current KeyboardFocusManager's default policy is
 128      * used. If the value is non-null, this policy will be inherited by all
 129      * focus-cycle-root children that have no keyboard-traversal policy of
 130      * their own (as will, recursively, their focus-cycle-root children).
 131      * <p>
 132      * If this Container is not a focus cycle root, the value will be
 133      * remembered, but will not be used or inherited by this or any other
 134      * Containers until this Container is made a focus cycle root.
 135      *
 136      * @see #setFocusTraversalPolicy
 137      * @see #getFocusTraversalPolicy
 138      * @since 1.4
 139      */
 140     private transient FocusTraversalPolicy focusTraversalPolicy;
 141 
 142     /**
 143      * Indicates whether this Component is the root of a focus traversal cycle.
 144      * Once focus enters a traversal cycle, typically it cannot leave it via
 145      * focus traversal unless one of the up- or down-cycle keys is pressed.
 146      * Normal traversal is limited to this Container, and all of this
 147      * Container's descendants that are not descendants of inferior focus cycle
 148      * roots.
 149      *
 150      * @see #setFocusCycleRoot
 151      * @see #isFocusCycleRoot
 152      * @since 1.4
 153      */
 154     private boolean focusCycleRoot = false;
 155 
 156 
 157     /**
 158      * Stores the value of focusTraversalPolicyProvider property.
 159      * @since 1.5
 160      * @see #setFocusTraversalPolicyProvider
 161      */
 162     private boolean focusTraversalPolicyProvider;
 163 
 164     // keeps track of the threads that are printing this component
 165     private transient Set<Thread> printingThreads;
 166     // True if there is at least one thread that's printing this component
 167     private transient boolean printing = false;
 168 
 169     transient ContainerListener containerListener;
 170 
 171     /* HierarchyListener and HierarchyBoundsListener support */
 172     transient int listeningChildren;
 173     transient int listeningBoundsChildren;
 174     transient int descendantsCount;
 175 
 176     /* Non-opaque window support -- see Window.setLayersOpaque */
 177     transient Color preserveBackgroundColor = null;
 178 
 179     /**
 180      * JDK 1.1 serialVersionUID
 181      */
 182     private static final long serialVersionUID = 4613797578919906343L;
 183 
 184     /**
 185      * A constant which toggles one of the controllable behaviors
 186      * of {@code getMouseEventTarget}. It is used to specify whether
 187      * the method can return the Container on which it is originally called
 188      * in case if none of its children are the current mouse event targets.
 189      *
 190      * @see #getMouseEventTarget(int, int, boolean)
 191      */
 192     static final boolean INCLUDE_SELF = true;
 193 
 194     /**
 195      * A constant which toggles one of the controllable behaviors
 196      * of {@code getMouseEventTarget}. It is used to specify whether
 197      * the method should search only lightweight components.
 198      *
 199      * @see #getMouseEventTarget(int, int, boolean)
 200      */
 201     static final boolean SEARCH_HEAVYWEIGHTS = true;
 202 
 203     /*
 204      * Number of HW or LW components in this container (including
 205      * all descendant containers).
 206      */
 207     private transient int numOfHWComponents = 0;
 208     private transient int numOfLWComponents = 0;
 209 
 210     private static final PlatformLogger mixingLog = PlatformLogger.getLogger("java.awt.mixing.Container");
 211 
 212     /**
 213      * @serialField ncomponents                     int
 214      *       The number of components in this container.
 215      *       This value can be null.
 216      * @serialField component                       Component[]
 217      *       The components in this container.
 218      * @serialField layoutMgr                       LayoutManager
 219      *       Layout manager for this container.
 220      * @serialField dispatcher                      LightweightDispatcher
 221      *       Event router for lightweight components.  If this container
 222      *       is native, this dispatcher takes care of forwarding and
 223      *       retargeting the events to lightweight components contained
 224      *       (if any).
 225      * @serialField maxSize                         Dimension
 226      *       Maximum size of this Container.
 227      * @serialField focusCycleRoot                  boolean
 228      *       Indicates whether this Component is the root of a focus traversal cycle.
 229      *       Once focus enters a traversal cycle, typically it cannot leave it via
 230      *       focus traversal unless one of the up- or down-cycle keys is pressed.
 231      *       Normal traversal is limited to this Container, and all of this
 232      *       Container's descendants that are not descendants of inferior focus cycle
 233      *       roots.
 234      * @serialField containerSerializedDataVersion  int
 235      *       Container Serial Data Version.
 236      * @serialField focusTraversalPolicyProvider    boolean
 237      *       Stores the value of focusTraversalPolicyProvider property.
 238      */
 239     private static final ObjectStreamField[] serialPersistentFields = {
 240         new ObjectStreamField("ncomponents", Integer.TYPE),
 241         new ObjectStreamField("component", Component[].class),
 242         new ObjectStreamField("layoutMgr", LayoutManager.class),
 243         new ObjectStreamField("dispatcher", LightweightDispatcher.class),
 244         new ObjectStreamField("maxSize", Dimension.class),
 245         new ObjectStreamField("focusCycleRoot", Boolean.TYPE),
 246         new ObjectStreamField("containerSerializedDataVersion", Integer.TYPE),
 247         new ObjectStreamField("focusTraversalPolicyProvider", Boolean.TYPE),
 248     };
 249 
 250     static {
 251         /* ensure that the necessary native libraries are loaded */
 252         Toolkit.loadLibraries();
 253         if (!GraphicsEnvironment.isHeadless()) {
 254             initIDs();
 255         }
 256 
 257         AWTAccessor.setContainerAccessor(new AWTAccessor.ContainerAccessor() {
 258             @Override
 259             public void validateUnconditionally(Container cont) {
 260                 cont.validateUnconditionally();
 261             }
 262 
 263             @Override
 264             public Component findComponentAt(Container cont, int x, int y,
 265                     boolean ignoreEnabled) {
 266                 return cont.findComponentAt(x, y, ignoreEnabled);
 267             }
 268 
 269             @Override
 270             public void startLWModal(Container cont) {
 271                 cont.startLWModal();
 272             }
 273 
 274             @Override
 275             public void stopLWModal(Container cont) {
 276                 cont.stopLWModal();
 277             }
 278         });
 279     }
 280 
 281     /**
 282      * Initialize JNI field and method IDs for fields that may be
 283        called from C.
 284      */
 285     private static native void initIDs();
 286 
 287     /**
 288      * Constructs a new Container. Containers can be extended directly,
 289      * but are lightweight in this case and must be contained by a parent
 290      * somewhere higher up in the component tree that is native.
 291      * (such as Frame for example).
 292      */
 293     public Container() {
 294     }
 295     @SuppressWarnings({"unchecked","rawtypes"})
 296     void initializeFocusTraversalKeys() {
 297         focusTraversalKeys = new Set[4];
 298     }
 299 
 300     /**
 301      * Gets the number of components in this panel.
 302      * <p>
 303      * Note: This method should be called under AWT tree lock.
 304      *
 305      * @return    the number of components in this panel.
 306      * @see       #getComponent
 307      * @since     1.1
 308      * @see Component#getTreeLock()
 309      */
 310     public int getComponentCount() {
 311         return countComponents();
 312     }
 313 
 314     /**
 315      * Returns the number of components in this container.
 316      *
 317      * @return the number of components in this container
 318      * @deprecated As of JDK version 1.1,
 319      * replaced by getComponentCount().
 320      */
 321     @Deprecated
 322     public int countComponents() {
 323         // This method is not synchronized under AWT tree lock.
 324         // Instead, the calling code is responsible for the
 325         // synchronization. See 6784816 for details.
 326         return component.size();
 327     }
 328 
 329     /**
 330      * Gets the nth component in this container.
 331      * <p>
 332      * Note: This method should be called under AWT tree lock.
 333      *
 334      * @param      n   the index of the component to get.
 335      * @return     the n<sup>th</sup> component in this container.
 336      * @exception  ArrayIndexOutOfBoundsException
 337      *                 if the n<sup>th</sup> value does not exist.
 338      * @see Component#getTreeLock()
 339      */
 340     public Component getComponent(int n) {
 341         // This method is not synchronized under AWT tree lock.
 342         // Instead, the calling code is responsible for the
 343         // synchronization. See 6784816 for details.
 344         try {
 345             return component.get(n);
 346         } catch (IndexOutOfBoundsException z) {
 347             throw new ArrayIndexOutOfBoundsException("No such child: " + n);
 348         }
 349     }
 350 
 351     /**
 352      * Gets all the components in this container.
 353      * <p>
 354      * Note: This method should be called under AWT tree lock.
 355      *
 356      * @return    an array of all the components in this container.
 357      * @see Component#getTreeLock()
 358      */
 359     public Component[] getComponents() {
 360         // This method is not synchronized under AWT tree lock.
 361         // Instead, the calling code is responsible for the
 362         // synchronization. See 6784816 for details.
 363         return getComponents_NoClientCode();
 364     }
 365 
 366     // NOTE: This method may be called by privileged threads.
 367     //       This functionality is implemented in a package-private method
 368     //       to insure that it cannot be overridden by client subclasses.
 369     //       DO NOT INVOKE CLIENT CODE ON THIS THREAD!
 370     final Component[] getComponents_NoClientCode() {
 371         return component.toArray(EMPTY_ARRAY);
 372     }
 373 
 374     /*
 375      * Wrapper for getComponents() method with a proper synchronization.
 376      */
 377     Component[] getComponentsSync() {
 378         synchronized (getTreeLock()) {
 379             return getComponents();
 380         }
 381     }
 382 
 383     /**
 384      * Determines the insets of this container, which indicate the size
 385      * of the container's border.
 386      * <p>
 387      * A {@code Frame} object, for example, has a top inset that
 388      * corresponds to the height of the frame's title bar.
 389      * @return    the insets of this container.
 390      * @see       Insets
 391      * @see       LayoutManager
 392      * @since     1.1
 393      */
 394     public Insets getInsets() {
 395         return insets();
 396     }
 397 
 398     /**
 399      * Returns the insets for this container.
 400      *
 401      * @deprecated As of JDK version 1.1,
 402      * replaced by {@code getInsets()}.
 403      * @return the insets for this container
 404      */
 405     @Deprecated
 406     public Insets insets() {
 407         ComponentPeer peer = this.peer;
 408         if (peer instanceof ContainerPeer) {
 409             ContainerPeer cpeer = (ContainerPeer)peer;
 410             return (Insets)cpeer.getInsets().clone();
 411         }
 412         return new Insets(0, 0, 0, 0);
 413     }
 414 
 415     /**
 416      * Appends the specified component to the end of this container.
 417      * This is a convenience method for {@link #addImpl}.
 418      * <p>
 419      * This method changes layout-related information, and therefore,
 420      * invalidates the component hierarchy. If the container has already been
 421      * displayed, the hierarchy must be validated thereafter in order to
 422      * display the added component.
 423      *
 424      * @param     comp   the component to be added
 425      * @exception NullPointerException if {@code comp} is {@code null}
 426      * @see #addImpl
 427      * @see #invalidate
 428      * @see #validate
 429      * @see javax.swing.JComponent#revalidate()
 430      * @return    the component argument
 431      */
 432     public Component add(Component comp) {
 433         addImpl(comp, null, -1);
 434         return comp;
 435     }
 436 
 437     /**
 438      * Adds the specified component to this container.
 439      * This is a convenience method for {@link #addImpl}.
 440      * <p>
 441      * This method is obsolete as of 1.1.  Please use the
 442      * method {@code add(Component, Object)} instead.
 443      * <p>
 444      * This method changes layout-related information, and therefore,
 445      * invalidates the component hierarchy. If the container has already been
 446      * displayed, the hierarchy must be validated thereafter in order to
 447      * display the added component.
 448      *
 449      * @param  name the name of the component to be added
 450      * @param  comp the component to be added
 451      * @return the component added
 452      * @exception NullPointerException if {@code comp} is {@code null}
 453      * @see #add(Component, Object)
 454      * @see #invalidate
 455      */
 456     public Component add(String name, Component comp) {
 457         addImpl(comp, name, -1);
 458         return comp;
 459     }
 460 
 461     /**
 462      * Adds the specified component to this container at the given
 463      * position.
 464      * This is a convenience method for {@link #addImpl}.
 465      * <p>
 466      * This method changes layout-related information, and therefore,
 467      * invalidates the component hierarchy. If the container has already been
 468      * displayed, the hierarchy must be validated thereafter in order to
 469      * display the added component.
 470      *
 471      *
 472      * @param     comp   the component to be added
 473      * @param     index    the position at which to insert the component,
 474      *                   or {@code -1} to append the component to the end
 475      * @exception NullPointerException if {@code comp} is {@code null}
 476      * @exception IllegalArgumentException if {@code index} is invalid (see
 477      *            {@link #addImpl} for details)
 478      * @return    the component {@code comp}
 479      * @see #addImpl
 480      * @see #remove
 481      * @see #invalidate
 482      * @see #validate
 483      * @see javax.swing.JComponent#revalidate()
 484      */
 485     public Component add(Component comp, int index) {
 486         addImpl(comp, null, index);
 487         return comp;
 488     }
 489 
 490     /**
 491      * Checks that the component
 492      * isn't supposed to be added into itself.
 493      */
 494     private void checkAddToSelf(Component comp){
 495         if (comp instanceof Container) {
 496             for (Container cn = this; cn != null; cn=cn.parent) {
 497                 if (cn == comp) {
 498                     throw new IllegalArgumentException("adding container's parent to itself");
 499                 }
 500             }
 501         }
 502     }
 503 
 504     /**
 505      * Checks that the component is not a Window instance.
 506      */
 507     private void checkNotAWindow(Component comp){
 508         if (comp instanceof Window) {
 509             throw new IllegalArgumentException("adding a window to a container");
 510         }
 511     }
 512 
 513     /**
 514      * Checks that the component comp can be added to this container
 515      * Checks :  index in bounds of container's size,
 516      * comp is not one of this container's parents,
 517      * and comp is not a window.
 518      * Comp and container must be on the same GraphicsDevice.
 519      * if comp is container, all sub-components must be on
 520      * same GraphicsDevice.
 521      *
 522      * @since 1.5
 523      */
 524     private void checkAdding(Component comp, int index) {
 525         checkTreeLock();
 526 
 527         GraphicsConfiguration thisGC = getGraphicsConfiguration();
 528 
 529         if (index > component.size() || index < 0) {
 530             throw new IllegalArgumentException("illegal component position");
 531         }
 532         if (comp.parent == this) {
 533             if (index == component.size()) {
 534                 throw new IllegalArgumentException("illegal component position " +
 535                                                    index + " should be less than " + component.size());
 536             }
 537         }
 538         checkAddToSelf(comp);
 539         checkNotAWindow(comp);
 540 
 541         Window thisTopLevel = getContainingWindow();
 542         Window compTopLevel = comp.getContainingWindow();
 543         if (thisTopLevel != compTopLevel) {
 544             throw new IllegalArgumentException("component and container should be in the same top-level window");
 545         }
 546         if (thisGC != null) {
 547             comp.checkGD(thisGC.getDevice().getIDstring());
 548         }
 549     }
 550 
 551     /**
 552      * Removes component comp from this container without making unnecessary changes
 553      * and generating unnecessary events. This function intended to perform optimized
 554      * remove, for example, if newParent and current parent are the same it just changes
 555      * index without calling removeNotify.
 556      * Note: Should be called while holding treeLock
 557      * Returns whether removeNotify was invoked
 558      * @since: 1.5
 559      */
 560     private boolean removeDelicately(Component comp, Container newParent, int newIndex) {
 561         checkTreeLock();
 562 
 563         int index = getComponentZOrder(comp);
 564         boolean needRemoveNotify = isRemoveNotifyNeeded(comp, this, newParent);
 565         if (needRemoveNotify) {
 566             comp.removeNotify();
 567         }
 568         if (newParent != this) {
 569             if (layoutMgr != null) {
 570                 layoutMgr.removeLayoutComponent(comp);
 571             }
 572             adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK,
 573                                     -comp.numListening(AWTEvent.HIERARCHY_EVENT_MASK));
 574             adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
 575                                     -comp.numListening(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));
 576             adjustDescendants(-(comp.countHierarchyMembers()));
 577 
 578             comp.parent = null;
 579             if (needRemoveNotify) {
 580                 comp.setGraphicsConfiguration(null);
 581             }
 582             component.remove(index);
 583 
 584             invalidateIfValid();
 585         } else {
 586             // We should remove component and then
 587             // add it by the newIndex without newIndex decrement if even we shift components to the left
 588             // after remove. Consult the rules below:
 589             // 2->4: 012345 -> 013425, 2->5: 012345 -> 013452
 590             // 4->2: 012345 -> 014235
 591             component.remove(index);
 592             component.add(newIndex, comp);
 593         }
 594         if (comp.parent == null) { // was actually removed
 595             if (containerListener != null ||
 596                 (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 ||
 597                 Toolkit.enabledOnToolkit(AWTEvent.CONTAINER_EVENT_MASK)) {
 598                 ContainerEvent e = new ContainerEvent(this,
 599                                                       ContainerEvent.COMPONENT_REMOVED,
 600                                                       comp);
 601                 dispatchEvent(e);
 602 
 603             }
 604             comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, comp,
 605                                        this, HierarchyEvent.PARENT_CHANGED,
 606                                        Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK));
 607             if (peer != null && layoutMgr == null && isVisible()) {
 608                 updateCursorImmediately();
 609             }
 610         }
 611         return needRemoveNotify;
 612     }
 613 
 614     /**
 615      * Checks whether this container can contain component which is focus owner.
 616      * Verifies that container is enable and showing, and if it is focus cycle root
 617      * its FTP allows component to be focus owner
 618      * @since 1.5
 619      */
 620     boolean canContainFocusOwner(Component focusOwnerCandidate) {
 621         if (!(isEnabled() && isDisplayable()
 622               && isVisible() && isFocusable()))
 623         {
 624             return false;
 625         }
 626         if (isFocusCycleRoot()) {
 627             FocusTraversalPolicy policy = getFocusTraversalPolicy();
 628             if (policy instanceof DefaultFocusTraversalPolicy) {
 629                 if (!((DefaultFocusTraversalPolicy)policy).accept(focusOwnerCandidate)) {
 630                     return false;
 631                 }
 632             }
 633         }
 634         synchronized(getTreeLock()) {
 635             if (parent != null) {
 636                 return parent.canContainFocusOwner(focusOwnerCandidate);
 637             }
 638         }
 639         return true;
 640     }
 641 
 642     /**
 643      * Checks whether or not this container has heavyweight children.
 644      * Note: Should be called while holding tree lock
 645      * @return true if there is at least one heavyweight children in a container, false otherwise
 646      * @since 1.5
 647      */
 648     final boolean hasHeavyweightDescendants() {
 649         checkTreeLock();
 650         return numOfHWComponents > 0;
 651     }
 652 
 653     /**
 654      * Checks whether or not this container has lightweight children.
 655      * Note: Should be called while holding tree lock
 656      * @return true if there is at least one lightweight children in a container, false otherwise
 657      * @since 1.7
 658      */
 659     final boolean hasLightweightDescendants() {
 660         checkTreeLock();
 661         return numOfLWComponents > 0;
 662     }
 663 
 664     /**
 665      * Returns closest heavyweight component to this container. If this container is heavyweight
 666      * returns this.
 667      * @since 1.5
 668      */
 669     Container getHeavyweightContainer() {
 670         checkTreeLock();
 671         if (peer != null && !(peer instanceof LightweightPeer)) {
 672             return this;
 673         } else {
 674             return getNativeContainer();
 675         }
 676     }
 677 
 678     /**
 679      * Detects whether or not remove from current parent and adding to new parent requires call of
 680      * removeNotify on the component. Since removeNotify destroys native window this might (not)
 681      * be required. For example, if new container and old containers are the same we don't need to
 682      * destroy native window.
 683      * @since: 1.5
 684      */
 685     private static boolean isRemoveNotifyNeeded(Component comp, Container oldContainer, Container newContainer) {
 686         if (oldContainer == null) { // Component didn't have parent - no removeNotify
 687             return false;
 688         }
 689         if (comp.peer == null) { // Component didn't have peer - no removeNotify
 690             return false;
 691         }
 692         if (newContainer.peer == null) {
 693             // Component has peer but new Container doesn't - call removeNotify
 694             return true;
 695         }
 696 
 697         // If component is lightweight non-Container or lightweight Container with all but heavyweight
 698         // children there is no need to call remove notify
 699         if (comp.isLightweight()) {
 700             boolean isContainer = comp instanceof Container;
 701 
 702             if (!isContainer || (isContainer && !((Container)comp).hasHeavyweightDescendants())) {
 703                 return false;
 704             }
 705         }
 706 
 707         // If this point is reached, then the comp is either a HW or a LW container with HW descendants.
 708 
 709         // All three components have peers, check for peer change
 710         Container newNativeContainer = oldContainer.getHeavyweightContainer();
 711         Container oldNativeContainer = newContainer.getHeavyweightContainer();
 712         if (newNativeContainer != oldNativeContainer) {
 713             // Native containers change - check whether or not current platform supports
 714             // changing of widget hierarchy on native level without recreation.
 715             // The current implementation forbids reparenting of LW containers with HW descendants
 716             // into another native container w/o destroying the peers. Actually such an operation
 717             // is quite rare. If we ever need to save the peers, we'll have to slightly change the
 718             // addDelicately() method in order to handle such LW containers recursively, reparenting
 719             // each HW descendant independently.
 720             return !comp.peer.isReparentSupported();
 721         } else {
 722             return false;
 723         }
 724     }
 725 
 726     /**
 727      * Moves the specified component to the specified z-order index in
 728      * the container. The z-order determines the order that components
 729      * are painted; the component with the highest z-order paints first
 730      * and the component with the lowest z-order paints last.
 731      * Where components overlap, the component with the lower
 732      * z-order paints over the component with the higher z-order.
 733      * <p>
 734      * If the component is a child of some other container, it is
 735      * removed from that container before being added to this container.
 736      * The important difference between this method and
 737      * {@code java.awt.Container.add(Component, int)} is that this method
 738      * doesn't call {@code removeNotify} on the component while
 739      * removing it from its previous container unless necessary and when
 740      * allowed by the underlying native windowing system. This way, if the
 741      * component has the keyboard focus, it maintains the focus when
 742      * moved to the new position.
 743      * <p>
 744      * This property is guaranteed to apply only to lightweight
 745      * non-{@code Container} components.
 746      * <p>
 747      * This method changes layout-related information, and therefore,
 748      * invalidates the component hierarchy.
 749      * <p>
 750      * <b>Note</b>: Not all platforms support changing the z-order of
 751      * heavyweight components from one container into another without
 752      * the call to {@code removeNotify}. There is no way to detect
 753      * whether a platform supports this, so developers shouldn't make
 754      * any assumptions.
 755      *
 756      * @param     comp the component to be moved
 757      * @param     index the position in the container's list to
 758      *            insert the component, where {@code getComponentCount()}
 759      *            appends to the end
 760      * @exception NullPointerException if {@code comp} is
 761      *            {@code null}
 762      * @exception IllegalArgumentException if {@code comp} is one of the
 763      *            container's parents
 764      * @exception IllegalArgumentException if {@code index} is not in
 765      *            the range {@code [0, getComponentCount()]} for moving
 766      *            between containers, or not in the range
 767      *            {@code [0, getComponentCount()-1]} for moving inside
 768      *            a container
 769      * @exception IllegalArgumentException if adding a container to itself
 770      * @exception IllegalArgumentException if adding a {@code Window}
 771      *            to a container
 772      * @see #getComponentZOrder(java.awt.Component)
 773      * @see #invalidate
 774      * @since 1.5
 775      */
 776     public void setComponentZOrder(Component comp, int index) {
 777          synchronized (getTreeLock()) {
 778              // Store parent because remove will clear it
 779              Container curParent = comp.parent;
 780              int oldZindex = getComponentZOrder(comp);
 781 
 782              if (curParent == this && index == oldZindex) {
 783                  return;
 784              }
 785              checkAdding(comp, index);
 786 
 787              boolean peerRecreated = (curParent != null) ?
 788                  curParent.removeDelicately(comp, this, index) : false;
 789 
 790              addDelicately(comp, curParent, index);
 791 
 792              // If the oldZindex == -1, the component gets inserted,
 793              // rather than it changes its z-order.
 794              if (!peerRecreated && oldZindex != -1) {
 795                  // The new 'index' cannot be == -1.
 796                  // It gets checked at the checkAdding() method.
 797                  // Therefore both oldZIndex and index denote
 798                  // some existing positions at this point and
 799                  // this is actually a Z-order changing.
 800                  comp.mixOnZOrderChanging(oldZindex, index);
 801              }
 802          }
 803     }
 804 
 805     /**
 806      * Traverses the tree of components and reparents children heavyweight component
 807      * to new heavyweight parent.
 808      * @since 1.5
 809      */
 810     @SuppressWarnings("deprecation")
 811     private void reparentTraverse(ContainerPeer parentPeer, Container child) {
 812         checkTreeLock();
 813 
 814         for (int i = 0; i < child.getComponentCount(); i++) {
 815             Component comp = child.getComponent(i);
 816             if (comp.isLightweight()) {
 817                 // If components is lightweight check if it is container
 818                 // If it is container it might contain heavyweight children we need to reparent
 819                 if (comp instanceof Container) {
 820                     reparentTraverse(parentPeer, (Container)comp);
 821                 }
 822             } else {
 823                 // Q: Need to update NativeInLightFixer?
 824                 comp.peer.reparent(parentPeer);
 825             }
 826         }
 827     }
 828 
 829     /**
 830      * Reparents child component peer to this container peer.
 831      * Container must be heavyweight.
 832      * @since 1.5
 833      */
 834     @SuppressWarnings("deprecation")
 835     private void reparentChild(Component comp) {
 836         checkTreeLock();
 837         if (comp == null) {
 838             return;
 839         }
 840         if (comp.isLightweight()) {
 841             // If component is lightweight container we need to reparent all its explicit  heavyweight children
 842             if (comp instanceof Container) {
 843                 // Traverse component's tree till depth-first until encountering heavyweight component
 844                 reparentTraverse((ContainerPeer)peer, (Container)comp);
 845             }
 846         } else {
 847             comp.peer.reparent((ContainerPeer) peer);
 848         }
 849     }
 850 
 851     /**
 852      * Adds component to this container. Tries to minimize side effects of this adding -
 853      * doesn't call remove notify if it is not required.
 854      * @since 1.5
 855      */
 856     private void addDelicately(Component comp, Container curParent, int index) {
 857         checkTreeLock();
 858 
 859         // Check if moving between containers
 860         if (curParent != this) {
 861             //index == -1 means add to the end.
 862             if (index == -1) {
 863                 component.add(comp);
 864             } else {
 865                 component.add(index, comp);
 866             }
 867             comp.parent = this;
 868             comp.setGraphicsConfiguration(getGraphicsConfiguration());
 869 
 870             adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK,
 871                                     comp.numListening(AWTEvent.HIERARCHY_EVENT_MASK));
 872             adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
 873                                     comp.numListening(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));
 874             adjustDescendants(comp.countHierarchyMembers());
 875         } else {
 876             if (index < component.size()) {
 877                 component.set(index, comp);
 878             }
 879         }
 880 
 881         invalidateIfValid();
 882         if (peer != null) {
 883             if (comp.peer == null) { // Remove notify was called or it didn't have peer - create new one
 884                 comp.addNotify();
 885             } else { // Both container and child have peers, it means child peer should be reparented.
 886                 // In both cases we need to reparent native widgets.
 887                 Container newNativeContainer = getHeavyweightContainer();
 888                 Container oldNativeContainer = curParent.getHeavyweightContainer();
 889                 if (oldNativeContainer != newNativeContainer) {
 890                     // Native container changed - need to reparent native widgets
 891                     newNativeContainer.reparentChild(comp);
 892                 }
 893                 comp.updateZOrder();
 894 
 895                 if (!comp.isLightweight() && isLightweight()) {
 896                     // If component is heavyweight and one of the containers is lightweight
 897                     // the location of the component should be fixed.
 898                     comp.relocateComponent();
 899                 }
 900             }
 901         }
 902         if (curParent != this) {
 903             /* Notify the layout manager of the added component. */
 904             if (layoutMgr != null) {
 905                 if (layoutMgr instanceof LayoutManager2) {
 906                     ((LayoutManager2)layoutMgr).addLayoutComponent(comp, null);
 907                 } else {
 908                     layoutMgr.addLayoutComponent(null, comp);
 909                 }
 910             }
 911             if (containerListener != null ||
 912                 (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 ||
 913                 Toolkit.enabledOnToolkit(AWTEvent.CONTAINER_EVENT_MASK)) {
 914                 ContainerEvent e = new ContainerEvent(this,
 915                                                       ContainerEvent.COMPONENT_ADDED,
 916                                                       comp);
 917                 dispatchEvent(e);
 918             }
 919             comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, comp,
 920                                        this, HierarchyEvent.PARENT_CHANGED,
 921                                        Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK));
 922 
 923             // If component is focus owner or parent container of focus owner check that after reparenting
 924             // focus owner moved out if new container prohibit this kind of focus owner.
 925             if (comp.isFocusOwner() && !comp.canBeFocusOwnerRecursively()) {
 926                 comp.transferFocus();
 927             } else if (comp instanceof Container) {
 928                 Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
 929                 if (focusOwner != null && isParentOf(focusOwner) && !focusOwner.canBeFocusOwnerRecursively()) {
 930                     focusOwner.transferFocus();
 931                 }
 932             }
 933         } else {
 934             comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, comp,
 935                                        this, HierarchyEvent.HIERARCHY_CHANGED,
 936                                        Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK));
 937         }
 938 
 939         if (peer != null && layoutMgr == null && isVisible()) {
 940             updateCursorImmediately();
 941         }
 942     }
 943 
 944     /**
 945      * Returns the z-order index of the component inside the container.
 946      * The higher a component is in the z-order hierarchy, the lower
 947      * its index.  The component with the lowest z-order index is
 948      * painted last, above all other child components.
 949      *
 950      * @param comp the component being queried
 951      * @return  the z-order index of the component; otherwise
 952      *          returns -1 if the component is {@code null}
 953      *          or doesn't belong to the container
 954      * @see #setComponentZOrder(java.awt.Component, int)
 955      * @since 1.5
 956      */
 957     public int getComponentZOrder(Component comp) {
 958         if (comp == null) {
 959             return -1;
 960         }
 961         synchronized(getTreeLock()) {
 962             // Quick check - container should be immediate parent of the component
 963             if (comp.parent != this) {
 964                 return -1;
 965             }
 966             return component.indexOf(comp);
 967         }
 968     }
 969 
 970     /**
 971      * Adds the specified component to the end of this container.
 972      * Also notifies the layout manager to add the component to
 973      * this container's layout using the specified constraints object.
 974      * This is a convenience method for {@link #addImpl}.
 975      * <p>
 976      * This method changes layout-related information, and therefore,
 977      * invalidates the component hierarchy. If the container has already been
 978      * displayed, the hierarchy must be validated thereafter in order to
 979      * display the added component.
 980      *
 981      *
 982      * @param     comp the component to be added
 983      * @param     constraints an object expressing
 984      *                  layout constraints for this component
 985      * @exception NullPointerException if {@code comp} is {@code null}
 986      * @see #addImpl
 987      * @see #invalidate
 988      * @see #validate
 989      * @see javax.swing.JComponent#revalidate()
 990      * @see       LayoutManager
 991      * @since     1.1
 992      */
 993     public void add(Component comp, Object constraints) {
 994         addImpl(comp, constraints, -1);
 995     }
 996 
 997     /**
 998      * Adds the specified component to this container with the specified
 999      * constraints at the specified index.  Also notifies the layout
1000      * manager to add the component to the this container's layout using
1001      * the specified constraints object.
1002      * This is a convenience method for {@link #addImpl}.
1003      * <p>
1004      * This method changes layout-related information, and therefore,
1005      * invalidates the component hierarchy. If the container has already been
1006      * displayed, the hierarchy must be validated thereafter in order to
1007      * display the added component.
1008      *
1009      *
1010      * @param comp the component to be added
1011      * @param constraints an object expressing layout constraints for this
1012      * @param index the position in the container's list at which to insert
1013      * the component; {@code -1} means insert at the end
1014      * component
1015      * @exception NullPointerException if {@code comp} is {@code null}
1016      * @exception IllegalArgumentException if {@code index} is invalid (see
1017      *            {@link #addImpl} for details)
1018      * @see #addImpl
1019      * @see #invalidate
1020      * @see #validate
1021      * @see javax.swing.JComponent#revalidate()
1022      * @see #remove
1023      * @see LayoutManager
1024      */
1025     public void add(Component comp, Object constraints, int index) {
1026        addImpl(comp, constraints, index);
1027     }
1028 
1029     /**
1030      * Adds the specified component to this container at the specified
1031      * index. This method also notifies the layout manager to add
1032      * the component to this container's layout using the specified
1033      * constraints object via the {@code addLayoutComponent}
1034      * method.
1035      * <p>
1036      * The constraints are
1037      * defined by the particular layout manager being used.  For
1038      * example, the {@code BorderLayout} class defines five
1039      * constraints: {@code BorderLayout.NORTH},
1040      * {@code BorderLayout.SOUTH}, {@code BorderLayout.EAST},
1041      * {@code BorderLayout.WEST}, and {@code BorderLayout.CENTER}.
1042      * <p>
1043      * The {@code GridBagLayout} class requires a
1044      * {@code GridBagConstraints} object.  Failure to pass
1045      * the correct type of constraints object results in an
1046      * {@code IllegalArgumentException}.
1047      * <p>
1048      * If the current layout manager implements {@code LayoutManager2}, then
1049      * {@link LayoutManager2#addLayoutComponent(Component,Object)} is invoked on
1050      * it. If the current layout manager does not implement
1051      * {@code LayoutManager2}, and constraints is a {@code String}, then
1052      * {@link LayoutManager#addLayoutComponent(String,Component)} is invoked on it.
1053      * <p>
1054      * If the component is not an ancestor of this container and has a non-null
1055      * parent, it is removed from its current parent before it is added to this
1056      * container.
1057      * <p>
1058      * This is the method to override if a program needs to track
1059      * every add request to a container as all other add methods defer
1060      * to this one. An overriding method should
1061      * usually include a call to the superclass's version of the method:
1062      *
1063      * <blockquote>
1064      * {@code super.addImpl(comp, constraints, index)}
1065      * </blockquote>
1066      * <p>
1067      * This method changes layout-related information, and therefore,
1068      * invalidates the component hierarchy. If the container has already been
1069      * displayed, the hierarchy must be validated thereafter in order to
1070      * display the added component.
1071      *
1072      * @param     comp       the component to be added
1073      * @param     constraints an object expressing layout constraints
1074      *                 for this component
1075      * @param     index the position in the container's list at which to
1076      *                 insert the component, where {@code -1}
1077      *                 means append to the end
1078      * @exception IllegalArgumentException if {@code index} is invalid;
1079      *            if {@code comp} is a child of this container, the valid
1080      *            range is {@code [-1, getComponentCount()-1]}; if component is
1081      *            not a child of this container, the valid range is
1082      *            {@code [-1, getComponentCount()]}
1083      *
1084      * @exception IllegalArgumentException if {@code comp} is an ancestor of
1085      *                                     this container
1086      * @exception IllegalArgumentException if adding a window to a container
1087      * @exception NullPointerException if {@code comp} is {@code null}
1088      * @see       #add(Component)
1089      * @see       #add(Component, int)
1090      * @see       #add(Component, java.lang.Object)
1091      * @see #invalidate
1092      * @see       LayoutManager
1093      * @see       LayoutManager2
1094      * @since     1.1
1095      */
1096     protected void addImpl(Component comp, Object constraints, int index) {
1097         synchronized (getTreeLock()) {
1098             /* Check for correct arguments:  index in bounds,
1099              * comp cannot be one of this container's parents,
1100              * and comp cannot be a window.
1101              * comp and container must be on the same GraphicsDevice.
1102              * if comp is container, all sub-components must be on
1103              * same GraphicsDevice.
1104              */
1105             GraphicsConfiguration thisGC = this.getGraphicsConfiguration();
1106 
1107             if (index > component.size() || (index < 0 && index != -1)) {
1108                 throw new IllegalArgumentException(
1109                           "illegal component position");
1110             }
1111             checkAddToSelf(comp);
1112             checkNotAWindow(comp);
1113             /* Reparent the component and tidy up the tree's state. */
1114             if (comp.parent != null) {
1115                 comp.parent.remove(comp);
1116                 if (index > component.size()) {
1117                     throw new IllegalArgumentException("illegal component position");
1118                 }
1119             }
1120             if (thisGC != null) {
1121                 comp.checkGD(thisGC.getDevice().getIDstring());
1122             }
1123 
1124 
1125 
1126             //index == -1 means add to the end.
1127             if (index == -1) {
1128                 component.add(comp);
1129             } else {
1130                 component.add(index, comp);
1131             }
1132             comp.parent = this;
1133             comp.setGraphicsConfiguration(thisGC);
1134 
1135             adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK,
1136                 comp.numListening(AWTEvent.HIERARCHY_EVENT_MASK));
1137             adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
1138                 comp.numListening(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));
1139             adjustDescendants(comp.countHierarchyMembers());
1140 
1141             invalidateIfValid();
1142             if (peer != null) {
1143                 comp.addNotify();
1144             }
1145 
1146             /* Notify the layout manager of the added component. */
1147             if (layoutMgr != null) {
1148                 if (layoutMgr instanceof LayoutManager2) {
1149                     ((LayoutManager2)layoutMgr).addLayoutComponent(comp, constraints);
1150                 } else if (constraints instanceof String) {
1151                     layoutMgr.addLayoutComponent((String)constraints, comp);
1152                 }
1153             }
1154             if (containerListener != null ||
1155                 (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 ||
1156                 Toolkit.enabledOnToolkit(AWTEvent.CONTAINER_EVENT_MASK)) {
1157                 ContainerEvent e = new ContainerEvent(this,
1158                                      ContainerEvent.COMPONENT_ADDED,
1159                                      comp);
1160                 dispatchEvent(e);
1161             }
1162 
1163             comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, comp,
1164                                        this, HierarchyEvent.PARENT_CHANGED,
1165                                        Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK));
1166             if (peer != null && layoutMgr == null && isVisible()) {
1167                 updateCursorImmediately();
1168             }
1169         }
1170     }
1171 
1172     @Override
1173     boolean updateGraphicsData(GraphicsConfiguration gc) {
1174         checkTreeLock();
1175 
1176         boolean ret = super.updateGraphicsData(gc);
1177 
1178         for (Component comp : component) {
1179             if (comp != null) {
1180                 ret |= comp.updateGraphicsData(gc);
1181             }
1182         }
1183         return ret;
1184     }
1185 
1186     /**
1187      * Checks that all Components that this Container contains are on
1188      * the same GraphicsDevice as this Container.  If not, throws an
1189      * IllegalArgumentException.
1190      */
1191     void checkGD(String stringID) {
1192         for (Component comp : component) {
1193             if (comp != null) {
1194                 comp.checkGD(stringID);
1195             }
1196         }
1197     }
1198 
1199     /**
1200      * Removes the component, specified by {@code index},
1201      * from this container.
1202      * This method also notifies the layout manager to remove the
1203      * component from this container's layout via the
1204      * {@code removeLayoutComponent} method.
1205      * <p>
1206      * This method changes layout-related information, and therefore,
1207      * invalidates the component hierarchy. If the container has already been
1208      * displayed, the hierarchy must be validated thereafter in order to
1209      * reflect the changes.
1210      *
1211      *
1212      * @param     index   the index of the component to be removed
1213      * @throws ArrayIndexOutOfBoundsException if {@code index} is not in
1214      *         range {@code [0, getComponentCount()-1]}
1215      * @see #add
1216      * @see #invalidate
1217      * @see #validate
1218      * @see #getComponentCount
1219      * @since 1.1
1220      */
1221     public void remove(int index) {
1222         synchronized (getTreeLock()) {
1223             if (index < 0  || index >= component.size()) {
1224                 throw new ArrayIndexOutOfBoundsException(index);
1225             }
1226             Component comp = component.get(index);
1227             if (peer != null) {
1228                 comp.removeNotify();
1229             }
1230             if (layoutMgr != null) {
1231                 layoutMgr.removeLayoutComponent(comp);
1232             }
1233 
1234             adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK,
1235                 -comp.numListening(AWTEvent.HIERARCHY_EVENT_MASK));
1236             adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
1237                 -comp.numListening(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));
1238             adjustDescendants(-(comp.countHierarchyMembers()));
1239 
1240             comp.parent = null;
1241             component.remove(index);
1242             comp.setGraphicsConfiguration(null);
1243 
1244             invalidateIfValid();
1245             if (containerListener != null ||
1246                 (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 ||
1247                 Toolkit.enabledOnToolkit(AWTEvent.CONTAINER_EVENT_MASK)) {
1248                 ContainerEvent e = new ContainerEvent(this,
1249                                      ContainerEvent.COMPONENT_REMOVED,
1250                                      comp);
1251                 dispatchEvent(e);
1252             }
1253 
1254             comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, comp,
1255                                        this, HierarchyEvent.PARENT_CHANGED,
1256                                        Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK));
1257             if (peer != null && layoutMgr == null && isVisible()) {
1258                 updateCursorImmediately();
1259             }
1260         }
1261     }
1262 
1263     /**
1264      * Removes the specified component from this container.
1265      * This method also notifies the layout manager to remove the
1266      * component from this container's layout via the
1267      * {@code removeLayoutComponent} method.
1268      * <p>
1269      * This method changes layout-related information, and therefore,
1270      * invalidates the component hierarchy. If the container has already been
1271      * displayed, the hierarchy must be validated thereafter in order to
1272      * reflect the changes.
1273      *
1274      * @param comp the component to be removed
1275      * @throws NullPointerException if {@code comp} is {@code null}
1276      * @see #add
1277      * @see #invalidate
1278      * @see #validate
1279      * @see #remove(int)
1280      */
1281     public void remove(Component comp) {
1282         synchronized (getTreeLock()) {
1283             if (comp.parent == this)  {
1284                 int index = component.indexOf(comp);
1285                 if (index >= 0) {
1286                     remove(index);
1287                 }
1288             }
1289         }
1290     }
1291 
1292     /**
1293      * Removes all the components from this container.
1294      * This method also notifies the layout manager to remove the
1295      * components from this container's layout via the
1296      * {@code removeLayoutComponent} method.
1297      * <p>
1298      * This method changes layout-related information, and therefore,
1299      * invalidates the component hierarchy. If the container has already been
1300      * displayed, the hierarchy must be validated thereafter in order to
1301      * reflect the changes.
1302      *
1303      * @see #add
1304      * @see #remove
1305      * @see #invalidate
1306      */
1307     public void removeAll() {
1308         synchronized (getTreeLock()) {
1309             adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK,
1310                                     -listeningChildren);
1311             adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
1312                                     -listeningBoundsChildren);
1313             adjustDescendants(-descendantsCount);
1314 
1315             while (!component.isEmpty()) {
1316                 Component comp = component.remove(component.size()-1);
1317 
1318                 if (peer != null) {
1319                     comp.removeNotify();
1320                 }
1321                 if (layoutMgr != null) {
1322                     layoutMgr.removeLayoutComponent(comp);
1323                 }
1324                 comp.parent = null;
1325                 comp.setGraphicsConfiguration(null);
1326                 if (containerListener != null ||
1327                    (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 ||
1328                     Toolkit.enabledOnToolkit(AWTEvent.CONTAINER_EVENT_MASK)) {
1329                     ContainerEvent e = new ContainerEvent(this,
1330                                      ContainerEvent.COMPONENT_REMOVED,
1331                                      comp);
1332                     dispatchEvent(e);
1333                 }
1334 
1335                 comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED,
1336                                            comp, this,
1337                                            HierarchyEvent.PARENT_CHANGED,
1338                                            Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK));
1339             }
1340             if (peer != null && layoutMgr == null && isVisible()) {
1341                 updateCursorImmediately();
1342             }
1343             invalidateIfValid();
1344         }
1345     }
1346 
1347     // Should only be called while holding tree lock
1348     int numListening(long mask) {
1349         int superListening = super.numListening(mask);
1350 
1351         if (mask == AWTEvent.HIERARCHY_EVENT_MASK) {
1352             if (eventLog.isLoggable(PlatformLogger.Level.FINE)) {
1353                 // Verify listeningChildren is correct
1354                 int sum = 0;
1355                 for (Component comp : component) {
1356                     sum += comp.numListening(mask);
1357                 }
1358                 if (listeningChildren != sum) {
1359                     eventLog.fine("Assertion (listeningChildren == sum) failed");
1360                 }
1361             }
1362             return listeningChildren + superListening;
1363         } else if (mask == AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) {
1364             if (eventLog.isLoggable(PlatformLogger.Level.FINE)) {
1365                 // Verify listeningBoundsChildren is correct
1366                 int sum = 0;
1367                 for (Component comp : component) {
1368                     sum += comp.numListening(mask);
1369                 }
1370                 if (listeningBoundsChildren != sum) {
1371                     eventLog.fine("Assertion (listeningBoundsChildren == sum) failed");
1372                 }
1373             }
1374             return listeningBoundsChildren + superListening;
1375         } else {
1376             // assert false;
1377             if (eventLog.isLoggable(PlatformLogger.Level.FINE)) {
1378                 eventLog.fine("This code must never be reached");
1379             }
1380             return superListening;
1381         }
1382     }
1383 
1384     // Should only be called while holding tree lock
1385     void adjustListeningChildren(long mask, int num) {
1386         if (eventLog.isLoggable(PlatformLogger.Level.FINE)) {
1387             boolean toAssert = (mask == AWTEvent.HIERARCHY_EVENT_MASK ||
1388                                 mask == AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK ||
1389                                 mask == (AWTEvent.HIERARCHY_EVENT_MASK |
1390                                          AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));
1391             if (!toAssert) {
1392                 eventLog.fine("Assertion failed");
1393             }
1394         }
1395 
1396         if (num == 0)
1397             return;
1398 
1399         if ((mask & AWTEvent.HIERARCHY_EVENT_MASK) != 0) {
1400             listeningChildren += num;
1401         }
1402         if ((mask & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) != 0) {
1403             listeningBoundsChildren += num;
1404         }
1405 
1406         adjustListeningChildrenOnParent(mask, num);
1407     }
1408 
1409     // Should only be called while holding tree lock
1410     void adjustDescendants(int num) {
1411         if (num == 0)
1412             return;
1413 
1414         descendantsCount += num;
1415         adjustDescendantsOnParent(num);
1416     }
1417 
1418     // Should only be called while holding tree lock
1419     void adjustDescendantsOnParent(int num) {
1420         if (parent != null) {
1421             parent.adjustDescendants(num);
1422         }
1423     }
1424 
1425     // Should only be called while holding tree lock
1426     int countHierarchyMembers() {
1427         if (log.isLoggable(PlatformLogger.Level.FINE)) {
1428             // Verify descendantsCount is correct
1429             int sum = 0;
1430             for (Component comp : component) {
1431                 sum += comp.countHierarchyMembers();
1432             }
1433             if (descendantsCount != sum) {
1434                 log.fine("Assertion (descendantsCount == sum) failed");
1435             }
1436         }
1437         return descendantsCount + 1;
1438     }
1439 
1440     private int getListenersCount(int id, boolean enabledOnToolkit) {
1441         checkTreeLock();
1442         if (enabledOnToolkit) {
1443             return descendantsCount;
1444         }
1445         switch (id) {
1446           case HierarchyEvent.HIERARCHY_CHANGED:
1447             return listeningChildren;
1448           case HierarchyEvent.ANCESTOR_MOVED:
1449           case HierarchyEvent.ANCESTOR_RESIZED:
1450             return listeningBoundsChildren;
1451           default:
1452             return 0;
1453         }
1454     }
1455 
1456     final int createHierarchyEvents(int id, Component changed,
1457         Container changedParent, long changeFlags, boolean enabledOnToolkit)
1458     {
1459         checkTreeLock();
1460         int listeners = getListenersCount(id, enabledOnToolkit);
1461 
1462         for (int count = listeners, i = 0; count > 0; i++) {
1463             count -= component.get(i).createHierarchyEvents(id, changed,
1464                 changedParent, changeFlags, enabledOnToolkit);
1465         }
1466         return listeners +
1467             super.createHierarchyEvents(id, changed, changedParent,
1468                                         changeFlags, enabledOnToolkit);
1469     }
1470 
1471     final void createChildHierarchyEvents(int id, long changeFlags,
1472         boolean enabledOnToolkit)
1473     {
1474         checkTreeLock();
1475         if (component.isEmpty()) {
1476             return;
1477         }
1478         int listeners = getListenersCount(id, enabledOnToolkit);
1479 
1480         for (int count = listeners, i = 0; count > 0; i++) {
1481             count -= component.get(i).createHierarchyEvents(id, this, parent,
1482                 changeFlags, enabledOnToolkit);
1483         }
1484     }
1485 
1486     /**
1487      * Gets the layout manager for this container.
1488      *
1489      * @see #doLayout
1490      * @see #setLayout
1491      * @return the current layout manager for this container
1492      */
1493     public LayoutManager getLayout() {
1494         return layoutMgr;
1495     }
1496 
1497     /**
1498      * Sets the layout manager for this container.
1499      * <p>
1500      * This method changes layout-related information, and therefore,
1501      * invalidates the component hierarchy.
1502      *
1503      * @param mgr the specified layout manager
1504      * @see #doLayout
1505      * @see #getLayout
1506      * @see #invalidate
1507      */
1508     public void setLayout(LayoutManager mgr) {
1509         layoutMgr = mgr;
1510         invalidateIfValid();
1511     }
1512 
1513     /**
1514      * Causes this container to lay out its components.  Most programs
1515      * should not call this method directly, but should invoke
1516      * the {@code validate} method instead.
1517      * @see LayoutManager#layoutContainer
1518      * @see #setLayout
1519      * @see #validate
1520      * @since 1.1
1521      */
1522     public void doLayout() {
1523         layout();
1524     }
1525 
1526     /**
1527      * @deprecated As of JDK version 1.1,
1528      * replaced by {@code doLayout()}.
1529      */
1530     @Deprecated
1531     public void layout() {
1532         LayoutManager layoutMgr = this.layoutMgr;
1533         if (layoutMgr != null) {
1534             layoutMgr.layoutContainer(this);
1535         }
1536     }
1537 
1538     /**
1539      * Indicates if this container is a <i>validate root</i>.
1540      * <p>
1541      * Layout-related changes, such as bounds of the validate root descendants,
1542      * do not affect the layout of the validate root parent. This peculiarity
1543      * enables the {@code invalidate()} method to stop invalidating the
1544      * component hierarchy when the method encounters a validate root. However,
1545      * to preserve backward compatibility this new optimized behavior is
1546      * enabled only when the {@code java.awt.smartInvalidate} system property
1547      * value is set to {@code true}.
1548      * <p>
1549      * If a component hierarchy contains validate roots and the new optimized
1550      * {@code invalidate()} behavior is enabled, the {@code validate()} method
1551      * must be invoked on the validate root of a previously invalidated
1552      * component to restore the validity of the hierarchy later. Otherwise,
1553      * calling the {@code validate()} method on the top-level container (such
1554      * as a {@code Frame} object) should be used to restore the validity of the
1555      * component hierarchy.
1556      * <p>
1557      * The {@code Window} class and the {@code Applet} class are the validate
1558      * roots in AWT.  Swing introduces more validate roots.
1559      *
1560      * @return whether this container is a validate root
1561      * @see #invalidate
1562      * @see java.awt.Component#invalidate
1563      * @see javax.swing.JComponent#isValidateRoot
1564      * @see javax.swing.JComponent#revalidate
1565      * @since 1.7
1566      */
1567     public boolean isValidateRoot() {
1568         return false;
1569     }
1570 
1571     private static final boolean isJavaAwtSmartInvalidate;
1572     static {
1573         // Don't lazy-read because every app uses invalidate()
1574         isJavaAwtSmartInvalidate = AccessController.doPrivileged(
1575                 new GetBooleanAction("java.awt.smartInvalidate"));
1576     }
1577 
1578     /**
1579      * Invalidates the parent of the container unless the container
1580      * is a validate root.
1581      */
1582     @Override
1583     void invalidateParent() {
1584         if (!isJavaAwtSmartInvalidate || !isValidateRoot()) {
1585             super.invalidateParent();
1586         }
1587     }
1588 
1589     /**
1590      * Invalidates the container.
1591      * <p>
1592      * If the {@code LayoutManager} installed on this container is an instance
1593      * of the {@code LayoutManager2} interface, then
1594      * the {@link LayoutManager2#invalidateLayout(Container)} method is invoked
1595      * on it supplying this {@code Container} as the argument.
1596      * <p>
1597      * Afterwards this method marks this container invalid, and invalidates its
1598      * ancestors. See the {@link Component#invalidate} method for more details.
1599      *
1600      * @see #validate
1601      * @see #layout
1602      * @see LayoutManager2
1603      */
1604     @Override
1605     public void invalidate() {
1606         LayoutManager layoutMgr = this.layoutMgr;
1607         if (layoutMgr instanceof LayoutManager2) {
1608             LayoutManager2 lm = (LayoutManager2) layoutMgr;
1609             lm.invalidateLayout(this);
1610         }
1611         super.invalidate();
1612     }
1613 
1614     /**
1615      * Validates this container and all of its subcomponents.
1616      * <p>
1617      * Validating a container means laying out its subcomponents.
1618      * Layout-related changes, such as setting the bounds of a component, or
1619      * adding a component to the container, invalidate the container
1620      * automatically.  Note that the ancestors of the container may be
1621      * invalidated also (see {@link Component#invalidate} for details.)
1622      * Therefore, to restore the validity of the hierarchy, the {@code
1623      * validate()} method should be invoked on the top-most invalid
1624      * container of the hierarchy.
1625      * <p>
1626      * Validating the container may be a quite time-consuming operation. For
1627      * performance reasons a developer may postpone the validation of the
1628      * hierarchy till a set of layout-related operations completes, e.g. after
1629      * adding all the children to the container.
1630      * <p>
1631      * If this {@code Container} is not valid, this method invokes
1632      * the {@code validateTree} method and marks this {@code Container}
1633      * as valid. Otherwise, no action is performed.
1634      *
1635      * @see #add(java.awt.Component)
1636      * @see #invalidate
1637      * @see Container#isValidateRoot
1638      * @see javax.swing.JComponent#revalidate()
1639      * @see #validateTree
1640      */
1641     public void validate() {
1642         boolean updateCur = false;
1643         synchronized (getTreeLock()) {
1644             if ((!isValid() || descendUnconditionallyWhenValidating)
1645                     && peer != null)
1646             {
1647                 ContainerPeer p = null;
1648                 if (peer instanceof ContainerPeer) {
1649                     p = (ContainerPeer) peer;
1650                 }
1651                 if (p != null) {
1652                     p.beginValidate();
1653                 }
1654                 validateTree();
1655                 if (p != null) {
1656                     p.endValidate();
1657                     // Avoid updating cursor if this is an internal call.
1658                     // See validateUnconditionally() for details.
1659                     if (!descendUnconditionallyWhenValidating) {
1660                         updateCur = isVisible();
1661                     }
1662                 }
1663             }
1664         }
1665         if (updateCur) {
1666             updateCursorImmediately();
1667         }
1668     }
1669 
1670     /**
1671      * Indicates whether valid containers should also traverse their
1672      * children and call the validateTree() method on them.
1673      *
1674      * Synchronization: TreeLock.
1675      *
1676      * The field is allowed to be static as long as the TreeLock itself is
1677      * static.
1678      *
1679      * @see #validateUnconditionally()
1680      */
1681     private static boolean descendUnconditionallyWhenValidating = false;
1682 
1683     /**
1684      * Unconditionally validate the component hierarchy.
1685      */
1686     final void validateUnconditionally() {
1687         boolean updateCur = false;
1688         synchronized (getTreeLock()) {
1689             descendUnconditionallyWhenValidating = true;
1690 
1691             validate();
1692             if (peer instanceof ContainerPeer) {
1693                 updateCur = isVisible();
1694             }
1695 
1696             descendUnconditionallyWhenValidating = false;
1697         }
1698         if (updateCur) {
1699             updateCursorImmediately();
1700         }
1701     }
1702 
1703     /**
1704      * Recursively descends the container tree and recomputes the
1705      * layout for any subtrees marked as needing it (those marked as
1706      * invalid).  Synchronization should be provided by the method
1707      * that calls this one:  {@code validate}.
1708      *
1709      * @see #doLayout
1710      * @see #validate
1711      */
1712     protected void validateTree() {
1713         checkTreeLock();
1714         if (!isValid() || descendUnconditionallyWhenValidating) {
1715             if (peer instanceof ContainerPeer) {
1716                 ((ContainerPeer)peer).beginLayout();
1717             }
1718             if (!isValid()) {
1719                 doLayout();
1720             }
1721             for (int i = 0; i < component.size(); i++) {
1722                 Component comp = component.get(i);
1723                 if (   (comp instanceof Container)
1724                        && !(comp instanceof Window)
1725                        && (!comp.isValid() ||
1726                            descendUnconditionallyWhenValidating))
1727                 {
1728                     ((Container)comp).validateTree();
1729                 } else {
1730                     comp.validate();
1731                 }
1732             }
1733             if (peer instanceof ContainerPeer) {
1734                 ((ContainerPeer)peer).endLayout();
1735             }
1736         }
1737         super.validate();
1738     }
1739 
1740     /**
1741      * Recursively descends the container tree and invalidates all
1742      * contained components.
1743      */
1744     void invalidateTree() {
1745         synchronized (getTreeLock()) {
1746             for (int i = 0; i < component.size(); i++) {
1747                 Component comp = component.get(i);
1748                 if (comp instanceof Container) {
1749                     ((Container)comp).invalidateTree();
1750                 }
1751                 else {
1752                     comp.invalidateIfValid();
1753                 }
1754             }
1755             invalidateIfValid();
1756         }
1757     }
1758 
1759     /**
1760      * Sets the font of this container.
1761      * <p>
1762      * This method changes layout-related information, and therefore,
1763      * invalidates the component hierarchy.
1764      *
1765      * @param f The font to become this container's font.
1766      * @see Component#getFont
1767      * @see #invalidate
1768      * @since 1.0
1769      */
1770     public void setFont(Font f) {
1771         boolean shouldinvalidate = false;
1772 
1773         Font oldfont = getFont();
1774         super.setFont(f);
1775         Font newfont = getFont();
1776         if (newfont != oldfont && (oldfont == null ||
1777                                    !oldfont.equals(newfont))) {
1778             invalidateTree();
1779         }
1780     }
1781 
1782     /**
1783      * Returns the preferred size of this container.  If the preferred size has
1784      * not been set explicitly by {@link Component#setPreferredSize(Dimension)}
1785      * and this {@code Container} has a {@code non-null} {@link LayoutManager},
1786      * then {@link LayoutManager#preferredLayoutSize(Container)}
1787      * is used to calculate the preferred size.
1788      *
1789      * <p>Note: some implementations may cache the value returned from the
1790      * {@code LayoutManager}.  Implementations that cache need not invoke
1791      * {@code preferredLayoutSize} on the {@code LayoutManager} every time
1792      * this method is invoked, rather the {@code LayoutManager} will only
1793      * be queried after the {@code Container} becomes invalid.
1794      *
1795      * @return    an instance of {@code Dimension} that represents
1796      *                the preferred size of this container.
1797      * @see       #getMinimumSize
1798      * @see       #getMaximumSize
1799      * @see       #getLayout
1800      * @see       LayoutManager#preferredLayoutSize(Container)
1801      * @see       Component#getPreferredSize
1802      */
1803     public Dimension getPreferredSize() {
1804         return preferredSize();
1805     }
1806 
1807     /**
1808      * @deprecated As of JDK version 1.1,
1809      * replaced by {@code getPreferredSize()}.
1810      */
1811     @Deprecated
1812     public Dimension preferredSize() {
1813         /* Avoid grabbing the lock if a reasonable cached size value
1814          * is available.
1815          */
1816         Dimension dim = prefSize;
1817         if (dim == null || !(isPreferredSizeSet() || isValid())) {
1818             synchronized (getTreeLock()) {
1819                 prefSize = (layoutMgr != null) ?
1820                     layoutMgr.preferredLayoutSize(this) :
1821                     super.preferredSize();
1822                 dim = prefSize;
1823             }
1824         }
1825         if (dim != null){
1826             return new Dimension(dim);
1827         }
1828         else{
1829             return dim;
1830         }
1831     }
1832 
1833     /**
1834      * Returns the minimum size of this container.  If the minimum size has
1835      * not been set explicitly by {@link Component#setMinimumSize(Dimension)}
1836      * and this {@code Container} has a {@code non-null} {@link LayoutManager},
1837      * then {@link LayoutManager#minimumLayoutSize(Container)}
1838      * is used to calculate the minimum size.
1839      *
1840      * <p>Note: some implementations may cache the value returned from the
1841      * {@code LayoutManager}.  Implementations that cache need not invoke
1842      * {@code minimumLayoutSize} on the {@code LayoutManager} every time
1843      * this method is invoked, rather the {@code LayoutManager} will only
1844      * be queried after the {@code Container} becomes invalid.
1845      *
1846      * @return    an instance of {@code Dimension} that represents
1847      *                the minimum size of this container.
1848      * @see       #getPreferredSize
1849      * @see       #getMaximumSize
1850      * @see       #getLayout
1851      * @see       LayoutManager#minimumLayoutSize(Container)
1852      * @see       Component#getMinimumSize
1853      * @since     1.1
1854      */
1855     public Dimension getMinimumSize() {
1856         return minimumSize();
1857     }
1858 
1859     /**
1860      * @deprecated As of JDK version 1.1,
1861      * replaced by {@code getMinimumSize()}.
1862      */
1863     @Deprecated
1864     public Dimension minimumSize() {
1865         /* Avoid grabbing the lock if a reasonable cached size value
1866          * is available.
1867          */
1868         Dimension dim = minSize;
1869         if (dim == null || !(isMinimumSizeSet() || isValid())) {
1870             synchronized (getTreeLock()) {
1871                 minSize = (layoutMgr != null) ?
1872                     layoutMgr.minimumLayoutSize(this) :
1873                     super.minimumSize();
1874                 dim = minSize;
1875             }
1876         }
1877         if (dim != null){
1878             return new Dimension(dim);
1879         }
1880         else{
1881             return dim;
1882         }
1883     }
1884 
1885     /**
1886      * Returns the maximum size of this container.  If the maximum size has
1887      * not been set explicitly by {@link Component#setMaximumSize(Dimension)}
1888      * and the {@link LayoutManager} installed on this {@code Container}
1889      * is an instance of {@link LayoutManager2}, then
1890      * {@link LayoutManager2#maximumLayoutSize(Container)}
1891      * is used to calculate the maximum size.
1892      *
1893      * <p>Note: some implementations may cache the value returned from the
1894      * {@code LayoutManager2}.  Implementations that cache need not invoke
1895      * {@code maximumLayoutSize} on the {@code LayoutManager2} every time
1896      * this method is invoked, rather the {@code LayoutManager2} will only
1897      * be queried after the {@code Container} becomes invalid.
1898      *
1899      * @return    an instance of {@code Dimension} that represents
1900      *                the maximum size of this container.
1901      * @see       #getPreferredSize
1902      * @see       #getMinimumSize
1903      * @see       #getLayout
1904      * @see       LayoutManager2#maximumLayoutSize(Container)
1905      * @see       Component#getMaximumSize
1906      */
1907     public Dimension getMaximumSize() {
1908         /* Avoid grabbing the lock if a reasonable cached size value
1909          * is available.
1910          */
1911         Dimension dim = maxSize;
1912         if (dim == null || !(isMaximumSizeSet() || isValid())) {
1913             synchronized (getTreeLock()) {
1914                if (layoutMgr instanceof LayoutManager2) {
1915                     LayoutManager2 lm = (LayoutManager2) layoutMgr;
1916                     maxSize = lm.maximumLayoutSize(this);
1917                } else {
1918                     maxSize = super.getMaximumSize();
1919                }
1920                dim = maxSize;
1921             }
1922         }
1923         if (dim != null){
1924             return new Dimension(dim);
1925         }
1926         else{
1927             return dim;
1928         }
1929     }
1930 
1931     /**
1932      * Returns the alignment along the x axis.  This specifies how
1933      * the component would like to be aligned relative to other
1934      * components.  The value should be a number between 0 and 1
1935      * where 0 represents alignment along the origin, 1 is aligned
1936      * the furthest away from the origin, 0.5 is centered, etc.
1937      */
1938     public float getAlignmentX() {
1939         float xAlign;
1940         if (layoutMgr instanceof LayoutManager2) {
1941             synchronized (getTreeLock()) {
1942                 LayoutManager2 lm = (LayoutManager2) layoutMgr;
1943                 xAlign = lm.getLayoutAlignmentX(this);
1944             }
1945         } else {
1946             xAlign = super.getAlignmentX();
1947         }
1948         return xAlign;
1949     }
1950 
1951     /**
1952      * Returns the alignment along the y axis.  This specifies how
1953      * the component would like to be aligned relative to other
1954      * components.  The value should be a number between 0 and 1
1955      * where 0 represents alignment along the origin, 1 is aligned
1956      * the furthest away from the origin, 0.5 is centered, etc.
1957      */
1958     public float getAlignmentY() {
1959         float yAlign;
1960         if (layoutMgr instanceof LayoutManager2) {
1961             synchronized (getTreeLock()) {
1962                 LayoutManager2 lm = (LayoutManager2) layoutMgr;
1963                 yAlign = lm.getLayoutAlignmentY(this);
1964             }
1965         } else {
1966             yAlign = super.getAlignmentY();
1967         }
1968         return yAlign;
1969     }
1970 
1971     /**
1972      * Paints the container. This forwards the paint to any lightweight
1973      * components that are children of this container. If this method is
1974      * reimplemented, super.paint(g) should be called so that lightweight
1975      * components are properly rendered. If a child component is entirely
1976      * clipped by the current clipping setting in g, paint() will not be
1977      * forwarded to that child.
1978      *
1979      * @param g the specified Graphics window
1980      * @see   Component#update(Graphics)
1981      */
1982     public void paint(Graphics g) {
1983         if (isShowing()) {
1984             synchronized (getObjectLock()) {
1985                 if (printing) {
1986                     if (printingThreads.contains(Thread.currentThread())) {
1987                         return;
1988                     }
1989                 }
1990             }
1991 
1992             // The container is showing on screen and
1993             // this paint() is not called from print().
1994             // Paint self and forward the paint to lightweight subcomponents.
1995 
1996             // super.paint(); -- Don't bother, since it's a NOP.
1997 
1998             GraphicsCallback.PaintCallback.getInstance().
1999                 runComponents(getComponentsSync(), g, GraphicsCallback.LIGHTWEIGHTS);
2000         }
2001     }
2002 
2003     /**
2004      * Updates the container.  This forwards the update to any lightweight
2005      * components that are children of this container.  If this method is
2006      * reimplemented, super.update(g) should be called so that lightweight
2007      * components are properly rendered.  If a child component is entirely
2008      * clipped by the current clipping setting in g, update() will not be
2009      * forwarded to that child.
2010      *
2011      * @param g the specified Graphics window
2012      * @see   Component#update(Graphics)
2013      */
2014     public void update(Graphics g) {
2015         if (isShowing()) {
2016             if (! (peer instanceof LightweightPeer)) {
2017                 g.clearRect(0, 0, width, height);
2018             }
2019             paint(g);
2020         }
2021     }
2022 
2023     /**
2024      * Prints the container. This forwards the print to any lightweight
2025      * components that are children of this container. If this method is
2026      * reimplemented, super.print(g) should be called so that lightweight
2027      * components are properly rendered. If a child component is entirely
2028      * clipped by the current clipping setting in g, print() will not be
2029      * forwarded to that child.
2030      *
2031      * @param g the specified Graphics window
2032      * @see   Component#update(Graphics)
2033      */
2034     public void print(Graphics g) {
2035         if (isShowing()) {
2036             Thread t = Thread.currentThread();
2037             try {
2038                 synchronized (getObjectLock()) {
2039                     if (printingThreads == null) {
2040                         printingThreads = new HashSet<>();
2041                     }
2042                     printingThreads.add(t);
2043                     printing = true;
2044                 }
2045                 super.print(g);  // By default, Component.print() calls paint()
2046             } finally {
2047                 synchronized (getObjectLock()) {
2048                     printingThreads.remove(t);
2049                     printing = !printingThreads.isEmpty();
2050                 }
2051             }
2052 
2053             GraphicsCallback.PrintCallback.getInstance().
2054                 runComponents(getComponentsSync(), g, GraphicsCallback.LIGHTWEIGHTS);
2055         }
2056     }
2057 
2058     /**
2059      * Paints each of the components in this container.
2060      * @param     g   the graphics context.
2061      * @see       Component#paint
2062      * @see       Component#paintAll
2063      */
2064     public void paintComponents(Graphics g) {
2065         if (isShowing()) {
2066             GraphicsCallback.PaintAllCallback.getInstance().
2067                 runComponents(getComponentsSync(), g, GraphicsCallback.TWO_PASSES);
2068         }
2069     }
2070 
2071     /**
2072      * Simulates the peer callbacks into java.awt for printing of
2073      * lightweight Containers.
2074      * @param     g   the graphics context to use for printing.
2075      * @see       Component#printAll
2076      * @see       #printComponents
2077      */
2078     void lightweightPaint(Graphics g) {
2079         super.lightweightPaint(g);
2080         paintHeavyweightComponents(g);
2081     }
2082 
2083     /**
2084      * Prints all the heavyweight subcomponents.
2085      */
2086     void paintHeavyweightComponents(Graphics g) {
2087         if (isShowing()) {
2088             GraphicsCallback.PaintHeavyweightComponentsCallback.getInstance().
2089                 runComponents(getComponentsSync(), g,
2090                               GraphicsCallback.LIGHTWEIGHTS | GraphicsCallback.HEAVYWEIGHTS);
2091         }
2092     }
2093 
2094     /**
2095      * Prints each of the components in this container.
2096      * @param     g   the graphics context.
2097      * @see       Component#print
2098      * @see       Component#printAll
2099      */
2100     public void printComponents(Graphics g) {
2101         if (isShowing()) {
2102             GraphicsCallback.PrintAllCallback.getInstance().
2103                 runComponents(getComponentsSync(), g, GraphicsCallback.TWO_PASSES);
2104         }
2105     }
2106 
2107     /**
2108      * Simulates the peer callbacks into java.awt for printing of
2109      * lightweight Containers.
2110      * @param     g   the graphics context to use for printing.
2111      * @see       Component#printAll
2112      * @see       #printComponents
2113      */
2114     void lightweightPrint(Graphics g) {
2115         super.lightweightPrint(g);
2116         printHeavyweightComponents(g);
2117     }
2118 
2119     /**
2120      * Prints all the heavyweight subcomponents.
2121      */
2122     void printHeavyweightComponents(Graphics g) {
2123         if (isShowing()) {
2124             GraphicsCallback.PrintHeavyweightComponentsCallback.getInstance().
2125                 runComponents(getComponentsSync(), g,
2126                               GraphicsCallback.LIGHTWEIGHTS | GraphicsCallback.HEAVYWEIGHTS);
2127         }
2128     }
2129 
2130     /**
2131      * Adds the specified container listener to receive container events
2132      * from this container.
2133      * If l is null, no exception is thrown and no action is performed.
2134      * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
2135      * >AWT Threading Issues</a> for details on AWT's threading model.
2136      *
2137      * @param    l the container listener
2138      *
2139      * @see #removeContainerListener
2140      * @see #getContainerListeners
2141      */
2142     public synchronized void addContainerListener(ContainerListener l) {
2143         if (l == null) {
2144             return;
2145         }
2146         containerListener = AWTEventMulticaster.add(containerListener, l);
2147         newEventsOnly = true;
2148     }
2149 
2150     /**
2151      * Removes the specified container listener so it no longer receives
2152      * container events from this container.
2153      * If l is null, no exception is thrown and no action is performed.
2154      * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
2155      * >AWT Threading Issues</a> for details on AWT's threading model.
2156      *
2157      * @param   l the container listener
2158      *
2159      * @see #addContainerListener
2160      * @see #getContainerListeners
2161      */
2162     public synchronized void removeContainerListener(ContainerListener l) {
2163         if (l == null) {
2164             return;
2165         }
2166         containerListener = AWTEventMulticaster.remove(containerListener, l);
2167     }
2168 
2169     /**
2170      * Returns an array of all the container listeners
2171      * registered on this container.
2172      *
2173      * @return all of this container's {@code ContainerListener}s
2174      *         or an empty array if no container
2175      *         listeners are currently registered
2176      *
2177      * @see #addContainerListener
2178      * @see #removeContainerListener
2179      * @since 1.4
2180      */
2181     public synchronized ContainerListener[] getContainerListeners() {
2182         return getListeners(ContainerListener.class);
2183     }
2184 
2185     /**
2186      * Returns an array of all the objects currently registered
2187      * as <code><em>Foo</em>Listener</code>s
2188      * upon this {@code Container}.
2189      * <code><em>Foo</em>Listener</code>s are registered using the
2190      * <code>add<em>Foo</em>Listener</code> method.
2191      *
2192      * <p>
2193      * You can specify the {@code listenerType} argument
2194      * with a class literal, such as
2195      * <code><em>Foo</em>Listener.class</code>.
2196      * For example, you can query a
2197      * {@code Container c}
2198      * for its container listeners with the following code:
2199      *
2200      * <pre>ContainerListener[] cls = (ContainerListener[])(c.getListeners(ContainerListener.class));</pre>
2201      *
2202      * If no such listeners exist, this method returns an empty array.
2203      *
2204      * @param listenerType the type of listeners requested; this parameter
2205      *          should specify an interface that descends from
2206      *          {@code java.util.EventListener}
2207      * @return an array of all objects registered as
2208      *          <code><em>Foo</em>Listener</code>s on this container,
2209      *          or an empty array if no such listeners have been added
2210      * @exception ClassCastException if {@code listenerType}
2211      *          doesn't specify a class or interface that implements
2212      *          {@code java.util.EventListener}
2213      * @exception NullPointerException if {@code listenerType} is {@code null}
2214      *
2215      * @see #getContainerListeners
2216      *
2217      * @since 1.3
2218      */
2219     public <T extends EventListener> T[] getListeners(Class<T> listenerType) {
2220         EventListener l = null;
2221         if  (listenerType == ContainerListener.class) {
2222             l = containerListener;
2223         } else {
2224             return super.getListeners(listenerType);
2225         }
2226         return AWTEventMulticaster.getListeners(l, listenerType);
2227     }
2228 
2229     // REMIND: remove when filtering is done at lower level
2230     boolean eventEnabled(AWTEvent e) {
2231         int id = e.getID();
2232 
2233         if (id == ContainerEvent.COMPONENT_ADDED ||
2234             id == ContainerEvent.COMPONENT_REMOVED) {
2235             if ((eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 ||
2236                 containerListener != null) {
2237                 return true;
2238             }
2239             return false;
2240         }
2241         return super.eventEnabled(e);
2242     }
2243 
2244     /**
2245      * Processes events on this container. If the event is a
2246      * {@code ContainerEvent}, it invokes the
2247      * {@code processContainerEvent} method, else it invokes
2248      * its superclass's {@code processEvent}.
2249      * <p>Note that if the event parameter is {@code null}
2250      * the behavior is unspecified and may result in an
2251      * exception.
2252      *
2253      * @param e the event
2254      */
2255     protected void processEvent(AWTEvent e) {
2256         if (e instanceof ContainerEvent) {
2257             processContainerEvent((ContainerEvent)e);
2258             return;
2259         }
2260         super.processEvent(e);
2261     }
2262 
2263     /**
2264      * Processes container events occurring on this container by
2265      * dispatching them to any registered ContainerListener objects.
2266      * NOTE: This method will not be called unless container events
2267      * are enabled for this component; this happens when one of the
2268      * following occurs:
2269      * <ul>
2270      * <li>A ContainerListener object is registered via
2271      *     {@code addContainerListener}
2272      * <li>Container events are enabled via {@code enableEvents}
2273      * </ul>
2274      * <p>Note that if the event parameter is {@code null}
2275      * the behavior is unspecified and may result in an
2276      * exception.
2277      *
2278      * @param e the container event
2279      * @see Component#enableEvents
2280      */
2281     protected void processContainerEvent(ContainerEvent e) {
2282         ContainerListener listener = containerListener;
2283         if (listener != null) {
2284             switch(e.getID()) {
2285               case ContainerEvent.COMPONENT_ADDED:
2286                 listener.componentAdded(e);
2287                 break;
2288               case ContainerEvent.COMPONENT_REMOVED:
2289                 listener.componentRemoved(e);
2290                 break;
2291             }
2292         }
2293     }
2294 
2295     /*
2296      * Dispatches an event to this component or one of its sub components.
2297      * Create ANCESTOR_RESIZED and ANCESTOR_MOVED events in response to
2298      * COMPONENT_RESIZED and COMPONENT_MOVED events. We have to do this
2299      * here instead of in processComponentEvent because ComponentEvents
2300      * may not be enabled for this Container.
2301      * @param e the event
2302      */
2303     void dispatchEventImpl(AWTEvent e) {
2304         if ((dispatcher != null) && dispatcher.dispatchEvent(e)) {
2305             // event was sent to a lightweight component.  The
2306             // native-produced event sent to the native container
2307             // must be properly disposed of by the peer, so it
2308             // gets forwarded.  If the native host has been removed
2309             // as a result of the sending the lightweight event,
2310             // the peer reference will be null.
2311             e.consume();
2312             if (peer != null) {
2313                 peer.handleEvent(e);
2314             }
2315             return;
2316         }
2317 
2318         super.dispatchEventImpl(e);
2319 
2320         synchronized (getTreeLock()) {
2321             switch (e.getID()) {
2322               case ComponentEvent.COMPONENT_RESIZED:
2323                 createChildHierarchyEvents(HierarchyEvent.ANCESTOR_RESIZED, 0,
2324                                            Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));
2325                 break;
2326               case ComponentEvent.COMPONENT_MOVED:
2327                 createChildHierarchyEvents(HierarchyEvent.ANCESTOR_MOVED, 0,
2328                                        Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));
2329                 break;
2330               default:
2331                 break;
2332             }
2333         }
2334     }
2335 
2336     /*
2337      * Dispatches an event to this component, without trying to forward
2338      * it to any subcomponents
2339      * @param e the event
2340      */
2341     void dispatchEventToSelf(AWTEvent e) {
2342         super.dispatchEventImpl(e);
2343     }
2344 
2345     /**
2346      * Fetches the top-most (deepest) lightweight component that is interested
2347      * in receiving mouse events.
2348      */
2349     Component getMouseEventTarget(int x, int y, boolean includeSelf) {
2350         return getMouseEventTarget(x, y, includeSelf,
2351                                    MouseEventTargetFilter.FILTER,
2352                                    !SEARCH_HEAVYWEIGHTS);
2353     }
2354 
2355     /**
2356      * Fetches the top-most (deepest) component to receive SunDropTargetEvents.
2357      */
2358     Component getDropTargetEventTarget(int x, int y, boolean includeSelf) {
2359         return getMouseEventTarget(x, y, includeSelf,
2360                                    DropTargetEventTargetFilter.FILTER,
2361                                    SEARCH_HEAVYWEIGHTS);
2362     }
2363 
2364     /**
2365      * A private version of getMouseEventTarget which has two additional
2366      * controllable behaviors. This method searches for the top-most
2367      * descendant of this container that contains the given coordinates
2368      * and is accepted by the given filter. The search will be constrained to
2369      * lightweight descendants if the last argument is {@code false}.
2370      *
2371      * @param filter EventTargetFilter instance to determine whether the
2372      *        given component is a valid target for this event.
2373      * @param searchHeavyweights if {@code false}, the method
2374      *        will bypass heavyweight components during the search.
2375      */
2376     private Component getMouseEventTarget(int x, int y, boolean includeSelf,
2377                                           EventTargetFilter filter,
2378                                           boolean searchHeavyweights) {
2379         Component comp = null;
2380         if (searchHeavyweights) {
2381             comp = getMouseEventTargetImpl(x, y, includeSelf, filter,
2382                                            SEARCH_HEAVYWEIGHTS,
2383                                            searchHeavyweights);
2384         }
2385 
2386         if (comp == null || comp == this) {
2387             comp = getMouseEventTargetImpl(x, y, includeSelf, filter,
2388                                            !SEARCH_HEAVYWEIGHTS,
2389                                            searchHeavyweights);
2390         }
2391 
2392         return comp;
2393     }
2394 
2395     /**
2396      * A private version of getMouseEventTarget which has three additional
2397      * controllable behaviors. This method searches for the top-most
2398      * descendant of this container that contains the given coordinates
2399      * and is accepted by the given filter. The search will be constrained to
2400      * descendants of only lightweight children or only heavyweight children
2401      * of this container depending on searchHeavyweightChildren. The search will
2402      * be constrained to only lightweight descendants of the searched children
2403      * of this container if searchHeavyweightDescendants is {@code false}.
2404      *
2405      * @param filter EventTargetFilter instance to determine whether the
2406      *        selected component is a valid target for this event.
2407      * @param searchHeavyweightChildren if {@code true}, the method
2408      *        will bypass immediate lightweight children during the search.
2409      *        If {@code false}, the methods will bypass immediate
2410      *        heavyweight children during the search.
2411      * @param searchHeavyweightDescendants if {@code false}, the method
2412      *        will bypass heavyweight descendants which are not immediate
2413      *        children during the search. If {@code true}, the method
2414      *        will traverse both lightweight and heavyweight descendants during
2415      *        the search.
2416      */
2417     private Component getMouseEventTargetImpl(int x, int y, boolean includeSelf,
2418                                          EventTargetFilter filter,
2419                                          boolean searchHeavyweightChildren,
2420                                          boolean searchHeavyweightDescendants) {
2421         synchronized (getTreeLock()) {
2422 
2423             for (int i = 0; i < component.size(); i++) {
2424                 Component comp = component.get(i);
2425                 if (comp != null && comp.visible &&
2426                     ((!searchHeavyweightChildren &&
2427                       comp.peer instanceof LightweightPeer) ||
2428                      (searchHeavyweightChildren &&
2429                       !(comp.peer instanceof LightweightPeer))) &&
2430                     comp.contains(x - comp.x, y - comp.y)) {
2431 
2432                     // found a component that intersects the point, see if there
2433                     // is a deeper possibility.
2434                     if (comp instanceof Container) {
2435                         Container child = (Container) comp;
2436                         Component deeper = child.getMouseEventTarget(
2437                                 x - child.x,
2438                                 y - child.y,
2439                                 includeSelf,
2440                                 filter,
2441                                 searchHeavyweightDescendants);
2442                         if (deeper != null) {
2443                             return deeper;
2444                         }
2445                     } else {
2446                         if (filter.accept(comp)) {
2447                             // there isn't a deeper target, but this component
2448                             // is a target
2449                             return comp;
2450                         }
2451                     }
2452                 }
2453             }
2454 
2455             boolean isPeerOK;
2456             boolean isMouseOverMe;
2457 
2458             isPeerOK = (peer instanceof LightweightPeer) || includeSelf;
2459             isMouseOverMe = contains(x,y);
2460 
2461             // didn't find a child target, return this component if it's
2462             // a possible target
2463             if (isMouseOverMe && isPeerOK && filter.accept(this)) {
2464                 return this;
2465             }
2466             // no possible target
2467             return null;
2468         }
2469     }
2470 
2471     static interface EventTargetFilter {
2472         boolean accept(final Component comp);
2473     }
2474 
2475     static class MouseEventTargetFilter implements EventTargetFilter {
2476         static final EventTargetFilter FILTER = new MouseEventTargetFilter();
2477 
2478         private MouseEventTargetFilter() {}
2479 
2480         public boolean accept(final Component comp) {
2481             return (comp.eventMask & AWTEvent.MOUSE_MOTION_EVENT_MASK) != 0
2482                 || (comp.eventMask & AWTEvent.MOUSE_EVENT_MASK) != 0
2483                 || (comp.eventMask & AWTEvent.MOUSE_WHEEL_EVENT_MASK) != 0
2484                 || comp.mouseListener != null
2485                 || comp.mouseMotionListener != null
2486                 || comp.mouseWheelListener != null;
2487         }
2488     }
2489 
2490     static class DropTargetEventTargetFilter implements EventTargetFilter {
2491         static final EventTargetFilter FILTER = new DropTargetEventTargetFilter();
2492 
2493         private DropTargetEventTargetFilter() {}
2494 
2495         public boolean accept(final Component comp) {
2496             DropTarget dt = comp.getDropTarget();
2497             return dt != null && dt.isActive();
2498         }
2499     }
2500 
2501     /**
2502      * This is called by lightweight components that want the containing
2503      * windowed parent to enable some kind of events on their behalf.
2504      * This is needed for events that are normally only dispatched to
2505      * windows to be accepted so that they can be forwarded downward to
2506      * the lightweight component that has enabled them.
2507      */
2508     void proxyEnableEvents(long events) {
2509         if (peer instanceof LightweightPeer) {
2510             // this container is lightweight.... continue sending it
2511             // upward.
2512             if (parent != null) {
2513                 parent.proxyEnableEvents(events);
2514             }
2515         } else {
2516             // This is a native container, so it needs to host
2517             // one of it's children.  If this function is called before
2518             // a peer has been created we don't yet have a dispatcher
2519             // because it has not yet been determined if this instance
2520             // is lightweight.
2521             if (dispatcher != null) {
2522                 dispatcher.enableEvents(events);
2523             }
2524         }
2525     }
2526 
2527     /**
2528      * @deprecated As of JDK version 1.1,
2529      * replaced by {@code dispatchEvent(AWTEvent e)}
2530      */
2531     @Deprecated
2532     public void deliverEvent(Event e) {
2533         Component comp = getComponentAt(e.x, e.y);
2534         if ((comp != null) && (comp != this)) {
2535             e.translate(-comp.x, -comp.y);
2536             comp.deliverEvent(e);
2537         } else {
2538             postEvent(e);
2539         }
2540     }
2541 
2542     /**
2543      * Locates the component that contains the x,y position.  The
2544      * top-most child component is returned in the case where there
2545      * is overlap in the components.  This is determined by finding
2546      * the component closest to the index 0 that claims to contain
2547      * the given point via Component.contains(), except that Components
2548      * which have native peers take precedence over those which do not
2549      * (i.e., lightweight Components).
2550      *
2551      * @param x the <i>x</i> coordinate
2552      * @param y the <i>y</i> coordinate
2553      * @return null if the component does not contain the position.
2554      * If there is no child component at the requested point and the
2555      * point is within the bounds of the container the container itself
2556      * is returned; otherwise the top-most child is returned.
2557      * @see Component#contains
2558      * @since 1.1
2559      */
2560     public Component getComponentAt(int x, int y) {
2561         return locate(x, y);
2562     }
2563 
2564     /**
2565      * @deprecated As of JDK version 1.1,
2566      * replaced by {@code getComponentAt(int, int)}.
2567      */
2568     @Deprecated
2569     public Component locate(int x, int y) {
2570         if (!contains(x, y)) {
2571             return null;
2572         }
2573         Component lightweight = null;
2574         synchronized (getTreeLock()) {
2575             // Optimized version of two passes:
2576             // see comment in sun.awt.SunGraphicsCallback
2577             for (final Component comp : component) {
2578                 if (comp.contains(x - comp.x, y - comp.y)) {
2579                     if (!comp.isLightweight()) {
2580                         // return heavyweight component as soon as possible
2581                         return comp;
2582                     }
2583                     if (lightweight == null) {
2584                         // save and return later the first lightweight component
2585                         lightweight = comp;
2586                     }
2587                 }
2588             }
2589         }
2590         return lightweight != null ? lightweight : this;
2591     }
2592 
2593     /**
2594      * Gets the component that contains the specified point.
2595      * @param      p   the point.
2596      * @return     returns the component that contains the point,
2597      *                 or {@code null} if the component does
2598      *                 not contain the point.
2599      * @see        Component#contains
2600      * @since      1.1
2601      */
2602     public Component getComponentAt(Point p) {
2603         return getComponentAt(p.x, p.y);
2604     }
2605 
2606     /**
2607      * Returns the position of the mouse pointer in this {@code Container}'s
2608      * coordinate space if the {@code Container} is under the mouse pointer,
2609      * otherwise returns {@code null}.
2610      * This method is similar to {@link Component#getMousePosition()} with the exception
2611      * that it can take the {@code Container}'s children into account.
2612      * If {@code allowChildren} is {@code false}, this method will return
2613      * a non-null value only if the mouse pointer is above the {@code Container}
2614      * directly, not above the part obscured by children.
2615      * If {@code allowChildren} is {@code true}, this method returns
2616      * a non-null value if the mouse pointer is above {@code Container} or any
2617      * of its descendants.
2618      *
2619      * @exception HeadlessException if GraphicsEnvironment.isHeadless() returns true
2620      * @param     allowChildren true if children should be taken into account
2621      * @see       Component#getMousePosition
2622      * @return    mouse coordinates relative to this {@code Component}, or null
2623      * @since     1.5
2624      */
2625     public Point getMousePosition(boolean allowChildren) throws HeadlessException {
2626         if (GraphicsEnvironment.isHeadless()) {
2627             throw new HeadlessException();
2628         }
2629         PointerInfo pi = java.security.AccessController.doPrivileged(
2630             new java.security.PrivilegedAction<PointerInfo>() {
2631                 public PointerInfo run() {
2632                     return MouseInfo.getPointerInfo();
2633                 }
2634             }
2635         );
2636         synchronized (getTreeLock()) {
2637             Component inTheSameWindow = findUnderMouseInWindow(pi);
2638             if (isSameOrAncestorOf(inTheSameWindow, allowChildren)) {
2639                 return  pointRelativeToComponent(pi.getLocation());
2640             }
2641             return null;
2642         }
2643     }
2644 
2645     boolean isSameOrAncestorOf(Component comp, boolean allowChildren) {
2646         return this == comp || (allowChildren && isParentOf(comp));
2647     }
2648 
2649     /**
2650      * Locates the visible child component that contains the specified
2651      * position.  The top-most child component is returned in the case
2652      * where there is overlap in the components.  If the containing child
2653      * component is a Container, this method will continue searching for
2654      * the deepest nested child component.  Components which are not
2655      * visible are ignored during the search.<p>
2656      *
2657      * The findComponentAt method is different from getComponentAt in
2658      * that getComponentAt only searches the Container's immediate
2659      * children; if the containing component is a Container,
2660      * findComponentAt will search that child to find a nested component.
2661      *
2662      * @param x the <i>x</i> coordinate
2663      * @param y the <i>y</i> coordinate
2664      * @return null if the component does not contain the position.
2665      * If there is no child component at the requested point and the
2666      * point is within the bounds of the container the container itself
2667      * is returned.
2668      * @see Component#contains
2669      * @see #getComponentAt
2670      * @since 1.2
2671      */
2672     public Component findComponentAt(int x, int y) {
2673         return findComponentAt(x, y, true);
2674     }
2675 
2676     /**
2677      * Private version of findComponentAt which has a controllable
2678      * behavior. Setting 'ignoreEnabled' to 'false' bypasses disabled
2679      * Components during the search. This behavior is used by the
2680      * lightweight cursor support in sun.awt.GlobalCursorManager.
2681      *
2682      * The addition of this feature is temporary, pending the
2683      * adoption of new, public API which exports this feature.
2684      */
2685     final Component findComponentAt(int x, int y, boolean ignoreEnabled) {
2686         synchronized (getTreeLock()) {
2687             if (isRecursivelyVisible()){
2688                 return findComponentAtImpl(x, y, ignoreEnabled);
2689             }
2690         }
2691         return null;
2692     }
2693 
2694     final Component findComponentAtImpl(int x, int y, boolean ignoreEnabled) {
2695         // checkTreeLock(); commented for a performance reason
2696 
2697         if (!(contains(x, y) && visible && (ignoreEnabled || enabled))) {
2698             return null;
2699         }
2700         Component lightweight = null;
2701         // Optimized version of two passes:
2702         // see comment in sun.awt.SunGraphicsCallback
2703         for (final Component comp : component) {
2704             final int x1 = x - comp.x;
2705             final int y1 = y - comp.y;
2706             if (!comp.contains(x1, y1)) {
2707                 continue; // fast path
2708             }
2709             if (!comp.isLightweight()) {
2710                 final Component child = getChildAt(comp, x1, y1, ignoreEnabled);
2711                 if (child != null) {
2712                     // return heavyweight component as soon as possible
2713                     return child;
2714                 }
2715             } else {
2716                 if (lightweight == null) {
2717                     // save and return later the first lightweight component
2718                     lightweight = getChildAt(comp, x1, y1, ignoreEnabled);
2719                 }
2720             }
2721         }
2722         return lightweight != null ? lightweight : this;
2723     }
2724 
2725     /**
2726      * Helper method for findComponentAtImpl. Finds a child component using
2727      * findComponentAtImpl for Container and getComponentAt for Component.
2728      */
2729     private static Component getChildAt(Component comp, int x, int y,
2730                                         boolean ignoreEnabled) {
2731         if (comp instanceof Container) {
2732             comp = ((Container) comp).findComponentAtImpl(x, y,
2733                                                           ignoreEnabled);
2734         } else {
2735             comp = comp.getComponentAt(x, y);
2736         }
2737         if (comp != null && comp.visible &&
2738                 (ignoreEnabled || comp.enabled)) {
2739             return comp;
2740         }
2741         return null;
2742     }
2743 
2744     /**
2745      * Locates the visible child component that contains the specified
2746      * point.  The top-most child component is returned in the case
2747      * where there is overlap in the components.  If the containing child
2748      * component is a Container, this method will continue searching for
2749      * the deepest nested child component.  Components which are not
2750      * visible are ignored during the search.<p>
2751      *
2752      * The findComponentAt method is different from getComponentAt in
2753      * that getComponentAt only searches the Container's immediate
2754      * children; if the containing component is a Container,
2755      * findComponentAt will search that child to find a nested component.
2756      *
2757      * @param      p   the point.
2758      * @return null if the component does not contain the position.
2759      * If there is no child component at the requested point and the
2760      * point is within the bounds of the container the container itself
2761      * is returned.
2762      * @throws NullPointerException if {@code p} is {@code null}
2763      * @see Component#contains
2764      * @see #getComponentAt
2765      * @since 1.2
2766      */
2767     public Component findComponentAt(Point p) {
2768         return findComponentAt(p.x, p.y);
2769     }
2770 
2771     /**
2772      * Makes this Container displayable by connecting it to
2773      * a native screen resource.  Making a container displayable will
2774      * cause all of its children to be made displayable.
2775      * This method is called internally by the toolkit and should
2776      * not be called directly by programs.
2777      * @see Component#isDisplayable
2778      * @see #removeNotify
2779      */
2780     public void addNotify() {
2781         synchronized (getTreeLock()) {
2782             // addNotify() on the children may cause proxy event enabling
2783             // on this instance, so we first call super.addNotify() and
2784             // possibly create an lightweight event dispatcher before calling
2785             // addNotify() on the children which may be lightweight.
2786             super.addNotify();
2787             if (! (peer instanceof LightweightPeer)) {
2788                 dispatcher = new LightweightDispatcher(this);
2789             }
2790 
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 = 0; i < component.size(); i++) {
2797                 component.get(i).addNotify();
2798             }
2799         }
2800     }
2801 
2802     /**
2803      * Makes this Container undisplayable by removing its connection
2804      * to its native screen resource.  Making a container undisplayable
2805      * will cause all of its children to be made undisplayable.
2806      * This method is called by the toolkit internally and should
2807      * not be called directly by programs.
2808      * @see Component#isDisplayable
2809      * @see #addNotify
2810      */
2811     public void removeNotify() {
2812         synchronized (getTreeLock()) {
2813             // We shouldn't use iterator because of the Swing menu
2814             // implementation specifics:
2815             // the menu is being assigned as a child to JLayeredPane
2816             // instead of particular component so always affect
2817             // collection of component if menu is becoming shown or hidden.
2818             for (int i = component.size()-1 ; i >= 0 ; i--) {
2819                 Component comp = component.get(i);
2820                 if (comp != null) {
2821                     // Fix for 6607170.
2822                     // We want to suppress focus change on disposal
2823                     // of the focused component. But because of focus
2824                     // is asynchronous, we should suppress focus change
2825                     // on every component in case it receives native focus
2826                     // in the process of disposal.
2827                     comp.setAutoFocusTransferOnDisposal(false);
2828                     comp.removeNotify();
2829                     comp.setAutoFocusTransferOnDisposal(true);
2830                  }
2831              }
2832             // If some of the children had focus before disposal then it still has.
2833             // Auto-transfer focus to the next (or previous) component if auto-transfer
2834             // is enabled.
2835             if (containsFocus() && KeyboardFocusManager.isAutoFocusTransferEnabledFor(this)) {
2836                 if (!transferFocus(false)) {
2837                     transferFocusBackward(true);
2838                 }
2839             }
2840             if ( dispatcher != null ) {
2841                 dispatcher.dispose();
2842                 dispatcher = null;
2843             }
2844             super.removeNotify();
2845         }
2846     }
2847 
2848     /**
2849      * Checks if the component is contained in the component hierarchy of
2850      * this container.
2851      * @param c the component
2852      * @return     {@code true} if it is an ancestor;
2853      *             {@code false} otherwise.
2854      * @since      1.1
2855      */
2856     public boolean isAncestorOf(Component c) {
2857         Container p;
2858         if (c == null || ((p = c.getParent()) == null)) {
2859             return false;
2860         }
2861         while (p != null) {
2862             if (p == this) {
2863                 return true;
2864             }
2865             p = p.getParent();
2866         }
2867         return false;
2868     }
2869 
2870     /*
2871      * The following code was added to support modal JInternalFrames
2872      * Unfortunately this code has to be added here so that we can get access to
2873      * some private AWT classes like SequencedEvent.
2874      *
2875      * The native container of the LW component has this field set
2876      * to tell it that it should block Mouse events for all LW
2877      * children except for the modal component.
2878      *
2879      * In the case of nested Modal components, we store the previous
2880      * modal component in the new modal components value of modalComp;
2881      */
2882 
2883     transient Component modalComp;
2884     transient AppContext modalAppContext;
2885 
2886     private void startLWModal() {
2887         // Store the app context on which this component is being shown.
2888         // Event dispatch thread of this app context will be sleeping until
2889         // we wake it by any event from hideAndDisposeHandler().
2890         modalAppContext = AppContext.getAppContext();
2891 
2892         // keep the KeyEvents from being dispatched
2893         // until the focus has been transferred
2894         long time = Toolkit.getEventQueue().getMostRecentKeyEventTime();
2895         Component predictedFocusOwner = (Component.isInstanceOf(this, "javax.swing.JInternalFrame")) ? ((javax.swing.JInternalFrame)(this)).getMostRecentFocusOwner() : null;
2896         if (predictedFocusOwner != null) {
2897             KeyboardFocusManager.getCurrentKeyboardFocusManager().
2898                 enqueueKeyEvents(time, predictedFocusOwner);
2899         }
2900         // We have two mechanisms for blocking: 1. If we're on the
2901         // EventDispatchThread, start a new event pump. 2. If we're
2902         // on any other thread, call wait() on the treelock.
2903         final Container nativeContainer;
2904         synchronized (getTreeLock()) {
2905             nativeContainer = getHeavyweightContainer();
2906             if (nativeContainer.modalComp != null) {
2907                 this.modalComp =  nativeContainer.modalComp;
2908                 nativeContainer.modalComp = this;
2909                 return;
2910             }
2911             else {
2912                 nativeContainer.modalComp = this;
2913             }
2914         }
2915 
2916         Runnable pumpEventsForHierarchy = () -> {
2917             EventDispatchThread dispatchThread = (EventDispatchThread)Thread.currentThread();
2918             dispatchThread.pumpEventsForHierarchy(() -> nativeContainer.modalComp != null,
2919                     Container.this);
2920         };
2921 
2922         if (EventQueue.isDispatchThread()) {
2923             SequencedEvent currentSequencedEvent =
2924                 KeyboardFocusManager.getCurrentKeyboardFocusManager().
2925                 getCurrentSequencedEvent();
2926             if (currentSequencedEvent != null) {
2927                 currentSequencedEvent.dispose();
2928             }
2929 
2930             pumpEventsForHierarchy.run();
2931         } else {
2932             synchronized (getTreeLock()) {
2933                 Toolkit.getEventQueue().
2934                     postEvent(new PeerEvent(this,
2935                                 pumpEventsForHierarchy,
2936                                 PeerEvent.PRIORITY_EVENT));
2937                 while (nativeContainer.modalComp != null)
2938                 {
2939                     try {
2940                         getTreeLock().wait();
2941                     } catch (InterruptedException e) {
2942                         break;
2943                     }
2944                 }
2945             }
2946         }
2947         if (predictedFocusOwner != null) {
2948             KeyboardFocusManager.getCurrentKeyboardFocusManager().
2949                 dequeueKeyEvents(time, predictedFocusOwner);
2950         }
2951     }
2952 
2953     private void stopLWModal() {
2954         synchronized (getTreeLock()) {
2955             if (modalAppContext != null) {
2956                 Container nativeContainer = getHeavyweightContainer();
2957                 if(nativeContainer != null) {
2958                     if (this.modalComp !=  null) {
2959                         nativeContainer.modalComp = this.modalComp;
2960                         this.modalComp = null;
2961                         return;
2962                     }
2963                     else {
2964                         nativeContainer.modalComp = null;
2965                     }
2966                 }
2967                 // Wake up event dispatch thread on which the dialog was
2968                 // initially shown
2969                 SunToolkit.postEvent(modalAppContext,
2970                         new PeerEvent(this,
2971                                 new WakingRunnable(),
2972                                 PeerEvent.PRIORITY_EVENT));
2973             }
2974             EventQueue.invokeLater(new WakingRunnable());
2975             getTreeLock().notifyAll();
2976         }
2977     }
2978 
2979     static final class WakingRunnable implements Runnable {
2980         public void run() {
2981         }
2982     }
2983 
2984     /* End of JOptionPane support code */
2985 
2986     /**
2987      * Returns a string representing the state of this {@code Container}.
2988      * This method is intended to be used only for debugging purposes, and the
2989      * content and format of the returned string may vary between
2990      * implementations. The returned string may be empty but may not be
2991      * {@code null}.
2992      *
2993      * @return    the parameter string of this container
2994      */
2995     protected String paramString() {
2996         String str = super.paramString();
2997         LayoutManager layoutMgr = this.layoutMgr;
2998         if (layoutMgr != null) {
2999             str += ",layout=" + layoutMgr.getClass().getName();
3000         }
3001         return str;
3002     }
3003 
3004     /**
3005      * Prints a listing of this container to the specified output
3006      * stream. The listing starts at the specified indentation.
3007      * <p>
3008      * The immediate children of the container are printed with
3009      * an indentation of {@code indent+1}.  The children
3010      * of those children are printed at {@code indent+2}
3011      * and so on.
3012      *
3013      * @param    out      a print stream
3014      * @param    indent   the number of spaces to indent
3015      * @throws   NullPointerException if {@code out} is {@code null}
3016      * @see      Component#list(java.io.PrintStream, int)
3017      * @since    1.0
3018      */
3019     public void list(PrintStream out, int indent) {
3020         super.list(out, indent);
3021         synchronized(getTreeLock()) {
3022             for (int i = 0; i < component.size(); i++) {
3023                 Component comp = component.get(i);
3024                 if (comp != null) {
3025                     comp.list(out, indent+1);
3026                 }
3027             }
3028         }
3029     }
3030 
3031     /**
3032      * Prints out a list, starting at the specified indentation,
3033      * to the specified print writer.
3034      * <p>
3035      * The immediate children of the container are printed with
3036      * an indentation of {@code indent+1}.  The children
3037      * of those children are printed at {@code indent+2}
3038      * and so on.
3039      *
3040      * @param    out      a print writer
3041      * @param    indent   the number of spaces to indent
3042      * @throws   NullPointerException if {@code out} is {@code null}
3043      * @see      Component#list(java.io.PrintWriter, int)
3044      * @since    1.1
3045      */
3046     public void list(PrintWriter out, int indent) {
3047         super.list(out, indent);
3048         synchronized(getTreeLock()) {
3049             for (int i = 0; i < component.size(); i++) {
3050                 Component comp = component.get(i);
3051                 if (comp != null) {
3052                     comp.list(out, indent+1);
3053                 }
3054             }
3055         }
3056     }
3057 
3058     /**
3059      * Sets the focus traversal keys for a given traversal operation for this
3060      * Container.
3061      * <p>
3062      * The default values for a Container's focus traversal keys are
3063      * implementation-dependent. Sun recommends that all implementations for a
3064      * particular native platform use the same default values. The
3065      * recommendations for Windows and Unix are listed below. These
3066      * recommendations are used in the Sun AWT implementations.
3067      *
3068      * <table class="striped">
3069      * <caption>Recommended default values for a Container's focus traversal
3070      * keys</caption>
3071      * <thead>
3072      * <tr>
3073      *    <th>Identifier</th>
3074      *    <th>Meaning</th>
3075      *    <th>Default</th>
3076      * </tr>
3077      * </thead>
3078      * <tbody>
3079      * <tr>
3080      *    <td>KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS</td>
3081      *    <td>Normal forward keyboard traversal</td>
3082      *    <td>TAB on KEY_PRESSED, CTRL-TAB on KEY_PRESSED</td>
3083      * </tr>
3084      * <tr>
3085      *    <td>KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS</td>
3086      *    <td>Normal reverse keyboard traversal</td>
3087      *    <td>SHIFT-TAB on KEY_PRESSED, CTRL-SHIFT-TAB on KEY_PRESSED</td>
3088      * </tr>
3089      * <tr>
3090      *    <td>KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS</td>
3091      *    <td>Go up one focus traversal cycle</td>
3092      *    <td>none</td>
3093      * </tr>
3094      * <tr>
3095      *    <td>KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS</td>
3096      *    <td>Go down one focus traversal cycle</td>
3097      *    <td>none</td>
3098      * </tr>
3099      * </tbody>
3100      * </table>
3101      *
3102      * To disable a traversal key, use an empty Set; Collections.EMPTY_SET is
3103      * recommended.
3104      * <p>
3105      * Using the AWTKeyStroke API, client code can specify on which of two
3106      * specific KeyEvents, KEY_PRESSED or KEY_RELEASED, the focus traversal
3107      * operation will occur. Regardless of which KeyEvent is specified,
3108      * however, all KeyEvents related to the focus traversal key, including the
3109      * associated KEY_TYPED event, will be consumed, and will not be dispatched
3110      * to any Container. It is a runtime error to specify a KEY_TYPED event as
3111      * mapping to a focus traversal operation, or to map the same event to
3112      * multiple default focus traversal operations.
3113      * <p>
3114      * If a value of null is specified for the Set, this Container inherits the
3115      * Set from its parent. If all ancestors of this Container have null
3116      * specified for the Set, then the current KeyboardFocusManager's default
3117      * Set is used.
3118      * <p>
3119      * This method may throw a {@code ClassCastException} if any {@code Object}
3120      * in {@code keystrokes} is not an {@code AWTKeyStroke}.
3121      *
3122      * @param id one of KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
3123      *        KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
3124      *        KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
3125      *        KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
3126      * @param keystrokes the Set of AWTKeyStroke for the specified operation
3127      * @see #getFocusTraversalKeys
3128      * @see KeyboardFocusManager#FORWARD_TRAVERSAL_KEYS
3129      * @see KeyboardFocusManager#BACKWARD_TRAVERSAL_KEYS
3130      * @see KeyboardFocusManager#UP_CYCLE_TRAVERSAL_KEYS
3131      * @see KeyboardFocusManager#DOWN_CYCLE_TRAVERSAL_KEYS
3132      * @throws IllegalArgumentException if id is not one of
3133      *         KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
3134      *         KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
3135      *         KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
3136      *         KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS, or if keystrokes
3137      *         contains null, or if any keystroke represents a KEY_TYPED event,
3138      *         or if any keystroke already maps to another focus traversal
3139      *         operation for this Container
3140      * @since 1.4
3141      */
3142     public void setFocusTraversalKeys(int id,
3143                                       Set<? extends AWTKeyStroke> keystrokes)
3144     {
3145         if (id < 0 || id >= KeyboardFocusManager.TRAVERSAL_KEY_LENGTH) {
3146             throw new IllegalArgumentException("invalid focus traversal key identifier");
3147         }
3148 
3149         // Don't call super.setFocusTraversalKey. The Component parameter check
3150         // does not allow DOWN_CYCLE_TRAVERSAL_KEYS, but we do.
3151         setFocusTraversalKeys_NoIDCheck(id, keystrokes);
3152     }
3153 
3154     /**
3155      * Returns the Set of focus traversal keys for a given traversal operation
3156      * for this Container. (See
3157      * {@code setFocusTraversalKeys} for a full description of each key.)
3158      * <p>
3159      * If a Set of traversal keys has not been explicitly defined for this
3160      * Container, then this Container's parent's Set is returned. If no Set
3161      * has been explicitly defined for any of this Container's ancestors, then
3162      * the current KeyboardFocusManager's default Set is returned.
3163      *
3164      * @param id one of KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
3165      *        KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
3166      *        KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
3167      *        KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
3168      * @return the Set of AWTKeyStrokes for the specified operation. The Set
3169      *         will be unmodifiable, and may be empty. null will never be
3170      *         returned.
3171      * @see #setFocusTraversalKeys
3172      * @see KeyboardFocusManager#FORWARD_TRAVERSAL_KEYS
3173      * @see KeyboardFocusManager#BACKWARD_TRAVERSAL_KEYS
3174      * @see KeyboardFocusManager#UP_CYCLE_TRAVERSAL_KEYS
3175      * @see KeyboardFocusManager#DOWN_CYCLE_TRAVERSAL_KEYS
3176      * @throws IllegalArgumentException if id is not one of
3177      *         KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
3178      *         KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
3179      *         KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
3180      *         KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
3181      * @since 1.4
3182      */
3183     public Set<AWTKeyStroke> getFocusTraversalKeys(int id) {
3184         if (id < 0 || id >= KeyboardFocusManager.TRAVERSAL_KEY_LENGTH) {
3185             throw new IllegalArgumentException("invalid focus traversal key identifier");
3186         }
3187 
3188         // Don't call super.getFocusTraversalKey. The Component parameter check
3189         // does not allow DOWN_CYCLE_TRAVERSAL_KEY, but we do.
3190         return getFocusTraversalKeys_NoIDCheck(id);
3191     }
3192 
3193     /**
3194      * Returns whether the Set of focus traversal keys for the given focus
3195      * traversal operation has been explicitly defined for this Container. If
3196      * this method returns {@code false}, this Container is inheriting the
3197      * Set from an ancestor, or from the current KeyboardFocusManager.
3198      *
3199      * @param id one of KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
3200      *        KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
3201      *        KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
3202      *        KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
3203      * @return {@code true} if the Set of focus traversal keys for the
3204      *         given focus traversal operation has been explicitly defined for
3205      *         this Component; {@code false} otherwise.
3206      * @throws IllegalArgumentException if id is not one of
3207      *         KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
3208      *        KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
3209      *        KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
3210      *        KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
3211      * @since 1.4
3212      */
3213     public boolean areFocusTraversalKeysSet(int id) {
3214         if (id < 0 || id >= KeyboardFocusManager.TRAVERSAL_KEY_LENGTH) {
3215             throw new IllegalArgumentException("invalid focus traversal key identifier");
3216         }
3217 
3218         return (focusTraversalKeys != null && focusTraversalKeys[id] != null);
3219     }
3220 
3221     /**
3222      * Returns whether the specified Container is the focus cycle root of this
3223      * Container's focus traversal cycle. Each focus traversal cycle has only
3224      * a single focus cycle root and each Container which is not a focus cycle
3225      * root belongs to only a single focus traversal cycle. Containers which
3226      * are focus cycle roots belong to two cycles: one rooted at the Container
3227      * itself, and one rooted at the Container's nearest focus-cycle-root
3228      * ancestor. This method will return {@code true} for both such
3229      * Containers in this case.
3230      *
3231      * @param container the Container to be tested
3232      * @return {@code true} if the specified Container is a focus-cycle-
3233      *         root of this Container; {@code false} otherwise
3234      * @see #isFocusCycleRoot()
3235      * @since 1.4
3236      */
3237     public boolean isFocusCycleRoot(Container container) {
3238         if (isFocusCycleRoot() && container == this) {
3239             return true;
3240         } else {
3241             return super.isFocusCycleRoot(container);
3242         }
3243     }
3244 
3245     private Container findTraversalRoot() {
3246         // I potentially have two roots, myself and my root parent
3247         // If I am the current root, then use me
3248         // If none of my parents are roots, then use me
3249         // If my root parent is the current root, then use my root parent
3250         // If neither I nor my root parent is the current root, then
3251         // use my root parent (a guess)
3252 
3253         Container currentFocusCycleRoot = KeyboardFocusManager.
3254             getCurrentKeyboardFocusManager().getCurrentFocusCycleRoot();
3255         Container root;
3256 
3257         if (currentFocusCycleRoot == this) {
3258             root = this;
3259         } else {
3260             root = getFocusCycleRootAncestor();
3261             if (root == null) {
3262                 root = this;
3263             }
3264         }
3265 
3266         if (root != currentFocusCycleRoot) {
3267             KeyboardFocusManager.getCurrentKeyboardFocusManager().
3268                 setGlobalCurrentFocusCycleRootPriv(root);
3269         }
3270         return root;
3271     }
3272 
3273     final boolean containsFocus() {
3274         final Component focusOwner = KeyboardFocusManager.
3275             getCurrentKeyboardFocusManager().getFocusOwner();
3276         return isParentOf(focusOwner);
3277     }
3278 
3279     /**
3280      * Check if this component is the child of this container or its children.
3281      * Note: this function acquires treeLock
3282      * Note: this function traverses children tree only in one Window.
3283      * @param comp a component in test, must not be null
3284      */
3285     private boolean isParentOf(Component comp) {
3286         synchronized(getTreeLock()) {
3287             while (comp != null && comp != this && !(comp instanceof Window)) {
3288                 comp = comp.getParent();
3289             }
3290             return (comp == this);
3291         }
3292     }
3293 
3294     void clearMostRecentFocusOwnerOnHide() {
3295         boolean reset = false;
3296         Window window = null;
3297 
3298         synchronized (getTreeLock()) {
3299             window = getContainingWindow();
3300             if (window != null) {
3301                 Component comp = KeyboardFocusManager.getMostRecentFocusOwner(window);
3302                 reset = ((comp == this) || isParentOf(comp));
3303                 // This synchronized should always be the second in a pair
3304                 // (tree lock, KeyboardFocusManager.class)
3305                 synchronized(KeyboardFocusManager.class) {
3306                     Component storedComp = window.getTemporaryLostComponent();
3307                     if (isParentOf(storedComp) || storedComp == this) {
3308                         window.setTemporaryLostComponent(null);
3309                     }
3310                 }
3311             }
3312         }
3313 
3314         if (reset) {
3315             KeyboardFocusManager.setMostRecentFocusOwner(window, null);
3316         }
3317     }
3318 
3319     void clearCurrentFocusCycleRootOnHide() {
3320         KeyboardFocusManager kfm =
3321             KeyboardFocusManager.getCurrentKeyboardFocusManager();
3322         Container cont = kfm.getCurrentFocusCycleRoot();
3323 
3324         if (cont == this || isParentOf(cont)) {
3325             kfm.setGlobalCurrentFocusCycleRootPriv(null);
3326         }
3327     }
3328 
3329     final Container getTraversalRoot() {
3330         if (isFocusCycleRoot()) {
3331             return findTraversalRoot();
3332         }
3333 
3334         return super.getTraversalRoot();
3335     }
3336 
3337     /**
3338      * Sets the focus traversal policy that will manage keyboard traversal of
3339      * this Container's children, if this Container is a focus cycle root. If
3340      * the argument is null, this Container inherits its policy from its focus-
3341      * cycle-root ancestor. If the argument is non-null, this policy will be
3342      * inherited by all focus-cycle-root children that have no keyboard-
3343      * traversal policy of their own (as will, recursively, their focus-cycle-
3344      * root children).
3345      * <p>
3346      * If this Container is not a focus cycle root, the policy will be
3347      * remembered, but will not be used or inherited by this or any other
3348      * Containers until this Container is made a focus cycle root.
3349      *
3350      * @param policy the new focus traversal policy for this Container
3351      * @see #getFocusTraversalPolicy
3352      * @see #setFocusCycleRoot
3353      * @see #isFocusCycleRoot
3354      * @since 1.4
3355      */
3356     public void setFocusTraversalPolicy(FocusTraversalPolicy policy) {
3357         FocusTraversalPolicy oldPolicy;
3358         synchronized (this) {
3359             oldPolicy = this.focusTraversalPolicy;
3360             this.focusTraversalPolicy = policy;
3361         }
3362         firePropertyChange("focusTraversalPolicy", oldPolicy, policy);
3363     }
3364 
3365     /**
3366      * Returns the focus traversal policy that will manage keyboard traversal
3367      * of this Container's children, or null if this Container is not a focus
3368      * cycle root. If no traversal policy has been explicitly set for this
3369      * Container, then this Container's focus-cycle-root ancestor's policy is
3370      * returned.
3371      *
3372      * @return this Container's focus traversal policy, or null if this
3373      *         Container is not a focus cycle root.
3374      * @see #setFocusTraversalPolicy
3375      * @see #setFocusCycleRoot
3376      * @see #isFocusCycleRoot
3377      * @since 1.4
3378      */
3379     public FocusTraversalPolicy getFocusTraversalPolicy() {
3380         if (!isFocusTraversalPolicyProvider() && !isFocusCycleRoot()) {
3381             return null;
3382         }
3383 
3384         FocusTraversalPolicy policy = this.focusTraversalPolicy;
3385         if (policy != null) {
3386             return policy;
3387         }
3388 
3389         Container rootAncestor = getFocusCycleRootAncestor();
3390         if (rootAncestor != null) {
3391             return rootAncestor.getFocusTraversalPolicy();
3392         } else {
3393             return KeyboardFocusManager.getCurrentKeyboardFocusManager().
3394                 getDefaultFocusTraversalPolicy();
3395         }
3396     }
3397 
3398     /**
3399      * Returns whether the focus traversal policy has been explicitly set for
3400      * this Container. If this method returns {@code false}, this
3401      * Container will inherit its focus traversal policy from an ancestor.
3402      *
3403      * @return {@code true} if the focus traversal policy has been
3404      *         explicitly set for this Container; {@code false} otherwise.
3405      * @since 1.4
3406      */
3407     public boolean isFocusTraversalPolicySet() {
3408         return (focusTraversalPolicy != null);
3409     }
3410 
3411     /**
3412      * Sets whether this Container is the root of a focus traversal cycle. Once
3413      * focus enters a traversal cycle, typically it cannot leave it via focus
3414      * traversal unless one of the up- or down-cycle keys is pressed. Normal
3415      * traversal is limited to this Container, and all of this Container's
3416      * descendants that are not descendants of inferior focus cycle roots. Note
3417      * that a FocusTraversalPolicy may bend these restrictions, however. For
3418      * example, ContainerOrderFocusTraversalPolicy supports implicit down-cycle
3419      * traversal.
3420      * <p>
3421      * The alternative way to specify the traversal order of this Container's
3422      * children is to make this Container a
3423      * <a href="doc-files/FocusSpec.html#FocusTraversalPolicyProviders">focus traversal policy provider</a>.
3424      *
3425      * @param focusCycleRoot indicates whether this Container is the root of a
3426      *        focus traversal cycle
3427      * @see #isFocusCycleRoot()
3428      * @see #setFocusTraversalPolicy
3429      * @see #getFocusTraversalPolicy
3430      * @see ContainerOrderFocusTraversalPolicy
3431      * @see #setFocusTraversalPolicyProvider
3432      * @since 1.4
3433      */
3434     public void setFocusCycleRoot(boolean focusCycleRoot) {
3435         boolean oldFocusCycleRoot;
3436         synchronized (this) {
3437             oldFocusCycleRoot = this.focusCycleRoot;
3438             this.focusCycleRoot = focusCycleRoot;
3439         }
3440         firePropertyChange("focusCycleRoot", oldFocusCycleRoot,
3441                            focusCycleRoot);
3442     }
3443 
3444     /**
3445      * Returns whether this Container is the root of a focus traversal cycle.
3446      * Once focus enters a traversal cycle, typically it cannot leave it via
3447      * focus traversal unless one of the up- or down-cycle keys is pressed.
3448      * Normal traversal is limited to this Container, and all of this
3449      * Container's descendants that are not descendants of inferior focus
3450      * cycle roots. Note that a FocusTraversalPolicy may bend these
3451      * restrictions, however. For example, ContainerOrderFocusTraversalPolicy
3452      * supports implicit down-cycle traversal.
3453      *
3454      * @return whether this Container is the root of a focus traversal cycle
3455      * @see #setFocusCycleRoot
3456      * @see #setFocusTraversalPolicy
3457      * @see #getFocusTraversalPolicy
3458      * @see ContainerOrderFocusTraversalPolicy
3459      * @since 1.4
3460      */
3461     public boolean isFocusCycleRoot() {
3462         return focusCycleRoot;
3463     }
3464 
3465     /**
3466      * Sets whether this container will be used to provide focus
3467      * traversal policy. Container with this property as
3468      * {@code true} will be used to acquire focus traversal policy
3469      * instead of closest focus cycle root ancestor.
3470      * @param provider indicates whether this container will be used to
3471      *                provide focus traversal policy
3472      * @see #setFocusTraversalPolicy
3473      * @see #getFocusTraversalPolicy
3474      * @see #isFocusTraversalPolicyProvider
3475      * @since 1.5
3476      */
3477     public final void setFocusTraversalPolicyProvider(boolean provider) {
3478         boolean oldProvider;
3479         synchronized(this) {
3480             oldProvider = focusTraversalPolicyProvider;
3481             focusTraversalPolicyProvider = provider;
3482         }
3483         firePropertyChange("focusTraversalPolicyProvider", oldProvider, provider);
3484     }
3485 
3486     /**
3487      * Returns whether this container provides focus traversal
3488      * policy. If this property is set to {@code true} then when
3489      * keyboard focus manager searches container hierarchy for focus
3490      * traversal policy and encounters this container before any other
3491      * container with this property as true or focus cycle roots then
3492      * its focus traversal policy will be used instead of focus cycle
3493      * root's policy.
3494      * @see #setFocusTraversalPolicy
3495      * @see #getFocusTraversalPolicy
3496      * @see #setFocusCycleRoot
3497      * @see #setFocusTraversalPolicyProvider
3498      * @return {@code true} if this container provides focus traversal
3499      *         policy, {@code false} otherwise
3500      * @since 1.5
3501      */
3502     public final boolean isFocusTraversalPolicyProvider() {
3503         return focusTraversalPolicyProvider;
3504     }
3505 
3506     /**
3507      * Transfers the focus down one focus traversal cycle. If this Container is
3508      * a focus cycle root, then the focus owner is set to this Container's
3509      * default Component to focus, and the current focus cycle root is set to
3510      * this Container. If this Container is not a focus cycle root, then no
3511      * focus traversal operation occurs.
3512      *
3513      * @see       Component#requestFocus()
3514      * @see       #isFocusCycleRoot
3515      * @see       #setFocusCycleRoot
3516      * @since     1.4
3517      */
3518     public void transferFocusDownCycle() {
3519         if (isFocusCycleRoot()) {
3520             KeyboardFocusManager.getCurrentKeyboardFocusManager().
3521                 setGlobalCurrentFocusCycleRootPriv(this);
3522             Component toFocus = getFocusTraversalPolicy().
3523                 getDefaultComponent(this);
3524             if (toFocus != null) {
3525                 toFocus.requestFocus(FocusEvent.Cause.TRAVERSAL_DOWN);
3526             }
3527         }
3528     }
3529 
3530     void preProcessKeyEvent(KeyEvent e) {
3531         Container parent = this.parent;
3532         if (parent != null) {
3533             parent.preProcessKeyEvent(e);
3534         }
3535     }
3536 
3537     void postProcessKeyEvent(KeyEvent e) {
3538         Container parent = this.parent;
3539         if (parent != null) {
3540             parent.postProcessKeyEvent(e);
3541         }
3542     }
3543 
3544     boolean postsOldMouseEvents() {
3545         return true;
3546     }
3547 
3548     /**
3549      * Sets the {@code ComponentOrientation} property of this container
3550      * and all components contained within it.
3551      * <p>
3552      * This method changes layout-related information, and therefore,
3553      * invalidates the component hierarchy.
3554      *
3555      * @param o the new component orientation of this container and
3556      *        the components contained within it.
3557      * @exception NullPointerException if {@code orientation} is null.
3558      * @see Component#setComponentOrientation
3559      * @see Component#getComponentOrientation
3560      * @see #invalidate
3561      * @since 1.4
3562      */
3563     public void applyComponentOrientation(ComponentOrientation o) {
3564         super.applyComponentOrientation(o);
3565         synchronized (getTreeLock()) {
3566             for (int i = 0; i < component.size(); i++) {
3567                 Component comp = component.get(i);
3568                 comp.applyComponentOrientation(o);
3569             }
3570         }
3571     }
3572 
3573     /**
3574      * Adds a PropertyChangeListener to the listener list. The listener is
3575      * registered for all bound properties of this class, including the
3576      * following:
3577      * <ul>
3578      *    <li>this Container's font ("font")</li>
3579      *    <li>this Container's background color ("background")</li>
3580      *    <li>this Container's foreground color ("foreground")</li>
3581      *    <li>this Container's focusability ("focusable")</li>
3582      *    <li>this Container's focus traversal keys enabled state
3583      *        ("focusTraversalKeysEnabled")</li>
3584      *    <li>this Container's Set of FORWARD_TRAVERSAL_KEYS
3585      *        ("forwardFocusTraversalKeys")</li>
3586      *    <li>this Container's Set of BACKWARD_TRAVERSAL_KEYS
3587      *        ("backwardFocusTraversalKeys")</li>
3588      *    <li>this Container's Set of UP_CYCLE_TRAVERSAL_KEYS
3589      *        ("upCycleFocusTraversalKeys")</li>
3590      *    <li>this Container's Set of DOWN_CYCLE_TRAVERSAL_KEYS
3591      *        ("downCycleFocusTraversalKeys")</li>
3592      *    <li>this Container's focus traversal policy ("focusTraversalPolicy")
3593      *        </li>
3594      *    <li>this Container's focus-cycle-root state ("focusCycleRoot")</li>
3595      * </ul>
3596      * Note that if this Container is inheriting a bound property, then no
3597      * event will be fired in response to a change in the inherited property.
3598      * <p>
3599      * If listener is null, no exception is thrown and no action is performed.
3600      *
3601      * @param    listener  the PropertyChangeListener to be added
3602      *
3603      * @see Component#removePropertyChangeListener
3604      * @see #addPropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
3605      */
3606     public void addPropertyChangeListener(PropertyChangeListener listener) {
3607         super.addPropertyChangeListener(listener);
3608     }
3609 
3610     /**
3611      * Adds a PropertyChangeListener to the listener list for a specific
3612      * property. The specified property may be user-defined, or one of the
3613      * following defaults:
3614      * <ul>
3615      *    <li>this Container's font ("font")</li>
3616      *    <li>this Container's background color ("background")</li>
3617      *    <li>this Container's foreground color ("foreground")</li>
3618      *    <li>this Container's focusability ("focusable")</li>
3619      *    <li>this Container's focus traversal keys enabled state
3620      *        ("focusTraversalKeysEnabled")</li>
3621      *    <li>this Container's Set of FORWARD_TRAVERSAL_KEYS
3622      *        ("forwardFocusTraversalKeys")</li>
3623      *    <li>this Container's Set of BACKWARD_TRAVERSAL_KEYS
3624      *        ("backwardFocusTraversalKeys")</li>
3625      *    <li>this Container's Set of UP_CYCLE_TRAVERSAL_KEYS
3626      *        ("upCycleFocusTraversalKeys")</li>
3627      *    <li>this Container's Set of DOWN_CYCLE_TRAVERSAL_KEYS
3628      *        ("downCycleFocusTraversalKeys")</li>
3629      *    <li>this Container's focus traversal policy ("focusTraversalPolicy")
3630      *        </li>
3631      *    <li>this Container's focus-cycle-root state ("focusCycleRoot")</li>
3632      *    <li>this Container's focus-traversal-policy-provider state("focusTraversalPolicyProvider")</li>
3633      *    <li>this Container's focus-traversal-policy-provider state("focusTraversalPolicyProvider")</li>
3634      * </ul>
3635      * Note that if this Container is inheriting a bound property, then no
3636      * event will be fired in response to a change in the inherited property.
3637      * <p>
3638      * If listener is null, no exception is thrown and no action is performed.
3639      *
3640      * @param propertyName one of the property names listed above
3641      * @param listener the PropertyChangeListener to be added
3642      *
3643      * @see #addPropertyChangeListener(java.beans.PropertyChangeListener)
3644      * @see Component#removePropertyChangeListener
3645      */
3646     public void addPropertyChangeListener(String propertyName,
3647                                           PropertyChangeListener listener) {
3648         super.addPropertyChangeListener(propertyName, listener);
3649     }
3650 
3651     // Serialization support. A Container is responsible for restoring the
3652     // parent fields of its component children.
3653 
3654     /**
3655      * Container Serial Data Version.
3656      */
3657     private int containerSerializedDataVersion = 1;
3658 
3659     /**
3660      * Serializes this {@code Container} to the specified
3661      * {@code ObjectOutputStream}.
3662      * <ul>
3663      *    <li>Writes default serializable fields to the stream.</li>
3664      *    <li>Writes a list of serializable ContainerListener(s) as optional
3665      *        data. The non-serializable ContainerListener(s) are detected and
3666      *        no attempt is made to serialize them.</li>
3667      *    <li>Write this Container's FocusTraversalPolicy if and only if it
3668      *        is Serializable; otherwise, {@code null} is written.</li>
3669      * </ul>
3670      *
3671      * @param s the {@code ObjectOutputStream} to write
3672      * @serialData {@code null} terminated sequence of 0 or more pairs;
3673      *   the pair consists of a {@code String} and {@code Object};
3674      *   the {@code String} indicates the type of object and
3675      *   is one of the following:
3676      *   {@code containerListenerK} indicating an
3677      *     {@code ContainerListener} object;
3678      *   the {@code Container}'s {@code FocusTraversalPolicy},
3679      *     or {@code null}
3680      *
3681      * @see AWTEventMulticaster#save(java.io.ObjectOutputStream, java.lang.String, java.util.EventListener)
3682      * @see Container#containerListenerK
3683      * @see #readObject(ObjectInputStream)
3684      */
3685     private void writeObject(ObjectOutputStream s) throws IOException {
3686         ObjectOutputStream.PutField f = s.putFields();
3687         f.put("ncomponents", component.size());
3688         f.put("component", component.toArray(EMPTY_ARRAY));
3689         f.put("layoutMgr", layoutMgr);
3690         f.put("dispatcher", dispatcher);
3691         f.put("maxSize", maxSize);
3692         f.put("focusCycleRoot", focusCycleRoot);
3693         f.put("containerSerializedDataVersion", containerSerializedDataVersion);
3694         f.put("focusTraversalPolicyProvider", focusTraversalPolicyProvider);
3695         s.writeFields();
3696 
3697         AWTEventMulticaster.save(s, containerListenerK, containerListener);
3698         s.writeObject(null);
3699 
3700         if (focusTraversalPolicy instanceof java.io.Serializable) {
3701             s.writeObject(focusTraversalPolicy);
3702         } else {
3703             s.writeObject(null);
3704         }
3705     }
3706 
3707     /**
3708      * Deserializes this {@code Container} from the specified
3709      * {@code ObjectInputStream}.
3710      * <ul>
3711      *    <li>Reads default serializable fields from the stream.</li>
3712      *    <li>Reads a list of serializable ContainerListener(s) as optional
3713      *        data. If the list is null, no Listeners are installed.</li>
3714      *    <li>Reads this Container's FocusTraversalPolicy, which may be null,
3715      *        as optional data.</li>
3716      * </ul>
3717      *
3718      * @param s the {@code ObjectInputStream} to read
3719      * @serial
3720      * @see #addContainerListener
3721      * @see #writeObject(ObjectOutputStream)
3722      */
3723     private void readObject(ObjectInputStream s)
3724         throws ClassNotFoundException, IOException
3725     {
3726         ObjectInputStream.GetField f = s.readFields();
3727         Component [] tmpComponent = (Component[])f.get("component", EMPTY_ARRAY);
3728         int ncomponents = (Integer) f.get("ncomponents", 0);
3729         component = new java.util.ArrayList<Component>(ncomponents);
3730         for (int i = 0; i < ncomponents; ++i) {
3731             component.add(tmpComponent[i]);
3732         }
3733         layoutMgr = (LayoutManager)f.get("layoutMgr", null);
3734         dispatcher = (LightweightDispatcher)f.get("dispatcher", null);
3735         // Old stream. Doesn't contain maxSize among Component's fields.
3736         if (maxSize == null) {
3737             maxSize = (Dimension)f.get("maxSize", null);
3738         }
3739         focusCycleRoot = f.get("focusCycleRoot", false);
3740         containerSerializedDataVersion = f.get("containerSerializedDataVersion", 1);
3741         focusTraversalPolicyProvider = f.get("focusTraversalPolicyProvider", false);
3742         java.util.List<Component> component = this.component;
3743         for(Component comp : component) {
3744             comp.parent = this;
3745             adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK,
3746                                     comp.numListening(AWTEvent.HIERARCHY_EVENT_MASK));
3747             adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
3748                                     comp.numListening(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));
3749             adjustDescendants(comp.countHierarchyMembers());
3750         }
3751 
3752         Object keyOrNull;
3753         while(null != (keyOrNull = s.readObject())) {
3754             String key = ((String)keyOrNull).intern();
3755 
3756             if (containerListenerK == key) {
3757                 addContainerListener((ContainerListener)(s.readObject()));
3758             } else {
3759                 // skip value for unrecognized key
3760                 s.readObject();
3761             }
3762         }
3763 
3764         try {
3765             Object policy = s.readObject();
3766             if (policy instanceof FocusTraversalPolicy) {
3767                 focusTraversalPolicy = (FocusTraversalPolicy)policy;
3768             }
3769         } catch (java.io.OptionalDataException e) {
3770             // JDK 1.1/1.2/1.3 instances will not have this optional data.
3771             // e.eof will be true to indicate that there is no more data
3772             // available for this object. If e.eof is not true, throw the
3773             // exception as it might have been caused by reasons unrelated to
3774             // focusTraversalPolicy.
3775 
3776             if (!e.eof) {
3777                 throw e;
3778             }
3779         }
3780     }
3781 
3782     /*
3783      * --- Accessibility Support ---
3784      */
3785 
3786     /**
3787      * Inner class of Container used to provide default support for
3788      * accessibility.  This class is not meant to be used directly by
3789      * application developers, but is instead meant only to be
3790      * subclassed by container developers.
3791      * <p>
3792      * The class used to obtain the accessible role for this object,
3793      * as well as implementing many of the methods in the
3794      * AccessibleContainer interface.
3795      * @since 1.3
3796      */
3797     protected class AccessibleAWTContainer extends AccessibleAWTComponent {
3798 
3799         /**
3800          * JDK1.3 serialVersionUID
3801          */
3802         private static final long serialVersionUID = 5081320404842566097L;
3803 
3804         /**
3805          * Returns the number of accessible children in the object.  If all
3806          * of the children of this object implement {@code Accessible},
3807          * then this method should return the number of children of this object.
3808          *
3809          * @return the number of accessible children in the object
3810          */
3811         public int getAccessibleChildrenCount() {
3812             return Container.this.getAccessibleChildrenCount();
3813         }
3814 
3815         /**
3816          * Returns the nth {@code Accessible} child of the object.
3817          *
3818          * @param i zero-based index of child
3819          * @return the nth {@code Accessible} child of the object
3820          */
3821         public Accessible getAccessibleChild(int i) {
3822             return Container.this.getAccessibleChild(i);
3823         }
3824 
3825         /**
3826          * Returns the {@code Accessible} child, if one exists,
3827          * contained at the local coordinate {@code Point}.
3828          *
3829          * @param p the point defining the top-left corner of the
3830          *    {@code Accessible}, given in the coordinate space
3831          *    of the object's parent
3832          * @return the {@code Accessible}, if it exists,
3833          *    at the specified location; else {@code null}
3834          */
3835         public Accessible getAccessibleAt(Point p) {
3836             return Container.this.getAccessibleAt(p);
3837         }
3838 
3839         /**
3840          * Number of PropertyChangeListener objects registered. It's used
3841          * to add/remove ContainerListener to track target Container's state.
3842          */
3843         private transient volatile int propertyListenersCount = 0;
3844 
3845         /**
3846          * The handler to fire {@code PropertyChange}
3847          * when children are added or removed
3848          */
3849         protected ContainerListener accessibleContainerHandler = null;
3850 
3851         /**
3852          * Fire {@code PropertyChange} listener, if one is registered,
3853          * when children are added or removed.
3854          * @since 1.3
3855          */
3856         protected class AccessibleContainerHandler
3857             implements ContainerListener {


3858             public void componentAdded(ContainerEvent e) {
3859                 Component c = e.getChild();
3860                 if (c != null && c instanceof Accessible) {
3861                     AccessibleAWTContainer.this.firePropertyChange(
3862                         AccessibleContext.ACCESSIBLE_CHILD_PROPERTY,
3863                         null, ((Accessible) c).getAccessibleContext());
3864                 }
3865             }
3866             public void componentRemoved(ContainerEvent e) {
3867                 Component c = e.getChild();
3868                 if (c != null && c instanceof Accessible) {
3869                     AccessibleAWTContainer.this.firePropertyChange(
3870                         AccessibleContext.ACCESSIBLE_CHILD_PROPERTY,
3871                         ((Accessible) c).getAccessibleContext(), null);
3872                 }
3873             }
3874         }
3875 
3876         /**
3877          * Adds a PropertyChangeListener to the listener list.
3878          *
3879          * @param listener  the PropertyChangeListener to be added
3880          */
3881         public void addPropertyChangeListener(PropertyChangeListener listener) {
3882             if (accessibleContainerHandler == null) {
3883                 accessibleContainerHandler = new AccessibleContainerHandler();
3884             }
3885             if (propertyListenersCount++ == 0) {
3886                 Container.this.addContainerListener(accessibleContainerHandler);
3887             }
3888             super.addPropertyChangeListener(listener);
3889         }
3890 
3891         /**
3892          * Remove a PropertyChangeListener from the listener list.
3893          * This removes a PropertyChangeListener that was registered
3894          * for all properties.
3895          *
3896          * @param listener the PropertyChangeListener to be removed
3897          */
3898         public void removePropertyChangeListener(PropertyChangeListener listener) {
3899             if (--propertyListenersCount == 0) {
3900                 Container.this.removeContainerListener(accessibleContainerHandler);
3901             }
3902             super.removePropertyChangeListener(listener);
3903         }
3904 
3905     } // inner class AccessibleAWTContainer
3906 
3907     /**
3908      * Returns the {@code Accessible} child contained at the local
3909      * coordinate {@code Point}, if one exists.  Otherwise
3910      * returns {@code null}.
3911      *
3912      * @param p the point defining the top-left corner of the
3913      *    {@code Accessible}, given in the coordinate space
3914      *    of the object's parent
3915      * @return the {@code Accessible} at the specified location,
3916      *    if it exists; otherwise {@code null}
3917      */
3918     Accessible getAccessibleAt(Point p) {
3919         synchronized (getTreeLock()) {
3920             if (this instanceof Accessible) {
3921                 Accessible a = (Accessible)this;
3922                 AccessibleContext ac = a.getAccessibleContext();
3923                 if (ac != null) {
3924                     AccessibleComponent acmp;
3925                     Point location;
3926                     int nchildren = ac.getAccessibleChildrenCount();
3927                     for (int i=0; i < nchildren; i++) {
3928                         a = ac.getAccessibleChild(i);
3929                         if ((a != null)) {
3930                             ac = a.getAccessibleContext();
3931                             if (ac != null) {
3932                                 acmp = ac.getAccessibleComponent();
3933                                 if ((acmp != null) && (acmp.isShowing())) {
3934                                     location = acmp.getLocation();
3935                                     Point np = new Point(p.x-location.x,
3936                                                          p.y-location.y);
3937                                     if (acmp.contains(np)){
3938                                         return a;
3939                                     }
3940                                 }
3941                             }
3942                         }
3943                     }
3944                 }
3945                 return (Accessible)this;
3946             } else {
3947                 Component ret = this;
3948                 if (!this.contains(p.x,p.y)) {
3949                     ret = null;
3950                 } else {
3951                     int ncomponents = this.getComponentCount();
3952                     for (int i=0; i < ncomponents; i++) {
3953                         Component comp = this.getComponent(i);
3954                         if ((comp != null) && comp.isShowing()) {
3955                             Point location = comp.getLocation();
3956                             if (comp.contains(p.x-location.x,p.y-location.y)) {
3957                                 ret = comp;
3958                             }
3959                         }
3960                     }
3961                 }
3962                 if (ret instanceof Accessible) {
3963                     return (Accessible) ret;
3964                 }
3965             }
3966             return null;
3967         }
3968     }
3969 
3970     /**
3971      * Returns the number of accessible children in the object.  If all
3972      * of the children of this object implement {@code Accessible},
3973      * then this method should return the number of children of this object.
3974      *
3975      * @return the number of accessible children in the object
3976      */
3977     int getAccessibleChildrenCount() {
3978         synchronized (getTreeLock()) {
3979             int count = 0;
3980             Component[] children = this.getComponents();
3981             for (int i = 0; i < children.length; i++) {
3982                 if (children[i] instanceof Accessible) {
3983                     count++;
3984                 }
3985             }
3986             return count;
3987         }
3988     }
3989 
3990     /**
3991      * Returns the nth {@code Accessible} child of the object.
3992      *
3993      * @param i zero-based index of child
3994      * @return the nth {@code Accessible} child of the object
3995      */
3996     Accessible getAccessibleChild(int i) {
3997         synchronized (getTreeLock()) {
3998             Component[] children = this.getComponents();
3999             int count = 0;
4000             for (int j = 0; j < children.length; j++) {
4001                 if (children[j] instanceof Accessible) {
4002                     if (count == i) {
4003                         return (Accessible) children[j];
4004                     } else {
4005                         count++;
4006                     }
4007                 }
4008             }
4009             return null;
4010         }
4011     }
4012 
4013     // ************************** MIXING CODE *******************************
4014 
4015     final void increaseComponentCount(Component c) {
4016         synchronized (getTreeLock()) {
4017             if (!c.isDisplayable()) {
4018                 throw new IllegalStateException(
4019                     "Peer does not exist while invoking the increaseComponentCount() method"
4020                 );
4021             }
4022 
4023             int addHW = 0;
4024             int addLW = 0;
4025 
4026             if (c instanceof Container) {
4027                 addLW = ((Container)c).numOfLWComponents;
4028                 addHW = ((Container)c).numOfHWComponents;
4029             }
4030             if (c.isLightweight()) {
4031                 addLW++;
4032             } else {
4033                 addHW++;
4034             }
4035 
4036             for (Container cont = this; cont != null; cont = cont.getContainer()) {
4037                 cont.numOfLWComponents += addLW;
4038                 cont.numOfHWComponents += addHW;
4039             }
4040         }
4041     }
4042 
4043     final void decreaseComponentCount(Component c) {
4044         synchronized (getTreeLock()) {
4045             if (!c.isDisplayable()) {
4046                 throw new IllegalStateException(
4047                     "Peer does not exist while invoking the decreaseComponentCount() method"
4048                 );
4049             }
4050 
4051             int subHW = 0;
4052             int subLW = 0;
4053 
4054             if (c instanceof Container) {
4055                 subLW = ((Container)c).numOfLWComponents;
4056                 subHW = ((Container)c).numOfHWComponents;
4057             }
4058             if (c.isLightweight()) {
4059                 subLW++;
4060             } else {
4061                 subHW++;
4062             }
4063 
4064             for (Container cont = this; cont != null; cont = cont.getContainer()) {
4065                 cont.numOfLWComponents -= subLW;
4066                 cont.numOfHWComponents -= subHW;
4067             }
4068         }
4069     }
4070 
4071     private int getTopmostComponentIndex() {
4072         checkTreeLock();
4073         if (getComponentCount() > 0) {
4074             return 0;
4075         }
4076         return -1;
4077     }
4078 
4079     private int getBottommostComponentIndex() {
4080         checkTreeLock();
4081         if (getComponentCount() > 0) {
4082             return getComponentCount() - 1;
4083         }
4084         return -1;
4085     }
4086 
4087     /*
4088      * This method is overriden to handle opaque children in non-opaque
4089      * containers.
4090      */
4091     @Override
4092     final Region getOpaqueShape() {
4093         checkTreeLock();
4094         if (isLightweight() && isNonOpaqueForMixing()
4095                 && hasLightweightDescendants())
4096         {
4097             Region s = Region.EMPTY_REGION;
4098             for (int index = 0; index < getComponentCount(); index++) {
4099                 Component c = getComponent(index);
4100                 if (c.isLightweight() && c.isShowing()) {
4101                     s = s.getUnion(c.getOpaqueShape());
4102                 }
4103             }
4104             return s.getIntersection(getNormalShape());
4105         }
4106         return super.getOpaqueShape();
4107     }
4108 
4109     final void recursiveSubtractAndApplyShape(Region shape) {
4110         recursiveSubtractAndApplyShape(shape, getTopmostComponentIndex(), getBottommostComponentIndex());
4111     }
4112 
4113     final void recursiveSubtractAndApplyShape(Region shape, int fromZorder) {
4114         recursiveSubtractAndApplyShape(shape, fromZorder, getBottommostComponentIndex());
4115     }
4116 
4117     final void recursiveSubtractAndApplyShape(Region shape, int fromZorder, int toZorder) {
4118         checkTreeLock();
4119         if (mixingLog.isLoggable(PlatformLogger.Level.FINE)) {
4120             mixingLog.fine("this = " + this +
4121                 "; shape=" + shape + "; fromZ=" + fromZorder + "; toZ=" + toZorder);
4122         }
4123         if (fromZorder == -1) {
4124             return;
4125         }
4126         if (shape.isEmpty()) {
4127             return;
4128         }
4129         // An invalid container with not-null layout should be ignored
4130         // by the mixing code, the container will be validated later
4131         // and the mixing code will be executed later.
4132         if (getLayout() != null && !isValid()) {
4133             return;
4134         }
4135         for (int index = fromZorder; index <= toZorder; index++) {
4136             Component comp = getComponent(index);
4137             if (!comp.isLightweight()) {
4138                 comp.subtractAndApplyShape(shape);
4139             } else if (comp instanceof Container &&
4140                     ((Container)comp).hasHeavyweightDescendants() && comp.isShowing()) {
4141                 ((Container)comp).recursiveSubtractAndApplyShape(shape);
4142             }
4143         }
4144     }
4145 
4146     final void recursiveApplyCurrentShape() {
4147         recursiveApplyCurrentShape(getTopmostComponentIndex(), getBottommostComponentIndex());
4148     }
4149 
4150     final void recursiveApplyCurrentShape(int fromZorder) {
4151         recursiveApplyCurrentShape(fromZorder, getBottommostComponentIndex());
4152     }
4153 
4154     final void recursiveApplyCurrentShape(int fromZorder, int toZorder) {
4155         checkTreeLock();
4156         if (mixingLog.isLoggable(PlatformLogger.Level.FINE)) {
4157             mixingLog.fine("this = " + this +
4158                 "; fromZ=" + fromZorder + "; toZ=" + toZorder);
4159         }
4160         if (fromZorder == -1) {
4161             return;
4162         }
4163         // An invalid container with not-null layout should be ignored
4164         // by the mixing code, the container will be validated later
4165         // and the mixing code will be executed later.
4166         if (getLayout() != null && !isValid()) {
4167             return;
4168         }
4169         for (int index = fromZorder; index <= toZorder; index++) {
4170             Component comp = getComponent(index);
4171             if (!comp.isLightweight()) {
4172                 comp.applyCurrentShape();
4173             }
4174             if (comp instanceof Container &&
4175                     ((Container)comp).hasHeavyweightDescendants()) {
4176                 ((Container)comp).recursiveApplyCurrentShape();
4177             }
4178         }
4179     }
4180 
4181     @SuppressWarnings("deprecation")
4182     private void recursiveShowHeavyweightChildren() {
4183         if (!hasHeavyweightDescendants() || !isVisible()) {
4184             return;
4185         }
4186         for (int index = 0; index < getComponentCount(); index++) {
4187             Component comp = getComponent(index);
4188             if (comp.isLightweight()) {
4189                 if  (comp instanceof Container) {
4190                     ((Container)comp).recursiveShowHeavyweightChildren();
4191                 }
4192             } else {
4193                 if (comp.isVisible()) {
4194                     ComponentPeer peer = comp.peer;
4195                     if (peer != null) {
4196                         peer.setVisible(true);
4197                     }
4198                 }
4199             }
4200         }
4201     }
4202 
4203     @SuppressWarnings("deprecation")
4204     private void recursiveHideHeavyweightChildren() {
4205         if (!hasHeavyweightDescendants()) {
4206             return;
4207         }
4208         for (int index = 0; index < getComponentCount(); index++) {
4209             Component comp = getComponent(index);
4210             if (comp.isLightweight()) {
4211                 if  (comp instanceof Container) {
4212                     ((Container)comp).recursiveHideHeavyweightChildren();
4213                 }
4214             } else {
4215                 if (comp.isVisible()) {
4216                     ComponentPeer peer = comp.peer;
4217                     if (peer != null) {
4218                         peer.setVisible(false);
4219                     }
4220                 }
4221             }
4222         }
4223     }
4224 
4225     @SuppressWarnings("deprecation")
4226     private void recursiveRelocateHeavyweightChildren(Point origin) {
4227         for (int index = 0; index < getComponentCount(); index++) {
4228             Component comp = getComponent(index);
4229             if (comp.isLightweight()) {
4230                 if  (comp instanceof Container &&
4231                         ((Container)comp).hasHeavyweightDescendants())
4232                 {
4233                     final Point newOrigin = new Point(origin);
4234                     newOrigin.translate(comp.getX(), comp.getY());
4235                     ((Container)comp).recursiveRelocateHeavyweightChildren(newOrigin);
4236                 }
4237             } else {
4238                 ComponentPeer peer = comp.peer;
4239                 if (peer != null) {
4240                     peer.setBounds(origin.x + comp.getX(), origin.y + comp.getY(),
4241                             comp.getWidth(), comp.getHeight(),
4242                             ComponentPeer.SET_LOCATION);
4243                 }
4244             }
4245         }
4246     }
4247 
4248     /**
4249      * Checks if the container and its direct lightweight containers are
4250      * visible.
4251      *
4252      * Consider the heavyweight container hides or shows the HW descendants
4253      * automatically. Therefore we care of LW containers' visibility only.
4254      *
4255      * This method MUST be invoked under the TreeLock.
4256      */
4257     final boolean isRecursivelyVisibleUpToHeavyweightContainer() {
4258         if (!isLightweight()) {
4259             return true;
4260         }
4261 
4262         for (Container cont = this;
4263                 cont != null && cont.isLightweight();
4264                 cont = cont.getContainer())
4265         {
4266             if (!cont.isVisible()) {
4267                 return false;
4268             }
4269         }
4270         return true;
4271     }
4272 
4273     @Override
4274     void mixOnShowing() {
4275         synchronized (getTreeLock()) {
4276             if (mixingLog.isLoggable(PlatformLogger.Level.FINE)) {
4277                 mixingLog.fine("this = " + this);
4278             }
4279 
4280             boolean isLightweight = isLightweight();
4281 
4282             if (isLightweight && isRecursivelyVisibleUpToHeavyweightContainer()) {
4283                 recursiveShowHeavyweightChildren();
4284             }
4285 
4286             if (!isMixingNeeded()) {
4287                 return;
4288             }
4289 
4290             if (!isLightweight || (isLightweight && hasHeavyweightDescendants())) {
4291                 recursiveApplyCurrentShape();
4292             }
4293 
4294             super.mixOnShowing();
4295         }
4296     }
4297 
4298     @Override
4299     void mixOnHiding(boolean isLightweight) {
4300         synchronized (getTreeLock()) {
4301             if (mixingLog.isLoggable(PlatformLogger.Level.FINE)) {
4302                 mixingLog.fine("this = " + this +
4303                         "; isLightweight=" + isLightweight);
4304             }
4305             if (isLightweight) {
4306                 recursiveHideHeavyweightChildren();
4307             }
4308             super.mixOnHiding(isLightweight);
4309         }
4310     }
4311 
4312     @Override
4313     void mixOnReshaping() {
4314         synchronized (getTreeLock()) {
4315             if (mixingLog.isLoggable(PlatformLogger.Level.FINE)) {
4316                 mixingLog.fine("this = " + this);
4317             }
4318 
4319             boolean isMixingNeeded = isMixingNeeded();
4320 
4321             if (isLightweight() && hasHeavyweightDescendants()) {
4322                 final Point origin = new Point(getX(), getY());
4323                 for (Container cont = getContainer();
4324                         cont != null && cont.isLightweight();
4325                         cont = cont.getContainer())
4326                 {
4327                     origin.translate(cont.getX(), cont.getY());
4328                 }
4329 
4330                 recursiveRelocateHeavyweightChildren(origin);
4331 
4332                 if (!isMixingNeeded) {
4333                     return;
4334                 }
4335 
4336                 recursiveApplyCurrentShape();
4337             }
4338 
4339             if (!isMixingNeeded) {
4340                 return;
4341             }
4342 
4343             super.mixOnReshaping();
4344         }
4345     }
4346 
4347     @Override
4348     void mixOnZOrderChanging(int oldZorder, int newZorder) {
4349         synchronized (getTreeLock()) {
4350             if (mixingLog.isLoggable(PlatformLogger.Level.FINE)) {
4351                 mixingLog.fine("this = " + this +
4352                     "; oldZ=" + oldZorder + "; newZ=" + newZorder);
4353             }
4354 
4355             if (!isMixingNeeded()) {
4356                 return;
4357             }
4358 
4359             boolean becameHigher = newZorder < oldZorder;
4360 
4361             if (becameHigher && isLightweight() && hasHeavyweightDescendants()) {
4362                 recursiveApplyCurrentShape();
4363             }
4364             super.mixOnZOrderChanging(oldZorder, newZorder);
4365         }
4366     }
4367 
4368     @Override
4369     void mixOnValidating() {
4370         synchronized (getTreeLock()) {
4371             if (mixingLog.isLoggable(PlatformLogger.Level.FINE)) {
4372                 mixingLog.fine("this = " + this);
4373             }
4374 
4375             if (!isMixingNeeded()) {
4376                 return;
4377             }
4378 
4379             if (hasHeavyweightDescendants()) {
4380                 recursiveApplyCurrentShape();
4381             }
4382 
4383             if (isLightweight() && isNonOpaqueForMixing()) {
4384                 subtractAndApplyShapeBelowMe();
4385             }
4386 
4387             super.mixOnValidating();
4388         }
4389     }
4390 
4391     // ****************** END OF MIXING CODE ********************************
4392 }
4393 
4394 
4395 /**
4396  * Class to manage the dispatching of MouseEvents to the lightweight descendants
4397  * and SunDropTargetEvents to both lightweight and heavyweight descendants
4398  * contained by a native container.
4399  *
4400  * NOTE: the class name is not appropriate anymore, but we cannot change it
4401  * because we must keep serialization compatibility.
4402  *
4403  * @author Timothy Prinzing
4404  */
4405 class LightweightDispatcher implements java.io.Serializable, AWTEventListener {
4406 
4407     /*
4408      * JDK 1.1 serialVersionUID
4409      */
4410     private static final long serialVersionUID = 5184291520170872969L;
4411     /*
4412      * Our own mouse event for when we're dragged over from another hw
4413      * container
4414      */
4415     private static final int  LWD_MOUSE_DRAGGED_OVER = 1500;
4416 
4417     private static final PlatformLogger eventLog = PlatformLogger.getLogger("java.awt.event.LightweightDispatcher");
4418 
4419     private static final int BUTTONS_DOWN_MASK;
4420 
4421     static {
4422         int[] buttonsDownMask = AWTAccessor.getInputEventAccessor().
4423                 getButtonDownMasks();
4424         int mask = 0;
4425         for (int buttonDownMask : buttonsDownMask) {
4426             mask |= buttonDownMask;
4427         }
4428         BUTTONS_DOWN_MASK = mask;
4429     }
4430 
4431     LightweightDispatcher(Container nativeContainer) {
4432         this.nativeContainer = nativeContainer;
4433         mouseEventTarget = new WeakReference<>(null);
4434         targetLastEntered = new WeakReference<>(null);
4435         targetLastEnteredDT = new WeakReference<>(null);
4436         eventMask = 0;
4437     }
4438 
4439     /*
4440      * Clean up any resources allocated when dispatcher was created;
4441      * should be called from Container.removeNotify
4442      */
4443     void dispose() {
4444         //System.out.println("Disposing lw dispatcher");
4445         stopListeningForOtherDrags();
4446         mouseEventTarget.clear();
4447         targetLastEntered.clear();
4448         targetLastEnteredDT.clear();
4449     }
4450 
4451     /**
4452      * Enables events to subcomponents.
4453      */
4454     void enableEvents(long events) {
4455         eventMask |= events;
4456     }
4457 
4458     /**
4459      * Dispatches an event to a sub-component if necessary, and
4460      * returns whether or not the event was forwarded to a
4461      * sub-component.
4462      *
4463      * @param e the event
4464      */
4465     boolean dispatchEvent(AWTEvent e) {
4466         boolean ret = false;
4467 
4468         /*
4469          * Fix for BugTraq Id 4389284.
4470          * Dispatch SunDropTargetEvents regardless of eventMask value.
4471          * Do not update cursor on dispatching SunDropTargetEvents.
4472          */
4473         if (e instanceof SunDropTargetEvent) {
4474 
4475             SunDropTargetEvent sdde = (SunDropTargetEvent) e;
4476             ret = processDropTargetEvent(sdde);
4477 
4478         } else {
4479             if (e instanceof MouseEvent && (eventMask & MOUSE_MASK) != 0) {
4480                 MouseEvent me = (MouseEvent) e;
4481                 ret = processMouseEvent(me);
4482             }
4483 
4484             if (e.getID() == MouseEvent.MOUSE_MOVED) {
4485                 nativeContainer.updateCursorImmediately();
4486             }
4487         }
4488 
4489         return ret;
4490     }
4491 
4492     /* This method effectively returns whether or not a mouse button was down
4493      * just BEFORE the event happened.  A better method name might be
4494      * wasAMouseButtonDownBeforeThisEvent().
4495      */
4496     private boolean isMouseGrab(MouseEvent e) {
4497         int modifiers = e.getModifiersEx();
4498 
4499         if (e.getID() == MouseEvent.MOUSE_PRESSED
4500                 || e.getID() == MouseEvent.MOUSE_RELEASED) {
4501             modifiers ^= InputEvent.getMaskForButton(e.getButton());
4502         }
4503         /* modifiers now as just before event */
4504         return ((modifiers & BUTTONS_DOWN_MASK) != 0);
4505     }
4506 
4507     /**
4508      * This method attempts to distribute a mouse event to a lightweight
4509      * component.  It tries to avoid doing any unnecessary probes down
4510      * into the component tree to minimize the overhead of determining
4511      * where to route the event, since mouse movement events tend to
4512      * come in large and frequent amounts.
4513      */
4514     private boolean processMouseEvent(MouseEvent e) {
4515         int id = e.getID();
4516         Component mouseOver =   // sensitive to mouse events
4517             nativeContainer.getMouseEventTarget(e.getX(), e.getY(),
4518                                                 Container.INCLUDE_SELF);
4519 
4520         trackMouseEnterExit(mouseOver, e);
4521 
4522         Component met = mouseEventTarget.get();
4523         // 4508327 : MOUSE_CLICKED should only go to the recipient of
4524         // the accompanying MOUSE_PRESSED, so don't reset mouseEventTarget on a
4525         // MOUSE_CLICKED.
4526         if (!isMouseGrab(e) && id != MouseEvent.MOUSE_CLICKED) {
4527             met = (mouseOver != nativeContainer) ? mouseOver : null;
4528             mouseEventTarget = new WeakReference<>(met);
4529         }
4530 
4531         if (met != null) {
4532             switch (id) {
4533                 case MouseEvent.MOUSE_ENTERED:
4534                 case MouseEvent.MOUSE_EXITED:
4535                     break;
4536                 case MouseEvent.MOUSE_PRESSED:
4537                     retargetMouseEvent(met, id, e);
4538                     break;
4539                 case MouseEvent.MOUSE_RELEASED:
4540                     retargetMouseEvent(met, id, e);
4541                     break;
4542                 case MouseEvent.MOUSE_CLICKED:
4543                     // 4508327: MOUSE_CLICKED should never be dispatched to a Component
4544                     // other than that which received the MOUSE_PRESSED event.  If the
4545                     // mouse is now over a different Component, don't dispatch the event.
4546                     // The previous fix for a similar problem was associated with bug
4547                     // 4155217.
4548                     if (mouseOver == met) {
4549                         retargetMouseEvent(mouseOver, id, e);
4550                     }
4551                     break;
4552                 case MouseEvent.MOUSE_MOVED:
4553                     retargetMouseEvent(met, id, e);
4554                     break;
4555                 case MouseEvent.MOUSE_DRAGGED:
4556                     if (isMouseGrab(e)) {
4557                         retargetMouseEvent(met, id, e);
4558                     }
4559                     break;
4560                 case MouseEvent.MOUSE_WHEEL:
4561                     // This may send it somewhere that doesn't have MouseWheelEvents
4562                     // enabled.  In this case, Component.dispatchEventImpl() will
4563                     // retarget the event to a parent that DOES have the events enabled.
4564                     if (eventLog.isLoggable(PlatformLogger.Level.FINEST) && (mouseOver != null)) {
4565                         eventLog.finest("retargeting mouse wheel to " +
4566                                 mouseOver.getName() + ", " +
4567                                 mouseOver.getClass());
4568                     }
4569                     retargetMouseEvent(mouseOver, id, e);
4570                     break;
4571             }
4572             //Consuming of wheel events is implemented in "retargetMouseEvent".
4573             if (id != MouseEvent.MOUSE_WHEEL) {
4574                 e.consume();
4575             }
4576         }
4577         return e.isConsumed();
4578     }
4579 
4580     private boolean processDropTargetEvent(SunDropTargetEvent e) {
4581         int id = e.getID();
4582         int x = e.getX();
4583         int y = e.getY();
4584 
4585         /*
4586          * Fix for BugTraq ID 4395290.
4587          * It is possible that SunDropTargetEvent's Point is outside of the
4588          * native container bounds. In this case we truncate coordinates.
4589          */
4590         if (!nativeContainer.contains(x, y)) {
4591             final Dimension d = nativeContainer.getSize();
4592             if (d.width <= x) {
4593                 x = d.width - 1;
4594             } else if (x < 0) {
4595                 x = 0;
4596             }
4597             if (d.height <= y) {
4598                 y = d.height - 1;
4599             } else if (y < 0) {
4600                 y = 0;
4601             }
4602         }
4603         Component mouseOver =   // not necessarily sensitive to mouse events
4604             nativeContainer.getDropTargetEventTarget(x, y,
4605                                                      Container.INCLUDE_SELF);
4606         trackMouseEnterExit(mouseOver, e);
4607 
4608         if (mouseOver != nativeContainer && mouseOver != null) {
4609             switch (id) {
4610             case SunDropTargetEvent.MOUSE_ENTERED:
4611             case SunDropTargetEvent.MOUSE_EXITED:
4612                 break;
4613             default:
4614                 retargetMouseEvent(mouseOver, id, e);
4615                 e.consume();
4616                 break;
4617             }
4618         }
4619         return e.isConsumed();
4620     }
4621 
4622     /*
4623      * Generates dnd enter/exit events as mouse moves over lw components
4624      * @param targetOver       Target mouse is over (including native container)
4625      * @param e                SunDropTarget mouse event in native container
4626      */
4627     private void trackDropTargetEnterExit(Component targetOver, MouseEvent e) {
4628         int id = e.getID();
4629         if (id == MouseEvent.MOUSE_ENTERED && isMouseDTInNativeContainer) {
4630             // This can happen if a lightweight component which initiated the
4631             // drag has an associated drop target. MOUSE_ENTERED comes when the
4632             // mouse is in the native container already. To propagate this event
4633             // properly we should null out targetLastEntered.
4634             targetLastEnteredDT.clear();
4635         } else if (id == MouseEvent.MOUSE_ENTERED) {
4636             isMouseDTInNativeContainer = true;
4637         } else if (id == MouseEvent.MOUSE_EXITED) {
4638             isMouseDTInNativeContainer = false;
4639         }
4640         Component tle = retargetMouseEnterExit(targetOver, e,
4641                                                      targetLastEnteredDT.get(),
4642                                                      isMouseDTInNativeContainer);
4643         targetLastEnteredDT = new WeakReference<>(tle);
4644     }
4645 
4646     /*
4647      * Generates enter/exit events as mouse moves over lw components
4648      * @param targetOver        Target mouse is over (including native container)
4649      * @param e                 Mouse event in native container
4650      */
4651     private void trackMouseEnterExit(Component targetOver, MouseEvent e) {
4652         if (e instanceof SunDropTargetEvent) {
4653             trackDropTargetEnterExit(targetOver, e);
4654             return;
4655         }
4656         int id = e.getID();
4657 
4658         if ( id != MouseEvent.MOUSE_EXITED &&
4659              id != MouseEvent.MOUSE_DRAGGED &&
4660              id != LWD_MOUSE_DRAGGED_OVER &&
4661                 !isMouseInNativeContainer) {
4662             // any event but an exit or drag means we're in the native container
4663             isMouseInNativeContainer = true;
4664             startListeningForOtherDrags();
4665         } else if (id == MouseEvent.MOUSE_EXITED) {
4666             isMouseInNativeContainer = false;
4667             stopListeningForOtherDrags();
4668         }
4669         Component tle = retargetMouseEnterExit(targetOver, e,
4670                                                    targetLastEntered.get(),
4671                                                    isMouseInNativeContainer);
4672         targetLastEntered = new WeakReference<>(tle);
4673     }
4674 
4675     private Component retargetMouseEnterExit(Component targetOver, MouseEvent e,
4676                                              Component lastEntered,
4677                                              boolean inNativeContainer) {
4678         int id = e.getID();
4679         Component targetEnter = inNativeContainer ? targetOver : null;
4680 
4681         if (lastEntered != targetEnter) {
4682             if (lastEntered != null) {
4683                 retargetMouseEvent(lastEntered, MouseEvent.MOUSE_EXITED, e);
4684             }
4685             if (id == MouseEvent.MOUSE_EXITED) {
4686                 // consume native exit event if we generate one
4687                 e.consume();
4688             }
4689 
4690             if (targetEnter != null) {
4691                 retargetMouseEvent(targetEnter, MouseEvent.MOUSE_ENTERED, e);
4692             }
4693             if (id == MouseEvent.MOUSE_ENTERED) {
4694                 // consume native enter event if we generate one
4695                 e.consume();
4696             }
4697         }
4698         return targetEnter;
4699     }
4700 
4701     /*
4702      * Listens to global mouse drag events so even drags originating
4703      * from other heavyweight containers will generate enter/exit
4704      * events in this container
4705      */
4706     private void startListeningForOtherDrags() {
4707         //System.out.println("Adding AWTEventListener");
4708         java.security.AccessController.doPrivileged(
4709             new java.security.PrivilegedAction<Object>() {
4710                 public Object run() {
4711                     nativeContainer.getToolkit().addAWTEventListener(
4712                         LightweightDispatcher.this,
4713                         AWTEvent.MOUSE_EVENT_MASK |
4714                         AWTEvent.MOUSE_MOTION_EVENT_MASK);
4715                     return null;
4716                 }
4717             }
4718         );
4719     }
4720 
4721     private void stopListeningForOtherDrags() {
4722         //System.out.println("Removing AWTEventListener");
4723         java.security.AccessController.doPrivileged(
4724             new java.security.PrivilegedAction<Object>() {
4725                 public Object run() {
4726                     nativeContainer.getToolkit().removeAWTEventListener(LightweightDispatcher.this);
4727                     return null;
4728                 }
4729             }
4730         );
4731     }
4732 
4733     /*
4734      * (Implementation of AWTEventListener)
4735      * Listen for drag events posted in other hw components so we can
4736      * track enter/exit regardless of where a drag originated
4737      */
4738     @SuppressWarnings("deprecation")
4739     public void eventDispatched(AWTEvent e) {
4740         boolean isForeignDrag = (e instanceof MouseEvent) &&
4741                                 !(e instanceof SunDropTargetEvent) &&
4742                                 (e.id == MouseEvent.MOUSE_DRAGGED) &&
4743                                 (e.getSource() != nativeContainer);
4744 
4745         if (!isForeignDrag) {
4746             // only interested in drags from other hw components
4747             return;
4748         }
4749 
4750         MouseEvent      srcEvent = (MouseEvent)e;
4751         MouseEvent      me;
4752 
4753         synchronized (nativeContainer.getTreeLock()) {
4754             Component srcComponent = srcEvent.getComponent();
4755 
4756             // component may have disappeared since drag event posted
4757             // (i.e. Swing hierarchical menus)
4758             if ( !srcComponent.isShowing() ) {
4759                 return;
4760             }
4761 
4762             // see 5083555
4763             // check if srcComponent is in any modal blocked window
4764             Component c = nativeContainer;
4765             while ((c != null) && !(c instanceof Window)) {
4766                 c = c.getParent_NoClientCode();
4767             }
4768             if ((c == null) || ((Window)c).isModalBlocked()) {
4769                 return;
4770             }
4771 
4772             //
4773             // create an internal 'dragged-over' event indicating
4774             // we are being dragged over from another hw component
4775             //
4776             me = new MouseEvent(nativeContainer,
4777                                LWD_MOUSE_DRAGGED_OVER,
4778                                srcEvent.getWhen(),
4779                                srcEvent.getModifiersEx() | srcEvent.getModifiers(),
4780                                srcEvent.getX(),
4781                                srcEvent.getY(),
4782                                srcEvent.getXOnScreen(),
4783                                srcEvent.getYOnScreen(),
4784                                srcEvent.getClickCount(),
4785                                srcEvent.isPopupTrigger(),
4786                                srcEvent.getButton());
4787             MouseEventAccessor meAccessor = AWTAccessor.getMouseEventAccessor();
4788             meAccessor.setCausedByTouchEvent(me,
4789                 meAccessor.isCausedByTouchEvent(srcEvent));
4790             ((AWTEvent)srcEvent).copyPrivateDataInto(me);
4791             // translate coordinates to this native container
4792             final Point ptSrcOrigin = srcComponent.getLocationOnScreen();
4793 
4794             if (AppContext.getAppContext() != nativeContainer.appContext) {
4795                 final MouseEvent mouseEvent = me;
4796                 Runnable r = new Runnable() {
4797                         public void run() {
4798                             if (!nativeContainer.isShowing() ) {
4799                                 return;
4800                             }
4801 
4802                             Point       ptDstOrigin = nativeContainer.getLocationOnScreen();
4803                             mouseEvent.translatePoint(ptSrcOrigin.x - ptDstOrigin.x,
4804                                               ptSrcOrigin.y - ptDstOrigin.y );
4805                             Component targetOver =
4806                                 nativeContainer.getMouseEventTarget(mouseEvent.getX(),
4807                                                                     mouseEvent.getY(),
4808                                                                     Container.INCLUDE_SELF);
4809                             trackMouseEnterExit(targetOver, mouseEvent);
4810                         }
4811                     };
4812                 SunToolkit.executeOnEventHandlerThread(nativeContainer, r);
4813                 return;
4814             } else {
4815                 if (!nativeContainer.isShowing() ) {
4816                     return;
4817                 }
4818 
4819                 Point   ptDstOrigin = nativeContainer.getLocationOnScreen();
4820                 me.translatePoint( ptSrcOrigin.x - ptDstOrigin.x, ptSrcOrigin.y - ptDstOrigin.y );
4821             }
4822         }
4823         //System.out.println("Track event: " + me);
4824         // feed the 'dragged-over' event directly to the enter/exit
4825         // code (not a real event so don't pass it to dispatchEvent)
4826         Component targetOver =
4827             nativeContainer.getMouseEventTarget(me.getX(), me.getY(),
4828                                                 Container.INCLUDE_SELF);
4829         trackMouseEnterExit(targetOver, me);
4830     }
4831 
4832     /**
4833      * Sends a mouse event to the current mouse event recipient using
4834      * the given event (sent to the windowed host) as a srcEvent.  If
4835      * the mouse event target is still in the component tree, the
4836      * coordinates of the event are translated to those of the target.
4837      * If the target has been removed, we don't bother to send the
4838      * message.
4839      */
4840     @SuppressWarnings("deprecation")
4841     void retargetMouseEvent(Component target, int id, MouseEvent e) {
4842         if (target == null) {
4843             return; // mouse is over another hw component or target is disabled
4844         }
4845 
4846         int x = e.getX(), y = e.getY();
4847         Component component;
4848 
4849         for(component = target;
4850             component != null && component != nativeContainer;
4851             component = component.getParent()) {
4852             x -= component.x;
4853             y -= component.y;
4854         }
4855         MouseEvent retargeted;
4856         if (component != null) {
4857             if (e instanceof SunDropTargetEvent) {
4858                 retargeted = new SunDropTargetEvent(target,
4859                                                     id,
4860                                                     x,
4861                                                     y,
4862                                                     ((SunDropTargetEvent)e).getDispatcher());
4863             } else if (id == MouseEvent.MOUSE_WHEEL) {
4864                 retargeted = new MouseWheelEvent(target,
4865                                       id,
4866                                        e.getWhen(),
4867                                        e.getModifiersEx() | e.getModifiers(),
4868                                        x,
4869                                        y,
4870                                        e.getXOnScreen(),
4871                                        e.getYOnScreen(),
4872                                        e.getClickCount(),
4873                                        e.isPopupTrigger(),
4874                                        ((MouseWheelEvent)e).getScrollType(),
4875                                        ((MouseWheelEvent)e).getScrollAmount(),
4876                                        ((MouseWheelEvent)e).getWheelRotation(),
4877                                        ((MouseWheelEvent)e).getPreciseWheelRotation());
4878             }
4879             else {
4880                 retargeted = new MouseEvent(target,
4881                                             id,
4882                                             e.getWhen(),
4883                                             e.getModifiersEx() | e.getModifiers(),
4884                                             x,
4885                                             y,
4886                                             e.getXOnScreen(),
4887                                             e.getYOnScreen(),
4888                                             e.getClickCount(),
4889                                             e.isPopupTrigger(),
4890                                             e.getButton());
4891                 MouseEventAccessor meAccessor = AWTAccessor.getMouseEventAccessor();
4892                 meAccessor.setCausedByTouchEvent(retargeted,
4893                     meAccessor.isCausedByTouchEvent(e));
4894             }
4895 
4896             ((AWTEvent)e).copyPrivateDataInto(retargeted);
4897 
4898             if (target == nativeContainer) {
4899                 // avoid recursively calling LightweightDispatcher...
4900                 ((Container)target).dispatchEventToSelf(retargeted);
4901             } else {
4902                 assert AppContext.getAppContext() == target.appContext;
4903 
4904                 if (nativeContainer.modalComp != null) {
4905                     if (((Container)nativeContainer.modalComp).isAncestorOf(target)) {
4906                         target.dispatchEvent(retargeted);
4907                     } else {
4908                         e.consume();
4909                     }
4910                 } else {
4911                     target.dispatchEvent(retargeted);
4912                 }
4913             }
4914             if (id == MouseEvent.MOUSE_WHEEL && retargeted.isConsumed()) {
4915                 //An exception for wheel bubbling to the native system.
4916                 //In "processMouseEvent" total event consuming for wheel events is skipped.
4917                 //Protection from bubbling of Java-accepted wheel events.
4918                 e.consume();
4919             }
4920         }
4921     }
4922 
4923     // --- member variables -------------------------------
4924 
4925     /**
4926      * The windowed container that might be hosting events for
4927      * subcomponents.
4928      */
4929     private Container nativeContainer;
4930 
4931     /**
4932      * This variable is not used, but kept for serialization compatibility
4933      */
4934     private Component focus;
4935 
4936     /**
4937      * The current subcomponent being hosted by this windowed
4938      * component that has events being forwarded to it.  If this
4939      * is null, there are currently no events being forwarded to
4940      * a subcomponent.
4941      */
4942     private transient WeakReference<Component> mouseEventTarget;
4943 
4944     /**
4945      * The last component entered by the {@code MouseEvent}.
4946      */
4947     private transient  WeakReference<Component> targetLastEntered;
4948 
4949     /**
4950      * The last component entered by the {@code SunDropTargetEvent}.
4951      */
4952     private transient  WeakReference<Component> targetLastEnteredDT;
4953 
4954     /**
4955      * Is the mouse over the native container.
4956      */
4957     private transient boolean isMouseInNativeContainer = false;
4958 
4959     /**
4960      * Is DnD over the native container.
4961      */
4962     private transient boolean isMouseDTInNativeContainer = false;
4963 
4964     /**
4965      * This variable is not used, but kept for serialization compatibility
4966      */
4967     private Cursor nativeCursor;
4968 
4969     /**
4970      * The event mask for contained lightweight components.  Lightweight
4971      * components need a windowed container to host window-related
4972      * events.  This separate mask indicates events that have been
4973      * requested by contained lightweight components without effecting
4974      * the mask of the windowed component itself.
4975      */
4976     private long eventMask;
4977 
4978     /**
4979      * The kind of events routed to lightweight components from windowed
4980      * hosts.
4981      */
4982     private static final long PROXY_EVENT_MASK =
4983         AWTEvent.FOCUS_EVENT_MASK |
4984         AWTEvent.KEY_EVENT_MASK |
4985         AWTEvent.MOUSE_EVENT_MASK |
4986         AWTEvent.MOUSE_MOTION_EVENT_MASK |
4987         AWTEvent.MOUSE_WHEEL_EVENT_MASK;
4988 
4989     private static final long MOUSE_MASK =
4990         AWTEvent.MOUSE_EVENT_MASK |
4991         AWTEvent.MOUSE_MOTION_EVENT_MASK |
4992         AWTEvent.MOUSE_WHEEL_EVENT_MASK;
4993 }
--- EOF ---