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