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