2 * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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.
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).
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.
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
27 import java.awt.dnd.DropTarget;
29 import java.awt.event.*;
31 import java.awt.peer.ContainerPeer;
32 import java.awt.peer.ComponentPeer;
33 import java.awt.peer.LightweightPeer;
35 import java.beans.PropertyChangeListener;
37 import java.io.IOException;
38 import java.io.ObjectInputStream;
39 import java.io.ObjectOutputStream;
40 import java.io.ObjectStreamField;
41 import java.io.PrintStream;
42 import java.io.PrintWriter;
44 import java.security.AccessController;
46 import java.util.Arrays;
47 import java.util.EventListener;
48 import java.util.HashSet;
51 import javax.accessibility.*;
53 import sun.util.logging.PlatformLogger;
55 import sun.awt.AppContext;
56 import sun.awt.AWTAccessor;
57 import sun.awt.CausedFocusEvent;
58 import sun.awt.PeerEvent;
59 import sun.awt.SunToolkit;
61 import sun.awt.dnd.SunDropTargetEvent;
63 import sun.java2d.pipe.Region;
65 import sun.security.action.GetBooleanAction;
68 * A generic Abstract Window Toolkit(AWT) container object is a component
69 * that can contain other AWT components.
71 * Components added to a container are tracked in a list. The order
72 * of the list will define the components' front-to-back stacking order
73 * within the container. If no index is specified when adding a
74 * component to a container, it will be added to the end of the list
75 * (and hence to the bottom of the stacking order).
77 * <b>Note</b>: For details on the focus subsystem, see
78 * <a href="http://java.sun.com/docs/books/tutorial/uiswing/misc/focus.html">
79 * How to Use the Focus Subsystem</a>,
80 * a section in <em>The Java Tutorial</em>, and the
81 * <a href="../../java/awt/doc-files/FocusSpec.html">Focus Specification</a>
82 * for more information.
84 * @author Arthur van Hoff
86 * @see #add(java.awt.Component, int)
87 * @see #getComponent(int)
91 public class Container extends Component {
93 private static final PlatformLogger log = PlatformLogger.getLogger("java.awt.Container");
94 private static final PlatformLogger eventLog = PlatformLogger.getLogger("java.awt.event.Container");
96 private static final Component[] EMPTY_ARRAY = new Component[0];
99 * The components in this container.
101 * @see #getComponents
103 private java.util.List<Component> component = new java.util.ArrayList<Component>();
106 * Layout manager for this container.
111 LayoutManager layoutMgr;
114 * Event router for lightweight components. If this container
115 * is native, this dispatcher takes care of forwarding and
116 * retargeting the events to lightweight components contained
119 private LightweightDispatcher dispatcher;
122 * The focus traversal policy that will manage keyboard traversal of this
123 * Container's children, if this Container is a focus cycle root. If the
124 * value is null, this Container inherits its policy from its focus-cycle-
125 * root ancestor. If all such ancestors of this Container have null
126 * policies, then the current KeyboardFocusManager's default policy is
127 * used. If the value is non-null, this policy will be inherited by all
128 * focus-cycle-root children that have no keyboard-traversal policy of
129 * their own (as will, recursively, their focus-cycle-root children).
131 * If this Container is not a focus cycle root, the value will be
132 * remembered, but will not be used or inherited by this or any other
133 * Containers until this Container is made a focus cycle root.
135 * @see #setFocusTraversalPolicy
136 * @see #getFocusTraversalPolicy
139 private transient FocusTraversalPolicy focusTraversalPolicy;
142 * Indicates whether this Component is the root of a focus traversal cycle.
143 * Once focus enters a traversal cycle, typically it cannot leave it via
144 * focus traversal unless one of the up- or down-cycle keys is pressed.
145 * Normal traversal is limited to this Container, and all of this
146 * Container's descendants that are not descendants of inferior focus cycle
149 * @see #setFocusCycleRoot
150 * @see #isFocusCycleRoot
153 private boolean focusCycleRoot = false;
157 * Stores the value of focusTraversalPolicyProvider property.
159 * @see #setFocusTraversalPolicyProvider
161 private boolean focusTraversalPolicyProvider;
163 // keeps track of the threads that are printing this component
164 private transient Set printingThreads;
165 // True if there is at least one thread that's printing this component
166 private transient boolean printing = false;
168 transient ContainerListener containerListener;
170 /* HierarchyListener and HierarchyBoundsListener support */
171 transient int listeningChildren;
172 transient int listeningBoundsChildren;
173 transient int descendantsCount;
175 /* Non-opaque window support -- see Window.setLayersOpaque */
176 transient Color preserveBackgroundColor = null;
179 * JDK 1.1 serialVersionUID
181 private static final long serialVersionUID = 4613797578919906343L;
184 * A constant which toggles one of the controllable behaviors
185 * of <code>getMouseEventTarget</code>. It is used to specify whether
186 * the method can return the Container on which it is originally called
187 * in case if none of its children are the current mouse event targets.
189 * @see #getMouseEventTarget(int, int, boolean, boolean, boolean)
191 static final boolean INCLUDE_SELF = true;
194 * A constant which toggles one of the controllable behaviors
195 * of <code>getMouseEventTarget</code>. It is used to specify whether
196 * the method should search only lightweight components.
198 * @see #getMouseEventTarget(int, int, boolean, boolean, boolean)
200 static final boolean SEARCH_HEAVYWEIGHTS = true;
203 * Number of HW or LW components in this container (including
204 * all descendant containers).
206 private transient int numOfHWComponents = 0;
207 private transient int numOfLWComponents = 0;
209 private static final PlatformLogger mixingLog = PlatformLogger.getLogger("java.awt.mixing.Container");
212 * @serialField ncomponents int
213 * The number of components in this container.
214 * This value can be null.
215 * @serialField component Component[]
216 * The components in this container.
217 * @serialField layoutMgr LayoutManager
218 * Layout manager for this container.
219 * @serialField dispatcher LightweightDispatcher
220 * Event router for lightweight components. If this container
221 * is native, this dispatcher takes care of forwarding and
222 * retargeting the events to lightweight components contained
224 * @serialField maxSize Dimension
225 * Maximum size of this Container.
226 * @serialField focusCycleRoot boolean
227 * Indicates whether this Component is the root of a focus traversal cycle.
228 * Once focus enters a traversal cycle, typically it cannot leave it via
229 * focus traversal unless one of the up- or down-cycle keys is pressed.
230 * Normal traversal is limited to this Container, and all of this
231 * Container's descendants that are not descendants of inferior focus cycle
233 * @serialField containerSerializedDataVersion int
234 * Container Serial Data Version.
235 * @serialField focusTraversalPolicyProvider boolean
236 * Stores the value of focusTraversalPolicyProvider property.
238 private static final ObjectStreamField[] serialPersistentFields = {
239 new ObjectStreamField("ncomponents", Integer.TYPE),
240 new ObjectStreamField("component", Component[].class),
241 new ObjectStreamField("layoutMgr", LayoutManager.class),
242 new ObjectStreamField("dispatcher", LightweightDispatcher.class),
243 new ObjectStreamField("maxSize", Dimension.class),
244 new ObjectStreamField("focusCycleRoot", Boolean.TYPE),
245 new ObjectStreamField("containerSerializedDataVersion", Integer.TYPE),
246 new ObjectStreamField("focusTraversalPolicyProvider", Boolean.TYPE),
250 /* ensure that the necessary native libraries are loaded */
251 Toolkit.loadLibraries();
252 if (!GraphicsEnvironment.isHeadless()) {
256 AWTAccessor.setContainerAccessor(new AWTAccessor.ContainerAccessor() {
258 public void validateUnconditionally(Container cont) {
259 cont.validateUnconditionally();
265 * Initialize JNI field and method IDs for fields that may be
268 private static native void initIDs();
271 * Constructs a new Container. Containers can be extended directly,
272 * but are lightweight in this case and must be contained by a parent
273 * somewhere higher up in the component tree that is native.
274 * (such as Frame for example).
279 void initializeFocusTraversalKeys() {
280 focusTraversalKeys = new Set[4];
284 * Gets the number of components in this panel.
286 * Note: This method should be called under AWT tree lock.
288 * @return the number of components in this panel.
291 * @see Component#getTreeLock()
293 public int getComponentCount() {
294 return countComponents();
298 * @deprecated As of JDK version 1.1,
299 * replaced by getComponentCount().
302 public int countComponents() {
303 // This method is not synchronized under AWT tree lock.
304 // Instead, the calling code is responsible for the
305 // synchronization. See 6784816 for details.
306 return component.size();
310 * Gets the nth component in this container.
312 * Note: This method should be called under AWT tree lock.
314 * @param n the index of the component to get.
315 * @return the n<sup>th</sup> component in this container.
316 * @exception ArrayIndexOutOfBoundsException
317 * if the n<sup>th</sup> value does not exist.
318 * @see Component#getTreeLock()
320 public Component getComponent(int n) {
321 // This method is not synchronized under AWT tree lock.
322 // Instead, the calling code is responsible for the
323 // synchronization. See 6784816 for details.
325 return component.get(n);
326 } catch (IndexOutOfBoundsException z) {
327 throw new ArrayIndexOutOfBoundsException("No such child: " + n);
332 * Gets all the components in this container.
334 * Note: This method should be called under AWT tree lock.
336 * @return an array of all the components in this container.
337 * @see Component#getTreeLock()
339 public Component[] getComponents() {
340 // This method is not synchronized under AWT tree lock.
341 // Instead, the calling code is responsible for the
342 // synchronization. See 6784816 for details.
343 return getComponents_NoClientCode();
346 // NOTE: This method may be called by privileged threads.
347 // This functionality is implemented in a package-private method
348 // to insure that it cannot be overridden by client subclasses.
349 // DO NOT INVOKE CLIENT CODE ON THIS THREAD!
350 final Component[] getComponents_NoClientCode() {
351 return component.toArray(EMPTY_ARRAY);
355 * Wrapper for getComponents() method with a proper synchronization.
357 Component[] getComponentsSync() {
358 synchronized (getTreeLock()) {
359 return getComponents();
364 * Determines the insets of this container, which indicate the size
365 * of the container's border.
367 * A <code>Frame</code> object, for example, has a top inset that
368 * corresponds to the height of the frame's title bar.
369 * @return the insets of this container.
374 public Insets getInsets() {
379 * @deprecated As of JDK version 1.1,
380 * replaced by <code>getInsets()</code>.
383 public Insets insets() {
384 ComponentPeer peer = this.peer;
385 if (peer instanceof ContainerPeer) {
386 ContainerPeer cpeer = (ContainerPeer)peer;
387 return (Insets)cpeer.getInsets().clone();
389 return new Insets(0, 0, 0, 0);
393 * Appends the specified component to the end of this container.
394 * This is a convenience method for {@link #addImpl}.
396 * This method changes layout-related information, and therefore,
397 * invalidates the component hierarchy. If the container has already been
398 * displayed, the hierarchy must be validated thereafter in order to
399 * display the added component.
401 * @param comp the component to be added
402 * @exception NullPointerException if {@code comp} is {@code null}
406 * @see javax.swing.JComponent#revalidate()
407 * @return the component argument
409 public Component add(Component comp) {
410 addImpl(comp, null, -1);
415 * Adds the specified component to this container.
416 * This is a convenience method for {@link #addImpl}.
418 * This method is obsolete as of 1.1. Please use the
419 * method <code>add(Component, Object)</code> instead.
421 * This method changes layout-related information, and therefore,
422 * invalidates the component hierarchy. If the container has already been
423 * displayed, the hierarchy must be validated thereafter in order to
424 * display the added component.
426 * @exception NullPointerException if {@code comp} is {@code null}
427 * @see #add(Component, Object)
430 public Component add(String name, Component comp) {
431 addImpl(comp, name, -1);
436 * Adds the specified component to this container at the given
438 * This is a convenience method for {@link #addImpl}.
440 * This method changes layout-related information, and therefore,
441 * invalidates the component hierarchy. If the container has already been
442 * displayed, the hierarchy must be validated thereafter in order to
443 * display the added component.
446 * @param comp the component to be added
447 * @param index the position at which to insert the component,
448 * or <code>-1</code> to append the component to the end
449 * @exception NullPointerException if {@code comp} is {@code null}
450 * @exception IllegalArgumentException if {@code index} is invalid (see
451 * {@link #addImpl} for details)
452 * @return the component <code>comp</code>
457 * @see javax.swing.JComponent#revalidate()
459 public Component add(Component comp, int index) {
460 addImpl(comp, null, index);
465 * Checks that the component
466 * isn't supposed to be added into itself.
468 private void checkAddToSelf(Component comp){
469 if (comp instanceof Container) {
470 for (Container cn = this; cn != null; cn=cn.parent) {
472 throw new IllegalArgumentException("adding container's parent to itself");
479 * Checks that the component is not a Window instance.
481 private void checkNotAWindow(Component comp){
482 if (comp instanceof Window) {
483 throw new IllegalArgumentException("adding a window to a container");
488 * Checks that the component comp can be added to this container
489 * Checks : index in bounds of container's size,
490 * comp is not one of this container's parents,
491 * and comp is not a window.
492 * Comp and container must be on the same GraphicsDevice.
493 * if comp is container, all sub-components must be on
494 * same GraphicsDevice.
498 private void checkAdding(Component comp, int index) {
501 GraphicsConfiguration thisGC = getGraphicsConfiguration();
503 if (index > component.size() || index < 0) {
504 throw new IllegalArgumentException("illegal component position");
506 if (comp.parent == this) {
507 if (index == component.size()) {
508 throw new IllegalArgumentException("illegal component position " +
509 index + " should be less then " + component.size());
512 checkAddToSelf(comp);
513 checkNotAWindow(comp);
515 Window thisTopLevel = getContainingWindow();
516 Window compTopLevel = comp.getContainingWindow();
517 if (thisTopLevel != compTopLevel) {
518 throw new IllegalArgumentException("component and container should be in the same top-level window");
520 if (thisGC != null) {
521 comp.checkGD(thisGC.getDevice().getIDstring());
526 * Removes component comp from this container without making unneccessary changes
527 * and generating unneccessary events. This function intended to perform optimized
528 * remove, for example, if newParent and current parent are the same it just changes
529 * index without calling removeNotify.
530 * Note: Should be called while holding treeLock
531 * Returns whether removeNotify was invoked
534 private boolean removeDelicately(Component comp, Container newParent, int newIndex) {
537 int index = getComponentZOrder(comp);
538 boolean needRemoveNotify = isRemoveNotifyNeeded(comp, this, newParent);
539 if (needRemoveNotify) {
542 if (newParent != this) {
543 if (layoutMgr != null) {
544 layoutMgr.removeLayoutComponent(comp);
546 adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK,
547 -comp.numListening(AWTEvent.HIERARCHY_EVENT_MASK));
548 adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
549 -comp.numListening(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));
550 adjustDescendants(-(comp.countHierarchyMembers()));
553 if (needRemoveNotify) {
554 comp.setGraphicsConfiguration(null);
556 component.remove(index);
560 // We should remove component and then
561 // add it by the newIndex without newIndex decrement if even we shift components to the left
562 // after remove. Consult the rules below:
563 // 2->4: 012345 -> 013425, 2->5: 012345 -> 013452
564 // 4->2: 012345 -> 014235
565 component.remove(index);
566 component.add(newIndex, comp);
568 if (comp.parent == null) { // was actually removed
569 if (containerListener != null ||
570 (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 ||
571 Toolkit.enabledOnToolkit(AWTEvent.CONTAINER_EVENT_MASK)) {
572 ContainerEvent e = new ContainerEvent(this,
573 ContainerEvent.COMPONENT_REMOVED,
578 comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, comp,
579 this, HierarchyEvent.PARENT_CHANGED,
580 Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK));
581 if (peer != null && layoutMgr == null && isVisible()) {
582 updateCursorImmediately();
585 return needRemoveNotify;
589 * Checks whether this container can contain component which is focus owner.
590 * Verifies that container is enable and showing, and if it is focus cycle root
591 * its FTP allows component to be focus owner
594 boolean canContainFocusOwner(Component focusOwnerCandidate) {
595 if (!(isEnabled() && isDisplayable()
596 && isVisible() && isFocusable()))
600 if (isFocusCycleRoot()) {
601 FocusTraversalPolicy policy = getFocusTraversalPolicy();
602 if (policy instanceof DefaultFocusTraversalPolicy) {
603 if (!((DefaultFocusTraversalPolicy)policy).accept(focusOwnerCandidate)) {
608 synchronized(getTreeLock()) {
609 if (parent != null) {
610 return parent.canContainFocusOwner(focusOwnerCandidate);
617 * Checks whether or not this container has heavyweight children.
618 * Note: Should be called while holding tree lock
619 * @return true if there is at least one heavyweight children in a container, false otherwise
622 final boolean hasHeavyweightDescendants() {
624 return numOfHWComponents > 0;
628 * Checks whether or not this container has lightweight children.
629 * Note: Should be called while holding tree lock
630 * @return true if there is at least one lightweight children in a container, false otherwise
633 final boolean hasLightweightDescendants() {
635 return numOfLWComponents > 0;
639 * Returns closest heavyweight component to this container. If this container is heavyweight
643 Container getHeavyweightContainer() {
645 if (peer != null && !(peer instanceof LightweightPeer)) {
648 return getNativeContainer();
653 * Detects whether or not remove from current parent and adding to new parent requires call of
654 * removeNotify on the component. Since removeNotify destroys native window this might (not)
655 * be required. For example, if new container and old containers are the same we don't need to
656 * destroy native window.
659 private static boolean isRemoveNotifyNeeded(Component comp, Container oldContainer, Container newContainer) {
660 if (oldContainer == null) { // Component didn't have parent - no removeNotify
663 if (comp.peer == null) { // Component didn't have peer - no removeNotify
666 if (newContainer.peer == null) {
667 // Component has peer but new Container doesn't - call removeNotify
671 // If component is lightweight non-Container or lightweight Container with all but heavyweight
672 // children there is no need to call remove notify
673 if (comp.isLightweight()) {
674 boolean isContainer = comp instanceof Container;
676 if (!isContainer || (isContainer && !((Container)comp).hasHeavyweightDescendants())) {
681 // If this point is reached, then the comp is either a HW or a LW container with HW descendants.
683 // All three components have peers, check for peer change
684 Container newNativeContainer = oldContainer.getHeavyweightContainer();
685 Container oldNativeContainer = newContainer.getHeavyweightContainer();
686 if (newNativeContainer != oldNativeContainer) {
687 // Native containers change - check whether or not current platform supports
688 // changing of widget hierarchy on native level without recreation.
689 // The current implementation forbids reparenting of LW containers with HW descendants
690 // into another native container w/o destroying the peers. Actually such an operation
691 // is quite rare. If we ever need to save the peers, we'll have to slightly change the
692 // addDelicately() method in order to handle such LW containers recursively, reparenting
693 // each HW descendant independently.
694 return !comp.peer.isReparentSupported();
701 * Moves the specified component to the specified z-order index in
702 * the container. The z-order determines the order that components
703 * are painted; the component with the highest z-order paints first
704 * and the component with the lowest z-order paints last.
705 * Where components overlap, the component with the lower
706 * z-order paints over the component with the higher z-order.
708 * If the component is a child of some other container, it is
709 * removed from that container before being added to this container.
710 * The important difference between this method and
711 * <code>java.awt.Container.add(Component, int)</code> is that this method
712 * doesn't call <code>removeNotify</code> on the component while
713 * removing it from its previous container unless necessary and when
714 * allowed by the underlying native windowing system. This way, if the
715 * component has the keyboard focus, it maintains the focus when
716 * moved to the new position.
718 * This property is guaranteed to apply only to lightweight
719 * non-<code>Container</code> components.
721 * This method changes layout-related information, and therefore,
722 * invalidates the component hierarchy.
724 * <b>Note</b>: Not all platforms support changing the z-order of
725 * heavyweight components from one container into another without
726 * the call to <code>removeNotify</code>. There is no way to detect
727 * whether a platform supports this, so developers shouldn't make
730 * @param comp the component to be moved
731 * @param index the position in the container's list to
732 * insert the component, where <code>getComponentCount()</code>
734 * @exception NullPointerException if <code>comp</code> is
736 * @exception IllegalArgumentException if <code>comp</code> is one of the
737 * container's parents
738 * @exception IllegalArgumentException if <code>index</code> is not in
739 * the range <code>[0, getComponentCount()]</code> for moving
740 * between containers, or not in the range
741 * <code>[0, getComponentCount()-1]</code> for moving inside
743 * @exception IllegalArgumentException if adding a container to itself
744 * @exception IllegalArgumentException if adding a <code>Window</code>
746 * @see #getComponentZOrder(java.awt.Component)
750 public void setComponentZOrder(Component comp, int index) {
751 synchronized (getTreeLock()) {
752 // Store parent because remove will clear it
753 Container curParent = comp.parent;
754 int oldZindex = getComponentZOrder(comp);
756 if (curParent == this && index == oldZindex) {
759 checkAdding(comp, index);
761 boolean peerRecreated = (curParent != null) ?
762 curParent.removeDelicately(comp, this, index) : false;
764 addDelicately(comp, curParent, index);
766 // If the oldZindex == -1, the component gets inserted,
767 // rather than it changes its z-order.
768 if (!peerRecreated && oldZindex != -1) {
769 // The new 'index' cannot be == -1.
770 // It gets checked at the checkAdding() method.
771 // Therefore both oldZIndex and index denote
772 // some existing positions at this point and
773 // this is actually a Z-order changing.
774 comp.mixOnZOrderChanging(oldZindex, index);
780 * Traverses the tree of components and reparents children heavyweight component
781 * to new heavyweight parent.
784 private void reparentTraverse(ContainerPeer parentPeer, Container child) {
787 for (int i = 0; i < child.getComponentCount(); i++) {
788 Component comp = child.getComponent(i);
789 if (comp.isLightweight()) {
790 // If components is lightweight check if it is container
791 // If it is container it might contain heavyweight children we need to reparent
792 if (comp instanceof Container) {
793 reparentTraverse(parentPeer, (Container)comp);
796 // Q: Need to update NativeInLightFixer?
797 comp.getPeer().reparent(parentPeer);
803 * Reparents child component peer to this container peer.
804 * Container must be heavyweight.
807 private void reparentChild(Component comp) {
812 if (comp.isLightweight()) {
813 // If component is lightweight container we need to reparent all its explicit heavyweight children
814 if (comp instanceof Container) {
815 // Traverse component's tree till depth-first until encountering heavyweight component
816 reparentTraverse((ContainerPeer)getPeer(), (Container)comp);
819 comp.getPeer().reparent((ContainerPeer)getPeer());
824 * Adds component to this container. Tries to minimize side effects of this adding -
825 * doesn't call remove notify if it is not required.
828 private void addDelicately(Component comp, Container curParent, int index) {
831 // Check if moving between containers
832 if (curParent != this) {
833 //index == -1 means add to the end.
837 component.add(index, comp);
840 comp.setGraphicsConfiguration(getGraphicsConfiguration());
842 adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK,
843 comp.numListening(AWTEvent.HIERARCHY_EVENT_MASK));
844 adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
845 comp.numListening(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));
846 adjustDescendants(comp.countHierarchyMembers());
848 if (index < component.size()) {
849 component.set(index, comp);
855 if (comp.peer == null) { // Remove notify was called or it didn't have peer - create new one
857 } else { // Both container and child have peers, it means child peer should be reparented.
858 // In both cases we need to reparent native widgets.
859 Container newNativeContainer = getHeavyweightContainer();
860 Container oldNativeContainer = curParent.getHeavyweightContainer();
861 if (oldNativeContainer != newNativeContainer) {
862 // Native container changed - need to reparent native widgets
863 newNativeContainer.reparentChild(comp);
867 if (!comp.isLightweight() && isLightweight()) {
868 // If component is heavyweight and one of the containers is lightweight
869 // the location of the component should be fixed.
870 comp.relocateComponent();
874 if (curParent != this) {
875 /* Notify the layout manager of the added component. */
876 if (layoutMgr != null) {
877 if (layoutMgr instanceof LayoutManager2) {
878 ((LayoutManager2)layoutMgr).addLayoutComponent(comp, null);
880 layoutMgr.addLayoutComponent(null, comp);
883 if (containerListener != null ||
884 (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 ||
885 Toolkit.enabledOnToolkit(AWTEvent.CONTAINER_EVENT_MASK)) {
886 ContainerEvent e = new ContainerEvent(this,
887 ContainerEvent.COMPONENT_ADDED,
891 comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, comp,
892 this, HierarchyEvent.PARENT_CHANGED,
893 Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK));
895 // If component is focus owner or parent container of focus owner check that after reparenting
896 // focus owner moved out if new container prohibit this kind of focus owner.
897 if (comp.isFocusOwner() && !comp.canBeFocusOwnerRecursively()) {
898 comp.transferFocus();
899 } else if (comp instanceof Container) {
900 Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
901 if (focusOwner != null && isParentOf(focusOwner) && !focusOwner.canBeFocusOwnerRecursively()) {
902 focusOwner.transferFocus();
906 comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, comp,
907 this, HierarchyEvent.HIERARCHY_CHANGED,
908 Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK));
911 if (peer != null && layoutMgr == null && isVisible()) {
912 updateCursorImmediately();
917 * Returns the z-order index of the component inside the container.
918 * The higher a component is in the z-order hierarchy, the lower
919 * its index. The component with the lowest z-order index is
920 * painted last, above all other child components.
922 * @param comp the component being queried
923 * @return the z-order index of the component; otherwise
924 * returns -1 if the component is <code>null</code>
925 * or doesn't belong to the container
926 * @see #setComponentZOrder(java.awt.Component, int)
929 public int getComponentZOrder(Component comp) {
933 synchronized(getTreeLock()) {
934 // Quick check - container should be immediate parent of the component
935 if (comp.parent != this) {
938 return component.indexOf(comp);
943 * Adds the specified component to the end of this container.
944 * Also notifies the layout manager to add the component to
945 * this container's layout using the specified constraints object.
946 * This is a convenience method for {@link #addImpl}.
948 * This method changes layout-related information, and therefore,
949 * invalidates the component hierarchy. If the container has already been
950 * displayed, the hierarchy must be validated thereafter in order to
951 * display the added component.
954 * @param comp the component to be added
955 * @param constraints an object expressing
956 * layout contraints for this component
957 * @exception NullPointerException if {@code comp} is {@code null}
961 * @see javax.swing.JComponent#revalidate()
965 public void add(Component comp, Object constraints) {
966 addImpl(comp, constraints, -1);
970 * Adds the specified component to this container with the specified
971 * constraints at the specified index. Also notifies the layout
972 * manager to add the component to the this container's layout using
973 * the specified constraints object.
974 * This is a convenience method for {@link #addImpl}.
976 * This method changes layout-related information, and therefore,
977 * invalidates the component hierarchy. If the container has already been
978 * displayed, the hierarchy must be validated thereafter in order to
979 * display the added component.
982 * @param comp the component to be added
983 * @param constraints an object expressing layout contraints for this
984 * @param index the position in the container's list at which to insert
985 * the component; <code>-1</code> means insert at the end
987 * @exception NullPointerException if {@code comp} is {@code null}
988 * @exception IllegalArgumentException if {@code index} is invalid (see
989 * {@link #addImpl} for details)
993 * @see javax.swing.JComponent#revalidate()
997 public void add(Component comp, Object constraints, int index) {
998 addImpl(comp, constraints, index);
1002 * Adds the specified component to this container at the specified
1003 * index. This method also notifies the layout manager to add
1004 * the component to this container's layout using the specified
1005 * constraints object via the <code>addLayoutComponent</code>
1008 * The constraints are
1009 * defined by the particular layout manager being used. For
1010 * example, the <code>BorderLayout</code> class defines five
1011 * constraints: <code>BorderLayout.NORTH</code>,
1012 * <code>BorderLayout.SOUTH</code>, <code>BorderLayout.EAST</code>,
1013 * <code>BorderLayout.WEST</code>, and <code>BorderLayout.CENTER</code>.
1015 * The <code>GridBagLayout</code> class requires a
1016 * <code>GridBagConstraints</code> object. Failure to pass
1017 * the correct type of constraints object results in an
1018 * <code>IllegalArgumentException</code>.
1020 * If the current layout manager implements {@code LayoutManager2}, then
1021 * {@link LayoutManager2#addLayoutComponent(Component,Object)} is invoked on
1022 * it. If the current layout manager does not implement
1023 * {@code LayoutManager2}, and constraints is a {@code String}, then
1024 * {@link LayoutManager#addLayoutComponent(String,Component)} is invoked on it.
1026 * If the component is not an ancestor of this container and has a non-null
1027 * parent, it is removed from its current parent before it is added to this
1030 * This is the method to override if a program needs to track
1031 * every add request to a container as all other add methods defer
1032 * to this one. An overriding method should
1033 * usually include a call to the superclass's version of the method:
1036 * <code>super.addImpl(comp, constraints, index)</code>
1039 * This method changes layout-related information, and therefore,
1040 * invalidates the component hierarchy. If the container has already been
1041 * displayed, the hierarchy must be validated thereafter in order to
1042 * display the added component.
1044 * @param comp the component to be added
1045 * @param constraints an object expressing layout constraints
1046 * for this component
1047 * @param index the position in the container's list at which to
1048 * insert the component, where <code>-1</code>
1049 * means append to the end
1050 * @exception IllegalArgumentException if {@code index} is invalid;
1051 * if {@code comp} is a child of this container, the valid
1052 * range is {@code [-1, getComponentCount()-1]}; if component is
1053 * not a child of this container, the valid range is
1054 * {@code [-1, getComponentCount()]}
1056 * @exception IllegalArgumentException if {@code comp} is an ancestor of
1058 * @exception IllegalArgumentException if adding a window to a container
1059 * @exception NullPointerException if {@code comp} is {@code null}
1060 * @see #add(Component)
1061 * @see #add(Component, int)
1062 * @see #add(Component, java.lang.Object)
1064 * @see LayoutManager
1065 * @see LayoutManager2
1068 protected void addImpl(Component comp, Object constraints, int index) {
1069 synchronized (getTreeLock()) {
1070 /* Check for correct arguments: index in bounds,
1071 * comp cannot be one of this container's parents,
1072 * and comp cannot be a window.
1073 * comp and container must be on the same GraphicsDevice.
1074 * if comp is container, all sub-components must be on
1075 * same GraphicsDevice.
1077 GraphicsConfiguration thisGC = this.getGraphicsConfiguration();
1079 if (index > component.size() || (index < 0 && index != -1)) {
1080 throw new IllegalArgumentException(
1081 "illegal component position");
1083 checkAddToSelf(comp);
1084 checkNotAWindow(comp);
1085 if (thisGC != null) {
1086 comp.checkGD(thisGC.getDevice().getIDstring());
1089 /* Reparent the component and tidy up the tree's state. */
1090 if (comp.parent != null) {
1091 comp.parent.remove(comp);
1092 if (index > component.size()) {
1093 throw new IllegalArgumentException("illegal component position");
1097 //index == -1 means add to the end.
1099 component.add(comp);
1101 component.add(index, comp);
1104 comp.setGraphicsConfiguration(thisGC);
1106 adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK,
1107 comp.numListening(AWTEvent.HIERARCHY_EVENT_MASK));
1108 adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
1109 comp.numListening(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));
1110 adjustDescendants(comp.countHierarchyMembers());
1112 invalidateIfValid();
1117 /* Notify the layout manager of the added component. */
1118 if (layoutMgr != null) {
1119 if (layoutMgr instanceof LayoutManager2) {
1120 ((LayoutManager2)layoutMgr).addLayoutComponent(comp, constraints);
1121 } else if (constraints instanceof String) {
1122 layoutMgr.addLayoutComponent((String)constraints, comp);
1125 if (containerListener != null ||
1126 (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 ||
1127 Toolkit.enabledOnToolkit(AWTEvent.CONTAINER_EVENT_MASK)) {
1128 ContainerEvent e = new ContainerEvent(this,
1129 ContainerEvent.COMPONENT_ADDED,
1134 comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, comp,
1135 this, HierarchyEvent.PARENT_CHANGED,
1136 Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK));
1137 if (peer != null && layoutMgr == null && isVisible()) {
1138 updateCursorImmediately();
1144 boolean updateGraphicsData(GraphicsConfiguration gc) {
1147 boolean ret = super.updateGraphicsData(gc);
1149 for (Component comp : component) {
1151 ret |= comp.updateGraphicsData(gc);
1158 * Checks that all Components that this Container contains are on
1159 * the same GraphicsDevice as this Container. If not, throws an
1160 * IllegalArgumentException.
1162 void checkGD(String stringID) {
1163 for (Component comp : component) {
1165 comp.checkGD(stringID);
1171 * Removes the component, specified by <code>index</code>,
1172 * from this container.
1173 * This method also notifies the layout manager to remove the
1174 * component from this container's layout via the
1175 * <code>removeLayoutComponent</code> method.
1177 * This method changes layout-related information, and therefore,
1178 * invalidates the component hierarchy. If the container has already been
1179 * displayed, the hierarchy must be validated thereafter in order to
1180 * reflect the changes.
1183 * @param index the index of the component to be removed
1184 * @throws ArrayIndexOutOfBoundsException if {@code index} is not in
1185 * range {@code [0, getComponentCount()-1]}
1189 * @see #getComponentCount
1192 public void remove(int index) {
1193 synchronized (getTreeLock()) {
1194 if (index < 0 || index >= component.size()) {
1195 throw new ArrayIndexOutOfBoundsException(index);
1197 Component comp = component.get(index);
1199 comp.removeNotify();
1201 if (layoutMgr != null) {
1202 layoutMgr.removeLayoutComponent(comp);
1205 adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK,
1206 -comp.numListening(AWTEvent.HIERARCHY_EVENT_MASK));
1207 adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
1208 -comp.numListening(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));
1209 adjustDescendants(-(comp.countHierarchyMembers()));
1212 component.remove(index);
1213 comp.setGraphicsConfiguration(null);
1215 invalidateIfValid();
1216 if (containerListener != null ||
1217 (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 ||
1218 Toolkit.enabledOnToolkit(AWTEvent.CONTAINER_EVENT_MASK)) {
1219 ContainerEvent e = new ContainerEvent(this,
1220 ContainerEvent.COMPONENT_REMOVED,
1225 comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, comp,
1226 this, HierarchyEvent.PARENT_CHANGED,
1227 Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK));
1228 if (peer != null && layoutMgr == null && isVisible()) {
1229 updateCursorImmediately();
1235 * Removes the specified component from this container.
1236 * This method also notifies the layout manager to remove the
1237 * component from this container's layout via the
1238 * <code>removeLayoutComponent</code> method.
1240 * This method changes layout-related information, and therefore,
1241 * invalidates the component hierarchy. If the container has already been
1242 * displayed, the hierarchy must be validated thereafter in order to
1243 * reflect the changes.
1245 * @param comp the component to be removed
1246 * @throws NullPointerException if {@code comp} is {@code null}
1252 public void remove(Component comp) {
1253 synchronized (getTreeLock()) {
1254 if (comp.parent == this) {
1255 int index = component.indexOf(comp);
1264 * Removes all the components from this container.
1265 * This method also notifies the layout manager to remove the
1266 * components from this container's layout via the
1267 * <code>removeLayoutComponent</code> method.
1269 * This method changes layout-related information, and therefore,
1270 * invalidates the component hierarchy. If the container has already been
1271 * displayed, the hierarchy must be validated thereafter in order to
1272 * reflect the changes.
1278 public void removeAll() {
1279 synchronized (getTreeLock()) {
1280 adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK,
1281 -listeningChildren);
1282 adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
1283 -listeningBoundsChildren);
1284 adjustDescendants(-descendantsCount);
1286 while (!component.isEmpty()) {
1287 Component comp = component.remove(component.size()-1);
1290 comp.removeNotify();
1292 if (layoutMgr != null) {
1293 layoutMgr.removeLayoutComponent(comp);
1296 comp.setGraphicsConfiguration(null);
1297 if (containerListener != null ||
1298 (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 ||
1299 Toolkit.enabledOnToolkit(AWTEvent.CONTAINER_EVENT_MASK)) {
1300 ContainerEvent e = new ContainerEvent(this,
1301 ContainerEvent.COMPONENT_REMOVED,
1306 comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED,
1308 HierarchyEvent.PARENT_CHANGED,
1309 Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK));
1311 if (peer != null && layoutMgr == null && isVisible()) {
1312 updateCursorImmediately();
1314 invalidateIfValid();
1318 // Should only be called while holding tree lock
1319 int numListening(long mask) {
1320 int superListening = super.numListening(mask);
1322 if (mask == AWTEvent.HIERARCHY_EVENT_MASK) {
1323 if (eventLog.isLoggable(PlatformLogger.FINE)) {
1324 // Verify listeningChildren is correct
1326 for (Component comp : component) {
1327 sum += comp.numListening(mask);
1329 if (listeningChildren != sum) {
1330 eventLog.fine("Assertion (listeningChildren == sum) failed");
1333 return listeningChildren + superListening;
1334 } else if (mask == AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) {
1335 if (eventLog.isLoggable(PlatformLogger.FINE)) {
1336 // Verify listeningBoundsChildren is correct
1338 for (Component comp : component) {
1339 sum += comp.numListening(mask);
1341 if (listeningBoundsChildren != sum) {
1342 eventLog.fine("Assertion (listeningBoundsChildren == sum) failed");
1345 return listeningBoundsChildren + superListening;
1348 if (eventLog.isLoggable(PlatformLogger.FINE)) {
1349 eventLog.fine("This code must never be reached");
1351 return superListening;
1355 // Should only be called while holding tree lock
1356 void adjustListeningChildren(long mask, int num) {
1357 if (eventLog.isLoggable(PlatformLogger.FINE)) {
1358 boolean toAssert = (mask == AWTEvent.HIERARCHY_EVENT_MASK ||
1359 mask == AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK ||
1360 mask == (AWTEvent.HIERARCHY_EVENT_MASK |
1361 AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));
1363 eventLog.fine("Assertion failed");
1370 if ((mask & AWTEvent.HIERARCHY_EVENT_MASK) != 0) {
1371 listeningChildren += num;
1373 if ((mask & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) != 0) {
1374 listeningBoundsChildren += num;
1377 adjustListeningChildrenOnParent(mask, num);
1380 // Should only be called while holding tree lock
1381 void adjustDescendants(int num) {
1385 descendantsCount += num;
1386 adjustDecendantsOnParent(num);
1389 // Should only be called while holding tree lock
1390 void adjustDecendantsOnParent(int num) {
1391 if (parent != null) {
1392 parent.adjustDescendants(num);
1396 // Should only be called while holding tree lock
1397 int countHierarchyMembers() {
1398 if (log.isLoggable(PlatformLogger.FINE)) {
1399 // Verify descendantsCount is correct
1401 for (Component comp : component) {
1402 sum += comp.countHierarchyMembers();
1404 if (descendantsCount != sum) {
1405 log.fine("Assertion (descendantsCount == sum) failed");
1408 return descendantsCount + 1;
1411 private int getListenersCount(int id, boolean enabledOnToolkit) {
1413 if (enabledOnToolkit) {
1414 return descendantsCount;
1417 case HierarchyEvent.HIERARCHY_CHANGED:
1418 return listeningChildren;
1419 case HierarchyEvent.ANCESTOR_MOVED:
1420 case HierarchyEvent.ANCESTOR_RESIZED:
1421 return listeningBoundsChildren;
1427 final int createHierarchyEvents(int id, Component changed,
1428 Container changedParent, long changeFlags, boolean enabledOnToolkit)
1431 int listeners = getListenersCount(id, enabledOnToolkit);
1433 for (int count = listeners, i = 0; count > 0; i++) {
1434 count -= component.get(i).createHierarchyEvents(id, changed,
1435 changedParent, changeFlags, enabledOnToolkit);
1438 super.createHierarchyEvents(id, changed, changedParent,
1439 changeFlags, enabledOnToolkit);
1442 final void createChildHierarchyEvents(int id, long changeFlags,
1443 boolean enabledOnToolkit)
1446 if (component.isEmpty()) {
1449 int listeners = getListenersCount(id, enabledOnToolkit);
1451 for (int count = listeners, i = 0; count > 0; i++) {
1452 count -= component.get(i).createHierarchyEvents(id, this, parent,
1453 changeFlags, enabledOnToolkit);
1458 * Gets the layout manager for this container.
1462 public LayoutManager getLayout() {
1467 * Sets the layout manager for this container.
1469 * This method changes layout-related information, and therefore,
1470 * invalidates the component hierarchy.
1472 * @param mgr the specified layout manager
1477 public void setLayout(LayoutManager mgr) {
1479 invalidateIfValid();
1483 * Causes this container to lay out its components. Most programs
1484 * should not call this method directly, but should invoke
1485 * the <code>validate</code> method instead.
1486 * @see LayoutManager#layoutContainer
1491 public void doLayout() {
1496 * @deprecated As of JDK version 1.1,
1497 * replaced by <code>doLayout()</code>.
1500 public void layout() {
1501 LayoutManager layoutMgr = this.layoutMgr;
1502 if (layoutMgr != null) {
1503 layoutMgr.layoutContainer(this);
1508 * Indicates if this container is a <i>validate root</i>.
1510 * Layout-related changes, such as bounds of the validate root descendants,
1511 * do not affect the layout of the validate root parent. This peculiarity
1512 * enables the {@code invalidate()} method to stop invalidating the
1513 * component hierarchy when the method encounters a validate root. However,
1514 * to preserve backward compatibility this new optimized behavior is
1515 * enabled only when the {@code java.awt.smartInvalidate} system property
1516 * value is set to {@code true}.
1518 * If a component hierarchy contains validate roots and the new optimized
1519 * {@code invalidate()} behavior is enabled, the {@code validate()} method
1520 * must be invoked on the validate root of a previously invalidated
1521 * component to restore the validity of the hierarchy later. Otherwise,
1522 * calling the {@code validate()} method on the top-level container (such
1523 * as a {@code Frame} object) should be used to restore the validity of the
1524 * component hierarchy.
1526 * The {@code Window} class and the {@code Applet} class are the validate
1527 * roots in AWT. Swing introduces more validate roots.
1529 * @return whether this container is a validate root
1531 * @see java.awt.Component#invalidate
1532 * @see javax.swing.JComponent#isValidateRoot
1533 * @see javax.swing.JComponent#revalidate
1536 public boolean isValidateRoot() {
1540 private static final boolean isJavaAwtSmartInvalidate;
1542 // Don't lazy-read because every app uses invalidate()
1543 isJavaAwtSmartInvalidate = AccessController.doPrivileged(
1544 new GetBooleanAction("java.awt.smartInvalidate"));
1548 * Invalidates the parent of the container unless the container
1549 * is a validate root.
1552 void invalidateParent() {
1553 if (!isJavaAwtSmartInvalidate || !isValidateRoot()) {
1554 super.invalidateParent();
1559 * Invalidates the container.
1561 * If the {@code LayoutManager} installed on this container is an instance
1562 * of the {@code LayoutManager2} interface, then
1563 * the {@link LayoutManager2#invalidateLayout(Container)} method is invoked
1564 * on it supplying this {@code Container} as the argument.
1566 * Afterwards this method marks this container invalid, and invalidates its
1567 * ancestors. See the {@link Component#invalidate} method for more details.
1571 * @see LayoutManager2
1574 public void invalidate() {
1575 LayoutManager layoutMgr = this.layoutMgr;
1576 if (layoutMgr instanceof LayoutManager2) {
1577 LayoutManager2 lm = (LayoutManager2) layoutMgr;
1578 lm.invalidateLayout(this);
1584 * Validates this container and all of its subcomponents.
1586 * Validating a container means laying out its subcomponents.
1587 * Layout-related changes, such as setting the bounds of a component, or
1588 * adding a component to the container, invalidate the container
1589 * automatically. Note that the ancestors of the container may be
1590 * invalidated also (see {@link Component#invalidate} for details.)
1591 * Therefore, to restore the validity of the hierarchy, the {@code
1592 * validate()} method should be invoked on the top-most invalid
1593 * container of the hierarchy.
1595 * Validating the container may be a quite time-consuming operation. For
1596 * performance reasons a developer may postpone the validation of the
1597 * hierarchy till a set of layout-related operations completes, e.g. after
1598 * adding all the children to the container.
1600 * If this {@code Container} is not valid, this method invokes
1601 * the {@code validateTree} method and marks this {@code Container}
1602 * as valid. Otherwise, no action is performed.
1604 * @see #add(java.awt.Component)
1606 * @see Container#isValidateRoot
1607 * @see javax.swing.JComponent#revalidate()
1608 * @see #validateTree
1610 public void validate() {
1611 boolean updateCur = false;
1612 synchronized (getTreeLock()) {
1613 if ((!isValid() || descendUnconditionallyWhenValidating)
1616 ContainerPeer p = null;
1617 if (peer instanceof ContainerPeer) {
1618 p = (ContainerPeer) peer;
1626 // Avoid updating cursor if this is an internal call.
1627 // See validateUnconditionally() for details.
1628 if (!descendUnconditionallyWhenValidating) {
1629 updateCur = isVisible();
1635 updateCursorImmediately();
1640 * Indicates whether valid containers should also traverse their
1641 * children and call the validateTree() method on them.
1643 * Synchronization: TreeLock.
1645 * The field is allowed to be static as long as the TreeLock itself is
1648 * @see #validateUnconditionally()
1650 private static boolean descendUnconditionallyWhenValidating = false;
1653 * Unconditionally validate the component hierarchy.
1655 final void validateUnconditionally() {
1656 boolean updateCur = false;
1657 synchronized (getTreeLock()) {
1658 descendUnconditionallyWhenValidating = true;
1661 if (peer instanceof ContainerPeer) {
1662 updateCur = isVisible();
1665 descendUnconditionallyWhenValidating = false;
1668 updateCursorImmediately();
1673 * Recursively descends the container tree and recomputes the
1674 * layout for any subtrees marked as needing it (those marked as
1675 * invalid). Synchronization should be provided by the method
1676 * that calls this one: <code>validate</code>.
1681 protected void validateTree() {
1683 if (!isValid() || descendUnconditionallyWhenValidating) {
1684 if (peer instanceof ContainerPeer) {
1685 ((ContainerPeer)peer).beginLayout();
1690 for (int i = 0; i < component.size(); i++) {
1691 Component comp = component.get(i);
1692 if ( (comp instanceof Container)
1693 && !(comp instanceof Window)
1694 && (!comp.isValid() ||
1695 descendUnconditionallyWhenValidating))
1697 ((Container)comp).validateTree();
1702 if (peer instanceof ContainerPeer) {
1703 ((ContainerPeer)peer).endLayout();
1710 * Recursively descends the container tree and invalidates all
1711 * contained components.
1713 void invalidateTree() {
1714 synchronized (getTreeLock()) {
1715 for (int i = 0; i < component.size(); i++) {
1716 Component comp = component.get(i);
1717 if (comp instanceof Container) {
1718 ((Container)comp).invalidateTree();
1721 comp.invalidateIfValid();
1724 invalidateIfValid();
1729 * Sets the font of this container.
1731 * This method changes layout-related information, and therefore,
1732 * invalidates the component hierarchy.
1734 * @param f The font to become this container's font.
1735 * @see Component#getFont
1739 public void setFont(Font f) {
1740 boolean shouldinvalidate = false;
1742 Font oldfont = getFont();
1744 Font newfont = getFont();
1745 if (newfont != oldfont && (oldfont == null ||
1746 !oldfont.equals(newfont))) {
1752 * Returns the preferred size of this container. If the preferred size has
1753 * not been set explicitly by {@link Component#setPreferredSize(Dimension)}
1754 * and this {@code Container} has a {@code non-null} {@link LayoutManager},
1755 * then {@link LayoutManager#preferredLayoutSize(Container)}
1756 * is used to calculate the preferred size.
1758 * <p>Note: some implementations may cache the value returned from the
1759 * {@code LayoutManager}. Implementations that cache need not invoke
1760 * {@code preferredLayoutSize} on the {@code LayoutManager} every time
1761 * this method is invoked, rather the {@code LayoutManager} will only
1762 * be queried after the {@code Container} becomes invalid.
1764 * @return an instance of <code>Dimension</code> that represents
1765 * the preferred size of this container.
1766 * @see #getMinimumSize
1767 * @see #getMaximumSize
1769 * @see LayoutManager#preferredLayoutSize(Container)
1770 * @see Component#getPreferredSize
1772 public Dimension getPreferredSize() {
1773 return preferredSize();
1777 * @deprecated As of JDK version 1.1,
1778 * replaced by <code>getPreferredSize()</code>.
1781 public Dimension preferredSize() {
1782 /* Avoid grabbing the lock if a reasonable cached size value
1785 Dimension dim = prefSize;
1786 if (dim == null || !(isPreferredSizeSet() || isValid())) {
1787 synchronized (getTreeLock()) {
1788 prefSize = (layoutMgr != null) ?
1789 layoutMgr.preferredLayoutSize(this) :
1790 super.preferredSize();
1795 return new Dimension(dim);
1803 * Returns the minimum size of this container. If the minimum size has
1804 * not been set explicitly by {@link Component#setMinimumSize(Dimension)}
1805 * and this {@code Container} has a {@code non-null} {@link LayoutManager},
1806 * then {@link LayoutManager#minimumLayoutSize(Container)}
1807 * is used to calculate the minimum size.
1809 * <p>Note: some implementations may cache the value returned from the
1810 * {@code LayoutManager}. Implementations that cache need not invoke
1811 * {@code minimumLayoutSize} on the {@code LayoutManager} every time
1812 * this method is invoked, rather the {@code LayoutManager} will only
1813 * be queried after the {@code Container} becomes invalid.
1815 * @return an instance of <code>Dimension</code> that represents
1816 * the minimum size of this container.
1817 * @see #getPreferredSize
1818 * @see #getMaximumSize
1820 * @see LayoutManager#minimumLayoutSize(Container)
1821 * @see Component#getMinimumSize
1824 public Dimension getMinimumSize() {
1825 return minimumSize();
1829 * @deprecated As of JDK version 1.1,
1830 * replaced by <code>getMinimumSize()</code>.
1833 public Dimension minimumSize() {
1834 /* Avoid grabbing the lock if a reasonable cached size value
1837 Dimension dim = minSize;
1838 if (dim == null || !(isMinimumSizeSet() || isValid())) {
1839 synchronized (getTreeLock()) {
1840 minSize = (layoutMgr != null) ?
1841 layoutMgr.minimumLayoutSize(this) :
1842 super.minimumSize();
1847 return new Dimension(dim);
1855 * Returns the maximum size of this container. If the maximum size has
1856 * not been set explicitly by {@link Component#setMaximumSize(Dimension)}
1857 * and the {@link LayoutManager} installed on this {@code Container}
1858 * is an instance of {@link LayoutManager2}, then
1859 * {@link LayoutManager2#maximumLayoutSize(Container)}
1860 * is used to calculate the maximum size.
1862 * <p>Note: some implementations may cache the value returned from the
1863 * {@code LayoutManager2}. Implementations that cache need not invoke
1864 * {@code maximumLayoutSize} on the {@code LayoutManager2} every time
1865 * this method is invoked, rather the {@code LayoutManager2} will only
1866 * be queried after the {@code Container} becomes invalid.
1868 * @return an instance of <code>Dimension</code> that represents
1869 * the maximum size of this container.
1870 * @see #getPreferredSize
1871 * @see #getMinimumSize
1873 * @see LayoutManager2#maximumLayoutSize(Container)
1874 * @see Component#getMaximumSize
1876 public Dimension getMaximumSize() {
1877 /* Avoid grabbing the lock if a reasonable cached size value
1880 Dimension dim = maxSize;
1881 if (dim == null || !(isMaximumSizeSet() || isValid())) {
1882 synchronized (getTreeLock()) {
1883 if (layoutMgr instanceof LayoutManager2) {
1884 LayoutManager2 lm = (LayoutManager2) layoutMgr;
1885 maxSize = lm.maximumLayoutSize(this);
1887 maxSize = super.getMaximumSize();
1893 return new Dimension(dim);
1901 * Returns the alignment along the x axis. This specifies how
1902 * the component would like to be aligned relative to other
1903 * components. The value should be a number between 0 and 1
1904 * where 0 represents alignment along the origin, 1 is aligned
1905 * the furthest away from the origin, 0.5 is centered, etc.
1907 public float getAlignmentX() {
1909 if (layoutMgr instanceof LayoutManager2) {
1910 synchronized (getTreeLock()) {
1911 LayoutManager2 lm = (LayoutManager2) layoutMgr;
1912 xAlign = lm.getLayoutAlignmentX(this);
1915 xAlign = super.getAlignmentX();
1921 * Returns the alignment along the y axis. This specifies how
1922 * the component would like to be aligned relative to other
1923 * components. The value should be a number between 0 and 1
1924 * where 0 represents alignment along the origin, 1 is aligned
1925 * the furthest away from the origin, 0.5 is centered, etc.
1927 public float getAlignmentY() {
1929 if (layoutMgr instanceof LayoutManager2) {
1930 synchronized (getTreeLock()) {
1931 LayoutManager2 lm = (LayoutManager2) layoutMgr;
1932 yAlign = lm.getLayoutAlignmentY(this);
1935 yAlign = super.getAlignmentY();
1941 * Paints the container. This forwards the paint to any lightweight
1942 * components that are children of this container. If this method is
1943 * reimplemented, super.paint(g) should be called so that lightweight
1944 * components are properly rendered. If a child component is entirely
1945 * clipped by the current clipping setting in g, paint() will not be
1946 * forwarded to that child.
1948 * @param g the specified Graphics window
1949 * @see Component#update(Graphics)
1951 public void paint(Graphics g) {
1953 synchronized (getObjectLock()) {
1955 if (printingThreads.contains(Thread.currentThread())) {
1961 // The container is showing on screen and
1962 // this paint() is not called from print().
1963 // Paint self and forward the paint to lightweight subcomponents.
1965 // super.paint(); -- Don't bother, since it's a NOP.
1967 GraphicsCallback.PaintCallback.getInstance().
1968 runComponents(getComponentsSync(), g, GraphicsCallback.LIGHTWEIGHTS);
1973 * Updates the container. This forwards the update to any lightweight
1974 * components that are children of this container. If this method is
1975 * reimplemented, super.update(g) should be called so that lightweight
1976 * components are properly rendered. If a child component is entirely
1977 * clipped by the current clipping setting in g, update() will not be
1978 * forwarded to that child.
1980 * @param g the specified Graphics window
1981 * @see Component#update(Graphics)
1983 public void update(Graphics g) {
1985 if (! (peer instanceof LightweightPeer)) {
1986 g.clearRect(0, 0, width, height);
1993 * Prints the container. This forwards the print to any lightweight
1994 * components that are children of this container. If this method is
1995 * reimplemented, super.print(g) should be called so that lightweight
1996 * components are properly rendered. If a child component is entirely
1997 * clipped by the current clipping setting in g, print() will not be
1998 * forwarded to that child.
2000 * @param g the specified Graphics window
2001 * @see Component#update(Graphics)
2003 public void print(Graphics g) {
2005 Thread t = Thread.currentThread();
2007 synchronized (getObjectLock()) {
2008 if (printingThreads == null) {
2009 printingThreads = new HashSet();
2011 printingThreads.add(t);
2014 super.print(g); // By default, Component.print() calls paint()
2016 synchronized (getObjectLock()) {
2017 printingThreads.remove(t);
2018 printing = !printingThreads.isEmpty();
2022 GraphicsCallback.PrintCallback.getInstance().
2023 runComponents(getComponentsSync(), g, GraphicsCallback.LIGHTWEIGHTS);
2028 * Paints each of the components in this container.
2029 * @param g the graphics context.
2030 * @see Component#paint
2031 * @see Component#paintAll
2033 public void paintComponents(Graphics g) {
2035 GraphicsCallback.PaintAllCallback.getInstance().
2036 runComponents(getComponentsSync(), g, GraphicsCallback.TWO_PASSES);
2041 * Simulates the peer callbacks into java.awt for printing of
2042 * lightweight Containers.
2043 * @param g the graphics context to use for printing.
2044 * @see Component#printAll
2045 * @see #printComponents
2047 void lightweightPaint(Graphics g) {
2048 super.lightweightPaint(g);
2049 paintHeavyweightComponents(g);
2053 * Prints all the heavyweight subcomponents.
2055 void paintHeavyweightComponents(Graphics g) {
2057 GraphicsCallback.PaintHeavyweightComponentsCallback.getInstance().
2058 runComponents(getComponentsSync(), g,
2059 GraphicsCallback.LIGHTWEIGHTS | GraphicsCallback.HEAVYWEIGHTS);
2064 * Prints each of the components in this container.
2065 * @param g the graphics context.
2066 * @see Component#print
2067 * @see Component#printAll
2069 public void printComponents(Graphics g) {
2071 GraphicsCallback.PrintAllCallback.getInstance().
2072 runComponents(getComponentsSync(), g, GraphicsCallback.TWO_PASSES);
2077 * Simulates the peer callbacks into java.awt for printing of
2078 * lightweight Containers.
2079 * @param g the graphics context to use for printing.
2080 * @see Component#printAll
2081 * @see #printComponents
2083 void lightweightPrint(Graphics g) {
2084 super.lightweightPrint(g);
2085 printHeavyweightComponents(g);
2089 * Prints all the heavyweight subcomponents.
2091 void printHeavyweightComponents(Graphics g) {
2093 GraphicsCallback.PrintHeavyweightComponentsCallback.getInstance().
2094 runComponents(getComponentsSync(), g,
2095 GraphicsCallback.LIGHTWEIGHTS | GraphicsCallback.HEAVYWEIGHTS);
2100 * Adds the specified container listener to receive container events
2101 * from this container.
2102 * If l is null, no exception is thrown and no action is performed.
2103 * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
2104 * >AWT Threading Issues</a> for details on AWT's threading model.
2106 * @param l the container listener
2108 * @see #removeContainerListener
2109 * @see #getContainerListeners
2111 public synchronized void addContainerListener(ContainerListener l) {
2115 containerListener = AWTEventMulticaster.add(containerListener, l);
2116 newEventsOnly = true;
2120 * Removes the specified container listener so it no longer receives
2121 * container events from this container.
2122 * If l is null, no exception is thrown and no action is performed.
2123 * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
2124 * >AWT Threading Issues</a> for details on AWT's threading model.
2126 * @param l the container listener
2128 * @see #addContainerListener
2129 * @see #getContainerListeners
2131 public synchronized void removeContainerListener(ContainerListener l) {
2135 containerListener = AWTEventMulticaster.remove(containerListener, l);
2139 * Returns an array of all the container listeners
2140 * registered on this container.
2142 * @return all of this container's <code>ContainerListener</code>s
2143 * or an empty array if no container
2144 * listeners are currently registered
2146 * @see #addContainerListener
2147 * @see #removeContainerListener
2150 public synchronized ContainerListener[] getContainerListeners() {
2151 return (ContainerListener[]) (getListeners(ContainerListener.class));
2155 * Returns an array of all the objects currently registered
2156 * as <code><em>Foo</em>Listener</code>s
2157 * upon this <code>Container</code>.
2158 * <code><em>Foo</em>Listener</code>s are registered using the
2159 * <code>add<em>Foo</em>Listener</code> method.
2162 * You can specify the <code>listenerType</code> argument
2163 * with a class literal, such as
2164 * <code><em>Foo</em>Listener.class</code>.
2165 * For example, you can query a
2166 * <code>Container</code> <code>c</code>
2167 * for its container listeners with the following code:
2169 * <pre>ContainerListener[] cls = (ContainerListener[])(c.getListeners(ContainerListener.class));</pre>
2171 * If no such listeners exist, this method returns an empty array.
2173 * @param listenerType the type of listeners requested; this parameter
2174 * should specify an interface that descends from
2175 * <code>java.util.EventListener</code>
2176 * @return an array of all objects registered as
2177 * <code><em>Foo</em>Listener</code>s on this container,
2178 * or an empty array if no such listeners have been added
2179 * @exception ClassCastException if <code>listenerType</code>
2180 * doesn't specify a class or interface that implements
2181 * <code>java.util.EventListener</code>
2182 * @exception NullPointerException if {@code listenerType} is {@code null}
2184 * @see #getContainerListeners
2188 public <T extends EventListener> T[] getListeners(Class<T> listenerType) {
2189 EventListener l = null;
2190 if (listenerType == ContainerListener.class) {
2191 l = containerListener;
2193 return super.getListeners(listenerType);
2195 return AWTEventMulticaster.getListeners(l, listenerType);
2198 // REMIND: remove when filtering is done at lower level
2199 boolean eventEnabled(AWTEvent e) {
2202 if (id == ContainerEvent.COMPONENT_ADDED ||
2203 id == ContainerEvent.COMPONENT_REMOVED) {
2204 if ((eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 ||
2205 containerListener != null) {
2210 return super.eventEnabled(e);
2214 * Processes events on this container. If the event is a
2215 * <code>ContainerEvent</code>, it invokes the
2216 * <code>processContainerEvent</code> method, else it invokes
2217 * its superclass's <code>processEvent</code>.
2218 * <p>Note that if the event parameter is <code>null</code>
2219 * the behavior is unspecified and may result in an
2222 * @param e the event
2224 protected void processEvent(AWTEvent e) {
2225 if (e instanceof ContainerEvent) {
2226 processContainerEvent((ContainerEvent)e);
2229 super.processEvent(e);
2233 * Processes container events occurring on this container by
2234 * dispatching them to any registered ContainerListener objects.
2235 * NOTE: This method will not be called unless container events
2236 * are enabled for this component; this happens when one of the
2239 * <li>A ContainerListener object is registered via
2240 * <code>addContainerListener</code>
2241 * <li>Container events are enabled via <code>enableEvents</code>
2243 * <p>Note that if the event parameter is <code>null</code>
2244 * the behavior is unspecified and may result in an
2247 * @param e the container event
2248 * @see Component#enableEvents
2250 protected void processContainerEvent(ContainerEvent e) {
2251 ContainerListener listener = containerListener;
2252 if (listener != null) {
2254 case ContainerEvent.COMPONENT_ADDED:
2255 listener.componentAdded(e);
2257 case ContainerEvent.COMPONENT_REMOVED:
2258 listener.componentRemoved(e);
2265 * Dispatches an event to this component or one of its sub components.
2266 * Create ANCESTOR_RESIZED and ANCESTOR_MOVED events in response to
2267 * COMPONENT_RESIZED and COMPONENT_MOVED events. We have to do this
2268 * here instead of in processComponentEvent because ComponentEvents
2269 * may not be enabled for this Container.
2270 * @param e the event
2272 void dispatchEventImpl(AWTEvent e) {
2273 if ((dispatcher != null) && dispatcher.dispatchEvent(e)) {
2274 // event was sent to a lightweight component. The
2275 // native-produced event sent to the native container
2276 // must be properly disposed of by the peer, so it
2277 // gets forwarded. If the native host has been removed
2278 // as a result of the sending the lightweight event,
2279 // the peer reference will be null.
2282 peer.handleEvent(e);
2287 super.dispatchEventImpl(e);
2289 synchronized (getTreeLock()) {
2290 switch (e.getID()) {
2291 case ComponentEvent.COMPONENT_RESIZED:
2292 createChildHierarchyEvents(HierarchyEvent.ANCESTOR_RESIZED, 0,
2293 Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));
2295 case ComponentEvent.COMPONENT_MOVED:
2296 createChildHierarchyEvents(HierarchyEvent.ANCESTOR_MOVED, 0,
2297 Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));
2306 * Dispatches an event to this component, without trying to forward
2307 * it to any subcomponents
2308 * @param e the event
2310 void dispatchEventToSelf(AWTEvent e) {
2311 super.dispatchEventImpl(e);
2315 * Fetchs the top-most (deepest) lightweight component that is interested
2316 * in receiving mouse events.
2318 Component getMouseEventTarget(int x, int y, boolean includeSelf) {
2319 return getMouseEventTarget(x, y, includeSelf,
2320 MouseEventTargetFilter.FILTER,
2321 !SEARCH_HEAVYWEIGHTS);
2325 * Fetches the top-most (deepest) component to receive SunDropTargetEvents.
2327 Component getDropTargetEventTarget(int x, int y, boolean includeSelf) {
2328 return getMouseEventTarget(x, y, includeSelf,
2329 DropTargetEventTargetFilter.FILTER,
2330 SEARCH_HEAVYWEIGHTS);
2334 * A private version of getMouseEventTarget which has two additional
2335 * controllable behaviors. This method searches for the top-most
2336 * descendant of this container that contains the given coordinates
2337 * and is accepted by the given filter. The search will be constrained to
2338 * lightweight descendants if the last argument is <code>false</code>.
2340 * @param filter EventTargetFilter instance to determine whether the
2341 * given component is a valid target for this event.
2342 * @param searchHeavyweights if <code>false</code>, the method
2343 * will bypass heavyweight components during the search.
2345 private Component getMouseEventTarget(int x, int y, boolean includeSelf,
2346 EventTargetFilter filter,
2347 boolean searchHeavyweights) {
2348 Component comp = null;
2349 if (searchHeavyweights) {
2350 comp = getMouseEventTargetImpl(x, y, includeSelf, filter,
2351 SEARCH_HEAVYWEIGHTS,
2352 searchHeavyweights);
2355 if (comp == null || comp == this) {
2356 comp = getMouseEventTargetImpl(x, y, includeSelf, filter,
2357 !SEARCH_HEAVYWEIGHTS,
2358 searchHeavyweights);
2365 * A private version of getMouseEventTarget which has three additional
2366 * controllable behaviors. This method searches for the top-most
2367 * descendant of this container that contains the given coordinates
2368 * and is accepted by the given filter. The search will be constrained to
2369 * descendants of only lightweight children or only heavyweight children
2370 * of this container depending on searchHeavyweightChildren. The search will
2371 * be constrained to only lightweight descendants of the searched children
2372 * of this container if searchHeavyweightDescendants is <code>false</code>.
2374 * @param filter EventTargetFilter instance to determine whether the
2375 * selected component is a valid target for this event.
2376 * @param searchHeavyweightChildren if <code>true</code>, the method
2377 * will bypass immediate lightweight children during the search.
2378 * If <code>false</code>, the methods will bypass immediate
2379 * heavyweight children during the search.
2380 * @param searchHeavyweightDescendants if <code>false</code>, the method
2381 * will bypass heavyweight descendants which are not immediate
2382 * children during the search. If <code>true</code>, the method
2383 * will traverse both lightweight and heavyweight descendants during
2386 private Component getMouseEventTargetImpl(int x, int y, boolean includeSelf,
2387 EventTargetFilter filter,
2388 boolean searchHeavyweightChildren,
2389 boolean searchHeavyweightDescendants) {
2390 synchronized (getTreeLock()) {
2392 for (int i = 0; i < component.size(); i++) {
2393 Component comp = component.get(i);
2394 if (comp != null && comp.visible &&
2395 ((!searchHeavyweightChildren &&
2396 comp.peer instanceof LightweightPeer) ||
2397 (searchHeavyweightChildren &&
2398 !(comp.peer instanceof LightweightPeer))) &&
2399 comp.contains(x - comp.x, y - comp.y)) {
2401 // found a component that intersects the point, see if there
2402 // is a deeper possibility.
2403 if (comp instanceof Container) {
2404 Container child = (Container) comp;
2405 Component deeper = child.getMouseEventTarget(
2410 searchHeavyweightDescendants);
2411 if (deeper != null) {
2415 if (filter.accept(comp)) {
2416 // there isn't a deeper target, but this component
2425 boolean isMouseOverMe;
2427 isPeerOK = (peer instanceof LightweightPeer) || includeSelf;
2428 isMouseOverMe = contains(x,y);
2430 // didn't find a child target, return this component if it's
2431 // a possible target
2432 if (isMouseOverMe && isPeerOK && filter.accept(this)) {
2435 // no possible target
2440 static interface EventTargetFilter {
2441 boolean accept(final Component comp);
2444 static class MouseEventTargetFilter implements EventTargetFilter {
2445 static final EventTargetFilter FILTER = new MouseEventTargetFilter();
2447 private MouseEventTargetFilter() {}
2449 public boolean accept(final Component comp) {
2450 return (comp.eventMask & AWTEvent.MOUSE_MOTION_EVENT_MASK) != 0
2451 || (comp.eventMask & AWTEvent.MOUSE_EVENT_MASK) != 0
2452 || (comp.eventMask & AWTEvent.MOUSE_WHEEL_EVENT_MASK) != 0
2453 || comp.mouseListener != null
2454 || comp.mouseMotionListener != null
2455 || comp.mouseWheelListener != null;
2459 static class DropTargetEventTargetFilter implements EventTargetFilter {
2460 static final EventTargetFilter FILTER = new DropTargetEventTargetFilter();
2462 private DropTargetEventTargetFilter() {}
2464 public boolean accept(final Component comp) {
2465 DropTarget dt = comp.getDropTarget();
2466 return dt != null && dt.isActive();
2471 * This is called by lightweight components that want the containing
2472 * windowed parent to enable some kind of events on their behalf.
2473 * This is needed for events that are normally only dispatched to
2474 * windows to be accepted so that they can be forwarded downward to
2475 * the lightweight component that has enabled them.
2477 void proxyEnableEvents(long events) {
2478 if (peer instanceof LightweightPeer) {
2479 // this container is lightweight.... continue sending it
2481 if (parent != null) {
2482 parent.proxyEnableEvents(events);
2485 // This is a native container, so it needs to host
2486 // one of it's children. If this function is called before
2487 // a peer has been created we don't yet have a dispatcher
2488 // because it has not yet been determined if this instance
2490 if (dispatcher != null) {
2491 dispatcher.enableEvents(events);
2497 * @deprecated As of JDK version 1.1,
2498 * replaced by <code>dispatchEvent(AWTEvent e)</code>
2501 public void deliverEvent(Event e) {
2502 Component comp = getComponentAt(e.x, e.y);
2503 if ((comp != null) && (comp != this)) {
2504 e.translate(-comp.x, -comp.y);
2505 comp.deliverEvent(e);
2512 * Locates the component that contains the x,y position. The
2513 * top-most child component is returned in the case where there
2514 * is overlap in the components. This is determined by finding
2515 * the component closest to the index 0 that claims to contain
2516 * the given point via Component.contains(), except that Components
2517 * which have native peers take precedence over those which do not
2518 * (i.e., lightweight Components).
2520 * @param x the <i>x</i> coordinate
2521 * @param y the <i>y</i> coordinate
2522 * @return null if the component does not contain the position.
2523 * If there is no child component at the requested point and the
2524 * point is within the bounds of the container the container itself
2525 * is returned; otherwise the top-most child is returned.
2526 * @see Component#contains
2529 public Component getComponentAt(int x, int y) {
2530 return locate(x, y);
2534 * @deprecated As of JDK version 1.1,
2535 * replaced by <code>getComponentAt(int, int)</code>.
2538 public Component locate(int x, int y) {
2539 if (!contains(x, y)) {
2542 synchronized (getTreeLock()) {
2543 // Two passes: see comment in sun.awt.SunGraphicsCallback
2544 for (int i = 0; i < component.size(); i++) {
2545 Component comp = component.get(i);
2547 !(comp.peer instanceof LightweightPeer)) {
2548 if (comp.contains(x - comp.x, y - comp.y)) {
2553 for (int i = 0; i < component.size(); i++) {
2554 Component comp = component.get(i);
2556 comp.peer instanceof LightweightPeer) {
2557 if (comp.contains(x - comp.x, y - comp.y)) {
2567 * Gets the component that contains the specified point.
2568 * @param p the point.
2569 * @return returns the component that contains the point,
2570 * or <code>null</code> if the component does
2571 * not contain the point.
2572 * @see Component#contains
2575 public Component getComponentAt(Point p) {
2576 return getComponentAt(p.x, p.y);
2580 * Returns the position of the mouse pointer in this <code>Container</code>'s
2581 * coordinate space if the <code>Container</code> is under the mouse pointer,
2582 * otherwise returns <code>null</code>.
2583 * This method is similar to {@link Component#getMousePosition()} with the exception
2584 * that it can take the <code>Container</code>'s children into account.
2585 * If <code>allowChildren</code> is <code>false</code>, this method will return
2586 * a non-null value only if the mouse pointer is above the <code>Container</code>
2587 * directly, not above the part obscured by children.
2588 * If <code>allowChildren</code> is <code>true</code>, this method returns
2589 * a non-null value if the mouse pointer is above <code>Container</code> or any
2590 * of its descendants.
2592 * @exception HeadlessException if GraphicsEnvironment.isHeadless() returns true
2593 * @param allowChildren true if children should be taken into account
2594 * @see Component#getMousePosition
2595 * @return mouse coordinates relative to this <code>Component</code>, or null
2598 public Point getMousePosition(boolean allowChildren) throws HeadlessException {
2599 if (GraphicsEnvironment.isHeadless()) {
2600 throw new HeadlessException();
2602 PointerInfo pi = (PointerInfo)java.security.AccessController.doPrivileged(
2603 new java.security.PrivilegedAction() {
2604 public Object run() {
2605 return MouseInfo.getPointerInfo();
2609 synchronized (getTreeLock()) {
2610 Component inTheSameWindow = findUnderMouseInWindow(pi);
2611 if (isSameOrAncestorOf(inTheSameWindow, allowChildren)) {
2612 return pointRelativeToComponent(pi.getLocation());
2618 boolean isSameOrAncestorOf(Component comp, boolean allowChildren) {
2619 return this == comp || (allowChildren && isParentOf(comp));
2623 * Locates the visible child component that contains the specified
2624 * position. The top-most child component is returned in the case
2625 * where there is overlap in the components. If the containing child
2626 * component is a Container, this method will continue searching for
2627 * the deepest nested child component. Components which are not
2628 * visible are ignored during the search.<p>
2630 * The findComponentAt method is different from getComponentAt in
2631 * that getComponentAt only searches the Container's immediate
2632 * children; if the containing component is a Container,
2633 * findComponentAt will search that child to find a nested component.
2635 * @param x the <i>x</i> coordinate
2636 * @param y the <i>y</i> coordinate
2637 * @return null if the component does not contain the position.
2638 * If there is no child component at the requested point and the
2639 * point is within the bounds of the container the container itself
2641 * @see Component#contains
2642 * @see #getComponentAt
2645 public Component findComponentAt(int x, int y) {
2646 return findComponentAt(x, y, true);
2650 * Private version of findComponentAt which has a controllable
2651 * behavior. Setting 'ignoreEnabled' to 'false' bypasses disabled
2652 * Components during the search. This behavior is used by the
2653 * lightweight cursor support in sun.awt.GlobalCursorManager.
2654 * The cursor code calls this function directly via native code.
2656 * The addition of this feature is temporary, pending the
2657 * adoption of new, public API which exports this feature.
2659 final Component findComponentAt(int x, int y, boolean ignoreEnabled) {
2660 synchronized (getTreeLock()) {
2661 if (isRecursivelyVisible()){
2662 return findComponentAtImpl(x, y, ignoreEnabled);
2668 final Component findComponentAtImpl(int x, int y, boolean ignoreEnabled){
2671 if (!(contains(x, y) && visible && (ignoreEnabled || enabled))) {
2675 // Two passes: see comment in sun.awt.SunGraphicsCallback
2676 for (int i = 0; i < component.size(); i++) {
2677 Component comp = component.get(i);
2679 !(comp.peer instanceof LightweightPeer)) {
2680 if (comp instanceof Container) {
2681 comp = ((Container)comp).findComponentAtImpl(x - comp.x,
2685 comp = comp.locate(x - comp.x, y - comp.y);
2687 if (comp != null && comp.visible &&
2688 (ignoreEnabled || comp.enabled))
2694 for (int i = 0; i < component.size(); i++) {
2695 Component comp = component.get(i);
2697 comp.peer instanceof LightweightPeer) {
2698 if (comp instanceof Container) {
2699 comp = ((Container)comp).findComponentAtImpl(x - comp.x,
2703 comp = comp.locate(x - comp.x, y - comp.y);
2705 if (comp != null && comp.visible &&
2706 (ignoreEnabled || comp.enabled))
2717 * Locates the visible child component that contains the specified
2718 * point. The top-most child component is returned in the case
2719 * where there is overlap in the components. If the containing child
2720 * component is a Container, this method will continue searching for
2721 * the deepest nested child component. Components which are not
2722 * visible are ignored during the search.<p>
2724 * The findComponentAt method is different from getComponentAt in
2725 * that getComponentAt only searches the Container's immediate
2726 * children; if the containing component is a Container,
2727 * findComponentAt will search that child to find a nested component.
2729 * @param p the point.
2730 * @return null if the component does not contain the position.
2731 * If there is no child component at the requested point and the
2732 * point is within the bounds of the container the container itself
2734 * @throws NullPointerException if {@code p} is {@code null}
2735 * @see Component#contains
2736 * @see #getComponentAt
2739 public Component findComponentAt(Point p) {
2740 return findComponentAt(p.x, p.y);
2744 * Makes this Container displayable by connecting it to
2745 * a native screen resource. Making a container displayable will
2746 * cause all of its children to be made displayable.
2747 * This method is called internally by the toolkit and should
2748 * not be called directly by programs.
2749 * @see Component#isDisplayable
2750 * @see #removeNotify
2752 public void addNotify() {
2753 synchronized (getTreeLock()) {
2754 // addNotify() on the children may cause proxy event enabling
2755 // on this instance, so we first call super.addNotify() and
2756 // possibly create an lightweight event dispatcher before calling
2757 // addNotify() on the children which may be lightweight.
2759 if (! (peer instanceof LightweightPeer)) {
2760 dispatcher = new LightweightDispatcher(this);
2763 // We shouldn't use iterator because of the Swing menu
2764 // implementation specifics:
2765 // the menu is being assigned as a child to JLayeredPane
2766 // instead of particular component so always affect
2767 // collection of component if menu is becoming shown or hidden.
2768 for (int i = 0; i < component.size(); i++) {
2769 component.get(i).addNotify();
2775 * Makes this Container undisplayable by removing its connection
2776 * to its native screen resource. Making a container undisplayable
2777 * will cause all of its children to be made undisplayable.
2778 * This method is called by the toolkit internally and should
2779 * not be called directly by programs.
2780 * @see Component#isDisplayable
2783 public void removeNotify() {
2784 synchronized (getTreeLock()) {
2785 // We shouldn't use iterator because of the Swing menu
2786 // implementation specifics:
2787 // the menu is being assigned as a child to JLayeredPane
2788 // instead of particular component so always affect
2789 // collection of component if menu is becoming shown or hidden.
2790 for (int i = component.size()-1 ; i >= 0 ; i--) {
2791 Component comp = component.get(i);
2794 // We want to suppress focus change on disposal
2795 // of the focused component. But because of focus
2796 // is asynchronous, we should suppress focus change
2797 // on every component in case it receives native focus
2798 // in the process of disposal.
2799 comp.setAutoFocusTransferOnDisposal(false);
2800 comp.removeNotify();
2801 comp.setAutoFocusTransferOnDisposal(true);
2804 // If some of the children had focus before disposal then it still has.
2805 // Auto-transfer focus to the next (or previous) component if auto-transfer
2807 if (containsFocus() && KeyboardFocusManager.isAutoFocusTransferEnabledFor(this)) {
2808 if (!transferFocus(false)) {
2809 transferFocusBackward(true);
2812 if ( dispatcher != null ) {
2813 dispatcher.dispose();
2816 super.removeNotify();
2821 * Checks if the component is contained in the component hierarchy of
2823 * @param c the component
2824 * @return <code>true</code> if it is an ancestor;
2825 * <code>false</code> otherwise.
2828 public boolean isAncestorOf(Component c) {
2830 if (c == null || ((p = c.getParent()) == null)) {
2843 * The following code was added to support modal JInternalFrames
2844 * Unfortunately this code has to be added here so that we can get access to
2845 * some private AWT classes like SequencedEvent.
2847 * The native container of the LW component has this field set
2848 * to tell it that it should block Mouse events for all LW
2849 * children except for the modal component.
2851 * In the case of nested Modal components, we store the previous
2852 * modal component in the new modal components value of modalComp;
2855 transient Component modalComp;
2856 transient AppContext modalAppContext;
2858 private void startLWModal() {
2859 // Store the app context on which this component is being shown.
2860 // Event dispatch thread of this app context will be sleeping until
2861 // we wake it by any event from hideAndDisposeHandler().
2862 modalAppContext = AppContext.getAppContext();
2864 // keep the KeyEvents from being dispatched
2865 // until the focus has been transfered
2866 long time = Toolkit.getEventQueue().getMostRecentEventTime();
2867 Component predictedFocusOwner = (Component.isInstanceOf(this, "javax.swing.JInternalFrame")) ? ((javax.swing.JInternalFrame)(this)).getMostRecentFocusOwner() : null;
2868 if (predictedFocusOwner != null) {
2869 KeyboardFocusManager.getCurrentKeyboardFocusManager().
2870 enqueueKeyEvents(time, predictedFocusOwner);
2872 // We have two mechanisms for blocking: 1. If we're on the
2873 // EventDispatchThread, start a new event pump. 2. If we're
2874 // on any other thread, call wait() on the treelock.
2875 final Container nativeContainer;
2876 synchronized (getTreeLock()) {
2877 nativeContainer = getHeavyweightContainer();
2878 if (nativeContainer.modalComp != null) {
2879 this.modalComp = nativeContainer.modalComp;
2880 nativeContainer.modalComp = this;
2884 nativeContainer.modalComp = this;
2888 Runnable pumpEventsForHierarchy = new Runnable() {
2890 EventDispatchThread dispatchThread = EventDispatchThread.findCurrent();
2891 dispatchThread.pumpEventsForHierarchy(
2893 public boolean evaluate() {
2894 return ((windowClosingException == null) && (nativeContainer.modalComp != null)) ;
2900 if (EventQueue.isDispatchThread()) {
2901 SequencedEvent currentSequencedEvent =
2902 KeyboardFocusManager.getCurrentKeyboardFocusManager().
2903 getCurrentSequencedEvent();
2904 if (currentSequencedEvent != null) {
2905 currentSequencedEvent.dispose();
2908 pumpEventsForHierarchy.run();
2910 synchronized (getTreeLock()) {
2911 Toolkit.getEventQueue().
2912 postEvent(new PeerEvent(this,
2913 pumpEventsForHierarchy,
2914 PeerEvent.PRIORITY_EVENT));
2915 while ((windowClosingException == null) &&
2916 (nativeContainer.modalComp != null))
2919 getTreeLock().wait();
2920 } catch (InterruptedException e) {
2926 if (windowClosingException != null) {
2927 windowClosingException.fillInStackTrace();
2928 throw windowClosingException;
2930 if (predictedFocusOwner != null) {
2931 KeyboardFocusManager.getCurrentKeyboardFocusManager().
2932 dequeueKeyEvents(time, predictedFocusOwner);
2936 private void stopLWModal() {
2937 synchronized (getTreeLock()) {
2938 if (modalAppContext != null) {
2939 Container nativeContainer = getHeavyweightContainer();
2940 if(nativeContainer != null) {
2941 if (this.modalComp != null) {
2942 nativeContainer.modalComp = this.modalComp;
2943 this.modalComp = null;
2947 nativeContainer.modalComp = null;
2950 // Wake up event dispatch thread on which the dialog was
2952 SunToolkit.postEvent(modalAppContext,
2954 new WakingRunnable(),
2955 PeerEvent.PRIORITY_EVENT));
2957 EventQueue.invokeLater(new WakingRunnable());
2958 getTreeLock().notifyAll();
2962 final static class WakingRunnable implements Runnable {
2967 /* End of JOptionPane support code */
2970 * Returns a string representing the state of this <code>Container</code>.
2971 * This method is intended to be used only for debugging purposes, and the
2972 * content and format of the returned string may vary between
2973 * implementations. The returned string may be empty but may not be
2974 * <code>null</code>.
2976 * @return the parameter string of this container
2978 protected String paramString() {
2979 String str = super.paramString();
2980 LayoutManager layoutMgr = this.layoutMgr;
2981 if (layoutMgr != null) {
2982 str += ",layout=" + layoutMgr.getClass().getName();
2988 * Prints a listing of this container to the specified output
2989 * stream. The listing starts at the specified indentation.
2991 * The immediate children of the container are printed with
2992 * an indentation of <code>indent+1</code>. The children
2993 * of those children are printed at <code>indent+2</code>
2996 * @param out a print stream
2997 * @param indent the number of spaces to indent
2998 * @throws NullPointerException if {@code out} is {@code null}
2999 * @see Component#list(java.io.PrintStream, int)
3002 public void list(PrintStream out, int indent) {
3003 super.list(out, indent);
3004 synchronized(getTreeLock()) {
3005 for (int i = 0; i < component.size(); i++) {
3006 Component comp = component.get(i);
3008 comp.list(out, indent+1);
3015 * Prints out a list, starting at the specified indentation,
3016 * to the specified print writer.
3018 * The immediate children of the container are printed with
3019 * an indentation of <code>indent+1</code>. The children
3020 * of those children are printed at <code>indent+2</code>
3023 * @param out a print writer
3024 * @param indent the number of spaces to indent
3025 * @throws NullPointerException if {@code out} is {@code null}
3026 * @see Component#list(java.io.PrintWriter, int)
3029 public void list(PrintWriter out, int indent) {
3030 super.list(out, indent);
3031 synchronized(getTreeLock()) {
3032 for (int i = 0; i < component.size(); i++) {
3033 Component comp = component.get(i);
3035 comp.list(out, indent+1);
3042 * Sets the focus traversal keys for a given traversal operation for this
3045 * The default values for a Container's focus traversal keys are
3046 * implementation-dependent. Sun recommends that all implementations for a
3047 * particular native platform use the same default values. The
3048 * recommendations for Windows and Unix are listed below. These
3049 * recommendations are used in the Sun AWT implementations.
3051 * <table border=1 summary="Recommended default values for a Container's focus traversal keys">
3053 * <th>Identifier</th>
3058 * <td>KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS</td>
3059 * <td>Normal forward keyboard traversal</td>
3060 * <td>TAB on KEY_PRESSED, CTRL-TAB on KEY_PRESSED</td>
3063 * <td>KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS</td>
3064 * <td>Normal reverse keyboard traversal</td>
3065 * <td>SHIFT-TAB on KEY_PRESSED, CTRL-SHIFT-TAB on KEY_PRESSED</td>
3068 * <td>KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS</td>
3069 * <td>Go up one focus traversal cycle</td>
3073 * <td>KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS<td>
3074 * <td>Go down one focus traversal cycle</td>
3079 * To disable a traversal key, use an empty Set; Collections.EMPTY_SET is
3082 * Using the AWTKeyStroke API, client code can specify on which of two
3083 * specific KeyEvents, KEY_PRESSED or KEY_RELEASED, the focus traversal
3084 * operation will occur. Regardless of which KeyEvent is specified,
3085 * however, all KeyEvents related to the focus traversal key, including the
3086 * associated KEY_TYPED event, will be consumed, and will not be dispatched
3087 * to any Container. It is a runtime error to specify a KEY_TYPED event as
3088 * mapping to a focus traversal operation, or to map the same event to
3089 * multiple default focus traversal operations.
3091 * If a value of null is specified for the Set, this Container inherits the
3092 * Set from its parent. If all ancestors of this Container have null
3093 * specified for the Set, then the current KeyboardFocusManager's default
3096 * @param id one of KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
3097 * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
3098 * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
3099 * KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
3100 * @param keystrokes the Set of AWTKeyStroke for the specified operation
3101 * @see #getFocusTraversalKeys
3102 * @see KeyboardFocusManager#FORWARD_TRAVERSAL_KEYS
3103 * @see KeyboardFocusManager#BACKWARD_TRAVERSAL_KEYS
3104 * @see KeyboardFocusManager#UP_CYCLE_TRAVERSAL_KEYS
3105 * @see KeyboardFocusManager#DOWN_CYCLE_TRAVERSAL_KEYS
3106 * @throws IllegalArgumentException if id is not one of
3107 * KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
3108 * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
3109 * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
3110 * KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS, or if keystrokes
3111 * contains null, or if any Object in keystrokes is not an
3112 * AWTKeyStroke, or if any keystroke represents a KEY_TYPED event,
3113 * or if any keystroke already maps to another focus traversal
3114 * operation for this Container
3119 public void setFocusTraversalKeys(int id,
3120 Set<? extends AWTKeyStroke> keystrokes)
3122 if (id < 0 || id >= KeyboardFocusManager.TRAVERSAL_KEY_LENGTH) {
3123 throw new IllegalArgumentException("invalid focus traversal key identifier");
3126 // Don't call super.setFocusTraversalKey. The Component parameter check
3127 // does not allow DOWN_CYCLE_TRAVERSAL_KEYS, but we do.
3128 setFocusTraversalKeys_NoIDCheck(id, keystrokes);
3132 * Returns the Set of focus traversal keys for a given traversal operation
3133 * for this Container. (See
3134 * <code>setFocusTraversalKeys</code> for a full description of each key.)
3136 * If a Set of traversal keys has not been explicitly defined for this
3137 * Container, then this Container's parent's Set is returned. If no Set
3138 * has been explicitly defined for any of this Container's ancestors, then
3139 * the current KeyboardFocusManager's default Set is returned.
3141 * @param id one of KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
3142 * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
3143 * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
3144 * KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
3145 * @return the Set of AWTKeyStrokes for the specified operation. The Set
3146 * will be unmodifiable, and may be empty. null will never be
3148 * @see #setFocusTraversalKeys
3149 * @see KeyboardFocusManager#FORWARD_TRAVERSAL_KEYS
3150 * @see KeyboardFocusManager#BACKWARD_TRAVERSAL_KEYS
3151 * @see KeyboardFocusManager#UP_CYCLE_TRAVERSAL_KEYS
3152 * @see KeyboardFocusManager#DOWN_CYCLE_TRAVERSAL_KEYS
3153 * @throws IllegalArgumentException if id is not one of
3154 * KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
3155 * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
3156 * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
3157 * KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
3160 public Set<AWTKeyStroke> getFocusTraversalKeys(int id) {
3161 if (id < 0 || id >= KeyboardFocusManager.TRAVERSAL_KEY_LENGTH) {
3162 throw new IllegalArgumentException("invalid focus traversal key identifier");
3165 // Don't call super.getFocusTraversalKey. The Component parameter check
3166 // does not allow DOWN_CYCLE_TRAVERSAL_KEY, but we do.
3167 return getFocusTraversalKeys_NoIDCheck(id);
3171 * Returns whether the Set of focus traversal keys for the given focus
3172 * traversal operation has been explicitly defined for this Container. If
3173 * this method returns <code>false</code>, this Container is inheriting the
3174 * Set from an ancestor, or from the current KeyboardFocusManager.
3176 * @param id one of KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
3177 * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
3178 * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
3179 * KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
3180 * @return <code>true</code> if the the Set of focus traversal keys for the
3181 * given focus traversal operation has been explicitly defined for
3182 * this Component; <code>false</code> otherwise.
3183 * @throws IllegalArgumentException if id is not one of
3184 * KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
3185 * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
3186 * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
3187 * KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
3190 public boolean areFocusTraversalKeysSet(int id) {
3191 if (id < 0 || id >= KeyboardFocusManager.TRAVERSAL_KEY_LENGTH) {
3192 throw new IllegalArgumentException("invalid focus traversal key identifier");
3195 return (focusTraversalKeys != null && focusTraversalKeys[id] != null);
3199 * Returns whether the specified Container is the focus cycle root of this
3200 * Container's focus traversal cycle. Each focus traversal cycle has only
3201 * a single focus cycle root and each Container which is not a focus cycle
3202 * root belongs to only a single focus traversal cycle. Containers which
3203 * are focus cycle roots belong to two cycles: one rooted at the Container
3204 * itself, and one rooted at the Container's nearest focus-cycle-root
3205 * ancestor. This method will return <code>true</code> for both such
3206 * Containers in this case.
3208 * @param container the Container to be tested
3209 * @return <code>true</code> if the specified Container is a focus-cycle-
3210 * root of this Container; <code>false</code> otherwise
3211 * @see #isFocusCycleRoot()
3214 public boolean isFocusCycleRoot(Container container) {
3215 if (isFocusCycleRoot() && container == this) {
3218 return super.isFocusCycleRoot(container);
3222 private Container findTraversalRoot() {
3223 // I potentially have two roots, myself and my root parent
3224 // If I am the current root, then use me
3225 // If none of my parents are roots, then use me
3226 // If my root parent is the current root, then use my root parent
3227 // If neither I nor my root parent is the current root, then
3228 // use my root parent (a guess)
3230 Container currentFocusCycleRoot = KeyboardFocusManager.
3231 getCurrentKeyboardFocusManager().getCurrentFocusCycleRoot();
3234 if (currentFocusCycleRoot == this) {
3237 root = getFocusCycleRootAncestor();
3243 if (root != currentFocusCycleRoot) {
3244 KeyboardFocusManager.getCurrentKeyboardFocusManager().
3245 setGlobalCurrentFocusCycleRoot(root);
3250 final boolean containsFocus() {
3251 final Component focusOwner = KeyboardFocusManager.
3252 getCurrentKeyboardFocusManager().getFocusOwner();
3253 return isParentOf(focusOwner);
3257 * Check if this component is the child of this container or its children.
3258 * Note: this function acquires treeLock
3259 * Note: this function traverses children tree only in one Window.
3260 * @param comp a component in test, must not be null
3262 private boolean isParentOf(Component comp) {
3263 synchronized(getTreeLock()) {
3264 while (comp != null && comp != this && !(comp instanceof Window)) {
3265 comp = comp.getParent();
3267 return (comp == this);
3271 void clearMostRecentFocusOwnerOnHide() {
3272 boolean reset = false;
3273 Window window = null;
3275 synchronized (getTreeLock()) {
3276 window = getContainingWindow();
3277 if (window != null) {
3278 Component comp = KeyboardFocusManager.getMostRecentFocusOwner(window);
3279 reset = ((comp == this) || isParentOf(comp));
3280 // This synchronized should always be the second in a pair
3281 // (tree lock, KeyboardFocusManager.class)
3282 synchronized(KeyboardFocusManager.class) {
3283 Component storedComp = window.getTemporaryLostComponent();
3284 if (isParentOf(storedComp) || storedComp == this) {
3285 window.setTemporaryLostComponent(null);
3292 KeyboardFocusManager.setMostRecentFocusOwner(window, null);
3296 void clearCurrentFocusCycleRootOnHide() {
3297 KeyboardFocusManager kfm =
3298 KeyboardFocusManager.getCurrentKeyboardFocusManager();
3299 Container cont = kfm.getCurrentFocusCycleRoot();
3301 if (cont == this || isParentOf(cont)) {
3302 kfm.setGlobalCurrentFocusCycleRoot(null);
3306 final Container getTraversalRoot() {
3307 if (isFocusCycleRoot()) {
3308 return findTraversalRoot();
3311 return super.getTraversalRoot();
3315 * Sets the focus traversal policy that will manage keyboard traversal of
3316 * this Container's children, if this Container is a focus cycle root. If
3317 * the argument is null, this Container inherits its policy from its focus-
3318 * cycle-root ancestor. If the argument is non-null, this policy will be
3319 * inherited by all focus-cycle-root children that have no keyboard-
3320 * traversal policy of their own (as will, recursively, their focus-cycle-
3323 * If this Container is not a focus cycle root, the policy will be
3324 * remembered, but will not be used or inherited by this or any other
3325 * Containers until this Container is made a focus cycle root.
3327 * @param policy the new focus traversal policy for this Container
3328 * @see #getFocusTraversalPolicy
3329 * @see #setFocusCycleRoot
3330 * @see #isFocusCycleRoot
3335 public void setFocusTraversalPolicy(FocusTraversalPolicy policy) {
3336 FocusTraversalPolicy oldPolicy;
3337 synchronized (this) {
3338 oldPolicy = this.focusTraversalPolicy;
3339 this.focusTraversalPolicy = policy;
3341 firePropertyChange("focusTraversalPolicy", oldPolicy, policy);
3345 * Returns the focus traversal policy that will manage keyboard traversal
3346 * of this Container's children, or null if this Container is not a focus
3347 * cycle root. If no traversal policy has been explicitly set for this
3348 * Container, then this Container's focus-cycle-root ancestor's policy is
3351 * @return this Container's focus traversal policy, or null if this
3352 * Container is not a focus cycle root.
3353 * @see #setFocusTraversalPolicy
3354 * @see #setFocusCycleRoot
3355 * @see #isFocusCycleRoot
3358 public FocusTraversalPolicy getFocusTraversalPolicy() {
3359 if (!isFocusTraversalPolicyProvider() && !isFocusCycleRoot()) {
3363 FocusTraversalPolicy policy = this.focusTraversalPolicy;
3364 if (policy != null) {
3368 Container rootAncestor = getFocusCycleRootAncestor();
3369 if (rootAncestor != null) {
3370 return rootAncestor.getFocusTraversalPolicy();
3372 return KeyboardFocusManager.getCurrentKeyboardFocusManager().
3373 getDefaultFocusTraversalPolicy();
3378 * Returns whether the focus traversal policy has been explicitly set for
3379 * this Container. If this method returns <code>false</code>, this
3380 * Container will inherit its focus traversal policy from an ancestor.
3382 * @return <code>true</code> if the focus traversal policy has been
3383 * explicitly set for this Container; <code>false</code> otherwise.
3386 public boolean isFocusTraversalPolicySet() {
3387 return (focusTraversalPolicy != null);
3391 * Sets whether this Container is the root of a focus traversal cycle. Once
3392 * focus enters a traversal cycle, typically it cannot leave it via focus
3393 * traversal unless one of the up- or down-cycle keys is pressed. Normal
3394 * traversal is limited to this Container, and all of this Container's
3395 * descendants that are not descendants of inferior focus cycle roots. Note
3396 * that a FocusTraversalPolicy may bend these restrictions, however. For
3397 * example, ContainerOrderFocusTraversalPolicy supports implicit down-cycle
3400 * The alternative way to specify the traversal order of this Container's
3401 * children is to make this Container a
3402 * <a href="doc-files/FocusSpec.html#FocusTraversalPolicyProviders">focus traversal policy provider</a>.
3404 * @param focusCycleRoot indicates whether this Container is the root of a
3405 * focus traversal cycle
3406 * @see #isFocusCycleRoot()
3407 * @see #setFocusTraversalPolicy
3408 * @see #getFocusTraversalPolicy
3409 * @see ContainerOrderFocusTraversalPolicy
3410 * @see #setFocusTraversalPolicyProvider
3415 public void setFocusCycleRoot(boolean focusCycleRoot) {
3416 boolean oldFocusCycleRoot;
3417 synchronized (this) {
3418 oldFocusCycleRoot = this.focusCycleRoot;
3419 this.focusCycleRoot = focusCycleRoot;
3421 firePropertyChange("focusCycleRoot", oldFocusCycleRoot,
3426 * Returns whether this Container is the root of a focus traversal cycle.
3427 * Once focus enters a traversal cycle, typically it cannot leave it via
3428 * focus traversal unless one of the up- or down-cycle keys is pressed.
3429 * Normal traversal is limited to this Container, and all of this
3430 * Container's descendants that are not descendants of inferior focus
3431 * cycle roots. Note that a FocusTraversalPolicy may bend these
3432 * restrictions, however. For example, ContainerOrderFocusTraversalPolicy
3433 * supports implicit down-cycle traversal.
3435 * @return whether this Container is the root of a focus traversal cycle
3436 * @see #setFocusCycleRoot
3437 * @see #setFocusTraversalPolicy
3438 * @see #getFocusTraversalPolicy
3439 * @see ContainerOrderFocusTraversalPolicy
3442 public boolean isFocusCycleRoot() {
3443 return focusCycleRoot;
3447 * Sets whether this container will be used to provide focus
3448 * traversal policy. Container with this property as
3449 * <code>true</code> will be used to acquire focus traversal policy
3450 * instead of closest focus cycle root ancestor.
3451 * @param provider indicates whether this container will be used to
3452 * provide focus traversal policy
3453 * @see #setFocusTraversalPolicy
3454 * @see #getFocusTraversalPolicy
3455 * @see #isFocusTraversalPolicyProvider
3460 public final void setFocusTraversalPolicyProvider(boolean provider) {
3461 boolean oldProvider;
3462 synchronized(this) {
3463 oldProvider = focusTraversalPolicyProvider;
3464 focusTraversalPolicyProvider = provider;
3466 firePropertyChange("focusTraversalPolicyProvider", oldProvider, provider);
3470 * Returns whether this container provides focus traversal
3471 * policy. If this property is set to <code>true</code> then when
3472 * keyboard focus manager searches container hierarchy for focus
3473 * traversal policy and encounters this container before any other
3474 * container with this property as true or focus cycle roots then
3475 * its focus traversal policy will be used instead of focus cycle
3477 * @see #setFocusTraversalPolicy
3478 * @see #getFocusTraversalPolicy
3479 * @see #setFocusCycleRoot
3480 * @see #setFocusTraversalPolicyProvider
3481 * @return <code>true</code> if this container provides focus traversal
3482 * policy, <code>false</code> otherwise
3487 public final boolean isFocusTraversalPolicyProvider() {
3488 return focusTraversalPolicyProvider;
3492 * Transfers the focus down one focus traversal cycle. If this Container is
3493 * a focus cycle root, then the focus owner is set to this Container's
3494 * default Component to focus, and the current focus cycle root is set to
3495 * this Container. If this Container is not a focus cycle root, then no
3496 * focus traversal operation occurs.
3498 * @see Component#requestFocus()
3499 * @see #isFocusCycleRoot
3500 * @see #setFocusCycleRoot
3503 public void transferFocusDownCycle() {
3504 if (isFocusCycleRoot()) {
3505 KeyboardFocusManager.getCurrentKeyboardFocusManager().
3506 setGlobalCurrentFocusCycleRoot(this);
3507 Component toFocus = getFocusTraversalPolicy().
3508 getDefaultComponent(this);
3509 if (toFocus != null) {
3510 toFocus.requestFocus(CausedFocusEvent.Cause.TRAVERSAL_DOWN);
3515 void preProcessKeyEvent(KeyEvent e) {
3516 Container parent = this.parent;
3517 if (parent != null) {
3518 parent.preProcessKeyEvent(e);
3522 void postProcessKeyEvent(KeyEvent e) {
3523 Container parent = this.parent;
3524 if (parent != null) {
3525 parent.postProcessKeyEvent(e);
3529 boolean postsOldMouseEvents() {
3534 * Sets the <code>ComponentOrientation</code> property of this container
3535 * and all components contained within it.
3537 * This method changes layout-related information, and therefore,
3538 * invalidates the component hierarchy.
3540 * @param o the new component orientation of this container and
3541 * the components contained within it.
3542 * @exception NullPointerException if <code>orientation</code> is null.
3543 * @see Component#setComponentOrientation
3544 * @see Component#getComponentOrientation
3548 public void applyComponentOrientation(ComponentOrientation o) {
3549 super.applyComponentOrientation(o);
3550 synchronized (getTreeLock()) {
3551 for (int i = 0; i < component.size(); i++) {
3552 Component comp = component.get(i);
3553 comp.applyComponentOrientation(o);
3559 * Adds a PropertyChangeListener to the listener list. The listener is
3560 * registered for all bound properties of this class, including the
3563 * <li>this Container's font ("font")</li>
3564 * <li>this Container's background color ("background")</li>
3565 * <li>this Container's foreground color ("foreground")</li>
3566 * <li>this Container's focusability ("focusable")</li>
3567 * <li>this Container's focus traversal keys enabled state
3568 * ("focusTraversalKeysEnabled")</li>
3569 * <li>this Container's Set of FORWARD_TRAVERSAL_KEYS
3570 * ("forwardFocusTraversalKeys")</li>
3571 * <li>this Container's Set of BACKWARD_TRAVERSAL_KEYS
3572 * ("backwardFocusTraversalKeys")</li>
3573 * <li>this Container's Set of UP_CYCLE_TRAVERSAL_KEYS
3574 * ("upCycleFocusTraversalKeys")</li>
3575 * <li>this Container's Set of DOWN_CYCLE_TRAVERSAL_KEYS
3576 * ("downCycleFocusTraversalKeys")</li>
3577 * <li>this Container's focus traversal policy ("focusTraversalPolicy")
3579 * <li>this Container's focus-cycle-root state ("focusCycleRoot")</li>
3581 * Note that if this Container is inheriting a bound property, then no
3582 * event will be fired in response to a change in the inherited property.
3584 * If listener is null, no exception is thrown and no action is performed.
3586 * @param listener the PropertyChangeListener to be added
3588 * @see Component#removePropertyChangeListener
3589 * @see #addPropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
3591 public void addPropertyChangeListener(PropertyChangeListener listener) {
3592 super.addPropertyChangeListener(listener);
3596 * Adds a PropertyChangeListener to the listener list for a specific
3597 * property. The specified property may be user-defined, or one of the
3598 * following defaults:
3600 * <li>this Container's font ("font")</li>
3601 * <li>this Container's background color ("background")</li>
3602 * <li>this Container's foreground color ("foreground")</li>
3603 * <li>this Container's focusability ("focusable")</li>
3604 * <li>this Container's focus traversal keys enabled state
3605 * ("focusTraversalKeysEnabled")</li>
3606 * <li>this Container's Set of FORWARD_TRAVERSAL_KEYS
3607 * ("forwardFocusTraversalKeys")</li>
3608 * <li>this Container's Set of BACKWARD_TRAVERSAL_KEYS
3609 * ("backwardFocusTraversalKeys")</li>
3610 * <li>this Container's Set of UP_CYCLE_TRAVERSAL_KEYS
3611 * ("upCycleFocusTraversalKeys")</li>
3612 * <li>this Container's Set of DOWN_CYCLE_TRAVERSAL_KEYS
3613 * ("downCycleFocusTraversalKeys")</li>
3614 * <li>this Container's focus traversal policy ("focusTraversalPolicy")
3616 * <li>this Container's focus-cycle-root state ("focusCycleRoot")</li>
3617 * <li>this Container's focus-traversal-policy-provider state("focusTraversalPolicyProvider")</li>
3618 * <li>this Container's focus-traversal-policy-provider state("focusTraversalPolicyProvider")</li>
3620 * Note that if this Container is inheriting a bound property, then no
3621 * event will be fired in response to a change in the inherited property.
3623 * If listener is null, no exception is thrown and no action is performed.
3625 * @param propertyName one of the property names listed above
3626 * @param listener the PropertyChangeListener to be added
3628 * @see #addPropertyChangeListener(java.beans.PropertyChangeListener)
3629 * @see Component#removePropertyChangeListener
3631 public void addPropertyChangeListener(String propertyName,
3632 PropertyChangeListener listener) {
3633 super.addPropertyChangeListener(propertyName, listener);
3636 // Serialization support. A Container is responsible for restoring the
3637 // parent fields of its component children.
3640 * Container Serial Data Version.
3642 private int containerSerializedDataVersion = 1;
3645 * Serializes this <code>Container</code> to the specified
3646 * <code>ObjectOutputStream</code>.
3648 * <li>Writes default serializable fields to the stream.</li>
3649 * <li>Writes a list of serializable ContainerListener(s) as optional
3650 * data. The non-serializable ContainerListner(s) are detected and
3651 * no attempt is made to serialize them.</li>
3652 * <li>Write this Container's FocusTraversalPolicy if and only if it
3653 * is Serializable; otherwise, <code>null</code> is written.</li>
3656 * @param s the <code>ObjectOutputStream</code> to write
3657 * @serialData <code>null</code> terminated sequence of 0 or more pairs;
3658 * the pair consists of a <code>String</code> and <code>Object</code>;
3659 * the <code>String</code> indicates the type of object and
3660 * is one of the following:
3661 * <code>containerListenerK</code> indicating an
3662 * <code>ContainerListener</code> object;
3663 * the <code>Container</code>'s <code>FocusTraversalPolicy</code>,
3664 * or <code>null</code>
3666 * @see AWTEventMulticaster#save(java.io.ObjectOutputStream, java.lang.String, java.util.EventListener)
3667 * @see Container#containerListenerK
3668 * @see #readObject(ObjectInputStream)
3670 private void writeObject(ObjectOutputStream s) throws IOException {
3671 ObjectOutputStream.PutField f = s.putFields();
3672 f.put("ncomponents", component.size());
3673 f.put("component", getComponentsSync());
3674 f.put("layoutMgr", layoutMgr);
3675 f.put("dispatcher", dispatcher);
3676 f.put("maxSize", maxSize);
3677 f.put("focusCycleRoot", focusCycleRoot);
3678 f.put("containerSerializedDataVersion", containerSerializedDataVersion);
3679 f.put("focusTraversalPolicyProvider", focusTraversalPolicyProvider);
3682 AWTEventMulticaster.save(s, containerListenerK, containerListener);
3683 s.writeObject(null);
3685 if (focusTraversalPolicy instanceof java.io.Serializable) {
3686 s.writeObject(focusTraversalPolicy);
3688 s.writeObject(null);
3693 * Deserializes this <code>Container</code> from the specified
3694 * <code>ObjectInputStream</code>.
3696 * <li>Reads default serializable fields from the stream.</li>
3697 * <li>Reads a list of serializable ContainerListener(s) as optional
3698 * data. If the list is null, no Listeners are installed.</li>
3699 * <li>Reads this Container's FocusTraversalPolicy, which may be null,
3700 * as optional data.</li>
3703 * @param s the <code>ObjectInputStream</code> to read
3705 * @see #addContainerListener
3706 * @see #writeObject(ObjectOutputStream)
3708 private void readObject(ObjectInputStream s)
3709 throws ClassNotFoundException, IOException
3711 ObjectInputStream.GetField f = s.readFields();
3712 Component [] tmpComponent = (Component[])f.get("component", EMPTY_ARRAY);
3713 int ncomponents = (Integer) f.get("ncomponents", 0);
3714 component = new java.util.ArrayList<Component>(ncomponents);
3715 for (int i = 0; i < ncomponents; ++i) {
3716 component.add(tmpComponent[i]);
3718 layoutMgr = (LayoutManager)f.get("layoutMgr", null);
3719 dispatcher = (LightweightDispatcher)f.get("dispatcher", null);
3720 // Old stream. Doesn't contain maxSize among Component's fields.
3721 if (maxSize == null) {
3722 maxSize = (Dimension)f.get("maxSize", null);
3724 focusCycleRoot = f.get("focusCycleRoot", false);
3725 containerSerializedDataVersion = f.get("containerSerializedDataVersion", 1);
3726 focusTraversalPolicyProvider = f.get("focusTraversalPolicyProvider", false);
3727 java.util.List<Component> component = this.component;
3728 for(Component comp : component) {
3730 adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK,
3731 comp.numListening(AWTEvent.HIERARCHY_EVENT_MASK));
3732 adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
3733 comp.numListening(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));
3734 adjustDescendants(comp.countHierarchyMembers());
3738 while(null != (keyOrNull = s.readObject())) {
3739 String key = ((String)keyOrNull).intern();
3741 if (containerListenerK == key) {
3742 addContainerListener((ContainerListener)(s.readObject()));
3744 // skip value for unrecognized key
3750 Object policy = s.readObject();
3751 if (policy instanceof FocusTraversalPolicy) {
3752 focusTraversalPolicy = (FocusTraversalPolicy)policy;
3754 } catch (java.io.OptionalDataException e) {
3755 // JDK 1.1/1.2/1.3 instances will not have this optional data.
3756 // e.eof will be true to indicate that there is no more data
3757 // available for this object. If e.eof is not true, throw the
3758 // exception as it might have been caused by reasons unrelated to
3759 // focusTraversalPolicy.
3768 * --- Accessibility Support ---
3772 * Inner class of Container used to provide default support for
3773 * accessibility. This class is not meant to be used directly by
3774 * application developers, but is instead meant only to be
3775 * subclassed by container developers.
3777 * The class used to obtain the accessible role for this object,
3778 * as well as implementing many of the methods in the
3779 * AccessibleContainer interface.
3782 protected class AccessibleAWTContainer extends AccessibleAWTComponent {
3785 * JDK1.3 serialVersionUID
3787 private static final long serialVersionUID = 5081320404842566097L;
3790 * Returns the number of accessible children in the object. If all
3791 * of the children of this object implement <code>Accessible</code>,
3792 * then this method should return the number of children of this object.
3794 * @return the number of accessible children in the object
3796 public int getAccessibleChildrenCount() {
3797 return Container.this.getAccessibleChildrenCount();
3801 * Returns the nth <code>Accessible</code> child of the object.
3803 * @param i zero-based index of child
3804 * @return the nth <code>Accessible</code> child of the object
3806 public Accessible getAccessibleChild(int i) {
3807 return Container.this.getAccessibleChild(i);
3811 * Returns the <code>Accessible</code> child, if one exists,
3812 * contained at the local coordinate <code>Point</code>.
3814 * @param p the point defining the top-left corner of the
3815 * <code>Accessible</code>, given in the coordinate space
3816 * of the object's parent
3817 * @return the <code>Accessible</code>, if it exists,
3818 * at the specified location; else <code>null</code>
3820 public Accessible getAccessibleAt(Point p) {
3821 return Container.this.getAccessibleAt(p);
3824 protected ContainerListener accessibleContainerHandler = null;
3827 * Fire <code>PropertyChange</code> listener, if one is registered,
3828 * when children are added or removed.
3831 protected class AccessibleContainerHandler
3832 implements ContainerListener {
3833 public void componentAdded(ContainerEvent e) {
3834 Component c = e.getChild();
3835 if (c != null && c instanceof Accessible) {
3836 AccessibleAWTContainer.this.firePropertyChange(
3837 AccessibleContext.ACCESSIBLE_CHILD_PROPERTY,
3838 null, ((Accessible) c).getAccessibleContext());
3841 public void componentRemoved(ContainerEvent e) {
3842 Component c = e.getChild();
3843 if (c != null && c instanceof Accessible) {
3844 AccessibleAWTContainer.this.firePropertyChange(
3845 AccessibleContext.ACCESSIBLE_CHILD_PROPERTY,
3846 ((Accessible) c).getAccessibleContext(), null);
3852 * Adds a PropertyChangeListener to the listener list.
3854 * @param listener the PropertyChangeListener to be added
3856 public void addPropertyChangeListener(PropertyChangeListener listener) {
3857 if (accessibleContainerHandler == null) {
3858 accessibleContainerHandler = new AccessibleContainerHandler();
3859 Container.this.addContainerListener(accessibleContainerHandler);
3861 super.addPropertyChangeListener(listener);
3864 } // inner class AccessibleAWTContainer
3867 * Returns the <code>Accessible</code> child contained at the local
3868 * coordinate <code>Point</code>, if one exists. Otherwise
3869 * returns <code>null</code>.
3871 * @param p the point defining the top-left corner of the
3872 * <code>Accessible</code>, given in the coordinate space
3873 * of the object's parent
3874 * @return the <code>Accessible</code> at the specified location,
3875 * if it exists; otherwise <code>null</code>
3877 Accessible getAccessibleAt(Point p) {
3878 synchronized (getTreeLock()) {
3879 if (this instanceof Accessible) {
3880 Accessible a = (Accessible)this;
3881 AccessibleContext ac = a.getAccessibleContext();
3883 AccessibleComponent acmp;
3885 int nchildren = ac.getAccessibleChildrenCount();
3886 for (int i=0; i < nchildren; i++) {
3887 a = ac.getAccessibleChild(i);
3889 ac = a.getAccessibleContext();
3891 acmp = ac.getAccessibleComponent();
3892 if ((acmp != null) && (acmp.isShowing())) {
3893 location = acmp.getLocation();
3894 Point np = new Point(p.x-location.x,
3896 if (acmp.contains(np)){
3904 return (Accessible)this;
3906 Component ret = this;
3907 if (!this.contains(p.x,p.y)) {
3910 int ncomponents = this.getComponentCount();
3911 for (int i=0; i < ncomponents; i++) {
3912 Component comp = this.getComponent(i);
3913 if ((comp != null) && comp.isShowing()) {
3914 Point location = comp.getLocation();
3915 if (comp.contains(p.x-location.x,p.y-location.y)) {
3921 if (ret instanceof Accessible) {
3922 return (Accessible) ret;
3930 * Returns the number of accessible children in the object. If all
3931 * of the children of this object implement <code>Accessible</code>,
3932 * then this method should return the number of children of this object.
3934 * @return the number of accessible children in the object
3936 int getAccessibleChildrenCount() {
3937 synchronized (getTreeLock()) {
3939 Component[] children = this.getComponents();
3940 for (int i = 0; i < children.length; i++) {
3941 if (children[i] instanceof Accessible) {
3950 * Returns the nth <code>Accessible</code> child of the object.
3952 * @param i zero-based index of child
3953 * @return the nth <code>Accessible</code> child of the object
3955 Accessible getAccessibleChild(int i) {
3956 synchronized (getTreeLock()) {
3957 Component[] children = this.getComponents();
3959 for (int j = 0; j < children.length; j++) {
3960 if (children[j] instanceof Accessible) {
3962 return (Accessible) children[j];
3972 // ************************** MIXING CODE *******************************
3974 final void increaseComponentCount(Component c) {
3975 synchronized (getTreeLock()) {
3976 if (!c.isDisplayable()) {
3977 throw new IllegalStateException(
3978 "Peer does not exist while invoking the increaseComponentCount() method"
3985 if (c instanceof Container) {
3986 addLW = ((Container)c).numOfLWComponents;
3987 addHW = ((Container)c).numOfHWComponents;
3989 if (c.isLightweight()) {
3995 for (Container cont = this; cont != null; cont = cont.getContainer()) {
3996 cont.numOfLWComponents += addLW;
3997 cont.numOfHWComponents += addHW;
4002 final void decreaseComponentCount(Component c) {
4003 synchronized (getTreeLock()) {
4004 if (!c.isDisplayable()) {
4005 throw new IllegalStateException(
4006 "Peer does not exist while invoking the decreaseComponentCount() method"
4013 if (c instanceof Container) {
4014 subLW = ((Container)c).numOfLWComponents;
4015 subHW = ((Container)c).numOfHWComponents;
4017 if (c.isLightweight()) {
4023 for (Container cont = this; cont != null; cont = cont.getContainer()) {
4024 cont.numOfLWComponents -= subLW;
4025 cont.numOfHWComponents -= subHW;
4030 private int getTopmostComponentIndex() {
4032 if (getComponentCount() > 0) {
4038 private int getBottommostComponentIndex() {
4040 if (getComponentCount() > 0) {
4041 return getComponentCount() - 1;
4047 * This method is overriden to handle opaque children in non-opaque
4051 final Region getOpaqueShape() {
4053 if (isLightweight() && isNonOpaqueForMixing()
4054 && hasLightweightDescendants())
4056 Region s = Region.EMPTY_REGION;
4057 for (int index = 0; index < getComponentCount(); index++) {
4058 Component c = getComponent(index);
4059 if (c.isLightweight() && c.isShowing()) {
4060 s = s.getUnion(c.getOpaqueShape());
4063 return s.getIntersection(getNormalShape());
4065 return super.getOpaqueShape();
4068 final void recursiveSubtractAndApplyShape(Region shape) {
4069 recursiveSubtractAndApplyShape(shape, getTopmostComponentIndex(), getBottommostComponentIndex());
4072 final void recursiveSubtractAndApplyShape(Region shape, int fromZorder) {
4073 recursiveSubtractAndApplyShape(shape, fromZorder, getBottommostComponentIndex());
4076 final void recursiveSubtractAndApplyShape(Region shape, int fromZorder, int toZorder) {
4078 if (mixingLog.isLoggable(PlatformLogger.FINE)) {
4079 mixingLog.fine("this = " + this +
4080 "; shape=" + shape + "; fromZ=" + fromZorder + "; toZ=" + toZorder);
4082 if (fromZorder == -1) {
4085 if (shape.isEmpty()) {
4088 // An invalid container with not-null layout should be ignored
4089 // by the mixing code, the container will be validated later
4090 // and the mixing code will be executed later.
4091 if (getLayout() != null && !isValid()) {
4094 for (int index = fromZorder; index <= toZorder; index++) {
4095 Component comp = getComponent(index);
4096 if (!comp.isLightweight()) {
4097 comp.subtractAndApplyShape(shape);
4098 } else if (comp instanceof Container &&
4099 ((Container)comp).hasHeavyweightDescendants() && comp.isShowing()) {
4100 ((Container)comp).recursiveSubtractAndApplyShape(shape);
4105 final void recursiveApplyCurrentShape() {
4106 recursiveApplyCurrentShape(getTopmostComponentIndex(), getBottommostComponentIndex());
4109 final void recursiveApplyCurrentShape(int fromZorder) {
4110 recursiveApplyCurrentShape(fromZorder, getBottommostComponentIndex());
4113 final void recursiveApplyCurrentShape(int fromZorder, int toZorder) {
4115 if (mixingLog.isLoggable(PlatformLogger.FINE)) {
4116 mixingLog.fine("this = " + this +
4117 "; fromZ=" + fromZorder + "; toZ=" + toZorder);
4119 if (fromZorder == -1) {
4122 // An invalid container with not-null layout should be ignored
4123 // by the mixing code, the container will be validated later
4124 // and the mixing code will be executed later.
4125 if (getLayout() != null && !isValid()) {
4128 for (int index = fromZorder; index <= toZorder; index++) {
4129 Component comp = getComponent(index);
4130 if (!comp.isLightweight()) {
4131 comp.applyCurrentShape();
4133 if (comp instanceof Container &&
4134 ((Container)comp).hasHeavyweightDescendants()) {
4135 ((Container)comp).recursiveApplyCurrentShape();
4140 private void recursiveShowHeavyweightChildren() {
4141 if (!hasHeavyweightDescendants() || !isVisible()) {
4144 for (int index = 0; index < getComponentCount(); index++) {
4145 Component comp = getComponent(index);
4146 if (comp.isLightweight()) {
4147 if (comp instanceof Container) {
4148 ((Container)comp).recursiveShowHeavyweightChildren();
4151 if (comp.isVisible()) {
4152 ComponentPeer peer = comp.getPeer();
4154 peer.setVisible(true);
4161 private void recursiveHideHeavyweightChildren() {
4162 if (!hasHeavyweightDescendants()) {
4165 for (int index = 0; index < getComponentCount(); index++) {
4166 Component comp = getComponent(index);
4167 if (comp.isLightweight()) {
4168 if (comp instanceof Container) {
4169 ((Container)comp).recursiveHideHeavyweightChildren();
4172 if (comp.isVisible()) {
4173 ComponentPeer peer = comp.getPeer();
4175 peer.setVisible(false);
4182 private void recursiveRelocateHeavyweightChildren(Point origin) {
4183 for (int index = 0; index < getComponentCount(); index++) {
4184 Component comp = getComponent(index);
4185 if (comp.isLightweight()) {
4186 if (comp instanceof Container &&
4187 ((Container)comp).hasHeavyweightDescendants())
4189 final Point newOrigin = new Point(origin);
4190 newOrigin.translate(comp.getX(), comp.getY());
4191 ((Container)comp).recursiveRelocateHeavyweightChildren(newOrigin);
4194 ComponentPeer peer = comp.getPeer();
4196 peer.setBounds(origin.x + comp.getX(), origin.y + comp.getY(),
4197 comp.getWidth(), comp.getHeight(),
4198 ComponentPeer.SET_LOCATION);
4205 * Checks if the container and its direct lightweight containers are
4208 * Consider the heavyweight container hides or shows the HW descendants
4209 * automatically. Therefore we care of LW containers' visibility only.
4211 * This method MUST be invoked under the TreeLock.
4213 final boolean isRecursivelyVisibleUpToHeavyweightContainer() {
4214 if (!isLightweight()) {
4218 for (Container cont = this;
4219 cont != null && cont.isLightweight();
4220 cont = cont.getContainer())
4222 if (!cont.isVisible()) {
4230 void mixOnShowing() {
4231 synchronized (getTreeLock()) {
4232 if (mixingLog.isLoggable(PlatformLogger.FINE)) {
4233 mixingLog.fine("this = " + this);
4236 boolean isLightweight = isLightweight();
4238 if (isLightweight && isRecursivelyVisibleUpToHeavyweightContainer()) {
4239 recursiveShowHeavyweightChildren();
4242 if (!isMixingNeeded()) {
4246 if (!isLightweight || (isLightweight && hasHeavyweightDescendants())) {
4247 recursiveApplyCurrentShape();
4250 super.mixOnShowing();
4255 void mixOnHiding(boolean isLightweight) {
4256 synchronized (getTreeLock()) {
4257 if (mixingLog.isLoggable(PlatformLogger.FINE)) {
4258 mixingLog.fine("this = " + this +
4259 "; isLightweight=" + isLightweight);
4261 if (isLightweight) {
4262 recursiveHideHeavyweightChildren();
4264 super.mixOnHiding(isLightweight);
4269 void mixOnReshaping() {
4270 synchronized (getTreeLock()) {
4271 if (mixingLog.isLoggable(PlatformLogger.FINE)) {
4272 mixingLog.fine("this = " + this);
4275 boolean isMixingNeeded = isMixingNeeded();
4277 if (isLightweight() && hasHeavyweightDescendants()) {
4278 final Point origin = new Point(getX(), getY());
4279 for (Container cont = getContainer();
4280 cont != null && cont.isLightweight();
4281 cont = cont.getContainer())
4283 origin.translate(cont.getX(), cont.getY());
4286 recursiveRelocateHeavyweightChildren(origin);
4288 if (!isMixingNeeded) {
4292 recursiveApplyCurrentShape();
4295 if (!isMixingNeeded) {
4299 super.mixOnReshaping();
4304 void mixOnZOrderChanging(int oldZorder, int newZorder) {
4305 synchronized (getTreeLock()) {
4306 if (mixingLog.isLoggable(PlatformLogger.FINE)) {
4307 mixingLog.fine("this = " + this +
4308 "; oldZ=" + oldZorder + "; newZ=" + newZorder);
4311 if (!isMixingNeeded()) {
4315 boolean becameHigher = newZorder < oldZorder;
4317 if (becameHigher && isLightweight() && hasHeavyweightDescendants()) {
4318 recursiveApplyCurrentShape();
4320 super.mixOnZOrderChanging(oldZorder, newZorder);
4325 void mixOnValidating() {
4326 synchronized (getTreeLock()) {
4327 if (mixingLog.isLoggable(PlatformLogger.FINE)) {
4328 mixingLog.fine("this = " + this);
4331 if (!isMixingNeeded()) {
4335 if (hasHeavyweightDescendants()) {
4336 recursiveApplyCurrentShape();
4339 if (isLightweight() && isNonOpaqueForMixing()) {
4340 subtractAndApplyShapeBelowMe();
4343 super.mixOnValidating();
4347 // ****************** END OF MIXING CODE ********************************
4352 * Class to manage the dispatching of MouseEvents to the lightweight descendants
4353 * and SunDropTargetEvents to both lightweight and heavyweight descendants
4354 * contained by a native container.
4356 * NOTE: the class name is not appropriate anymore, but we cannot change it
4357 * because we must keep serialization compatibility.
4359 * @author Timothy Prinzing
4361 class LightweightDispatcher implements java.io.Serializable, AWTEventListener {
4364 * JDK 1.1 serialVersionUID
4366 private static final long serialVersionUID = 5184291520170872969L;
4368 * Our own mouse event for when we're dragged over from another hw
4371 private static final int LWD_MOUSE_DRAGGED_OVER = 1500;
4373 private static final PlatformLogger eventLog = PlatformLogger.getLogger("java.awt.event.LightweightDispatcher");
4375 LightweightDispatcher(Container nativeContainer) {
4376 this.nativeContainer = nativeContainer;
4377 mouseEventTarget = null;
4382 * Clean up any resources allocated when dispatcher was created;
4383 * should be called from Container.removeNotify
4386 //System.out.println("Disposing lw dispatcher");
4387 stopListeningForOtherDrags();
4388 mouseEventTarget = null;
4392 * Enables events to subcomponents.
4394 void enableEvents(long events) {
4395 eventMask |= events;
4399 * Dispatches an event to a sub-component if necessary, and
4400 * returns whether or not the event was forwarded to a
4403 * @param e the event
4405 boolean dispatchEvent(AWTEvent e) {
4406 boolean ret = false;
4409 * Fix for BugTraq Id 4389284.
4410 * Dispatch SunDropTargetEvents regardless of eventMask value.
4411 * Do not update cursor on dispatching SunDropTargetEvents.
4413 if (e instanceof SunDropTargetEvent) {
4415 SunDropTargetEvent sdde = (SunDropTargetEvent) e;
4416 ret = processDropTargetEvent(sdde);
4419 if (e instanceof MouseEvent && (eventMask & MOUSE_MASK) != 0) {
4420 MouseEvent me = (MouseEvent) e;
4421 ret = processMouseEvent(me);
4424 if (e.getID() == MouseEvent.MOUSE_MOVED) {
4425 nativeContainer.updateCursorImmediately();
4432 /* This method effectively returns whether or not a mouse button was down
4433 * just BEFORE the event happened. A better method name might be
4434 * wasAMouseButtonDownBeforeThisEvent().
4436 private boolean isMouseGrab(MouseEvent e) {
4437 int modifiers = e.getModifiersEx();
4439 if(e.getID() == MouseEvent.MOUSE_PRESSED
4440 || e.getID() == MouseEvent.MOUSE_RELEASED)
4442 switch (e.getButton()) {
4443 case MouseEvent.BUTTON1:
4444 modifiers ^= InputEvent.BUTTON1_DOWN_MASK;
4446 case MouseEvent.BUTTON2:
4447 modifiers ^= InputEvent.BUTTON2_DOWN_MASK;
4449 case MouseEvent.BUTTON3:
4450 modifiers ^= InputEvent.BUTTON3_DOWN_MASK;
4454 /* modifiers now as just before event */
4455 return ((modifiers & (InputEvent.BUTTON1_DOWN_MASK
4456 | InputEvent.BUTTON2_DOWN_MASK
4457 | InputEvent.BUTTON3_DOWN_MASK)) != 0);
4461 * This method attempts to distribute a mouse event to a lightweight
4462 * component. It tries to avoid doing any unnecessary probes down
4463 * into the component tree to minimize the overhead of determining
4464 * where to route the event, since mouse movement events tend to
4465 * come in large and frequent amounts.
4467 private boolean processMouseEvent(MouseEvent e) {
4469 Component mouseOver = // sensitive to mouse events
4470 nativeContainer.getMouseEventTarget(e.getX(), e.getY(),
4471 Container.INCLUDE_SELF);
4473 trackMouseEnterExit(mouseOver, e);
4475 // 4508327 : MOUSE_CLICKED should only go to the recipient of
4476 // the accompanying MOUSE_PRESSED, so don't reset mouseEventTarget on a
4478 if (!isMouseGrab(e) && id != MouseEvent.MOUSE_CLICKED) {
4479 mouseEventTarget = (mouseOver != nativeContainer) ? mouseOver: null;
4482 if (mouseEventTarget != null) {
4484 case MouseEvent.MOUSE_ENTERED:
4485 case MouseEvent.MOUSE_EXITED:
4487 case MouseEvent.MOUSE_PRESSED:
4488 retargetMouseEvent(mouseEventTarget, id, e);
4490 case MouseEvent.MOUSE_RELEASED:
4491 retargetMouseEvent(mouseEventTarget, id, e);
4493 case MouseEvent.MOUSE_CLICKED:
4494 // 4508327: MOUSE_CLICKED should never be dispatched to a Component
4495 // other than that which received the MOUSE_PRESSED event. If the
4496 // mouse is now over a different Component, don't dispatch the event.
4497 // The previous fix for a similar problem was associated with bug
4499 if (mouseOver == mouseEventTarget) {
4500 retargetMouseEvent(mouseOver, id, e);
4503 case MouseEvent.MOUSE_MOVED:
4504 retargetMouseEvent(mouseEventTarget, id, e);
4506 case MouseEvent.MOUSE_DRAGGED:
4507 if (isMouseGrab(e)) {
4508 retargetMouseEvent(mouseEventTarget, id, e);
4511 case MouseEvent.MOUSE_WHEEL:
4512 // This may send it somewhere that doesn't have MouseWheelEvents
4513 // enabled. In this case, Component.dispatchEventImpl() will
4514 // retarget the event to a parent that DOES have the events enabled.
4515 if (eventLog.isLoggable(PlatformLogger.FINEST) && (mouseOver != null)) {
4516 eventLog.finest("retargeting mouse wheel to " +
4517 mouseOver.getName() + ", " +
4518 mouseOver.getClass());
4520 retargetMouseEvent(mouseOver, id, e);
4523 //Consuming of wheel events is implemented in "retargetMouseEvent".
4524 if (id != MouseEvent.MOUSE_WHEEL) {
4528 return e.isConsumed();
4531 private boolean processDropTargetEvent(SunDropTargetEvent e) {
4537 * Fix for BugTraq ID 4395290.
4538 * It is possible that SunDropTargetEvent's Point is outside of the
4539 * native container bounds. In this case we truncate coordinates.
4541 if (!nativeContainer.contains(x, y)) {
4542 final Dimension d = nativeContainer.getSize();
4548 if (d.height <= y) {
4554 Component mouseOver = // not necessarily sensitive to mouse events
4555 nativeContainer.getDropTargetEventTarget(x, y,
4556 Container.INCLUDE_SELF);
4557 trackMouseEnterExit(mouseOver, e);
4559 if (mouseOver != nativeContainer && mouseOver != null) {
4561 case SunDropTargetEvent.MOUSE_ENTERED:
4562 case SunDropTargetEvent.MOUSE_EXITED:
4565 retargetMouseEvent(mouseOver, id, e);
4570 return e.isConsumed();
4574 * Generates enter/exit events as mouse moves over lw components
4575 * @param targetOver Target mouse is over (including native container)
4576 * @param e Mouse event in native container
4578 private void trackMouseEnterExit(Component targetOver, MouseEvent e) {
4579 Component targetEnter = null;
4582 if (e instanceof SunDropTargetEvent &&
4583 id == MouseEvent.MOUSE_ENTERED &&
4584 isMouseInNativeContainer == true) {
4585 // This can happen if a lightweight component which initiated the
4586 // drag has an associated drop target. MOUSE_ENTERED comes when the
4587 // mouse is in the native container already. To propagate this event
4588 // properly we should null out targetLastEntered.
4589 targetLastEntered = null;
4590 } else if ( id != MouseEvent.MOUSE_EXITED &&
4591 id != MouseEvent.MOUSE_DRAGGED &&
4592 id != LWD_MOUSE_DRAGGED_OVER &&
4593 isMouseInNativeContainer == false ) {
4594 // any event but an exit or drag means we're in the native container
4595 isMouseInNativeContainer = true;
4596 startListeningForOtherDrags();
4597 } else if ( id == MouseEvent.MOUSE_EXITED ) {
4598 isMouseInNativeContainer = false;
4599 stopListeningForOtherDrags();
4602 if (isMouseInNativeContainer) {
4603 targetEnter = targetOver;
4606 if (targetLastEntered == targetEnter) {
4610 if (targetLastEntered != null) {
4611 retargetMouseEvent(targetLastEntered, MouseEvent.MOUSE_EXITED, e);
4613 if (id == MouseEvent.MOUSE_EXITED) {
4614 // consume native exit event if we generate one
4618 if (targetEnter != null) {
4619 retargetMouseEvent(targetEnter, MouseEvent.MOUSE_ENTERED, e);
4621 if (id == MouseEvent.MOUSE_ENTERED) {
4622 // consume native enter event if we generate one
4626 targetLastEntered = targetEnter;
4630 * Listens to global mouse drag events so even drags originating
4631 * from other heavyweight containers will generate enter/exit
4632 * events in this container
4634 private void startListeningForOtherDrags() {
4635 //System.out.println("Adding AWTEventListener");
4636 java.security.AccessController.doPrivileged(
4637 new java.security.PrivilegedAction() {
4638 public Object run() {
4639 nativeContainer.getToolkit().addAWTEventListener(
4640 LightweightDispatcher.this,
4641 AWTEvent.MOUSE_EVENT_MASK |
4642 AWTEvent.MOUSE_MOTION_EVENT_MASK);
4649 private void stopListeningForOtherDrags() {
4650 //System.out.println("Removing AWTEventListener");
4651 java.security.AccessController.doPrivileged(
4652 new java.security.PrivilegedAction() {
4653 public Object run() {
4654 nativeContainer.getToolkit().removeAWTEventListener(LightweightDispatcher.this);
4662 * (Implementation of AWTEventListener)
4663 * Listen for drag events posted in other hw components so we can
4664 * track enter/exit regardless of where a drag originated
4666 public void eventDispatched(AWTEvent e) {
4667 boolean isForeignDrag = (e instanceof MouseEvent) &&
4668 !(e instanceof SunDropTargetEvent) &&
4669 (e.id == MouseEvent.MOUSE_DRAGGED) &&
4670 (e.getSource() != nativeContainer);
4672 if (!isForeignDrag) {
4673 // only interested in drags from other hw components
4677 MouseEvent srcEvent = (MouseEvent)e;
4680 synchronized (nativeContainer.getTreeLock()) {
4681 Component srcComponent = srcEvent.getComponent();
4683 // component may have disappeared since drag event posted
4684 // (i.e. Swing hierarchical menus)
4685 if ( !srcComponent.isShowing() ) {
4690 // check if srcComponent is in any modal blocked window
4691 Component c = nativeContainer;
4692 while ((c != null) && !(c instanceof Window)) {
4693 c = c.getParent_NoClientCode();
4695 if ((c == null) || ((Window)c).isModalBlocked()) {
4700 // create an internal 'dragged-over' event indicating
4701 // we are being dragged over from another hw component
4703 me = new MouseEvent(nativeContainer,
4704 LWD_MOUSE_DRAGGED_OVER,
4706 srcEvent.getModifiersEx() | srcEvent.getModifiers(),
4709 srcEvent.getXOnScreen(),
4710 srcEvent.getYOnScreen(),
4711 srcEvent.getClickCount(),
4712 srcEvent.isPopupTrigger(),
4713 srcEvent.getButton());
4714 ((AWTEvent)srcEvent).copyPrivateDataInto(me);
4715 // translate coordinates to this native container
4716 final Point ptSrcOrigin = srcComponent.getLocationOnScreen();
4718 if (AppContext.getAppContext() != nativeContainer.appContext) {
4719 final MouseEvent mouseEvent = me;
4720 Runnable r = new Runnable() {
4722 if (!nativeContainer.isShowing() ) {
4726 Point ptDstOrigin = nativeContainer.getLocationOnScreen();
4727 mouseEvent.translatePoint(ptSrcOrigin.x - ptDstOrigin.x,
4728 ptSrcOrigin.y - ptDstOrigin.y );
4729 Component targetOver =
4730 nativeContainer.getMouseEventTarget(mouseEvent.getX(),
4732 Container.INCLUDE_SELF);
4733 trackMouseEnterExit(targetOver, mouseEvent);
4736 SunToolkit.executeOnEventHandlerThread(nativeContainer, r);
4739 if (!nativeContainer.isShowing() ) {
4743 Point ptDstOrigin = nativeContainer.getLocationOnScreen();
4744 me.translatePoint( ptSrcOrigin.x - ptDstOrigin.x, ptSrcOrigin.y - ptDstOrigin.y );
4747 //System.out.println("Track event: " + me);
4748 // feed the 'dragged-over' event directly to the enter/exit
4749 // code (not a real event so don't pass it to dispatchEvent)
4750 Component targetOver =
4751 nativeContainer.getMouseEventTarget(me.getX(), me.getY(),
4752 Container.INCLUDE_SELF);
4753 trackMouseEnterExit(targetOver, me);
4757 * Sends a mouse event to the current mouse event recipient using
4758 * the given event (sent to the windowed host) as a srcEvent. If
4759 * the mouse event target is still in the component tree, the
4760 * coordinates of the event are translated to those of the target.
4761 * If the target has been removed, we don't bother to send the
4764 void retargetMouseEvent(Component target, int id, MouseEvent e) {
4765 if (target == null) {
4766 return; // mouse is over another hw component or target is disabled
4769 int x = e.getX(), y = e.getY();
4770 Component component;
4772 for(component = target;
4773 component != null && component != nativeContainer;
4774 component = component.getParent()) {
4778 MouseEvent retargeted;
4779 if (component != null) {
4780 if (e instanceof SunDropTargetEvent) {
4781 retargeted = new SunDropTargetEvent(target,
4785 ((SunDropTargetEvent)e).getDispatcher());
4786 } else if (id == MouseEvent.MOUSE_WHEEL) {
4787 retargeted = new MouseWheelEvent(target,
4790 e.getModifiersEx() | e.getModifiers(),
4797 ((MouseWheelEvent)e).getScrollType(),
4798 ((MouseWheelEvent)e).getScrollAmount(),
4799 ((MouseWheelEvent)e).getWheelRotation(),
4800 ((MouseWheelEvent)e).getPreciseWheelRotation());
4803 retargeted = new MouseEvent(target,
4806 e.getModifiersEx() | e.getModifiers(),
4816 ((AWTEvent)e).copyPrivateDataInto(retargeted);
4818 if (target == nativeContainer) {
4819 // avoid recursively calling LightweightDispatcher...
4820 ((Container)target).dispatchEventToSelf(retargeted);
4822 assert AppContext.getAppContext() == target.appContext;
4824 if (nativeContainer.modalComp != null) {
4825 if (((Container)nativeContainer.modalComp).isAncestorOf(target)) {
4826 target.dispatchEvent(retargeted);
4831 target.dispatchEvent(retargeted);
4834 if (id == MouseEvent.MOUSE_WHEEL && retargeted.isConsumed()) {
4835 //An exception for wheel bubbling to the native system.
4836 //In "processMouseEvent" total event consuming for wheel events is skipped.
4837 //Protection from bubbling of Java-accepted wheel events.
4843 // --- member variables -------------------------------
4846 * The windowed container that might be hosting events for
4849 private Container nativeContainer;
4852 * This variable is not used, but kept for serialization compatibility
4854 private Component focus;
4857 * The current subcomponent being hosted by this windowed
4858 * component that has events being forwarded to it. If this
4859 * is null, there are currently no events being forwarded to
4862 private transient Component mouseEventTarget;
4865 * The last component entered
4867 private transient Component targetLastEntered;
4870 * Is the mouse over the native container
4872 private transient boolean isMouseInNativeContainer = false;
4875 * This variable is not used, but kept for serialization compatibility
4877 private Cursor nativeCursor;
4880 * The event mask for contained lightweight components. Lightweight
4881 * components need a windowed container to host window-related
4882 * events. This separate mask indicates events that have been
4883 * requested by contained lightweight components without effecting
4884 * the mask of the windowed component itself.
4886 private long eventMask;
4889 * The kind of events routed to lightweight components from windowed
4892 private static final long PROXY_EVENT_MASK =
4893 AWTEvent.FOCUS_EVENT_MASK |
4894 AWTEvent.KEY_EVENT_MASK |
4895 AWTEvent.MOUSE_EVENT_MASK |
4896 AWTEvent.MOUSE_MOTION_EVENT_MASK |
4897 AWTEvent.MOUSE_WHEEL_EVENT_MASK;
4899 private static final long MOUSE_MASK =
4900 AWTEvent.MOUSE_EVENT_MASK |
4901 AWTEvent.MOUSE_MOTION_EVENT_MASK |
4902 AWTEvent.MOUSE_WHEEL_EVENT_MASK;