Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/java/awt/Container.java
38829 views
/*1* Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/24package java.awt;2526import java.awt.dnd.DropTarget;2728import java.awt.event.*;2930import java.awt.peer.ContainerPeer;31import java.awt.peer.ComponentPeer;32import java.awt.peer.LightweightPeer;3334import java.beans.PropertyChangeListener;3536import java.io.IOException;37import java.io.InvalidObjectException;38import java.io.ObjectInputStream;39import java.io.ObjectOutputStream;40import java.io.ObjectStreamField;41import java.io.PrintStream;42import java.io.PrintWriter;4344import java.lang.ref.WeakReference;45import java.security.AccessController;4647import java.util.ArrayList;48import java.util.EventListener;49import java.util.HashSet;50import java.util.Set;5152import javax.accessibility.*;5354import sun.util.logging.PlatformLogger;5556import sun.awt.AppContext;57import sun.awt.AWTAccessor;58import sun.awt.AWTAccessor.MouseEventAccessor;59import sun.awt.CausedFocusEvent;60import sun.awt.PeerEvent;61import sun.awt.SunToolkit;6263import sun.awt.dnd.SunDropTargetEvent;6465import sun.java2d.pipe.Region;6667import sun.security.action.GetBooleanAction;6869/**70* A generic Abstract Window Toolkit(AWT) container object is a component71* that can contain other AWT components.72* <p>73* Components added to a container are tracked in a list. The order74* of the list will define the components' front-to-back stacking order75* within the container. If no index is specified when adding a76* component to a container, it will be added to the end of the list77* (and hence to the bottom of the stacking order).78* <p>79* <b>Note</b>: For details on the focus subsystem, see80* <a href="https://docs.oracle.com/javase/tutorial/uiswing/misc/focus.html">81* How to Use the Focus Subsystem</a>,82* a section in <em>The Java Tutorial</em>, and the83* <a href="../../java/awt/doc-files/FocusSpec.html">Focus Specification</a>84* for more information.85*86* @author Arthur van Hoff87* @author Sami Shaio88* @see #add(java.awt.Component, int)89* @see #getComponent(int)90* @see LayoutManager91* @since JDK1.092*/93public class Container extends Component {9495private static final PlatformLogger log = PlatformLogger.getLogger("java.awt.Container");96private static final PlatformLogger eventLog = PlatformLogger.getLogger("java.awt.event.Container");9798private static final Component[] EMPTY_ARRAY = new Component[0];99100/**101* The components in this container.102* @see #add103* @see #getComponents104*/105private java.util.List<Component> component = new ArrayList<>();106107/**108* Layout manager for this container.109* @see #doLayout110* @see #setLayout111* @see #getLayout112*/113LayoutManager layoutMgr;114115/**116* Event router for lightweight components. If this container117* is native, this dispatcher takes care of forwarding and118* retargeting the events to lightweight components contained119* (if any).120*/121private LightweightDispatcher dispatcher;122123/**124* The focus traversal policy that will manage keyboard traversal of this125* Container's children, if this Container is a focus cycle root. If the126* value is null, this Container inherits its policy from its focus-cycle-127* root ancestor. If all such ancestors of this Container have null128* policies, then the current KeyboardFocusManager's default policy is129* used. If the value is non-null, this policy will be inherited by all130* focus-cycle-root children that have no keyboard-traversal policy of131* their own (as will, recursively, their focus-cycle-root children).132* <p>133* If this Container is not a focus cycle root, the value will be134* remembered, but will not be used or inherited by this or any other135* Containers until this Container is made a focus cycle root.136*137* @see #setFocusTraversalPolicy138* @see #getFocusTraversalPolicy139* @since 1.4140*/141private transient FocusTraversalPolicy focusTraversalPolicy;142143/**144* Indicates whether this Component is the root of a focus traversal cycle.145* Once focus enters a traversal cycle, typically it cannot leave it via146* focus traversal unless one of the up- or down-cycle keys is pressed.147* Normal traversal is limited to this Container, and all of this148* Container's descendants that are not descendants of inferior focus cycle149* roots.150*151* @see #setFocusCycleRoot152* @see #isFocusCycleRoot153* @since 1.4154*/155private boolean focusCycleRoot = false;156157158/**159* Stores the value of focusTraversalPolicyProvider property.160* @since 1.5161* @see #setFocusTraversalPolicyProvider162*/163private boolean focusTraversalPolicyProvider;164165// keeps track of the threads that are printing this component166private transient Set<Thread> printingThreads;167// True if there is at least one thread that's printing this component168private transient boolean printing = false;169170transient ContainerListener containerListener;171172/* HierarchyListener and HierarchyBoundsListener support */173transient int listeningChildren;174transient int listeningBoundsChildren;175transient int descendantsCount;176177/* Non-opaque window support -- see Window.setLayersOpaque */178transient Color preserveBackgroundColor = null;179180/**181* JDK 1.1 serialVersionUID182*/183private static final long serialVersionUID = 4613797578919906343L;184185/**186* A constant which toggles one of the controllable behaviors187* of <code>getMouseEventTarget</code>. It is used to specify whether188* the method can return the Container on which it is originally called189* in case if none of its children are the current mouse event targets.190*191* @see #getMouseEventTarget(int, int, boolean)192*/193static final boolean INCLUDE_SELF = true;194195/**196* A constant which toggles one of the controllable behaviors197* of <code>getMouseEventTarget</code>. It is used to specify whether198* the method should search only lightweight components.199*200* @see #getMouseEventTarget(int, int, boolean)201*/202static final boolean SEARCH_HEAVYWEIGHTS = true;203204/*205* Number of HW or LW components in this container (including206* all descendant containers).207*/208private transient int numOfHWComponents = 0;209private transient int numOfLWComponents = 0;210211private static final PlatformLogger mixingLog = PlatformLogger.getLogger("java.awt.mixing.Container");212213/**214* @serialField ncomponents int215* The number of components in this container.216* This value can be null.217* @serialField component Component[]218* The components in this container.219* @serialField layoutMgr LayoutManager220* Layout manager for this container.221* @serialField dispatcher LightweightDispatcher222* Event router for lightweight components. If this container223* is native, this dispatcher takes care of forwarding and224* retargeting the events to lightweight components contained225* (if any).226* @serialField maxSize Dimension227* Maximum size of this Container.228* @serialField focusCycleRoot boolean229* Indicates whether this Component is the root of a focus traversal cycle.230* Once focus enters a traversal cycle, typically it cannot leave it via231* focus traversal unless one of the up- or down-cycle keys is pressed.232* Normal traversal is limited to this Container, and all of this233* Container's descendants that are not descendants of inferior focus cycle234* roots.235* @serialField containerSerializedDataVersion int236* Container Serial Data Version.237* @serialField focusTraversalPolicyProvider boolean238* Stores the value of focusTraversalPolicyProvider property.239*/240private static final ObjectStreamField[] serialPersistentFields = {241new ObjectStreamField("ncomponents", Integer.TYPE),242new ObjectStreamField("component", Component[].class),243new ObjectStreamField("layoutMgr", LayoutManager.class),244new ObjectStreamField("dispatcher", LightweightDispatcher.class),245new ObjectStreamField("maxSize", Dimension.class),246new ObjectStreamField("focusCycleRoot", Boolean.TYPE),247new ObjectStreamField("containerSerializedDataVersion", Integer.TYPE),248new ObjectStreamField("focusTraversalPolicyProvider", Boolean.TYPE),249};250251static {252/* ensure that the necessary native libraries are loaded */253Toolkit.loadLibraries();254if (!GraphicsEnvironment.isHeadless()) {255initIDs();256}257258AWTAccessor.setContainerAccessor(new AWTAccessor.ContainerAccessor() {259@Override260public void validateUnconditionally(Container cont) {261cont.validateUnconditionally();262}263264@Override265public Component findComponentAt(Container cont, int x, int y,266boolean ignoreEnabled) {267return cont.findComponentAt(x, y, ignoreEnabled);268}269});270}271272/**273* Initialize JNI field and method IDs for fields that may be274called from C.275*/276private static native void initIDs();277278/**279* Constructs a new Container. Containers can be extended directly,280* but are lightweight in this case and must be contained by a parent281* somewhere higher up in the component tree that is native.282* (such as Frame for example).283*/284public Container() {285}286@SuppressWarnings({"unchecked","rawtypes"})287void initializeFocusTraversalKeys() {288focusTraversalKeys = new Set[4];289}290291/**292* Gets the number of components in this panel.293* <p>294* Note: This method should be called under AWT tree lock.295*296* @return the number of components in this panel.297* @see #getComponent298* @since JDK1.1299* @see Component#getTreeLock()300*/301public int getComponentCount() {302return countComponents();303}304305/**306* @deprecated As of JDK version 1.1,307* replaced by getComponentCount().308*/309@Deprecated310public int countComponents() {311// This method is not synchronized under AWT tree lock.312// Instead, the calling code is responsible for the313// synchronization. See 6784816 for details.314return component.size();315}316317/**318* Gets the nth component in this container.319* <p>320* Note: This method should be called under AWT tree lock.321*322* @param n the index of the component to get.323* @return the n<sup>th</sup> component in this container.324* @exception ArrayIndexOutOfBoundsException325* if the n<sup>th</sup> value does not exist.326* @see Component#getTreeLock()327*/328public Component getComponent(int n) {329// This method is not synchronized under AWT tree lock.330// Instead, the calling code is responsible for the331// synchronization. See 6784816 for details.332try {333return component.get(n);334} catch (IndexOutOfBoundsException z) {335throw new ArrayIndexOutOfBoundsException("No such child: " + n);336}337}338339/**340* Gets all the components in this container.341* <p>342* Note: This method should be called under AWT tree lock.343*344* @return an array of all the components in this container.345* @see Component#getTreeLock()346*/347public Component[] getComponents() {348// This method is not synchronized under AWT tree lock.349// Instead, the calling code is responsible for the350// synchronization. See 6784816 for details.351return getComponents_NoClientCode();352}353354// NOTE: This method may be called by privileged threads.355// This functionality is implemented in a package-private method356// to insure that it cannot be overridden by client subclasses.357// DO NOT INVOKE CLIENT CODE ON THIS THREAD!358final Component[] getComponents_NoClientCode() {359return component.toArray(EMPTY_ARRAY);360}361362/*363* Wrapper for getComponents() method with a proper synchronization.364*/365Component[] getComponentsSync() {366synchronized (getTreeLock()) {367return getComponents();368}369}370371/**372* Determines the insets of this container, which indicate the size373* of the container's border.374* <p>375* A <code>Frame</code> object, for example, has a top inset that376* corresponds to the height of the frame's title bar.377* @return the insets of this container.378* @see Insets379* @see LayoutManager380* @since JDK1.1381*/382public Insets getInsets() {383return insets();384}385386/**387* @deprecated As of JDK version 1.1,388* replaced by <code>getInsets()</code>.389*/390@Deprecated391public Insets insets() {392ComponentPeer peer = this.peer;393if (peer instanceof ContainerPeer) {394ContainerPeer cpeer = (ContainerPeer)peer;395return (Insets)cpeer.getInsets().clone();396}397return new Insets(0, 0, 0, 0);398}399400/**401* Appends the specified component to the end of this container.402* This is a convenience method for {@link #addImpl}.403* <p>404* This method changes layout-related information, and therefore,405* invalidates the component hierarchy. If the container has already been406* displayed, the hierarchy must be validated thereafter in order to407* display the added component.408*409* @param comp the component to be added410* @exception NullPointerException if {@code comp} is {@code null}411* @see #addImpl412* @see #invalidate413* @see #validate414* @see javax.swing.JComponent#revalidate()415* @return the component argument416*/417public Component add(Component comp) {418addImpl(comp, null, -1);419return comp;420}421422/**423* Adds the specified component to this container.424* This is a convenience method for {@link #addImpl}.425* <p>426* This method is obsolete as of 1.1. Please use the427* method <code>add(Component, Object)</code> instead.428* <p>429* This method changes layout-related information, and therefore,430* invalidates the component hierarchy. If the container has already been431* displayed, the hierarchy must be validated thereafter in order to432* display the added component.433*434* @exception NullPointerException if {@code comp} is {@code null}435* @see #add(Component, Object)436* @see #invalidate437*/438public Component add(String name, Component comp) {439addImpl(comp, name, -1);440return comp;441}442443/**444* Adds the specified component to this container at the given445* position.446* This is a convenience method for {@link #addImpl}.447* <p>448* This method changes layout-related information, and therefore,449* invalidates the component hierarchy. If the container has already been450* displayed, the hierarchy must be validated thereafter in order to451* display the added component.452*453*454* @param comp the component to be added455* @param index the position at which to insert the component,456* or <code>-1</code> to append the component to the end457* @exception NullPointerException if {@code comp} is {@code null}458* @exception IllegalArgumentException if {@code index} is invalid (see459* {@link #addImpl} for details)460* @return the component <code>comp</code>461* @see #addImpl462* @see #remove463* @see #invalidate464* @see #validate465* @see javax.swing.JComponent#revalidate()466*/467public Component add(Component comp, int index) {468addImpl(comp, null, index);469return comp;470}471472/**473* Checks that the component474* isn't supposed to be added into itself.475*/476private void checkAddToSelf(Component comp){477if (comp instanceof Container) {478for (Container cn = this; cn != null; cn=cn.parent) {479if (cn == comp) {480throw new IllegalArgumentException("adding container's parent to itself");481}482}483}484}485486/**487* Checks that the component is not a Window instance.488*/489private void checkNotAWindow(Component comp){490if (comp instanceof Window) {491throw new IllegalArgumentException("adding a window to a container");492}493}494495/**496* Checks that the component comp can be added to this container497* Checks : index in bounds of container's size,498* comp is not one of this container's parents,499* and comp is not a window.500* Comp and container must be on the same GraphicsDevice.501* if comp is container, all sub-components must be on502* same GraphicsDevice.503*504* @since 1.5505*/506private void checkAdding(Component comp, int index) {507checkTreeLock();508509GraphicsConfiguration thisGC = getGraphicsConfiguration();510511if (index > component.size() || index < 0) {512throw new IllegalArgumentException("illegal component position");513}514if (comp.parent == this) {515if (index == component.size()) {516throw new IllegalArgumentException("illegal component position " +517index + " should be less then " + component.size());518}519}520checkAddToSelf(comp);521checkNotAWindow(comp);522523Window thisTopLevel = getContainingWindow();524Window compTopLevel = comp.getContainingWindow();525if (thisTopLevel != compTopLevel) {526throw new IllegalArgumentException("component and container should be in the same top-level window");527}528if (thisGC != null) {529comp.checkGD(thisGC.getDevice().getIDstring());530}531}532533/**534* Removes component comp from this container without making unneccessary changes535* and generating unneccessary events. This function intended to perform optimized536* remove, for example, if newParent and current parent are the same it just changes537* index without calling removeNotify.538* Note: Should be called while holding treeLock539* Returns whether removeNotify was invoked540* @since: 1.5541*/542private boolean removeDelicately(Component comp, Container newParent, int newIndex) {543checkTreeLock();544545int index = getComponentZOrder(comp);546boolean needRemoveNotify = isRemoveNotifyNeeded(comp, this, newParent);547if (needRemoveNotify) {548comp.removeNotify();549}550if (newParent != this) {551if (layoutMgr != null) {552layoutMgr.removeLayoutComponent(comp);553}554adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK,555-comp.numListening(AWTEvent.HIERARCHY_EVENT_MASK));556adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,557-comp.numListening(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));558adjustDescendants(-(comp.countHierarchyMembers()));559560comp.parent = null;561if (needRemoveNotify) {562comp.setGraphicsConfiguration(null);563}564component.remove(index);565566invalidateIfValid();567} else {568// We should remove component and then569// add it by the newIndex without newIndex decrement if even we shift components to the left570// after remove. Consult the rules below:571// 2->4: 012345 -> 013425, 2->5: 012345 -> 013452572// 4->2: 012345 -> 014235573component.remove(index);574component.add(newIndex, comp);575}576if (comp.parent == null) { // was actually removed577if (containerListener != null ||578(eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 ||579Toolkit.enabledOnToolkit(AWTEvent.CONTAINER_EVENT_MASK)) {580ContainerEvent e = new ContainerEvent(this,581ContainerEvent.COMPONENT_REMOVED,582comp);583dispatchEvent(e);584585}586comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, comp,587this, HierarchyEvent.PARENT_CHANGED,588Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK));589if (peer != null && layoutMgr == null && isVisible()) {590updateCursorImmediately();591}592}593return needRemoveNotify;594}595596/**597* Checks whether this container can contain component which is focus owner.598* Verifies that container is enable and showing, and if it is focus cycle root599* its FTP allows component to be focus owner600* @since 1.5601*/602boolean canContainFocusOwner(Component focusOwnerCandidate) {603if (!(isEnabled() && isDisplayable()604&& isVisible() && isFocusable()))605{606return false;607}608if (isFocusCycleRoot()) {609FocusTraversalPolicy policy = getFocusTraversalPolicy();610if (policy instanceof DefaultFocusTraversalPolicy) {611if (!((DefaultFocusTraversalPolicy)policy).accept(focusOwnerCandidate)) {612return false;613}614}615}616synchronized(getTreeLock()) {617if (parent != null) {618return parent.canContainFocusOwner(focusOwnerCandidate);619}620}621return true;622}623624/**625* Checks whether or not this container has heavyweight children.626* Note: Should be called while holding tree lock627* @return true if there is at least one heavyweight children in a container, false otherwise628* @since 1.5629*/630final boolean hasHeavyweightDescendants() {631checkTreeLock();632return numOfHWComponents > 0;633}634635/**636* Checks whether or not this container has lightweight children.637* Note: Should be called while holding tree lock638* @return true if there is at least one lightweight children in a container, false otherwise639* @since 1.7640*/641final boolean hasLightweightDescendants() {642checkTreeLock();643return numOfLWComponents > 0;644}645646/**647* Returns closest heavyweight component to this container. If this container is heavyweight648* returns this.649* @since 1.5650*/651Container getHeavyweightContainer() {652checkTreeLock();653if (peer != null && !(peer instanceof LightweightPeer)) {654return this;655} else {656return getNativeContainer();657}658}659660/**661* Detects whether or not remove from current parent and adding to new parent requires call of662* removeNotify on the component. Since removeNotify destroys native window this might (not)663* be required. For example, if new container and old containers are the same we don't need to664* destroy native window.665* @since: 1.5666*/667private static boolean isRemoveNotifyNeeded(Component comp, Container oldContainer, Container newContainer) {668if (oldContainer == null) { // Component didn't have parent - no removeNotify669return false;670}671if (comp.peer == null) { // Component didn't have peer - no removeNotify672return false;673}674if (newContainer.peer == null) {675// Component has peer but new Container doesn't - call removeNotify676return true;677}678679// If component is lightweight non-Container or lightweight Container with all but heavyweight680// children there is no need to call remove notify681if (comp.isLightweight()) {682boolean isContainer = comp instanceof Container;683684if (!isContainer || (isContainer && !((Container)comp).hasHeavyweightDescendants())) {685return false;686}687}688689// If this point is reached, then the comp is either a HW or a LW container with HW descendants.690691// All three components have peers, check for peer change692Container newNativeContainer = oldContainer.getHeavyweightContainer();693Container oldNativeContainer = newContainer.getHeavyweightContainer();694if (newNativeContainer != oldNativeContainer) {695// Native containers change - check whether or not current platform supports696// changing of widget hierarchy on native level without recreation.697// The current implementation forbids reparenting of LW containers with HW descendants698// into another native container w/o destroying the peers. Actually such an operation699// is quite rare. If we ever need to save the peers, we'll have to slightly change the700// addDelicately() method in order to handle such LW containers recursively, reparenting701// each HW descendant independently.702return !comp.peer.isReparentSupported();703} else {704return false;705}706}707708/**709* Moves the specified component to the specified z-order index in710* the container. The z-order determines the order that components711* are painted; the component with the highest z-order paints first712* and the component with the lowest z-order paints last.713* Where components overlap, the component with the lower714* z-order paints over the component with the higher z-order.715* <p>716* If the component is a child of some other container, it is717* removed from that container before being added to this container.718* The important difference between this method and719* <code>java.awt.Container.add(Component, int)</code> is that this method720* doesn't call <code>removeNotify</code> on the component while721* removing it from its previous container unless necessary and when722* allowed by the underlying native windowing system. This way, if the723* component has the keyboard focus, it maintains the focus when724* moved to the new position.725* <p>726* This property is guaranteed to apply only to lightweight727* non-<code>Container</code> components.728* <p>729* This method changes layout-related information, and therefore,730* invalidates the component hierarchy.731* <p>732* <b>Note</b>: Not all platforms support changing the z-order of733* heavyweight components from one container into another without734* the call to <code>removeNotify</code>. There is no way to detect735* whether a platform supports this, so developers shouldn't make736* any assumptions.737*738* @param comp the component to be moved739* @param index the position in the container's list to740* insert the component, where <code>getComponentCount()</code>741* appends to the end742* @exception NullPointerException if <code>comp</code> is743* <code>null</code>744* @exception IllegalArgumentException if <code>comp</code> is one of the745* container's parents746* @exception IllegalArgumentException if <code>index</code> is not in747* the range <code>[0, getComponentCount()]</code> for moving748* between containers, or not in the range749* <code>[0, getComponentCount()-1]</code> for moving inside750* a container751* @exception IllegalArgumentException if adding a container to itself752* @exception IllegalArgumentException if adding a <code>Window</code>753* to a container754* @see #getComponentZOrder(java.awt.Component)755* @see #invalidate756* @since 1.5757*/758public void setComponentZOrder(Component comp, int index) {759synchronized (getTreeLock()) {760// Store parent because remove will clear it761Container curParent = comp.parent;762int oldZindex = getComponentZOrder(comp);763764if (curParent == this && index == oldZindex) {765return;766}767checkAdding(comp, index);768769boolean peerRecreated = (curParent != null) ?770curParent.removeDelicately(comp, this, index) : false;771772addDelicately(comp, curParent, index);773774// If the oldZindex == -1, the component gets inserted,775// rather than it changes its z-order.776if (!peerRecreated && oldZindex != -1) {777// The new 'index' cannot be == -1.778// It gets checked at the checkAdding() method.779// Therefore both oldZIndex and index denote780// some existing positions at this point and781// this is actually a Z-order changing.782comp.mixOnZOrderChanging(oldZindex, index);783}784}785}786787/**788* Traverses the tree of components and reparents children heavyweight component789* to new heavyweight parent.790* @since 1.5791*/792private void reparentTraverse(ContainerPeer parentPeer, Container child) {793checkTreeLock();794795for (int i = 0; i < child.getComponentCount(); i++) {796Component comp = child.getComponent(i);797if (comp.isLightweight()) {798// If components is lightweight check if it is container799// If it is container it might contain heavyweight children we need to reparent800if (comp instanceof Container) {801reparentTraverse(parentPeer, (Container)comp);802}803} else {804// Q: Need to update NativeInLightFixer?805comp.getPeer().reparent(parentPeer);806}807}808}809810/**811* Reparents child component peer to this container peer.812* Container must be heavyweight.813* @since 1.5814*/815private void reparentChild(Component comp) {816checkTreeLock();817if (comp == null) {818return;819}820if (comp.isLightweight()) {821// If component is lightweight container we need to reparent all its explicit heavyweight children822if (comp instanceof Container) {823// Traverse component's tree till depth-first until encountering heavyweight component824reparentTraverse((ContainerPeer)getPeer(), (Container)comp);825}826} else {827comp.getPeer().reparent((ContainerPeer)getPeer());828}829}830831/**832* Adds component to this container. Tries to minimize side effects of this adding -833* doesn't call remove notify if it is not required.834* @since 1.5835*/836private void addDelicately(Component comp, Container curParent, int index) {837checkTreeLock();838839// Check if moving between containers840if (curParent != this) {841//index == -1 means add to the end.842if (index == -1) {843component.add(comp);844} else {845component.add(index, comp);846}847comp.parent = this;848comp.setGraphicsConfiguration(getGraphicsConfiguration());849850adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK,851comp.numListening(AWTEvent.HIERARCHY_EVENT_MASK));852adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,853comp.numListening(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));854adjustDescendants(comp.countHierarchyMembers());855} else {856if (index < component.size()) {857component.set(index, comp);858}859}860861invalidateIfValid();862if (peer != null) {863if (comp.peer == null) { // Remove notify was called or it didn't have peer - create new one864comp.addNotify();865} else { // Both container and child have peers, it means child peer should be reparented.866// In both cases we need to reparent native widgets.867Container newNativeContainer = getHeavyweightContainer();868Container oldNativeContainer = curParent.getHeavyweightContainer();869if (oldNativeContainer != newNativeContainer) {870// Native container changed - need to reparent native widgets871newNativeContainer.reparentChild(comp);872}873comp.updateZOrder();874875if (!comp.isLightweight() && isLightweight()) {876// If component is heavyweight and one of the containers is lightweight877// the location of the component should be fixed.878comp.relocateComponent();879}880}881}882if (curParent != this) {883/* Notify the layout manager of the added component. */884if (layoutMgr != null) {885if (layoutMgr instanceof LayoutManager2) {886((LayoutManager2)layoutMgr).addLayoutComponent(comp, null);887} else {888layoutMgr.addLayoutComponent(null, comp);889}890}891if (containerListener != null ||892(eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 ||893Toolkit.enabledOnToolkit(AWTEvent.CONTAINER_EVENT_MASK)) {894ContainerEvent e = new ContainerEvent(this,895ContainerEvent.COMPONENT_ADDED,896comp);897dispatchEvent(e);898}899comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, comp,900this, HierarchyEvent.PARENT_CHANGED,901Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK));902903// If component is focus owner or parent container of focus owner check that after reparenting904// focus owner moved out if new container prohibit this kind of focus owner.905if (comp.isFocusOwner() && !comp.canBeFocusOwnerRecursively()) {906comp.transferFocus();907} else if (comp instanceof Container) {908Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();909if (focusOwner != null && isParentOf(focusOwner) && !focusOwner.canBeFocusOwnerRecursively()) {910focusOwner.transferFocus();911}912}913} else {914comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, comp,915this, HierarchyEvent.HIERARCHY_CHANGED,916Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK));917}918919if (peer != null && layoutMgr == null && isVisible()) {920updateCursorImmediately();921}922}923924/**925* Returns the z-order index of the component inside the container.926* The higher a component is in the z-order hierarchy, the lower927* its index. The component with the lowest z-order index is928* painted last, above all other child components.929*930* @param comp the component being queried931* @return the z-order index of the component; otherwise932* returns -1 if the component is <code>null</code>933* or doesn't belong to the container934* @see #setComponentZOrder(java.awt.Component, int)935* @since 1.5936*/937public int getComponentZOrder(Component comp) {938if (comp == null) {939return -1;940}941synchronized(getTreeLock()) {942// Quick check - container should be immediate parent of the component943if (comp.parent != this) {944return -1;945}946return component.indexOf(comp);947}948}949950/**951* Adds the specified component to the end of this container.952* Also notifies the layout manager to add the component to953* this container's layout using the specified constraints object.954* This is a convenience method for {@link #addImpl}.955* <p>956* This method changes layout-related information, and therefore,957* invalidates the component hierarchy. If the container has already been958* displayed, the hierarchy must be validated thereafter in order to959* display the added component.960*961*962* @param comp the component to be added963* @param constraints an object expressing964* layout constraints for this component965* @exception NullPointerException if {@code comp} is {@code null}966* @see #addImpl967* @see #invalidate968* @see #validate969* @see javax.swing.JComponent#revalidate()970* @see LayoutManager971* @since JDK1.1972*/973public void add(Component comp, Object constraints) {974addImpl(comp, constraints, -1);975}976977/**978* Adds the specified component to this container with the specified979* constraints at the specified index. Also notifies the layout980* manager to add the component to the this container's layout using981* the specified constraints object.982* This is a convenience method for {@link #addImpl}.983* <p>984* This method changes layout-related information, and therefore,985* invalidates the component hierarchy. If the container has already been986* displayed, the hierarchy must be validated thereafter in order to987* display the added component.988*989*990* @param comp the component to be added991* @param constraints an object expressing layout constraints for this992* @param index the position in the container's list at which to insert993* the component; <code>-1</code> means insert at the end994* component995* @exception NullPointerException if {@code comp} is {@code null}996* @exception IllegalArgumentException if {@code index} is invalid (see997* {@link #addImpl} for details)998* @see #addImpl999* @see #invalidate1000* @see #validate1001* @see javax.swing.JComponent#revalidate()1002* @see #remove1003* @see LayoutManager1004*/1005public void add(Component comp, Object constraints, int index) {1006addImpl(comp, constraints, index);1007}10081009/**1010* Adds the specified component to this container at the specified1011* index. This method also notifies the layout manager to add1012* the component to this container's layout using the specified1013* constraints object via the <code>addLayoutComponent</code>1014* method.1015* <p>1016* The constraints are1017* defined by the particular layout manager being used. For1018* example, the <code>BorderLayout</code> class defines five1019* constraints: <code>BorderLayout.NORTH</code>,1020* <code>BorderLayout.SOUTH</code>, <code>BorderLayout.EAST</code>,1021* <code>BorderLayout.WEST</code>, and <code>BorderLayout.CENTER</code>.1022* <p>1023* The <code>GridBagLayout</code> class requires a1024* <code>GridBagConstraints</code> object. Failure to pass1025* the correct type of constraints object results in an1026* <code>IllegalArgumentException</code>.1027* <p>1028* If the current layout manager implements {@code LayoutManager2}, then1029* {@link LayoutManager2#addLayoutComponent(Component,Object)} is invoked on1030* it. If the current layout manager does not implement1031* {@code LayoutManager2}, and constraints is a {@code String}, then1032* {@link LayoutManager#addLayoutComponent(String,Component)} is invoked on it.1033* <p>1034* If the component is not an ancestor of this container and has a non-null1035* parent, it is removed from its current parent before it is added to this1036* container.1037* <p>1038* This is the method to override if a program needs to track1039* every add request to a container as all other add methods defer1040* to this one. An overriding method should1041* usually include a call to the superclass's version of the method:1042*1043* <blockquote>1044* <code>super.addImpl(comp, constraints, index)</code>1045* </blockquote>1046* <p>1047* This method changes layout-related information, and therefore,1048* invalidates the component hierarchy. If the container has already been1049* displayed, the hierarchy must be validated thereafter in order to1050* display the added component.1051*1052* @param comp the component to be added1053* @param constraints an object expressing layout constraints1054* for this component1055* @param index the position in the container's list at which to1056* insert the component, where <code>-1</code>1057* means append to the end1058* @exception IllegalArgumentException if {@code index} is invalid;1059* if {@code comp} is a child of this container, the valid1060* range is {@code [-1, getComponentCount()-1]}; if component is1061* not a child of this container, the valid range is1062* {@code [-1, getComponentCount()]}1063*1064* @exception IllegalArgumentException if {@code comp} is an ancestor of1065* this container1066* @exception IllegalArgumentException if adding a window to a container1067* @exception NullPointerException if {@code comp} is {@code null}1068* @see #add(Component)1069* @see #add(Component, int)1070* @see #add(Component, java.lang.Object)1071* @see #invalidate1072* @see LayoutManager1073* @see LayoutManager21074* @since JDK1.11075*/1076protected void addImpl(Component comp, Object constraints, int index) {1077synchronized (getTreeLock()) {1078/* Check for correct arguments: index in bounds,1079* comp cannot be one of this container's parents,1080* and comp cannot be a window.1081* comp and container must be on the same GraphicsDevice.1082* if comp is container, all sub-components must be on1083* same GraphicsDevice.1084*/1085GraphicsConfiguration thisGC = this.getGraphicsConfiguration();10861087if (index > component.size() || (index < 0 && index != -1)) {1088throw new IllegalArgumentException(1089"illegal component position");1090}1091checkAddToSelf(comp);1092checkNotAWindow(comp);1093/* Reparent the component and tidy up the tree's state. */1094if (comp.parent != null) {1095comp.parent.remove(comp);1096if (index > component.size()) {1097throw new IllegalArgumentException("illegal component position");1098}1099}1100if (thisGC != null) {1101comp.checkGD(thisGC.getDevice().getIDstring());1102}1103110411051106//index == -1 means add to the end.1107if (index == -1) {1108component.add(comp);1109} else {1110component.add(index, comp);1111}1112comp.parent = this;1113comp.setGraphicsConfiguration(thisGC);11141115adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK,1116comp.numListening(AWTEvent.HIERARCHY_EVENT_MASK));1117adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,1118comp.numListening(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));1119adjustDescendants(comp.countHierarchyMembers());11201121invalidateIfValid();1122if (peer != null) {1123comp.addNotify();1124}11251126/* Notify the layout manager of the added component. */1127if (layoutMgr != null) {1128if (layoutMgr instanceof LayoutManager2) {1129((LayoutManager2)layoutMgr).addLayoutComponent(comp, constraints);1130} else if (constraints instanceof String) {1131layoutMgr.addLayoutComponent((String)constraints, comp);1132}1133}1134if (containerListener != null ||1135(eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 ||1136Toolkit.enabledOnToolkit(AWTEvent.CONTAINER_EVENT_MASK)) {1137ContainerEvent e = new ContainerEvent(this,1138ContainerEvent.COMPONENT_ADDED,1139comp);1140dispatchEvent(e);1141}11421143comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, comp,1144this, HierarchyEvent.PARENT_CHANGED,1145Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK));1146if (peer != null && layoutMgr == null && isVisible()) {1147updateCursorImmediately();1148}1149}1150}11511152@Override1153boolean updateGraphicsData(GraphicsConfiguration gc) {1154checkTreeLock();11551156boolean ret = super.updateGraphicsData(gc);11571158for (Component comp : component) {1159if (comp != null) {1160ret |= comp.updateGraphicsData(gc);1161}1162}1163return ret;1164}11651166/**1167* Checks that all Components that this Container contains are on1168* the same GraphicsDevice as this Container. If not, throws an1169* IllegalArgumentException.1170*/1171void checkGD(String stringID) {1172for (Component comp : component) {1173if (comp != null) {1174comp.checkGD(stringID);1175}1176}1177}11781179/**1180* Removes the component, specified by <code>index</code>,1181* from this container.1182* This method also notifies the layout manager to remove the1183* component from this container's layout via the1184* <code>removeLayoutComponent</code> method.1185* <p>1186* This method changes layout-related information, and therefore,1187* invalidates the component hierarchy. If the container has already been1188* displayed, the hierarchy must be validated thereafter in order to1189* reflect the changes.1190*1191*1192* @param index the index of the component to be removed1193* @throws ArrayIndexOutOfBoundsException if {@code index} is not in1194* range {@code [0, getComponentCount()-1]}1195* @see #add1196* @see #invalidate1197* @see #validate1198* @see #getComponentCount1199* @since JDK1.11200*/1201public void remove(int index) {1202synchronized (getTreeLock()) {1203if (index < 0 || index >= component.size()) {1204throw new ArrayIndexOutOfBoundsException(index);1205}1206Component comp = component.get(index);1207if (peer != null) {1208comp.removeNotify();1209}1210if (layoutMgr != null) {1211layoutMgr.removeLayoutComponent(comp);1212}12131214adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK,1215-comp.numListening(AWTEvent.HIERARCHY_EVENT_MASK));1216adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,1217-comp.numListening(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));1218adjustDescendants(-(comp.countHierarchyMembers()));12191220comp.parent = null;1221component.remove(index);1222comp.setGraphicsConfiguration(null);12231224invalidateIfValid();1225if (containerListener != null ||1226(eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 ||1227Toolkit.enabledOnToolkit(AWTEvent.CONTAINER_EVENT_MASK)) {1228ContainerEvent e = new ContainerEvent(this,1229ContainerEvent.COMPONENT_REMOVED,1230comp);1231dispatchEvent(e);1232}12331234comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, comp,1235this, HierarchyEvent.PARENT_CHANGED,1236Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK));1237if (peer != null && layoutMgr == null && isVisible()) {1238updateCursorImmediately();1239}1240}1241}12421243/**1244* Removes the specified component from this container.1245* This method also notifies the layout manager to remove the1246* component from this container's layout via the1247* <code>removeLayoutComponent</code> method.1248* <p>1249* This method changes layout-related information, and therefore,1250* invalidates the component hierarchy. If the container has already been1251* displayed, the hierarchy must be validated thereafter in order to1252* reflect the changes.1253*1254* @param comp the component to be removed1255* @throws NullPointerException if {@code comp} is {@code null}1256* @see #add1257* @see #invalidate1258* @see #validate1259* @see #remove(int)1260*/1261public void remove(Component comp) {1262synchronized (getTreeLock()) {1263if (comp.parent == this) {1264int index = component.indexOf(comp);1265if (index >= 0) {1266remove(index);1267}1268}1269}1270}12711272/**1273* Removes all the components from this container.1274* This method also notifies the layout manager to remove the1275* components from this container's layout via the1276* <code>removeLayoutComponent</code> method.1277* <p>1278* This method changes layout-related information, and therefore,1279* invalidates the component hierarchy. If the container has already been1280* displayed, the hierarchy must be validated thereafter in order to1281* reflect the changes.1282*1283* @see #add1284* @see #remove1285* @see #invalidate1286*/1287public void removeAll() {1288synchronized (getTreeLock()) {1289adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK,1290-listeningChildren);1291adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,1292-listeningBoundsChildren);1293adjustDescendants(-descendantsCount);12941295while (!component.isEmpty()) {1296Component comp = component.remove(component.size()-1);12971298if (peer != null) {1299comp.removeNotify();1300}1301if (layoutMgr != null) {1302layoutMgr.removeLayoutComponent(comp);1303}1304comp.parent = null;1305comp.setGraphicsConfiguration(null);1306if (containerListener != null ||1307(eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 ||1308Toolkit.enabledOnToolkit(AWTEvent.CONTAINER_EVENT_MASK)) {1309ContainerEvent e = new ContainerEvent(this,1310ContainerEvent.COMPONENT_REMOVED,1311comp);1312dispatchEvent(e);1313}13141315comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED,1316comp, this,1317HierarchyEvent.PARENT_CHANGED,1318Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK));1319}1320if (peer != null && layoutMgr == null && isVisible()) {1321updateCursorImmediately();1322}1323invalidateIfValid();1324}1325}13261327// Should only be called while holding tree lock1328int numListening(long mask) {1329int superListening = super.numListening(mask);13301331if (mask == AWTEvent.HIERARCHY_EVENT_MASK) {1332if (eventLog.isLoggable(PlatformLogger.Level.FINE)) {1333// Verify listeningChildren is correct1334int sum = 0;1335for (Component comp : component) {1336sum += comp.numListening(mask);1337}1338if (listeningChildren != sum) {1339eventLog.fine("Assertion (listeningChildren == sum) failed");1340}1341}1342return listeningChildren + superListening;1343} else if (mask == AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) {1344if (eventLog.isLoggable(PlatformLogger.Level.FINE)) {1345// Verify listeningBoundsChildren is correct1346int sum = 0;1347for (Component comp : component) {1348sum += comp.numListening(mask);1349}1350if (listeningBoundsChildren != sum) {1351eventLog.fine("Assertion (listeningBoundsChildren == sum) failed");1352}1353}1354return listeningBoundsChildren + superListening;1355} else {1356// assert false;1357if (eventLog.isLoggable(PlatformLogger.Level.FINE)) {1358eventLog.fine("This code must never be reached");1359}1360return superListening;1361}1362}13631364// Should only be called while holding tree lock1365void adjustListeningChildren(long mask, int num) {1366if (eventLog.isLoggable(PlatformLogger.Level.FINE)) {1367boolean toAssert = (mask == AWTEvent.HIERARCHY_EVENT_MASK ||1368mask == AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK ||1369mask == (AWTEvent.HIERARCHY_EVENT_MASK |1370AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));1371if (!toAssert) {1372eventLog.fine("Assertion failed");1373}1374}13751376if (num == 0)1377return;13781379if ((mask & AWTEvent.HIERARCHY_EVENT_MASK) != 0) {1380listeningChildren += num;1381}1382if ((mask & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) != 0) {1383listeningBoundsChildren += num;1384}13851386adjustListeningChildrenOnParent(mask, num);1387}13881389// Should only be called while holding tree lock1390void adjustDescendants(int num) {1391if (num == 0)1392return;13931394descendantsCount += num;1395adjustDecendantsOnParent(num);1396}13971398// Should only be called while holding tree lock1399void adjustDecendantsOnParent(int num) {1400if (parent != null) {1401parent.adjustDescendants(num);1402}1403}14041405// Should only be called while holding tree lock1406int countHierarchyMembers() {1407if (log.isLoggable(PlatformLogger.Level.FINE)) {1408// Verify descendantsCount is correct1409int sum = 0;1410for (Component comp : component) {1411sum += comp.countHierarchyMembers();1412}1413if (descendantsCount != sum) {1414log.fine("Assertion (descendantsCount == sum) failed");1415}1416}1417return descendantsCount + 1;1418}14191420private int getListenersCount(int id, boolean enabledOnToolkit) {1421checkTreeLock();1422if (enabledOnToolkit) {1423return descendantsCount;1424}1425switch (id) {1426case HierarchyEvent.HIERARCHY_CHANGED:1427return listeningChildren;1428case HierarchyEvent.ANCESTOR_MOVED:1429case HierarchyEvent.ANCESTOR_RESIZED:1430return listeningBoundsChildren;1431default:1432return 0;1433}1434}14351436final int createHierarchyEvents(int id, Component changed,1437Container changedParent, long changeFlags, boolean enabledOnToolkit)1438{1439checkTreeLock();1440int listeners = getListenersCount(id, enabledOnToolkit);14411442for (int count = listeners, i = 0; count > 0; i++) {1443count -= component.get(i).createHierarchyEvents(id, changed,1444changedParent, changeFlags, enabledOnToolkit);1445}1446return listeners +1447super.createHierarchyEvents(id, changed, changedParent,1448changeFlags, enabledOnToolkit);1449}14501451final void createChildHierarchyEvents(int id, long changeFlags,1452boolean enabledOnToolkit)1453{1454checkTreeLock();1455if (component.isEmpty()) {1456return;1457}1458int listeners = getListenersCount(id, enabledOnToolkit);14591460for (int count = listeners, i = 0; count > 0; i++) {1461count -= component.get(i).createHierarchyEvents(id, this, parent,1462changeFlags, enabledOnToolkit);1463}1464}14651466/**1467* Gets the layout manager for this container.1468* @see #doLayout1469* @see #setLayout1470*/1471public LayoutManager getLayout() {1472return layoutMgr;1473}14741475/**1476* Sets the layout manager for this container.1477* <p>1478* This method changes layout-related information, and therefore,1479* invalidates the component hierarchy.1480*1481* @param mgr the specified layout manager1482* @see #doLayout1483* @see #getLayout1484* @see #invalidate1485*/1486public void setLayout(LayoutManager mgr) {1487layoutMgr = mgr;1488invalidateIfValid();1489}14901491/**1492* Causes this container to lay out its components. Most programs1493* should not call this method directly, but should invoke1494* the <code>validate</code> method instead.1495* @see LayoutManager#layoutContainer1496* @see #setLayout1497* @see #validate1498* @since JDK1.11499*/1500public void doLayout() {1501layout();1502}15031504/**1505* @deprecated As of JDK version 1.1,1506* replaced by <code>doLayout()</code>.1507*/1508@Deprecated1509public void layout() {1510LayoutManager layoutMgr = this.layoutMgr;1511if (layoutMgr != null) {1512layoutMgr.layoutContainer(this);1513}1514}15151516/**1517* Indicates if this container is a <i>validate root</i>.1518* <p>1519* Layout-related changes, such as bounds of the validate root descendants,1520* do not affect the layout of the validate root parent. This peculiarity1521* enables the {@code invalidate()} method to stop invalidating the1522* component hierarchy when the method encounters a validate root. However,1523* to preserve backward compatibility this new optimized behavior is1524* enabled only when the {@code java.awt.smartInvalidate} system property1525* value is set to {@code true}.1526* <p>1527* If a component hierarchy contains validate roots and the new optimized1528* {@code invalidate()} behavior is enabled, the {@code validate()} method1529* must be invoked on the validate root of a previously invalidated1530* component to restore the validity of the hierarchy later. Otherwise,1531* calling the {@code validate()} method on the top-level container (such1532* as a {@code Frame} object) should be used to restore the validity of the1533* component hierarchy.1534* <p>1535* The {@code Window} class and the {@code Applet} class are the validate1536* roots in AWT. Swing introduces more validate roots.1537*1538* @return whether this container is a validate root1539* @see #invalidate1540* @see java.awt.Component#invalidate1541* @see javax.swing.JComponent#isValidateRoot1542* @see javax.swing.JComponent#revalidate1543* @since 1.71544*/1545public boolean isValidateRoot() {1546return false;1547}15481549private static final boolean isJavaAwtSmartInvalidate;1550static {1551// Don't lazy-read because every app uses invalidate()1552isJavaAwtSmartInvalidate = AccessController.doPrivileged(1553new GetBooleanAction("java.awt.smartInvalidate"));1554}15551556/**1557* Invalidates the parent of the container unless the container1558* is a validate root.1559*/1560@Override1561void invalidateParent() {1562if (!isJavaAwtSmartInvalidate || !isValidateRoot()) {1563super.invalidateParent();1564}1565}15661567/**1568* Invalidates the container.1569* <p>1570* If the {@code LayoutManager} installed on this container is an instance1571* of the {@code LayoutManager2} interface, then1572* the {@link LayoutManager2#invalidateLayout(Container)} method is invoked1573* on it supplying this {@code Container} as the argument.1574* <p>1575* Afterwards this method marks this container invalid, and invalidates its1576* ancestors. See the {@link Component#invalidate} method for more details.1577*1578* @see #validate1579* @see #layout1580* @see LayoutManager21581*/1582@Override1583public void invalidate() {1584LayoutManager layoutMgr = this.layoutMgr;1585if (layoutMgr instanceof LayoutManager2) {1586LayoutManager2 lm = (LayoutManager2) layoutMgr;1587lm.invalidateLayout(this);1588}1589super.invalidate();1590}15911592/**1593* Validates this container and all of its subcomponents.1594* <p>1595* Validating a container means laying out its subcomponents.1596* Layout-related changes, such as setting the bounds of a component, or1597* adding a component to the container, invalidate the container1598* automatically. Note that the ancestors of the container may be1599* invalidated also (see {@link Component#invalidate} for details.)1600* Therefore, to restore the validity of the hierarchy, the {@code1601* validate()} method should be invoked on the top-most invalid1602* container of the hierarchy.1603* <p>1604* Validating the container may be a quite time-consuming operation. For1605* performance reasons a developer may postpone the validation of the1606* hierarchy till a set of layout-related operations completes, e.g. after1607* adding all the children to the container.1608* <p>1609* If this {@code Container} is not valid, this method invokes1610* the {@code validateTree} method and marks this {@code Container}1611* as valid. Otherwise, no action is performed.1612*1613* @see #add(java.awt.Component)1614* @see #invalidate1615* @see Container#isValidateRoot1616* @see javax.swing.JComponent#revalidate()1617* @see #validateTree1618*/1619public void validate() {1620boolean updateCur = false;1621synchronized (getTreeLock()) {1622if ((!isValid() || descendUnconditionallyWhenValidating)1623&& peer != null)1624{1625ContainerPeer p = null;1626if (peer instanceof ContainerPeer) {1627p = (ContainerPeer) peer;1628}1629if (p != null) {1630p.beginValidate();1631}1632validateTree();1633if (p != null) {1634p.endValidate();1635// Avoid updating cursor if this is an internal call.1636// See validateUnconditionally() for details.1637if (!descendUnconditionallyWhenValidating) {1638updateCur = isVisible();1639}1640}1641}1642}1643if (updateCur) {1644updateCursorImmediately();1645}1646}16471648/**1649* Indicates whether valid containers should also traverse their1650* children and call the validateTree() method on them.1651*1652* Synchronization: TreeLock.1653*1654* The field is allowed to be static as long as the TreeLock itself is1655* static.1656*1657* @see #validateUnconditionally()1658*/1659private static boolean descendUnconditionallyWhenValidating = false;16601661/**1662* Unconditionally validate the component hierarchy.1663*/1664final void validateUnconditionally() {1665boolean updateCur = false;1666synchronized (getTreeLock()) {1667descendUnconditionallyWhenValidating = true;16681669validate();1670if (peer instanceof ContainerPeer) {1671updateCur = isVisible();1672}16731674descendUnconditionallyWhenValidating = false;1675}1676if (updateCur) {1677updateCursorImmediately();1678}1679}16801681/**1682* Recursively descends the container tree and recomputes the1683* layout for any subtrees marked as needing it (those marked as1684* invalid). Synchronization should be provided by the method1685* that calls this one: <code>validate</code>.1686*1687* @see #doLayout1688* @see #validate1689*/1690protected void validateTree() {1691checkTreeLock();1692if (!isValid() || descendUnconditionallyWhenValidating) {1693if (peer instanceof ContainerPeer) {1694((ContainerPeer)peer).beginLayout();1695}1696if (!isValid()) {1697doLayout();1698}1699for (int i = 0; i < component.size(); i++) {1700Component comp = component.get(i);1701if ( (comp instanceof Container)1702&& !(comp instanceof Window)1703&& (!comp.isValid() ||1704descendUnconditionallyWhenValidating))1705{1706((Container)comp).validateTree();1707} else {1708comp.validate();1709}1710}1711if (peer instanceof ContainerPeer) {1712((ContainerPeer)peer).endLayout();1713}1714}1715super.validate();1716}17171718/**1719* Recursively descends the container tree and invalidates all1720* contained components.1721*/1722void invalidateTree() {1723synchronized (getTreeLock()) {1724for (int i = 0; i < component.size(); i++) {1725Component comp = component.get(i);1726if (comp instanceof Container) {1727((Container)comp).invalidateTree();1728}1729else {1730comp.invalidateIfValid();1731}1732}1733invalidateIfValid();1734}1735}17361737/**1738* Sets the font of this container.1739* <p>1740* This method changes layout-related information, and therefore,1741* invalidates the component hierarchy.1742*1743* @param f The font to become this container's font.1744* @see Component#getFont1745* @see #invalidate1746* @since JDK1.01747*/1748public void setFont(Font f) {1749boolean shouldinvalidate = false;17501751Font oldfont = getFont();1752super.setFont(f);1753Font newfont = getFont();1754if (newfont != oldfont && (oldfont == null ||1755!oldfont.equals(newfont))) {1756invalidateTree();1757}1758}17591760/**1761* Returns the preferred size of this container. If the preferred size has1762* not been set explicitly by {@link Component#setPreferredSize(Dimension)}1763* and this {@code Container} has a {@code non-null} {@link LayoutManager},1764* then {@link LayoutManager#preferredLayoutSize(Container)}1765* is used to calculate the preferred size.1766*1767* <p>Note: some implementations may cache the value returned from the1768* {@code LayoutManager}. Implementations that cache need not invoke1769* {@code preferredLayoutSize} on the {@code LayoutManager} every time1770* this method is invoked, rather the {@code LayoutManager} will only1771* be queried after the {@code Container} becomes invalid.1772*1773* @return an instance of <code>Dimension</code> that represents1774* the preferred size of this container.1775* @see #getMinimumSize1776* @see #getMaximumSize1777* @see #getLayout1778* @see LayoutManager#preferredLayoutSize(Container)1779* @see Component#getPreferredSize1780*/1781public Dimension getPreferredSize() {1782return preferredSize();1783}17841785/**1786* @deprecated As of JDK version 1.1,1787* replaced by <code>getPreferredSize()</code>.1788*/1789@Deprecated1790public Dimension preferredSize() {1791/* Avoid grabbing the lock if a reasonable cached size value1792* is available.1793*/1794Dimension dim = prefSize;1795if (dim == null || !(isPreferredSizeSet() || isValid())) {1796synchronized (getTreeLock()) {1797prefSize = (layoutMgr != null) ?1798layoutMgr.preferredLayoutSize(this) :1799super.preferredSize();1800dim = prefSize;1801}1802}1803if (dim != null){1804return new Dimension(dim);1805}1806else{1807return dim;1808}1809}18101811/**1812* Returns the minimum size of this container. If the minimum size has1813* not been set explicitly by {@link Component#setMinimumSize(Dimension)}1814* and this {@code Container} has a {@code non-null} {@link LayoutManager},1815* then {@link LayoutManager#minimumLayoutSize(Container)}1816* is used to calculate the minimum size.1817*1818* <p>Note: some implementations may cache the value returned from the1819* {@code LayoutManager}. Implementations that cache need not invoke1820* {@code minimumLayoutSize} on the {@code LayoutManager} every time1821* this method is invoked, rather the {@code LayoutManager} will only1822* be queried after the {@code Container} becomes invalid.1823*1824* @return an instance of <code>Dimension</code> that represents1825* the minimum size of this container.1826* @see #getPreferredSize1827* @see #getMaximumSize1828* @see #getLayout1829* @see LayoutManager#minimumLayoutSize(Container)1830* @see Component#getMinimumSize1831* @since JDK1.11832*/1833public Dimension getMinimumSize() {1834return minimumSize();1835}18361837/**1838* @deprecated As of JDK version 1.1,1839* replaced by <code>getMinimumSize()</code>.1840*/1841@Deprecated1842public Dimension minimumSize() {1843/* Avoid grabbing the lock if a reasonable cached size value1844* is available.1845*/1846Dimension dim = minSize;1847if (dim == null || !(isMinimumSizeSet() || isValid())) {1848synchronized (getTreeLock()) {1849minSize = (layoutMgr != null) ?1850layoutMgr.minimumLayoutSize(this) :1851super.minimumSize();1852dim = minSize;1853}1854}1855if (dim != null){1856return new Dimension(dim);1857}1858else{1859return dim;1860}1861}18621863/**1864* Returns the maximum size of this container. If the maximum size has1865* not been set explicitly by {@link Component#setMaximumSize(Dimension)}1866* and the {@link LayoutManager} installed on this {@code Container}1867* is an instance of {@link LayoutManager2}, then1868* {@link LayoutManager2#maximumLayoutSize(Container)}1869* is used to calculate the maximum size.1870*1871* <p>Note: some implementations may cache the value returned from the1872* {@code LayoutManager2}. Implementations that cache need not invoke1873* {@code maximumLayoutSize} on the {@code LayoutManager2} every time1874* this method is invoked, rather the {@code LayoutManager2} will only1875* be queried after the {@code Container} becomes invalid.1876*1877* @return an instance of <code>Dimension</code> that represents1878* the maximum size of this container.1879* @see #getPreferredSize1880* @see #getMinimumSize1881* @see #getLayout1882* @see LayoutManager2#maximumLayoutSize(Container)1883* @see Component#getMaximumSize1884*/1885public Dimension getMaximumSize() {1886/* Avoid grabbing the lock if a reasonable cached size value1887* is available.1888*/1889Dimension dim = maxSize;1890if (dim == null || !(isMaximumSizeSet() || isValid())) {1891synchronized (getTreeLock()) {1892if (layoutMgr instanceof LayoutManager2) {1893LayoutManager2 lm = (LayoutManager2) layoutMgr;1894maxSize = lm.maximumLayoutSize(this);1895} else {1896maxSize = super.getMaximumSize();1897}1898dim = maxSize;1899}1900}1901if (dim != null){1902return new Dimension(dim);1903}1904else{1905return dim;1906}1907}19081909/**1910* Returns the alignment along the x axis. This specifies how1911* the component would like to be aligned relative to other1912* components. The value should be a number between 0 and 11913* where 0 represents alignment along the origin, 1 is aligned1914* the furthest away from the origin, 0.5 is centered, etc.1915*/1916public float getAlignmentX() {1917float xAlign;1918if (layoutMgr instanceof LayoutManager2) {1919synchronized (getTreeLock()) {1920LayoutManager2 lm = (LayoutManager2) layoutMgr;1921xAlign = lm.getLayoutAlignmentX(this);1922}1923} else {1924xAlign = super.getAlignmentX();1925}1926return xAlign;1927}19281929/**1930* Returns the alignment along the y axis. This specifies how1931* the component would like to be aligned relative to other1932* components. The value should be a number between 0 and 11933* where 0 represents alignment along the origin, 1 is aligned1934* the furthest away from the origin, 0.5 is centered, etc.1935*/1936public float getAlignmentY() {1937float yAlign;1938if (layoutMgr instanceof LayoutManager2) {1939synchronized (getTreeLock()) {1940LayoutManager2 lm = (LayoutManager2) layoutMgr;1941yAlign = lm.getLayoutAlignmentY(this);1942}1943} else {1944yAlign = super.getAlignmentY();1945}1946return yAlign;1947}19481949/**1950* Paints the container. This forwards the paint to any lightweight1951* components that are children of this container. If this method is1952* reimplemented, super.paint(g) should be called so that lightweight1953* components are properly rendered. If a child component is entirely1954* clipped by the current clipping setting in g, paint() will not be1955* forwarded to that child.1956*1957* @param g the specified Graphics window1958* @see Component#update(Graphics)1959*/1960public void paint(Graphics g) {1961if (isShowing()) {1962synchronized (getObjectLock()) {1963if (printing) {1964if (printingThreads.contains(Thread.currentThread())) {1965return;1966}1967}1968}19691970// The container is showing on screen and1971// this paint() is not called from print().1972// Paint self and forward the paint to lightweight subcomponents.19731974// super.paint(); -- Don't bother, since it's a NOP.19751976GraphicsCallback.PaintCallback.getInstance().1977runComponents(getComponentsSync(), g, GraphicsCallback.LIGHTWEIGHTS);1978}1979}19801981/**1982* Updates the container. This forwards the update to any lightweight1983* components that are children of this container. If this method is1984* reimplemented, super.update(g) should be called so that lightweight1985* components are properly rendered. If a child component is entirely1986* clipped by the current clipping setting in g, update() will not be1987* forwarded to that child.1988*1989* @param g the specified Graphics window1990* @see Component#update(Graphics)1991*/1992public void update(Graphics g) {1993if (isShowing()) {1994if (! (peer instanceof LightweightPeer)) {1995g.clearRect(0, 0, width, height);1996}1997paint(g);1998}1999}20002001/**2002* Prints the container. This forwards the print to any lightweight2003* components that are children of this container. If this method is2004* reimplemented, super.print(g) should be called so that lightweight2005* components are properly rendered. If a child component is entirely2006* clipped by the current clipping setting in g, print() will not be2007* forwarded to that child.2008*2009* @param g the specified Graphics window2010* @see Component#update(Graphics)2011*/2012public void print(Graphics g) {2013if (isShowing()) {2014Thread t = Thread.currentThread();2015try {2016synchronized (getObjectLock()) {2017if (printingThreads == null) {2018printingThreads = new HashSet<>();2019}2020printingThreads.add(t);2021printing = true;2022}2023super.print(g); // By default, Component.print() calls paint()2024} finally {2025synchronized (getObjectLock()) {2026printingThreads.remove(t);2027printing = !printingThreads.isEmpty();2028}2029}20302031GraphicsCallback.PrintCallback.getInstance().2032runComponents(getComponentsSync(), g, GraphicsCallback.LIGHTWEIGHTS);2033}2034}20352036/**2037* Paints each of the components in this container.2038* @param g the graphics context.2039* @see Component#paint2040* @see Component#paintAll2041*/2042public void paintComponents(Graphics g) {2043if (isShowing()) {2044GraphicsCallback.PaintAllCallback.getInstance().2045runComponents(getComponentsSync(), g, GraphicsCallback.TWO_PASSES);2046}2047}20482049/**2050* Simulates the peer callbacks into java.awt for printing of2051* lightweight Containers.2052* @param g the graphics context to use for printing.2053* @see Component#printAll2054* @see #printComponents2055*/2056void lightweightPaint(Graphics g) {2057super.lightweightPaint(g);2058paintHeavyweightComponents(g);2059}20602061/**2062* Prints all the heavyweight subcomponents.2063*/2064void paintHeavyweightComponents(Graphics g) {2065if (isShowing()) {2066GraphicsCallback.PaintHeavyweightComponentsCallback.getInstance().2067runComponents(getComponentsSync(), g,2068GraphicsCallback.LIGHTWEIGHTS | GraphicsCallback.HEAVYWEIGHTS);2069}2070}20712072/**2073* Prints each of the components in this container.2074* @param g the graphics context.2075* @see Component#print2076* @see Component#printAll2077*/2078public void printComponents(Graphics g) {2079if (isShowing()) {2080GraphicsCallback.PrintAllCallback.getInstance().2081runComponents(getComponentsSync(), g, GraphicsCallback.TWO_PASSES);2082}2083}20842085/**2086* Simulates the peer callbacks into java.awt for printing of2087* lightweight Containers.2088* @param g the graphics context to use for printing.2089* @see Component#printAll2090* @see #printComponents2091*/2092void lightweightPrint(Graphics g) {2093super.lightweightPrint(g);2094printHeavyweightComponents(g);2095}20962097/**2098* Prints all the heavyweight subcomponents.2099*/2100void printHeavyweightComponents(Graphics g) {2101if (isShowing()) {2102GraphicsCallback.PrintHeavyweightComponentsCallback.getInstance().2103runComponents(getComponentsSync(), g,2104GraphicsCallback.LIGHTWEIGHTS | GraphicsCallback.HEAVYWEIGHTS);2105}2106}21072108/**2109* Adds the specified container listener to receive container events2110* from this container.2111* If l is null, no exception is thrown and no action is performed.2112* <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"2113* >AWT Threading Issues</a> for details on AWT's threading model.2114*2115* @param l the container listener2116*2117* @see #removeContainerListener2118* @see #getContainerListeners2119*/2120public synchronized void addContainerListener(ContainerListener l) {2121if (l == null) {2122return;2123}2124containerListener = AWTEventMulticaster.add(containerListener, l);2125newEventsOnly = true;2126}21272128/**2129* Removes the specified container listener so it no longer receives2130* container events from this container.2131* If l is null, no exception is thrown and no action is performed.2132* <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"2133* >AWT Threading Issues</a> for details on AWT's threading model.2134*2135* @param l the container listener2136*2137* @see #addContainerListener2138* @see #getContainerListeners2139*/2140public synchronized void removeContainerListener(ContainerListener l) {2141if (l == null) {2142return;2143}2144containerListener = AWTEventMulticaster.remove(containerListener, l);2145}21462147/**2148* Returns an array of all the container listeners2149* registered on this container.2150*2151* @return all of this container's <code>ContainerListener</code>s2152* or an empty array if no container2153* listeners are currently registered2154*2155* @see #addContainerListener2156* @see #removeContainerListener2157* @since 1.42158*/2159public synchronized ContainerListener[] getContainerListeners() {2160return getListeners(ContainerListener.class);2161}21622163/**2164* Returns an array of all the objects currently registered2165* as <code><em>Foo</em>Listener</code>s2166* upon this <code>Container</code>.2167* <code><em>Foo</em>Listener</code>s are registered using the2168* <code>add<em>Foo</em>Listener</code> method.2169*2170* <p>2171* You can specify the <code>listenerType</code> argument2172* with a class literal, such as2173* <code><em>Foo</em>Listener.class</code>.2174* For example, you can query a2175* <code>Container</code> <code>c</code>2176* for its container listeners with the following code:2177*2178* <pre>ContainerListener[] cls = (ContainerListener[])(c.getListeners(ContainerListener.class));</pre>2179*2180* If no such listeners exist, this method returns an empty array.2181*2182* @param listenerType the type of listeners requested; this parameter2183* should specify an interface that descends from2184* <code>java.util.EventListener</code>2185* @return an array of all objects registered as2186* <code><em>Foo</em>Listener</code>s on this container,2187* or an empty array if no such listeners have been added2188* @exception ClassCastException if <code>listenerType</code>2189* doesn't specify a class or interface that implements2190* <code>java.util.EventListener</code>2191* @exception NullPointerException if {@code listenerType} is {@code null}2192*2193* @see #getContainerListeners2194*2195* @since 1.32196*/2197public <T extends EventListener> T[] getListeners(Class<T> listenerType) {2198EventListener l = null;2199if (listenerType == ContainerListener.class) {2200l = containerListener;2201} else {2202return super.getListeners(listenerType);2203}2204return AWTEventMulticaster.getListeners(l, listenerType);2205}22062207// REMIND: remove when filtering is done at lower level2208boolean eventEnabled(AWTEvent e) {2209int id = e.getID();22102211if (id == ContainerEvent.COMPONENT_ADDED ||2212id == ContainerEvent.COMPONENT_REMOVED) {2213if ((eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 ||2214containerListener != null) {2215return true;2216}2217return false;2218}2219return super.eventEnabled(e);2220}22212222/**2223* Processes events on this container. If the event is a2224* <code>ContainerEvent</code>, it invokes the2225* <code>processContainerEvent</code> method, else it invokes2226* its superclass's <code>processEvent</code>.2227* <p>Note that if the event parameter is <code>null</code>2228* the behavior is unspecified and may result in an2229* exception.2230*2231* @param e the event2232*/2233protected void processEvent(AWTEvent e) {2234if (e instanceof ContainerEvent) {2235processContainerEvent((ContainerEvent)e);2236return;2237}2238super.processEvent(e);2239}22402241/**2242* Processes container events occurring on this container by2243* dispatching them to any registered ContainerListener objects.2244* NOTE: This method will not be called unless container events2245* are enabled for this component; this happens when one of the2246* following occurs:2247* <ul>2248* <li>A ContainerListener object is registered via2249* <code>addContainerListener</code>2250* <li>Container events are enabled via <code>enableEvents</code>2251* </ul>2252* <p>Note that if the event parameter is <code>null</code>2253* the behavior is unspecified and may result in an2254* exception.2255*2256* @param e the container event2257* @see Component#enableEvents2258*/2259protected void processContainerEvent(ContainerEvent e) {2260ContainerListener listener = containerListener;2261if (listener != null) {2262switch(e.getID()) {2263case ContainerEvent.COMPONENT_ADDED:2264listener.componentAdded(e);2265break;2266case ContainerEvent.COMPONENT_REMOVED:2267listener.componentRemoved(e);2268break;2269}2270}2271}22722273/*2274* Dispatches an event to this component or one of its sub components.2275* Create ANCESTOR_RESIZED and ANCESTOR_MOVED events in response to2276* COMPONENT_RESIZED and COMPONENT_MOVED events. We have to do this2277* here instead of in processComponentEvent because ComponentEvents2278* may not be enabled for this Container.2279* @param e the event2280*/2281void dispatchEventImpl(AWTEvent e) {2282if ((dispatcher != null) && dispatcher.dispatchEvent(e)) {2283// event was sent to a lightweight component. The2284// native-produced event sent to the native container2285// must be properly disposed of by the peer, so it2286// gets forwarded. If the native host has been removed2287// as a result of the sending the lightweight event,2288// the peer reference will be null.2289e.consume();2290if (peer != null) {2291peer.handleEvent(e);2292}2293return;2294}22952296super.dispatchEventImpl(e);22972298synchronized (getTreeLock()) {2299switch (e.getID()) {2300case ComponentEvent.COMPONENT_RESIZED:2301createChildHierarchyEvents(HierarchyEvent.ANCESTOR_RESIZED, 0,2302Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));2303break;2304case ComponentEvent.COMPONENT_MOVED:2305createChildHierarchyEvents(HierarchyEvent.ANCESTOR_MOVED, 0,2306Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));2307break;2308default:2309break;2310}2311}2312}23132314/*2315* Dispatches an event to this component, without trying to forward2316* it to any subcomponents2317* @param e the event2318*/2319void dispatchEventToSelf(AWTEvent e) {2320super.dispatchEventImpl(e);2321}23222323/**2324* Fetchs the top-most (deepest) lightweight component that is interested2325* in receiving mouse events.2326*/2327Component getMouseEventTarget(int x, int y, boolean includeSelf) {2328return getMouseEventTarget(x, y, includeSelf,2329MouseEventTargetFilter.FILTER,2330!SEARCH_HEAVYWEIGHTS);2331}23322333/**2334* Fetches the top-most (deepest) component to receive SunDropTargetEvents.2335*/2336Component getDropTargetEventTarget(int x, int y, boolean includeSelf) {2337return getMouseEventTarget(x, y, includeSelf,2338DropTargetEventTargetFilter.FILTER,2339SEARCH_HEAVYWEIGHTS);2340}23412342/**2343* A private version of getMouseEventTarget which has two additional2344* controllable behaviors. This method searches for the top-most2345* descendant of this container that contains the given coordinates2346* and is accepted by the given filter. The search will be constrained to2347* lightweight descendants if the last argument is <code>false</code>.2348*2349* @param filter EventTargetFilter instance to determine whether the2350* given component is a valid target for this event.2351* @param searchHeavyweights if <code>false</code>, the method2352* will bypass heavyweight components during the search.2353*/2354private Component getMouseEventTarget(int x, int y, boolean includeSelf,2355EventTargetFilter filter,2356boolean searchHeavyweights) {2357Component comp = null;2358if (searchHeavyweights) {2359comp = getMouseEventTargetImpl(x, y, includeSelf, filter,2360SEARCH_HEAVYWEIGHTS,2361searchHeavyweights);2362}23632364if (comp == null || comp == this) {2365comp = getMouseEventTargetImpl(x, y, includeSelf, filter,2366!SEARCH_HEAVYWEIGHTS,2367searchHeavyweights);2368}23692370return comp;2371}23722373/**2374* A private version of getMouseEventTarget which has three additional2375* controllable behaviors. This method searches for the top-most2376* descendant of this container that contains the given coordinates2377* and is accepted by the given filter. The search will be constrained to2378* descendants of only lightweight children or only heavyweight children2379* of this container depending on searchHeavyweightChildren. The search will2380* be constrained to only lightweight descendants of the searched children2381* of this container if searchHeavyweightDescendants is <code>false</code>.2382*2383* @param filter EventTargetFilter instance to determine whether the2384* selected component is a valid target for this event.2385* @param searchHeavyweightChildren if <code>true</code>, the method2386* will bypass immediate lightweight children during the search.2387* If <code>false</code>, the methods will bypass immediate2388* heavyweight children during the search.2389* @param searchHeavyweightDescendants if <code>false</code>, the method2390* will bypass heavyweight descendants which are not immediate2391* children during the search. If <code>true</code>, the method2392* will traverse both lightweight and heavyweight descendants during2393* the search.2394*/2395private Component getMouseEventTargetImpl(int x, int y, boolean includeSelf,2396EventTargetFilter filter,2397boolean searchHeavyweightChildren,2398boolean searchHeavyweightDescendants) {2399synchronized (getTreeLock()) {24002401for (int i = 0; i < component.size(); i++) {2402Component comp = component.get(i);2403if (comp != null && comp.visible &&2404((!searchHeavyweightChildren &&2405comp.peer instanceof LightweightPeer) ||2406(searchHeavyweightChildren &&2407!(comp.peer instanceof LightweightPeer))) &&2408comp.contains(x - comp.x, y - comp.y)) {24092410// found a component that intersects the point, see if there2411// is a deeper possibility.2412if (comp instanceof Container) {2413Container child = (Container) comp;2414Component deeper = child.getMouseEventTarget(2415x - child.x,2416y - child.y,2417includeSelf,2418filter,2419searchHeavyweightDescendants);2420if (deeper != null) {2421return deeper;2422}2423} else {2424if (filter.accept(comp)) {2425// there isn't a deeper target, but this component2426// is a target2427return comp;2428}2429}2430}2431}24322433boolean isPeerOK;2434boolean isMouseOverMe;24352436isPeerOK = (peer instanceof LightweightPeer) || includeSelf;2437isMouseOverMe = contains(x,y);24382439// didn't find a child target, return this component if it's2440// a possible target2441if (isMouseOverMe && isPeerOK && filter.accept(this)) {2442return this;2443}2444// no possible target2445return null;2446}2447}24482449static interface EventTargetFilter {2450boolean accept(final Component comp);2451}24522453static class MouseEventTargetFilter implements EventTargetFilter {2454static final EventTargetFilter FILTER = new MouseEventTargetFilter();24552456private MouseEventTargetFilter() {}24572458public boolean accept(final Component comp) {2459return (comp.eventMask & AWTEvent.MOUSE_MOTION_EVENT_MASK) != 02460|| (comp.eventMask & AWTEvent.MOUSE_EVENT_MASK) != 02461|| (comp.eventMask & AWTEvent.MOUSE_WHEEL_EVENT_MASK) != 02462|| comp.mouseListener != null2463|| comp.mouseMotionListener != null2464|| comp.mouseWheelListener != null;2465}2466}24672468static class DropTargetEventTargetFilter implements EventTargetFilter {2469static final EventTargetFilter FILTER = new DropTargetEventTargetFilter();24702471private DropTargetEventTargetFilter() {}24722473public boolean accept(final Component comp) {2474DropTarget dt = comp.getDropTarget();2475return dt != null && dt.isActive();2476}2477}24782479/**2480* This is called by lightweight components that want the containing2481* windowed parent to enable some kind of events on their behalf.2482* This is needed for events that are normally only dispatched to2483* windows to be accepted so that they can be forwarded downward to2484* the lightweight component that has enabled them.2485*/2486void proxyEnableEvents(long events) {2487if (peer instanceof LightweightPeer) {2488// this container is lightweight.... continue sending it2489// upward.2490if (parent != null) {2491parent.proxyEnableEvents(events);2492}2493} else {2494// This is a native container, so it needs to host2495// one of it's children. If this function is called before2496// a peer has been created we don't yet have a dispatcher2497// because it has not yet been determined if this instance2498// is lightweight.2499if (dispatcher != null) {2500dispatcher.enableEvents(events);2501}2502}2503}25042505/**2506* @deprecated As of JDK version 1.1,2507* replaced by <code>dispatchEvent(AWTEvent e)</code>2508*/2509@Deprecated2510public void deliverEvent(Event e) {2511Component comp = getComponentAt(e.x, e.y);2512if ((comp != null) && (comp != this)) {2513e.translate(-comp.x, -comp.y);2514comp.deliverEvent(e);2515} else {2516postEvent(e);2517}2518}25192520/**2521* Locates the component that contains the x,y position. The2522* top-most child component is returned in the case where there2523* is overlap in the components. This is determined by finding2524* the component closest to the index 0 that claims to contain2525* the given point via Component.contains(), except that Components2526* which have native peers take precedence over those which do not2527* (i.e., lightweight Components).2528*2529* @param x the <i>x</i> coordinate2530* @param y the <i>y</i> coordinate2531* @return null if the component does not contain the position.2532* If there is no child component at the requested point and the2533* point is within the bounds of the container the container itself2534* is returned; otherwise the top-most child is returned.2535* @see Component#contains2536* @since JDK1.12537*/2538public Component getComponentAt(int x, int y) {2539return locate(x, y);2540}25412542/**2543* @deprecated As of JDK version 1.1,2544* replaced by <code>getComponentAt(int, int)</code>.2545*/2546@Deprecated2547public Component locate(int x, int y) {2548if (!contains(x, y)) {2549return null;2550}2551Component lightweight = null;2552synchronized (getTreeLock()) {2553// Optimized version of two passes:2554// see comment in sun.awt.SunGraphicsCallback2555for (final Component comp : component) {2556if (comp.contains(x - comp.x, y - comp.y)) {2557if (!comp.isLightweight()) {2558// return heavyweight component as soon as possible2559return comp;2560}2561if (lightweight == null) {2562// save and return later the first lightweight component2563lightweight = comp;2564}2565}2566}2567}2568return lightweight != null ? lightweight : this;2569}25702571/**2572* Gets the component that contains the specified point.2573* @param p the point.2574* @return returns the component that contains the point,2575* or <code>null</code> if the component does2576* not contain the point.2577* @see Component#contains2578* @since JDK1.12579*/2580public Component getComponentAt(Point p) {2581return getComponentAt(p.x, p.y);2582}25832584/**2585* Returns the position of the mouse pointer in this <code>Container</code>'s2586* coordinate space if the <code>Container</code> is under the mouse pointer,2587* otherwise returns <code>null</code>.2588* This method is similar to {@link Component#getMousePosition()} with the exception2589* that it can take the <code>Container</code>'s children into account.2590* If <code>allowChildren</code> is <code>false</code>, this method will return2591* a non-null value only if the mouse pointer is above the <code>Container</code>2592* directly, not above the part obscured by children.2593* If <code>allowChildren</code> is <code>true</code>, this method returns2594* a non-null value if the mouse pointer is above <code>Container</code> or any2595* of its descendants.2596*2597* @exception HeadlessException if GraphicsEnvironment.isHeadless() returns true2598* @param allowChildren true if children should be taken into account2599* @see Component#getMousePosition2600* @return mouse coordinates relative to this <code>Component</code>, or null2601* @since 1.52602*/2603public Point getMousePosition(boolean allowChildren) throws HeadlessException {2604if (GraphicsEnvironment.isHeadless()) {2605throw new HeadlessException();2606}2607PointerInfo pi = java.security.AccessController.doPrivileged(2608new java.security.PrivilegedAction<PointerInfo>() {2609public PointerInfo run() {2610return MouseInfo.getPointerInfo();2611}2612}2613);2614synchronized (getTreeLock()) {2615Component inTheSameWindow = findUnderMouseInWindow(pi);2616if (isSameOrAncestorOf(inTheSameWindow, allowChildren)) {2617return pointRelativeToComponent(pi.getLocation());2618}2619return null;2620}2621}26222623boolean isSameOrAncestorOf(Component comp, boolean allowChildren) {2624return this == comp || (allowChildren && isParentOf(comp));2625}26262627/**2628* Locates the visible child component that contains the specified2629* position. The top-most child component is returned in the case2630* where there is overlap in the components. If the containing child2631* component is a Container, this method will continue searching for2632* the deepest nested child component. Components which are not2633* visible are ignored during the search.<p>2634*2635* The findComponentAt method is different from getComponentAt in2636* that getComponentAt only searches the Container's immediate2637* children; if the containing component is a Container,2638* findComponentAt will search that child to find a nested component.2639*2640* @param x the <i>x</i> coordinate2641* @param y the <i>y</i> coordinate2642* @return null if the component does not contain the position.2643* If there is no child component at the requested point and the2644* point is within the bounds of the container the container itself2645* is returned.2646* @see Component#contains2647* @see #getComponentAt2648* @since 1.22649*/2650public Component findComponentAt(int x, int y) {2651return findComponentAt(x, y, true);2652}26532654/**2655* Private version of findComponentAt which has a controllable2656* behavior. Setting 'ignoreEnabled' to 'false' bypasses disabled2657* Components during the search. This behavior is used by the2658* lightweight cursor support in sun.awt.GlobalCursorManager.2659*2660* The addition of this feature is temporary, pending the2661* adoption of new, public API which exports this feature.2662*/2663final Component findComponentAt(int x, int y, boolean ignoreEnabled) {2664synchronized (getTreeLock()) {2665if (isRecursivelyVisible()){2666return findComponentAtImpl(x, y, ignoreEnabled);2667}2668}2669return null;2670}26712672final Component findComponentAtImpl(int x, int y, boolean ignoreEnabled) {2673// checkTreeLock(); commented for a performance reason26742675if (!(contains(x, y) && visible && (ignoreEnabled || enabled))) {2676return null;2677}2678Component lightweight = null;2679// Optimized version of two passes:2680// see comment in sun.awt.SunGraphicsCallback2681for (final Component comp : component) {2682final int x1 = x - comp.x;2683final int y1 = y - comp.y;2684if (!comp.contains(x1, y1)) {2685continue; // fast path2686}2687if (!comp.isLightweight()) {2688final Component child = getChildAt(comp, x1, y1, ignoreEnabled);2689if (child != null) {2690// return heavyweight component as soon as possible2691return child;2692}2693} else {2694if (lightweight == null) {2695// save and return later the first lightweight component2696lightweight = getChildAt(comp, x1, y1, ignoreEnabled);2697}2698}2699}2700return lightweight != null ? lightweight : this;2701}27022703/**2704* Helper method for findComponentAtImpl. Finds a child component using2705* findComponentAtImpl for Container and getComponentAt for Component.2706*/2707private static Component getChildAt(Component comp, int x, int y,2708boolean ignoreEnabled) {2709if (comp instanceof Container) {2710comp = ((Container) comp).findComponentAtImpl(x, y,2711ignoreEnabled);2712} else {2713comp = comp.getComponentAt(x, y);2714}2715if (comp != null && comp.visible &&2716(ignoreEnabled || comp.enabled)) {2717return comp;2718}2719return null;2720}27212722/**2723* Locates the visible child component that contains the specified2724* point. The top-most child component is returned in the case2725* where there is overlap in the components. If the containing child2726* component is a Container, this method will continue searching for2727* the deepest nested child component. Components which are not2728* visible are ignored during the search.<p>2729*2730* The findComponentAt method is different from getComponentAt in2731* that getComponentAt only searches the Container's immediate2732* children; if the containing component is a Container,2733* findComponentAt will search that child to find a nested component.2734*2735* @param p the point.2736* @return null if the component does not contain the position.2737* If there is no child component at the requested point and the2738* point is within the bounds of the container the container itself2739* is returned.2740* @throws NullPointerException if {@code p} is {@code null}2741* @see Component#contains2742* @see #getComponentAt2743* @since 1.22744*/2745public Component findComponentAt(Point p) {2746return findComponentAt(p.x, p.y);2747}27482749/**2750* Makes this Container displayable by connecting it to2751* a native screen resource. Making a container displayable will2752* cause all of its children to be made displayable.2753* This method is called internally by the toolkit and should2754* not be called directly by programs.2755* @see Component#isDisplayable2756* @see #removeNotify2757*/2758public void addNotify() {2759synchronized (getTreeLock()) {2760// addNotify() on the children may cause proxy event enabling2761// on this instance, so we first call super.addNotify() and2762// possibly create an lightweight event dispatcher before calling2763// addNotify() on the children which may be lightweight.2764super.addNotify();2765if (! (peer instanceof LightweightPeer)) {2766dispatcher = new LightweightDispatcher(this);2767}27682769// We shouldn't use iterator because of the Swing menu2770// implementation specifics:2771// the menu is being assigned as a child to JLayeredPane2772// instead of particular component so always affect2773// collection of component if menu is becoming shown or hidden.2774for (int i = 0; i < component.size(); i++) {2775component.get(i).addNotify();2776}2777}2778}27792780/**2781* Makes this Container undisplayable by removing its connection2782* to its native screen resource. Making a container undisplayable2783* will cause all of its children to be made undisplayable.2784* This method is called by the toolkit internally and should2785* not be called directly by programs.2786* @see Component#isDisplayable2787* @see #addNotify2788*/2789public void removeNotify() {2790synchronized (getTreeLock()) {2791// We shouldn't use iterator because of the Swing menu2792// implementation specifics:2793// the menu is being assigned as a child to JLayeredPane2794// instead of particular component so always affect2795// collection of component if menu is becoming shown or hidden.2796for (int i = component.size()-1 ; i >= 0 ; i--) {2797Component comp = component.get(i);2798if (comp != null) {2799// Fix for 6607170.2800// We want to suppress focus change on disposal2801// of the focused component. But because of focus2802// is asynchronous, we should suppress focus change2803// on every component in case it receives native focus2804// in the process of disposal.2805comp.setAutoFocusTransferOnDisposal(false);2806comp.removeNotify();2807comp.setAutoFocusTransferOnDisposal(true);2808}2809}2810// If some of the children had focus before disposal then it still has.2811// Auto-transfer focus to the next (or previous) component if auto-transfer2812// is enabled.2813if (containsFocus() && KeyboardFocusManager.isAutoFocusTransferEnabledFor(this)) {2814if (!transferFocus(false)) {2815transferFocusBackward(true);2816}2817}2818if ( dispatcher != null ) {2819dispatcher.dispose();2820dispatcher = null;2821}2822super.removeNotify();2823}2824}28252826/**2827* Checks if the component is contained in the component hierarchy of2828* this container.2829* @param c the component2830* @return <code>true</code> if it is an ancestor;2831* <code>false</code> otherwise.2832* @since JDK1.12833*/2834public boolean isAncestorOf(Component c) {2835Container p;2836if (c == null || ((p = c.getParent()) == null)) {2837return false;2838}2839while (p != null) {2840if (p == this) {2841return true;2842}2843p = p.getParent();2844}2845return false;2846}28472848/*2849* The following code was added to support modal JInternalFrames2850* Unfortunately this code has to be added here so that we can get access to2851* some private AWT classes like SequencedEvent.2852*2853* The native container of the LW component has this field set2854* to tell it that it should block Mouse events for all LW2855* children except for the modal component.2856*2857* In the case of nested Modal components, we store the previous2858* modal component in the new modal components value of modalComp;2859*/28602861transient Component modalComp;2862transient AppContext modalAppContext;28632864private void startLWModal() {2865// Store the app context on which this component is being shown.2866// Event dispatch thread of this app context will be sleeping until2867// we wake it by any event from hideAndDisposeHandler().2868modalAppContext = AppContext.getAppContext();28692870// keep the KeyEvents from being dispatched2871// until the focus has been transfered2872long time = Toolkit.getEventQueue().getMostRecentKeyEventTime();2873Component predictedFocusOwner = (Component.isInstanceOf(this, "javax.swing.JInternalFrame")) ? ((javax.swing.JInternalFrame)(this)).getMostRecentFocusOwner() : null;2874if (predictedFocusOwner != null) {2875KeyboardFocusManager.getCurrentKeyboardFocusManager().2876enqueueKeyEvents(time, predictedFocusOwner);2877}2878// We have two mechanisms for blocking: 1. If we're on the2879// EventDispatchThread, start a new event pump. 2. If we're2880// on any other thread, call wait() on the treelock.2881final Container nativeContainer;2882synchronized (getTreeLock()) {2883nativeContainer = getHeavyweightContainer();2884if (nativeContainer.modalComp != null) {2885this.modalComp = nativeContainer.modalComp;2886nativeContainer.modalComp = this;2887return;2888}2889else {2890nativeContainer.modalComp = this;2891}2892}28932894Runnable pumpEventsForHierarchy = new Runnable() {2895public void run() {2896EventDispatchThread dispatchThread =2897(EventDispatchThread)Thread.currentThread();2898dispatchThread.pumpEventsForHierarchy(2899new Conditional() {2900public boolean evaluate() {2901return ((windowClosingException == null) && (nativeContainer.modalComp != null)) ;2902}2903}, Container.this);2904}2905};29062907if (EventQueue.isDispatchThread()) {2908SequencedEvent currentSequencedEvent =2909KeyboardFocusManager.getCurrentKeyboardFocusManager().2910getCurrentSequencedEvent();2911if (currentSequencedEvent != null) {2912currentSequencedEvent.dispose();2913}29142915pumpEventsForHierarchy.run();2916} else {2917synchronized (getTreeLock()) {2918Toolkit.getEventQueue().2919postEvent(new PeerEvent(this,2920pumpEventsForHierarchy,2921PeerEvent.PRIORITY_EVENT));2922while ((windowClosingException == null) &&2923(nativeContainer.modalComp != null))2924{2925try {2926getTreeLock().wait();2927} catch (InterruptedException e) {2928break;2929}2930}2931}2932}2933if (windowClosingException != null) {2934windowClosingException.fillInStackTrace();2935throw windowClosingException;2936}2937if (predictedFocusOwner != null) {2938KeyboardFocusManager.getCurrentKeyboardFocusManager().2939dequeueKeyEvents(time, predictedFocusOwner);2940}2941}29422943private void stopLWModal() {2944synchronized (getTreeLock()) {2945if (modalAppContext != null) {2946Container nativeContainer = getHeavyweightContainer();2947if(nativeContainer != null) {2948if (this.modalComp != null) {2949nativeContainer.modalComp = this.modalComp;2950this.modalComp = null;2951return;2952}2953else {2954nativeContainer.modalComp = null;2955}2956}2957// Wake up event dispatch thread on which the dialog was2958// initially shown2959SunToolkit.postEvent(modalAppContext,2960new PeerEvent(this,2961new WakingRunnable(),2962PeerEvent.PRIORITY_EVENT));2963}2964EventQueue.invokeLater(new WakingRunnable());2965getTreeLock().notifyAll();2966}2967}29682969final static class WakingRunnable implements Runnable {2970public void run() {2971}2972}29732974/* End of JOptionPane support code */29752976/**2977* Returns a string representing the state of this <code>Container</code>.2978* This method is intended to be used only for debugging purposes, and the2979* content and format of the returned string may vary between2980* implementations. The returned string may be empty but may not be2981* <code>null</code>.2982*2983* @return the parameter string of this container2984*/2985protected String paramString() {2986String str = super.paramString();2987LayoutManager layoutMgr = this.layoutMgr;2988if (layoutMgr != null) {2989str += ",layout=" + layoutMgr.getClass().getName();2990}2991return str;2992}29932994/**2995* Prints a listing of this container to the specified output2996* stream. The listing starts at the specified indentation.2997* <p>2998* The immediate children of the container are printed with2999* an indentation of <code>indent+1</code>. The children3000* of those children are printed at <code>indent+2</code>3001* and so on.3002*3003* @param out a print stream3004* @param indent the number of spaces to indent3005* @throws NullPointerException if {@code out} is {@code null}3006* @see Component#list(java.io.PrintStream, int)3007* @since JDK1.03008*/3009public void list(PrintStream out, int indent) {3010super.list(out, indent);3011synchronized(getTreeLock()) {3012for (int i = 0; i < component.size(); i++) {3013Component comp = component.get(i);3014if (comp != null) {3015comp.list(out, indent+1);3016}3017}3018}3019}30203021/**3022* Prints out a list, starting at the specified indentation,3023* to the specified print writer.3024* <p>3025* The immediate children of the container are printed with3026* an indentation of <code>indent+1</code>. The children3027* of those children are printed at <code>indent+2</code>3028* and so on.3029*3030* @param out a print writer3031* @param indent the number of spaces to indent3032* @throws NullPointerException if {@code out} is {@code null}3033* @see Component#list(java.io.PrintWriter, int)3034* @since JDK1.13035*/3036public void list(PrintWriter out, int indent) {3037super.list(out, indent);3038synchronized(getTreeLock()) {3039for (int i = 0; i < component.size(); i++) {3040Component comp = component.get(i);3041if (comp != null) {3042comp.list(out, indent+1);3043}3044}3045}3046}30473048/**3049* Sets the focus traversal keys for a given traversal operation for this3050* Container.3051* <p>3052* The default values for a Container's focus traversal keys are3053* implementation-dependent. Sun recommends that all implementations for a3054* particular native platform use the same default values. The3055* recommendations for Windows and Unix are listed below. These3056* recommendations are used in the Sun AWT implementations.3057*3058* <table border=1 summary="Recommended default values for a Container's focus traversal keys">3059* <tr>3060* <th>Identifier</th>3061* <th>Meaning</th>3062* <th>Default</th>3063* </tr>3064* <tr>3065* <td>KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS</td>3066* <td>Normal forward keyboard traversal</td>3067* <td>TAB on KEY_PRESSED, CTRL-TAB on KEY_PRESSED</td>3068* </tr>3069* <tr>3070* <td>KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS</td>3071* <td>Normal reverse keyboard traversal</td>3072* <td>SHIFT-TAB on KEY_PRESSED, CTRL-SHIFT-TAB on KEY_PRESSED</td>3073* </tr>3074* <tr>3075* <td>KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS</td>3076* <td>Go up one focus traversal cycle</td>3077* <td>none</td>3078* </tr>3079* <tr>3080* <td>KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS<td>3081* <td>Go down one focus traversal cycle</td>3082* <td>none</td>3083* </tr>3084* </table>3085*3086* To disable a traversal key, use an empty Set; Collections.EMPTY_SET is3087* recommended.3088* <p>3089* Using the AWTKeyStroke API, client code can specify on which of two3090* specific KeyEvents, KEY_PRESSED or KEY_RELEASED, the focus traversal3091* operation will occur. Regardless of which KeyEvent is specified,3092* however, all KeyEvents related to the focus traversal key, including the3093* associated KEY_TYPED event, will be consumed, and will not be dispatched3094* to any Container. It is a runtime error to specify a KEY_TYPED event as3095* mapping to a focus traversal operation, or to map the same event to3096* multiple default focus traversal operations.3097* <p>3098* If a value of null is specified for the Set, this Container inherits the3099* Set from its parent. If all ancestors of this Container have null3100* specified for the Set, then the current KeyboardFocusManager's default3101* Set is used.3102* <p>3103* This method may throw a {@code ClassCastException} if any {@code Object}3104* in {@code keystrokes} is not an {@code AWTKeyStroke}.3105*3106* @param id one of KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,3107* KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,3108* KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or3109* KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS3110* @param keystrokes the Set of AWTKeyStroke for the specified operation3111* @see #getFocusTraversalKeys3112* @see KeyboardFocusManager#FORWARD_TRAVERSAL_KEYS3113* @see KeyboardFocusManager#BACKWARD_TRAVERSAL_KEYS3114* @see KeyboardFocusManager#UP_CYCLE_TRAVERSAL_KEYS3115* @see KeyboardFocusManager#DOWN_CYCLE_TRAVERSAL_KEYS3116* @throws IllegalArgumentException if id is not one of3117* KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,3118* KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,3119* KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or3120* KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS, or if keystrokes3121* contains null, or if any keystroke represents a KEY_TYPED event,3122* or if any keystroke already maps to another focus traversal3123* operation for this Container3124* @since 1.43125* @beaninfo3126* bound: true3127*/3128public void setFocusTraversalKeys(int id,3129Set<? extends AWTKeyStroke> keystrokes)3130{3131if (id < 0 || id >= KeyboardFocusManager.TRAVERSAL_KEY_LENGTH) {3132throw new IllegalArgumentException("invalid focus traversal key identifier");3133}31343135// Don't call super.setFocusTraversalKey. The Component parameter check3136// does not allow DOWN_CYCLE_TRAVERSAL_KEYS, but we do.3137setFocusTraversalKeys_NoIDCheck(id, keystrokes);3138}31393140/**3141* Returns the Set of focus traversal keys for a given traversal operation3142* for this Container. (See3143* <code>setFocusTraversalKeys</code> for a full description of each key.)3144* <p>3145* If a Set of traversal keys has not been explicitly defined for this3146* Container, then this Container's parent's Set is returned. If no Set3147* has been explicitly defined for any of this Container's ancestors, then3148* the current KeyboardFocusManager's default Set is returned.3149*3150* @param id one of KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,3151* KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,3152* KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or3153* KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS3154* @return the Set of AWTKeyStrokes for the specified operation. The Set3155* will be unmodifiable, and may be empty. null will never be3156* returned.3157* @see #setFocusTraversalKeys3158* @see KeyboardFocusManager#FORWARD_TRAVERSAL_KEYS3159* @see KeyboardFocusManager#BACKWARD_TRAVERSAL_KEYS3160* @see KeyboardFocusManager#UP_CYCLE_TRAVERSAL_KEYS3161* @see KeyboardFocusManager#DOWN_CYCLE_TRAVERSAL_KEYS3162* @throws IllegalArgumentException if id is not one of3163* KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,3164* KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,3165* KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or3166* KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS3167* @since 1.43168*/3169public Set<AWTKeyStroke> getFocusTraversalKeys(int id) {3170if (id < 0 || id >= KeyboardFocusManager.TRAVERSAL_KEY_LENGTH) {3171throw new IllegalArgumentException("invalid focus traversal key identifier");3172}31733174// Don't call super.getFocusTraversalKey. The Component parameter check3175// does not allow DOWN_CYCLE_TRAVERSAL_KEY, but we do.3176return getFocusTraversalKeys_NoIDCheck(id);3177}31783179/**3180* Returns whether the Set of focus traversal keys for the given focus3181* traversal operation has been explicitly defined for this Container. If3182* this method returns <code>false</code>, this Container is inheriting the3183* Set from an ancestor, or from the current KeyboardFocusManager.3184*3185* @param id one of KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,3186* KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,3187* KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or3188* KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS3189* @return <code>true</code> if the the Set of focus traversal keys for the3190* given focus traversal operation has been explicitly defined for3191* this Component; <code>false</code> otherwise.3192* @throws IllegalArgumentException if id is not one of3193* KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,3194* KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,3195* KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or3196* KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS3197* @since 1.43198*/3199public boolean areFocusTraversalKeysSet(int id) {3200if (id < 0 || id >= KeyboardFocusManager.TRAVERSAL_KEY_LENGTH) {3201throw new IllegalArgumentException("invalid focus traversal key identifier");3202}32033204return (focusTraversalKeys != null && focusTraversalKeys[id] != null);3205}32063207/**3208* Returns whether the specified Container is the focus cycle root of this3209* Container's focus traversal cycle. Each focus traversal cycle has only3210* a single focus cycle root and each Container which is not a focus cycle3211* root belongs to only a single focus traversal cycle. Containers which3212* are focus cycle roots belong to two cycles: one rooted at the Container3213* itself, and one rooted at the Container's nearest focus-cycle-root3214* ancestor. This method will return <code>true</code> for both such3215* Containers in this case.3216*3217* @param container the Container to be tested3218* @return <code>true</code> if the specified Container is a focus-cycle-3219* root of this Container; <code>false</code> otherwise3220* @see #isFocusCycleRoot()3221* @since 1.43222*/3223public boolean isFocusCycleRoot(Container container) {3224if (isFocusCycleRoot() && container == this) {3225return true;3226} else {3227return super.isFocusCycleRoot(container);3228}3229}32303231private Container findTraversalRoot() {3232// I potentially have two roots, myself and my root parent3233// If I am the current root, then use me3234// If none of my parents are roots, then use me3235// If my root parent is the current root, then use my root parent3236// If neither I nor my root parent is the current root, then3237// use my root parent (a guess)32383239Container currentFocusCycleRoot = KeyboardFocusManager.3240getCurrentKeyboardFocusManager().getCurrentFocusCycleRoot();3241Container root;32423243if (currentFocusCycleRoot == this) {3244root = this;3245} else {3246root = getFocusCycleRootAncestor();3247if (root == null) {3248root = this;3249}3250}32513252if (root != currentFocusCycleRoot) {3253KeyboardFocusManager.getCurrentKeyboardFocusManager().3254setGlobalCurrentFocusCycleRootPriv(root);3255}3256return root;3257}32583259final boolean containsFocus() {3260final Component focusOwner = KeyboardFocusManager.3261getCurrentKeyboardFocusManager().getFocusOwner();3262return isParentOf(focusOwner);3263}32643265/**3266* Check if this component is the child of this container or its children.3267* Note: this function acquires treeLock3268* Note: this function traverses children tree only in one Window.3269* @param comp a component in test, must not be null3270*/3271private boolean isParentOf(Component comp) {3272synchronized(getTreeLock()) {3273while (comp != null && comp != this && !(comp instanceof Window)) {3274comp = comp.getParent();3275}3276return (comp == this);3277}3278}32793280void clearMostRecentFocusOwnerOnHide() {3281boolean reset = false;3282Window window = null;32833284synchronized (getTreeLock()) {3285window = getContainingWindow();3286if (window != null) {3287Component comp = KeyboardFocusManager.getMostRecentFocusOwner(window);3288reset = ((comp == this) || isParentOf(comp));3289// This synchronized should always be the second in a pair3290// (tree lock, KeyboardFocusManager.class)3291synchronized(KeyboardFocusManager.class) {3292Component storedComp = window.getTemporaryLostComponent();3293if (isParentOf(storedComp) || storedComp == this) {3294window.setTemporaryLostComponent(null);3295}3296}3297}3298}32993300if (reset) {3301KeyboardFocusManager.setMostRecentFocusOwner(window, null);3302}3303}33043305void clearCurrentFocusCycleRootOnHide() {3306KeyboardFocusManager kfm =3307KeyboardFocusManager.getCurrentKeyboardFocusManager();3308Container cont = kfm.getCurrentFocusCycleRoot();33093310if (cont == this || isParentOf(cont)) {3311kfm.setGlobalCurrentFocusCycleRootPriv(null);3312}3313}33143315final Container getTraversalRoot() {3316if (isFocusCycleRoot()) {3317return findTraversalRoot();3318}33193320return super.getTraversalRoot();3321}33223323/**3324* Sets the focus traversal policy that will manage keyboard traversal of3325* this Container's children, if this Container is a focus cycle root. If3326* the argument is null, this Container inherits its policy from its focus-3327* cycle-root ancestor. If the argument is non-null, this policy will be3328* inherited by all focus-cycle-root children that have no keyboard-3329* traversal policy of their own (as will, recursively, their focus-cycle-3330* root children).3331* <p>3332* If this Container is not a focus cycle root, the policy will be3333* remembered, but will not be used or inherited by this or any other3334* Containers until this Container is made a focus cycle root.3335*3336* @param policy the new focus traversal policy for this Container3337* @see #getFocusTraversalPolicy3338* @see #setFocusCycleRoot3339* @see #isFocusCycleRoot3340* @since 1.43341* @beaninfo3342* bound: true3343*/3344public void setFocusTraversalPolicy(FocusTraversalPolicy policy) {3345FocusTraversalPolicy oldPolicy;3346synchronized (this) {3347oldPolicy = this.focusTraversalPolicy;3348this.focusTraversalPolicy = policy;3349}3350firePropertyChange("focusTraversalPolicy", oldPolicy, policy);3351}33523353/**3354* Returns the focus traversal policy that will manage keyboard traversal3355* of this Container's children, or null if this Container is not a focus3356* cycle root. If no traversal policy has been explicitly set for this3357* Container, then this Container's focus-cycle-root ancestor's policy is3358* returned.3359*3360* @return this Container's focus traversal policy, or null if this3361* Container is not a focus cycle root.3362* @see #setFocusTraversalPolicy3363* @see #setFocusCycleRoot3364* @see #isFocusCycleRoot3365* @since 1.43366*/3367public FocusTraversalPolicy getFocusTraversalPolicy() {3368if (!isFocusTraversalPolicyProvider() && !isFocusCycleRoot()) {3369return null;3370}33713372FocusTraversalPolicy policy = this.focusTraversalPolicy;3373if (policy != null) {3374return policy;3375}33763377Container rootAncestor = getFocusCycleRootAncestor();3378if (rootAncestor != null) {3379return rootAncestor.getFocusTraversalPolicy();3380} else {3381return KeyboardFocusManager.getCurrentKeyboardFocusManager().3382getDefaultFocusTraversalPolicy();3383}3384}33853386/**3387* Returns whether the focus traversal policy has been explicitly set for3388* this Container. If this method returns <code>false</code>, this3389* Container will inherit its focus traversal policy from an ancestor.3390*3391* @return <code>true</code> if the focus traversal policy has been3392* explicitly set for this Container; <code>false</code> otherwise.3393* @since 1.43394*/3395public boolean isFocusTraversalPolicySet() {3396return (focusTraversalPolicy != null);3397}33983399/**3400* Sets whether this Container is the root of a focus traversal cycle. Once3401* focus enters a traversal cycle, typically it cannot leave it via focus3402* traversal unless one of the up- or down-cycle keys is pressed. Normal3403* traversal is limited to this Container, and all of this Container's3404* descendants that are not descendants of inferior focus cycle roots. Note3405* that a FocusTraversalPolicy may bend these restrictions, however. For3406* example, ContainerOrderFocusTraversalPolicy supports implicit down-cycle3407* traversal.3408* <p>3409* The alternative way to specify the traversal order of this Container's3410* children is to make this Container a3411* <a href="doc-files/FocusSpec.html#FocusTraversalPolicyProviders">focus traversal policy provider</a>.3412*3413* @param focusCycleRoot indicates whether this Container is the root of a3414* focus traversal cycle3415* @see #isFocusCycleRoot()3416* @see #setFocusTraversalPolicy3417* @see #getFocusTraversalPolicy3418* @see ContainerOrderFocusTraversalPolicy3419* @see #setFocusTraversalPolicyProvider3420* @since 1.43421* @beaninfo3422* bound: true3423*/3424public void setFocusCycleRoot(boolean focusCycleRoot) {3425boolean oldFocusCycleRoot;3426synchronized (this) {3427oldFocusCycleRoot = this.focusCycleRoot;3428this.focusCycleRoot = focusCycleRoot;3429}3430firePropertyChange("focusCycleRoot", oldFocusCycleRoot,3431focusCycleRoot);3432}34333434/**3435* Returns whether this Container is the root of a focus traversal cycle.3436* Once focus enters a traversal cycle, typically it cannot leave it via3437* focus traversal unless one of the up- or down-cycle keys is pressed.3438* Normal traversal is limited to this Container, and all of this3439* Container's descendants that are not descendants of inferior focus3440* cycle roots. Note that a FocusTraversalPolicy may bend these3441* restrictions, however. For example, ContainerOrderFocusTraversalPolicy3442* supports implicit down-cycle traversal.3443*3444* @return whether this Container is the root of a focus traversal cycle3445* @see #setFocusCycleRoot3446* @see #setFocusTraversalPolicy3447* @see #getFocusTraversalPolicy3448* @see ContainerOrderFocusTraversalPolicy3449* @since 1.43450*/3451public boolean isFocusCycleRoot() {3452return focusCycleRoot;3453}34543455/**3456* Sets whether this container will be used to provide focus3457* traversal policy. Container with this property as3458* <code>true</code> will be used to acquire focus traversal policy3459* instead of closest focus cycle root ancestor.3460* @param provider indicates whether this container will be used to3461* provide focus traversal policy3462* @see #setFocusTraversalPolicy3463* @see #getFocusTraversalPolicy3464* @see #isFocusTraversalPolicyProvider3465* @since 1.53466* @beaninfo3467* bound: true3468*/3469public final void setFocusTraversalPolicyProvider(boolean provider) {3470boolean oldProvider;3471synchronized(this) {3472oldProvider = focusTraversalPolicyProvider;3473focusTraversalPolicyProvider = provider;3474}3475firePropertyChange("focusTraversalPolicyProvider", oldProvider, provider);3476}34773478/**3479* Returns whether this container provides focus traversal3480* policy. If this property is set to <code>true</code> then when3481* keyboard focus manager searches container hierarchy for focus3482* traversal policy and encounters this container before any other3483* container with this property as true or focus cycle roots then3484* its focus traversal policy will be used instead of focus cycle3485* root's policy.3486* @see #setFocusTraversalPolicy3487* @see #getFocusTraversalPolicy3488* @see #setFocusCycleRoot3489* @see #setFocusTraversalPolicyProvider3490* @return <code>true</code> if this container provides focus traversal3491* policy, <code>false</code> otherwise3492* @since 1.53493* @beaninfo3494* bound: true3495*/3496public final boolean isFocusTraversalPolicyProvider() {3497return focusTraversalPolicyProvider;3498}34993500/**3501* Transfers the focus down one focus traversal cycle. If this Container is3502* a focus cycle root, then the focus owner is set to this Container's3503* default Component to focus, and the current focus cycle root is set to3504* this Container. If this Container is not a focus cycle root, then no3505* focus traversal operation occurs.3506*3507* @see Component#requestFocus()3508* @see #isFocusCycleRoot3509* @see #setFocusCycleRoot3510* @since 1.43511*/3512public void transferFocusDownCycle() {3513if (isFocusCycleRoot()) {3514KeyboardFocusManager.getCurrentKeyboardFocusManager().3515setGlobalCurrentFocusCycleRootPriv(this);3516Component toFocus = getFocusTraversalPolicy().3517getDefaultComponent(this);3518if (toFocus != null) {3519toFocus.requestFocus(CausedFocusEvent.Cause.TRAVERSAL_DOWN);3520}3521}3522}35233524void preProcessKeyEvent(KeyEvent e) {3525Container parent = this.parent;3526if (parent != null) {3527parent.preProcessKeyEvent(e);3528}3529}35303531void postProcessKeyEvent(KeyEvent e) {3532Container parent = this.parent;3533if (parent != null) {3534parent.postProcessKeyEvent(e);3535}3536}35373538boolean postsOldMouseEvents() {3539return true;3540}35413542/**3543* Sets the <code>ComponentOrientation</code> property of this container3544* and all components contained within it.3545* <p>3546* This method changes layout-related information, and therefore,3547* invalidates the component hierarchy.3548*3549* @param o the new component orientation of this container and3550* the components contained within it.3551* @exception NullPointerException if <code>orientation</code> is null.3552* @see Component#setComponentOrientation3553* @see Component#getComponentOrientation3554* @see #invalidate3555* @since 1.43556*/3557public void applyComponentOrientation(ComponentOrientation o) {3558super.applyComponentOrientation(o);3559synchronized (getTreeLock()) {3560for (int i = 0; i < component.size(); i++) {3561Component comp = component.get(i);3562comp.applyComponentOrientation(o);3563}3564}3565}35663567/**3568* Adds a PropertyChangeListener to the listener list. The listener is3569* registered for all bound properties of this class, including the3570* following:3571* <ul>3572* <li>this Container's font ("font")</li>3573* <li>this Container's background color ("background")</li>3574* <li>this Container's foreground color ("foreground")</li>3575* <li>this Container's focusability ("focusable")</li>3576* <li>this Container's focus traversal keys enabled state3577* ("focusTraversalKeysEnabled")</li>3578* <li>this Container's Set of FORWARD_TRAVERSAL_KEYS3579* ("forwardFocusTraversalKeys")</li>3580* <li>this Container's Set of BACKWARD_TRAVERSAL_KEYS3581* ("backwardFocusTraversalKeys")</li>3582* <li>this Container's Set of UP_CYCLE_TRAVERSAL_KEYS3583* ("upCycleFocusTraversalKeys")</li>3584* <li>this Container's Set of DOWN_CYCLE_TRAVERSAL_KEYS3585* ("downCycleFocusTraversalKeys")</li>3586* <li>this Container's focus traversal policy ("focusTraversalPolicy")3587* </li>3588* <li>this Container's focus-cycle-root state ("focusCycleRoot")</li>3589* </ul>3590* Note that if this Container is inheriting a bound property, then no3591* event will be fired in response to a change in the inherited property.3592* <p>3593* If listener is null, no exception is thrown and no action is performed.3594*3595* @param listener the PropertyChangeListener to be added3596*3597* @see Component#removePropertyChangeListener3598* @see #addPropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)3599*/3600public void addPropertyChangeListener(PropertyChangeListener listener) {3601super.addPropertyChangeListener(listener);3602}36033604/**3605* Adds a PropertyChangeListener to the listener list for a specific3606* property. The specified property may be user-defined, or one of the3607* following defaults:3608* <ul>3609* <li>this Container's font ("font")</li>3610* <li>this Container's background color ("background")</li>3611* <li>this Container's foreground color ("foreground")</li>3612* <li>this Container's focusability ("focusable")</li>3613* <li>this Container's focus traversal keys enabled state3614* ("focusTraversalKeysEnabled")</li>3615* <li>this Container's Set of FORWARD_TRAVERSAL_KEYS3616* ("forwardFocusTraversalKeys")</li>3617* <li>this Container's Set of BACKWARD_TRAVERSAL_KEYS3618* ("backwardFocusTraversalKeys")</li>3619* <li>this Container's Set of UP_CYCLE_TRAVERSAL_KEYS3620* ("upCycleFocusTraversalKeys")</li>3621* <li>this Container's Set of DOWN_CYCLE_TRAVERSAL_KEYS3622* ("downCycleFocusTraversalKeys")</li>3623* <li>this Container's focus traversal policy ("focusTraversalPolicy")3624* </li>3625* <li>this Container's focus-cycle-root state ("focusCycleRoot")</li>3626* <li>this Container's focus-traversal-policy-provider state("focusTraversalPolicyProvider")</li>3627* <li>this Container's focus-traversal-policy-provider state("focusTraversalPolicyProvider")</li>3628* </ul>3629* Note that if this Container is inheriting a bound property, then no3630* event will be fired in response to a change in the inherited property.3631* <p>3632* If listener is null, no exception is thrown and no action is performed.3633*3634* @param propertyName one of the property names listed above3635* @param listener the PropertyChangeListener to be added3636*3637* @see #addPropertyChangeListener(java.beans.PropertyChangeListener)3638* @see Component#removePropertyChangeListener3639*/3640public void addPropertyChangeListener(String propertyName,3641PropertyChangeListener listener) {3642super.addPropertyChangeListener(propertyName, listener);3643}36443645// Serialization support. A Container is responsible for restoring the3646// parent fields of its component children.36473648/**3649* Container Serial Data Version.3650*/3651private int containerSerializedDataVersion = 1;36523653/**3654* Serializes this <code>Container</code> to the specified3655* <code>ObjectOutputStream</code>.3656* <ul>3657* <li>Writes default serializable fields to the stream.</li>3658* <li>Writes a list of serializable ContainerListener(s) as optional3659* data. The non-serializable ContainerListner(s) are detected and3660* no attempt is made to serialize them.</li>3661* <li>Write this Container's FocusTraversalPolicy if and only if it3662* is Serializable; otherwise, <code>null</code> is written.</li>3663* </ul>3664*3665* @param s the <code>ObjectOutputStream</code> to write3666* @serialData <code>null</code> terminated sequence of 0 or more pairs;3667* the pair consists of a <code>String</code> and <code>Object</code>;3668* the <code>String</code> indicates the type of object and3669* is one of the following:3670* <code>containerListenerK</code> indicating an3671* <code>ContainerListener</code> object;3672* the <code>Container</code>'s <code>FocusTraversalPolicy</code>,3673* or <code>null</code>3674*3675* @see AWTEventMulticaster#save(java.io.ObjectOutputStream, java.lang.String, java.util.EventListener)3676* @see Container#containerListenerK3677* @see #readObject(ObjectInputStream)3678*/3679private void writeObject(ObjectOutputStream s) throws IOException {3680ObjectOutputStream.PutField f = s.putFields();3681f.put("ncomponents", component.size());3682f.put("component", component.toArray(EMPTY_ARRAY));3683f.put("layoutMgr", layoutMgr);3684f.put("dispatcher", dispatcher);3685f.put("maxSize", maxSize);3686f.put("focusCycleRoot", focusCycleRoot);3687f.put("containerSerializedDataVersion", containerSerializedDataVersion);3688f.put("focusTraversalPolicyProvider", focusTraversalPolicyProvider);3689s.writeFields();36903691AWTEventMulticaster.save(s, containerListenerK, containerListener);3692s.writeObject(null);36933694if (focusTraversalPolicy instanceof java.io.Serializable) {3695s.writeObject(focusTraversalPolicy);3696} else {3697s.writeObject(null);3698}3699}37003701/**3702* Deserializes this <code>Container</code> from the specified3703* <code>ObjectInputStream</code>.3704* <ul>3705* <li>Reads default serializable fields from the stream.</li>3706* <li>Reads a list of serializable ContainerListener(s) as optional3707* data. If the list is null, no Listeners are installed.</li>3708* <li>Reads this Container's FocusTraversalPolicy, which may be null,3709* as optional data.</li>3710* </ul>3711*3712* @param s the <code>ObjectInputStream</code> to read3713* @serial3714* @see #addContainerListener3715* @see #writeObject(ObjectOutputStream)3716*/3717private void readObject(ObjectInputStream s)3718throws ClassNotFoundException, IOException3719{3720ObjectInputStream.GetField f = s.readFields();3721// array of components may not be present in the stream or may be null3722Component [] tmpComponent = (Component[])f.get("component", null);3723if (tmpComponent == null) {3724tmpComponent = EMPTY_ARRAY;3725}3726int ncomponents = (Integer) f.get("ncomponents", 0);3727if (ncomponents < 0 || ncomponents > tmpComponent.length) {3728throw new InvalidObjectException("Incorrect number of components");3729}3730component = new java.util.ArrayList<Component>(ncomponents);3731for (int i = 0; i < ncomponents; ++i) {3732component.add(tmpComponent[i]);3733}3734layoutMgr = (LayoutManager)f.get("layoutMgr", null);3735dispatcher = (LightweightDispatcher)f.get("dispatcher", null);3736// Old stream. Doesn't contain maxSize among Component's fields.3737if (maxSize == null) {3738maxSize = (Dimension)f.get("maxSize", null);3739}3740focusCycleRoot = f.get("focusCycleRoot", false);3741containerSerializedDataVersion = f.get("containerSerializedDataVersion", 1);3742focusTraversalPolicyProvider = f.get("focusTraversalPolicyProvider", false);3743java.util.List<Component> component = this.component;3744for(Component comp : component) {3745comp.parent = this;3746adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK,3747comp.numListening(AWTEvent.HIERARCHY_EVENT_MASK));3748adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,3749comp.numListening(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));3750adjustDescendants(comp.countHierarchyMembers());3751}37523753Object keyOrNull;3754while(null != (keyOrNull = s.readObject())) {3755String key = ((String)keyOrNull).intern();37563757if (containerListenerK == key) {3758addContainerListener((ContainerListener)(s.readObject()));3759} else {3760// skip value for unrecognized key3761s.readObject();3762}3763}37643765try {3766Object policy = s.readObject();3767if (policy instanceof FocusTraversalPolicy) {3768focusTraversalPolicy = (FocusTraversalPolicy)policy;3769}3770} catch (java.io.OptionalDataException e) {3771// JDK 1.1/1.2/1.3 instances will not have this optional data.3772// e.eof will be true to indicate that there is no more data3773// available for this object. If e.eof is not true, throw the3774// exception as it might have been caused by reasons unrelated to3775// focusTraversalPolicy.37763777if (!e.eof) {3778throw e;3779}3780}3781}37823783/*3784* --- Accessibility Support ---3785*/37863787/**3788* Inner class of Container used to provide default support for3789* accessibility. This class is not meant to be used directly by3790* application developers, but is instead meant only to be3791* subclassed by container developers.3792* <p>3793* The class used to obtain the accessible role for this object,3794* as well as implementing many of the methods in the3795* AccessibleContainer interface.3796* @since 1.33797*/3798protected class AccessibleAWTContainer extends AccessibleAWTComponent {37993800/**3801* JDK1.3 serialVersionUID3802*/3803private static final long serialVersionUID = 5081320404842566097L;38043805/**3806* Returns the number of accessible children in the object. If all3807* of the children of this object implement <code>Accessible</code>,3808* then this method should return the number of children of this object.3809*3810* @return the number of accessible children in the object3811*/3812public int getAccessibleChildrenCount() {3813return Container.this.getAccessibleChildrenCount();3814}38153816/**3817* Returns the nth <code>Accessible</code> child of the object.3818*3819* @param i zero-based index of child3820* @return the nth <code>Accessible</code> child of the object3821*/3822public Accessible getAccessibleChild(int i) {3823return Container.this.getAccessibleChild(i);3824}38253826/**3827* Returns the <code>Accessible</code> child, if one exists,3828* contained at the local coordinate <code>Point</code>.3829*3830* @param p the point defining the top-left corner of the3831* <code>Accessible</code>, given in the coordinate space3832* of the object's parent3833* @return the <code>Accessible</code>, if it exists,3834* at the specified location; else <code>null</code>3835*/3836public Accessible getAccessibleAt(Point p) {3837return Container.this.getAccessibleAt(p);3838}38393840/**3841* Number of PropertyChangeListener objects registered. It's used3842* to add/remove ContainerListener to track target Container's state.3843*/3844private volatile transient int propertyListenersCount = 0;38453846protected ContainerListener accessibleContainerHandler = null;38473848/**3849* Fire <code>PropertyChange</code> listener, if one is registered,3850* when children are added or removed.3851* @since 1.33852*/3853protected class AccessibleContainerHandler3854implements ContainerListener {3855public void componentAdded(ContainerEvent e) {3856Component c = e.getChild();3857if (c != null && c instanceof Accessible) {3858AccessibleAWTContainer.this.firePropertyChange(3859AccessibleContext.ACCESSIBLE_CHILD_PROPERTY,3860null, ((Accessible) c).getAccessibleContext());3861}3862}3863public void componentRemoved(ContainerEvent e) {3864Component c = e.getChild();3865if (c != null && c instanceof Accessible) {3866AccessibleAWTContainer.this.firePropertyChange(3867AccessibleContext.ACCESSIBLE_CHILD_PROPERTY,3868((Accessible) c).getAccessibleContext(), null);3869}3870}3871}38723873/**3874* Adds a PropertyChangeListener to the listener list.3875*3876* @param listener the PropertyChangeListener to be added3877*/3878public void addPropertyChangeListener(PropertyChangeListener listener) {3879if (accessibleContainerHandler == null) {3880accessibleContainerHandler = new AccessibleContainerHandler();3881}3882if (propertyListenersCount++ == 0) {3883Container.this.addContainerListener(accessibleContainerHandler);3884}3885super.addPropertyChangeListener(listener);3886}38873888/**3889* Remove a PropertyChangeListener from the listener list.3890* This removes a PropertyChangeListener that was registered3891* for all properties.3892*3893* @param listener the PropertyChangeListener to be removed3894*/3895public void removePropertyChangeListener(PropertyChangeListener listener) {3896if (--propertyListenersCount == 0) {3897Container.this.removeContainerListener(accessibleContainerHandler);3898}3899super.removePropertyChangeListener(listener);3900}39013902} // inner class AccessibleAWTContainer39033904/**3905* Returns the <code>Accessible</code> child contained at the local3906* coordinate <code>Point</code>, if one exists. Otherwise3907* returns <code>null</code>.3908*3909* @param p the point defining the top-left corner of the3910* <code>Accessible</code>, given in the coordinate space3911* of the object's parent3912* @return the <code>Accessible</code> at the specified location,3913* if it exists; otherwise <code>null</code>3914*/3915Accessible getAccessibleAt(Point p) {3916synchronized (getTreeLock()) {3917if (this instanceof Accessible) {3918Accessible a = (Accessible)this;3919AccessibleContext ac = a.getAccessibleContext();3920if (ac != null) {3921AccessibleComponent acmp;3922Point location;3923int nchildren = ac.getAccessibleChildrenCount();3924for (int i=0; i < nchildren; i++) {3925a = ac.getAccessibleChild(i);3926if ((a != null)) {3927ac = a.getAccessibleContext();3928if (ac != null) {3929acmp = ac.getAccessibleComponent();3930if ((acmp != null) && (acmp.isShowing())) {3931location = acmp.getLocation();3932Point np = new Point(p.x-location.x,3933p.y-location.y);3934if (acmp.contains(np)){3935return a;3936}3937}3938}3939}3940}3941}3942return (Accessible)this;3943} else {3944Component ret = this;3945if (!this.contains(p.x,p.y)) {3946ret = null;3947} else {3948int ncomponents = this.getComponentCount();3949for (int i=0; i < ncomponents; i++) {3950Component comp = this.getComponent(i);3951if ((comp != null) && comp.isShowing()) {3952Point location = comp.getLocation();3953if (comp.contains(p.x-location.x,p.y-location.y)) {3954ret = comp;3955}3956}3957}3958}3959if (ret instanceof Accessible) {3960return (Accessible) ret;3961}3962}3963return null;3964}3965}39663967/**3968* Returns the number of accessible children in the object. If all3969* of the children of this object implement <code>Accessible</code>,3970* then this method should return the number of children of this object.3971*3972* @return the number of accessible children in the object3973*/3974int getAccessibleChildrenCount() {3975synchronized (getTreeLock()) {3976int count = 0;3977Component[] children = this.getComponents();3978for (int i = 0; i < children.length; i++) {3979if (children[i] instanceof Accessible) {3980count++;3981}3982}3983return count;3984}3985}39863987/**3988* Returns the nth <code>Accessible</code> child of the object.3989*3990* @param i zero-based index of child3991* @return the nth <code>Accessible</code> child of the object3992*/3993Accessible getAccessibleChild(int i) {3994synchronized (getTreeLock()) {3995Component[] children = this.getComponents();3996int count = 0;3997for (int j = 0; j < children.length; j++) {3998if (children[j] instanceof Accessible) {3999if (count == i) {4000return (Accessible) children[j];4001} else {4002count++;4003}4004}4005}4006return null;4007}4008}40094010// ************************** MIXING CODE *******************************40114012final void increaseComponentCount(Component c) {4013synchronized (getTreeLock()) {4014if (!c.isDisplayable()) {4015throw new IllegalStateException(4016"Peer does not exist while invoking the increaseComponentCount() method"4017);4018}40194020int addHW = 0;4021int addLW = 0;40224023if (c instanceof Container) {4024addLW = ((Container)c).numOfLWComponents;4025addHW = ((Container)c).numOfHWComponents;4026}4027if (c.isLightweight()) {4028addLW++;4029} else {4030addHW++;4031}40324033for (Container cont = this; cont != null; cont = cont.getContainer()) {4034cont.numOfLWComponents += addLW;4035cont.numOfHWComponents += addHW;4036}4037}4038}40394040final void decreaseComponentCount(Component c) {4041synchronized (getTreeLock()) {4042if (!c.isDisplayable()) {4043throw new IllegalStateException(4044"Peer does not exist while invoking the decreaseComponentCount() method"4045);4046}40474048int subHW = 0;4049int subLW = 0;40504051if (c instanceof Container) {4052subLW = ((Container)c).numOfLWComponents;4053subHW = ((Container)c).numOfHWComponents;4054}4055if (c.isLightweight()) {4056subLW++;4057} else {4058subHW++;4059}40604061for (Container cont = this; cont != null; cont = cont.getContainer()) {4062cont.numOfLWComponents -= subLW;4063cont.numOfHWComponents -= subHW;4064}4065}4066}40674068private int getTopmostComponentIndex() {4069checkTreeLock();4070if (getComponentCount() > 0) {4071return 0;4072}4073return -1;4074}40754076private int getBottommostComponentIndex() {4077checkTreeLock();4078if (getComponentCount() > 0) {4079return getComponentCount() - 1;4080}4081return -1;4082}40834084/*4085* This method is overriden to handle opaque children in non-opaque4086* containers.4087*/4088@Override4089final Region getOpaqueShape() {4090checkTreeLock();4091if (isLightweight() && isNonOpaqueForMixing()4092&& hasLightweightDescendants())4093{4094Region s = Region.EMPTY_REGION;4095for (int index = 0; index < getComponentCount(); index++) {4096Component c = getComponent(index);4097if (c.isLightweight() && c.isShowing()) {4098s = s.getUnion(c.getOpaqueShape());4099}4100}4101return s.getIntersection(getNormalShape());4102}4103return super.getOpaqueShape();4104}41054106final void recursiveSubtractAndApplyShape(Region shape) {4107recursiveSubtractAndApplyShape(shape, getTopmostComponentIndex(), getBottommostComponentIndex());4108}41094110final void recursiveSubtractAndApplyShape(Region shape, int fromZorder) {4111recursiveSubtractAndApplyShape(shape, fromZorder, getBottommostComponentIndex());4112}41134114final void recursiveSubtractAndApplyShape(Region shape, int fromZorder, int toZorder) {4115checkTreeLock();4116if (mixingLog.isLoggable(PlatformLogger.Level.FINE)) {4117mixingLog.fine("this = " + this +4118"; shape=" + shape + "; fromZ=" + fromZorder + "; toZ=" + toZorder);4119}4120if (fromZorder == -1) {4121return;4122}4123if (shape.isEmpty()) {4124return;4125}4126// An invalid container with not-null layout should be ignored4127// by the mixing code, the container will be validated later4128// and the mixing code will be executed later.4129if (getLayout() != null && !isValid()) {4130return;4131}4132for (int index = fromZorder; index <= toZorder; index++) {4133Component comp = getComponent(index);4134if (!comp.isLightweight()) {4135comp.subtractAndApplyShape(shape);4136} else if (comp instanceof Container &&4137((Container)comp).hasHeavyweightDescendants() && comp.isShowing()) {4138((Container)comp).recursiveSubtractAndApplyShape(shape);4139}4140}4141}41424143final void recursiveApplyCurrentShape() {4144recursiveApplyCurrentShape(getTopmostComponentIndex(), getBottommostComponentIndex());4145}41464147final void recursiveApplyCurrentShape(int fromZorder) {4148recursiveApplyCurrentShape(fromZorder, getBottommostComponentIndex());4149}41504151final void recursiveApplyCurrentShape(int fromZorder, int toZorder) {4152checkTreeLock();4153if (mixingLog.isLoggable(PlatformLogger.Level.FINE)) {4154mixingLog.fine("this = " + this +4155"; fromZ=" + fromZorder + "; toZ=" + toZorder);4156}4157if (fromZorder == -1) {4158return;4159}4160// An invalid container with not-null layout should be ignored4161// by the mixing code, the container will be validated later4162// and the mixing code will be executed later.4163if (getLayout() != null && !isValid()) {4164return;4165}4166for (int index = fromZorder; index <= toZorder; index++) {4167Component comp = getComponent(index);4168if (!comp.isLightweight()) {4169comp.applyCurrentShape();4170}4171if (comp instanceof Container &&4172((Container)comp).hasHeavyweightDescendants()) {4173((Container)comp).recursiveApplyCurrentShape();4174}4175}4176}41774178private void recursiveShowHeavyweightChildren() {4179if (!hasHeavyweightDescendants() || !isVisible()) {4180return;4181}4182for (int index = 0; index < getComponentCount(); index++) {4183Component comp = getComponent(index);4184if (comp.isLightweight()) {4185if (comp instanceof Container) {4186((Container)comp).recursiveShowHeavyweightChildren();4187}4188} else {4189if (comp.isVisible()) {4190ComponentPeer peer = comp.getPeer();4191if (peer != null) {4192peer.setVisible(true);4193}4194}4195}4196}4197}41984199private void recursiveHideHeavyweightChildren() {4200if (!hasHeavyweightDescendants()) {4201return;4202}4203for (int index = 0; index < getComponentCount(); index++) {4204Component comp = getComponent(index);4205if (comp.isLightweight()) {4206if (comp instanceof Container) {4207((Container)comp).recursiveHideHeavyweightChildren();4208}4209} else {4210if (comp.isVisible()) {4211ComponentPeer peer = comp.getPeer();4212if (peer != null) {4213peer.setVisible(false);4214}4215}4216}4217}4218}42194220private void recursiveRelocateHeavyweightChildren(Point origin) {4221for (int index = 0; index < getComponentCount(); index++) {4222Component comp = getComponent(index);4223if (comp.isLightweight()) {4224if (comp instanceof Container &&4225((Container)comp).hasHeavyweightDescendants())4226{4227final Point newOrigin = new Point(origin);4228newOrigin.translate(comp.getX(), comp.getY());4229((Container)comp).recursiveRelocateHeavyweightChildren(newOrigin);4230}4231} else {4232ComponentPeer peer = comp.getPeer();4233if (peer != null) {4234peer.setBounds(origin.x + comp.getX(), origin.y + comp.getY(),4235comp.getWidth(), comp.getHeight(),4236ComponentPeer.SET_LOCATION);4237}4238}4239}4240}42414242/**4243* Checks if the container and its direct lightweight containers are4244* visible.4245*4246* Consider the heavyweight container hides or shows the HW descendants4247* automatically. Therefore we care of LW containers' visibility only.4248*4249* This method MUST be invoked under the TreeLock.4250*/4251final boolean isRecursivelyVisibleUpToHeavyweightContainer() {4252if (!isLightweight()) {4253return true;4254}42554256for (Container cont = this;4257cont != null && cont.isLightweight();4258cont = cont.getContainer())4259{4260if (!cont.isVisible()) {4261return false;4262}4263}4264return true;4265}42664267@Override4268void mixOnShowing() {4269synchronized (getTreeLock()) {4270if (mixingLog.isLoggable(PlatformLogger.Level.FINE)) {4271mixingLog.fine("this = " + this);4272}42734274boolean isLightweight = isLightweight();42754276if (isLightweight && isRecursivelyVisibleUpToHeavyweightContainer()) {4277recursiveShowHeavyweightChildren();4278}42794280if (!isMixingNeeded()) {4281return;4282}42834284if (!isLightweight || (isLightweight && hasHeavyweightDescendants())) {4285recursiveApplyCurrentShape();4286}42874288super.mixOnShowing();4289}4290}42914292@Override4293void mixOnHiding(boolean isLightweight) {4294synchronized (getTreeLock()) {4295if (mixingLog.isLoggable(PlatformLogger.Level.FINE)) {4296mixingLog.fine("this = " + this +4297"; isLightweight=" + isLightweight);4298}4299if (isLightweight) {4300recursiveHideHeavyweightChildren();4301}4302super.mixOnHiding(isLightweight);4303}4304}43054306@Override4307void mixOnReshaping() {4308synchronized (getTreeLock()) {4309if (mixingLog.isLoggable(PlatformLogger.Level.FINE)) {4310mixingLog.fine("this = " + this);4311}43124313boolean isMixingNeeded = isMixingNeeded();43144315if (isLightweight() && hasHeavyweightDescendants()) {4316final Point origin = new Point(getX(), getY());4317for (Container cont = getContainer();4318cont != null && cont.isLightweight();4319cont = cont.getContainer())4320{4321origin.translate(cont.getX(), cont.getY());4322}43234324recursiveRelocateHeavyweightChildren(origin);43254326if (!isMixingNeeded) {4327return;4328}43294330recursiveApplyCurrentShape();4331}43324333if (!isMixingNeeded) {4334return;4335}43364337super.mixOnReshaping();4338}4339}43404341@Override4342void mixOnZOrderChanging(int oldZorder, int newZorder) {4343synchronized (getTreeLock()) {4344if (mixingLog.isLoggable(PlatformLogger.Level.FINE)) {4345mixingLog.fine("this = " + this +4346"; oldZ=" + oldZorder + "; newZ=" + newZorder);4347}43484349if (!isMixingNeeded()) {4350return;4351}43524353boolean becameHigher = newZorder < oldZorder;43544355if (becameHigher && isLightweight() && hasHeavyweightDescendants()) {4356recursiveApplyCurrentShape();4357}4358super.mixOnZOrderChanging(oldZorder, newZorder);4359}4360}43614362@Override4363void mixOnValidating() {4364synchronized (getTreeLock()) {4365if (mixingLog.isLoggable(PlatformLogger.Level.FINE)) {4366mixingLog.fine("this = " + this);4367}43684369if (!isMixingNeeded()) {4370return;4371}43724373if (hasHeavyweightDescendants()) {4374recursiveApplyCurrentShape();4375}43764377if (isLightweight() && isNonOpaqueForMixing()) {4378subtractAndApplyShapeBelowMe();4379}43804381super.mixOnValidating();4382}4383}43844385// ****************** END OF MIXING CODE ********************************4386}438743884389/**4390* Class to manage the dispatching of MouseEvents to the lightweight descendants4391* and SunDropTargetEvents to both lightweight and heavyweight descendants4392* contained by a native container.4393*4394* NOTE: the class name is not appropriate anymore, but we cannot change it4395* because we must keep serialization compatibility.4396*4397* @author Timothy Prinzing4398*/4399class LightweightDispatcher implements java.io.Serializable, AWTEventListener {44004401/*4402* JDK 1.1 serialVersionUID4403*/4404private static final long serialVersionUID = 5184291520170872969L;4405/*4406* Our own mouse event for when we're dragged over from another hw4407* container4408*/4409private static final int LWD_MOUSE_DRAGGED_OVER = 1500;44104411private static final PlatformLogger eventLog = PlatformLogger.getLogger("java.awt.event.LightweightDispatcher");44124413private static final int BUTTONS_DOWN_MASK;44144415static {4416int[] buttonsDownMask = AWTAccessor.getInputEventAccessor().4417getButtonDownMasks();4418int mask = 0;4419for (int buttonDownMask : buttonsDownMask) {4420mask |= buttonDownMask;4421}4422BUTTONS_DOWN_MASK = mask;4423}44244425LightweightDispatcher(Container nativeContainer) {4426this.nativeContainer = nativeContainer;4427mouseEventTarget = new WeakReference<>(null);4428targetLastEntered = new WeakReference<>(null);4429targetLastEnteredDT = new WeakReference<>(null);4430eventMask = 0;4431}44324433/*4434* Clean up any resources allocated when dispatcher was created;4435* should be called from Container.removeNotify4436*/4437void dispose() {4438//System.out.println("Disposing lw dispatcher");4439stopListeningForOtherDrags();4440mouseEventTarget.clear();4441targetLastEntered.clear();4442targetLastEnteredDT.clear();4443}44444445/**4446* Enables events to subcomponents.4447*/4448void enableEvents(long events) {4449eventMask |= events;4450}44514452/**4453* Dispatches an event to a sub-component if necessary, and4454* returns whether or not the event was forwarded to a4455* sub-component.4456*4457* @param e the event4458*/4459boolean dispatchEvent(AWTEvent e) {4460boolean ret = false;44614462/*4463* Fix for BugTraq Id 4389284.4464* Dispatch SunDropTargetEvents regardless of eventMask value.4465* Do not update cursor on dispatching SunDropTargetEvents.4466*/4467if (e instanceof SunDropTargetEvent) {44684469SunDropTargetEvent sdde = (SunDropTargetEvent) e;4470ret = processDropTargetEvent(sdde);44714472} else {4473if (e instanceof MouseEvent && (eventMask & MOUSE_MASK) != 0) {4474MouseEvent me = (MouseEvent) e;4475ret = processMouseEvent(me);4476}44774478if (e.getID() == MouseEvent.MOUSE_MOVED) {4479nativeContainer.updateCursorImmediately();4480}4481}44824483return ret;4484}44854486/* This method effectively returns whether or not a mouse button was down4487* just BEFORE the event happened. A better method name might be4488* wasAMouseButtonDownBeforeThisEvent().4489*/4490private boolean isMouseGrab(MouseEvent e) {4491int modifiers = e.getModifiersEx();44924493if (e.getID() == MouseEvent.MOUSE_PRESSED4494|| e.getID() == MouseEvent.MOUSE_RELEASED) {4495modifiers ^= InputEvent.getMaskForButton(e.getButton());4496}4497/* modifiers now as just before event */4498return ((modifiers & BUTTONS_DOWN_MASK) != 0);4499}45004501/**4502* This method attempts to distribute a mouse event to a lightweight4503* component. It tries to avoid doing any unnecessary probes down4504* into the component tree to minimize the overhead of determining4505* where to route the event, since mouse movement events tend to4506* come in large and frequent amounts.4507*/4508private boolean processMouseEvent(MouseEvent e) {4509int id = e.getID();4510Component mouseOver = // sensitive to mouse events4511nativeContainer.getMouseEventTarget(e.getX(), e.getY(),4512Container.INCLUDE_SELF);45134514trackMouseEnterExit(mouseOver, e);45154516Component met = mouseEventTarget.get();4517// 4508327 : MOUSE_CLICKED should only go to the recipient of4518// the accompanying MOUSE_PRESSED, so don't reset mouseEventTarget on a4519// MOUSE_CLICKED.4520if (!isMouseGrab(e) && id != MouseEvent.MOUSE_CLICKED) {4521met = (mouseOver != nativeContainer) ? mouseOver : null;4522mouseEventTarget = new WeakReference<>(met);4523}45244525if (met != null) {4526switch (id) {4527case MouseEvent.MOUSE_ENTERED:4528case MouseEvent.MOUSE_EXITED:4529break;4530case MouseEvent.MOUSE_PRESSED:4531retargetMouseEvent(met, id, e);4532break;4533case MouseEvent.MOUSE_RELEASED:4534retargetMouseEvent(met, id, e);4535break;4536case MouseEvent.MOUSE_CLICKED:4537// 4508327: MOUSE_CLICKED should never be dispatched to a Component4538// other than that which received the MOUSE_PRESSED event. If the4539// mouse is now over a different Component, don't dispatch the event.4540// The previous fix for a similar problem was associated with bug4541// 4155217.4542if (mouseOver == met) {4543retargetMouseEvent(mouseOver, id, e);4544}4545break;4546case MouseEvent.MOUSE_MOVED:4547retargetMouseEvent(met, id, e);4548break;4549case MouseEvent.MOUSE_DRAGGED:4550if (isMouseGrab(e)) {4551retargetMouseEvent(met, id, e);4552}4553break;4554case MouseEvent.MOUSE_WHEEL:4555// This may send it somewhere that doesn't have MouseWheelEvents4556// enabled. In this case, Component.dispatchEventImpl() will4557// retarget the event to a parent that DOES have the events enabled.4558if (eventLog.isLoggable(PlatformLogger.Level.FINEST) && (mouseOver != null)) {4559eventLog.finest("retargeting mouse wheel to " +4560mouseOver.getName() + ", " +4561mouseOver.getClass());4562}4563retargetMouseEvent(mouseOver, id, e);4564break;4565}4566//Consuming of wheel events is implemented in "retargetMouseEvent".4567if (id != MouseEvent.MOUSE_WHEEL) {4568e.consume();4569}4570}4571return e.isConsumed();4572}45734574private boolean processDropTargetEvent(SunDropTargetEvent e) {4575int id = e.getID();4576int x = e.getX();4577int y = e.getY();45784579/*4580* Fix for BugTraq ID 4395290.4581* It is possible that SunDropTargetEvent's Point is outside of the4582* native container bounds. In this case we truncate coordinates.4583*/4584if (!nativeContainer.contains(x, y)) {4585final Dimension d = nativeContainer.getSize();4586if (d.width <= x) {4587x = d.width - 1;4588} else if (x < 0) {4589x = 0;4590}4591if (d.height <= y) {4592y = d.height - 1;4593} else if (y < 0) {4594y = 0;4595}4596}4597Component mouseOver = // not necessarily sensitive to mouse events4598nativeContainer.getDropTargetEventTarget(x, y,4599Container.INCLUDE_SELF);4600trackMouseEnterExit(mouseOver, e);46014602if (mouseOver != nativeContainer && mouseOver != null) {4603switch (id) {4604case SunDropTargetEvent.MOUSE_ENTERED:4605case SunDropTargetEvent.MOUSE_EXITED:4606break;4607default:4608retargetMouseEvent(mouseOver, id, e);4609e.consume();4610break;4611}4612}4613return e.isConsumed();4614}46154616/*4617* Generates dnd enter/exit events as mouse moves over lw components4618* @param targetOver Target mouse is over (including native container)4619* @param e SunDropTarget mouse event in native container4620*/4621private void trackDropTargetEnterExit(Component targetOver, MouseEvent e) {4622int id = e.getID();4623if (id == MouseEvent.MOUSE_ENTERED && isMouseDTInNativeContainer) {4624// This can happen if a lightweight component which initiated the4625// drag has an associated drop target. MOUSE_ENTERED comes when the4626// mouse is in the native container already. To propagate this event4627// properly we should null out targetLastEntered.4628targetLastEnteredDT.clear();4629} else if (id == MouseEvent.MOUSE_ENTERED) {4630isMouseDTInNativeContainer = true;4631} else if (id == MouseEvent.MOUSE_EXITED) {4632isMouseDTInNativeContainer = false;4633}4634Component tle = retargetMouseEnterExit(targetOver, e,4635targetLastEnteredDT.get(),4636isMouseDTInNativeContainer);4637targetLastEnteredDT = new WeakReference<>(tle);4638}46394640/*4641* Generates enter/exit events as mouse moves over lw components4642* @param targetOver Target mouse is over (including native container)4643* @param e Mouse event in native container4644*/4645private void trackMouseEnterExit(Component targetOver, MouseEvent e) {4646if (e instanceof SunDropTargetEvent) {4647trackDropTargetEnterExit(targetOver, e);4648return;4649}4650int id = e.getID();46514652if ( id != MouseEvent.MOUSE_EXITED &&4653id != MouseEvent.MOUSE_DRAGGED &&4654id != LWD_MOUSE_DRAGGED_OVER &&4655!isMouseInNativeContainer) {4656// any event but an exit or drag means we're in the native container4657isMouseInNativeContainer = true;4658startListeningForOtherDrags();4659} else if (id == MouseEvent.MOUSE_EXITED) {4660isMouseInNativeContainer = false;4661stopListeningForOtherDrags();4662}4663Component tle = retargetMouseEnterExit(targetOver, e,4664targetLastEntered.get(),4665isMouseInNativeContainer);4666targetLastEntered = new WeakReference<>(tle);4667}46684669private Component retargetMouseEnterExit(Component targetOver, MouseEvent e,4670Component lastEntered,4671boolean inNativeContainer) {4672int id = e.getID();4673Component targetEnter = inNativeContainer ? targetOver : null;46744675if (lastEntered != targetEnter) {4676if (lastEntered != null) {4677retargetMouseEvent(lastEntered, MouseEvent.MOUSE_EXITED, e);4678}4679if (id == MouseEvent.MOUSE_EXITED) {4680// consume native exit event if we generate one4681e.consume();4682}46834684if (targetEnter != null) {4685retargetMouseEvent(targetEnter, MouseEvent.MOUSE_ENTERED, e);4686}4687if (id == MouseEvent.MOUSE_ENTERED) {4688// consume native enter event if we generate one4689e.consume();4690}4691}4692return targetEnter;4693}46944695/*4696* Listens to global mouse drag events so even drags originating4697* from other heavyweight containers will generate enter/exit4698* events in this container4699*/4700private void startListeningForOtherDrags() {4701//System.out.println("Adding AWTEventListener");4702java.security.AccessController.doPrivileged(4703new java.security.PrivilegedAction<Object>() {4704public Object run() {4705nativeContainer.getToolkit().addAWTEventListener(4706LightweightDispatcher.this,4707AWTEvent.MOUSE_EVENT_MASK |4708AWTEvent.MOUSE_MOTION_EVENT_MASK);4709return null;4710}4711}4712);4713}47144715private void stopListeningForOtherDrags() {4716//System.out.println("Removing AWTEventListener");4717java.security.AccessController.doPrivileged(4718new java.security.PrivilegedAction<Object>() {4719public Object run() {4720nativeContainer.getToolkit().removeAWTEventListener(LightweightDispatcher.this);4721return null;4722}4723}4724);4725}47264727/*4728* (Implementation of AWTEventListener)4729* Listen for drag events posted in other hw components so we can4730* track enter/exit regardless of where a drag originated4731*/4732public void eventDispatched(AWTEvent e) {4733boolean isForeignDrag = (e instanceof MouseEvent) &&4734!(e instanceof SunDropTargetEvent) &&4735(e.id == MouseEvent.MOUSE_DRAGGED) &&4736(e.getSource() != nativeContainer);47374738if (!isForeignDrag) {4739// only interested in drags from other hw components4740return;4741}47424743MouseEvent srcEvent = (MouseEvent)e;4744MouseEvent me;47454746synchronized (nativeContainer.getTreeLock()) {4747Component srcComponent = srcEvent.getComponent();47484749// component may have disappeared since drag event posted4750// (i.e. Swing hierarchical menus)4751if ( !srcComponent.isShowing() ) {4752return;4753}47544755// see 50835554756// check if srcComponent is in any modal blocked window4757Component c = nativeContainer;4758while ((c != null) && !(c instanceof Window)) {4759c = c.getParent_NoClientCode();4760}4761if ((c == null) || ((Window)c).isModalBlocked()) {4762return;4763}47644765//4766// create an internal 'dragged-over' event indicating4767// we are being dragged over from another hw component4768//4769me = new MouseEvent(nativeContainer,4770LWD_MOUSE_DRAGGED_OVER,4771srcEvent.getWhen(),4772srcEvent.getModifiersEx() | srcEvent.getModifiers(),4773srcEvent.getX(),4774srcEvent.getY(),4775srcEvent.getXOnScreen(),4776srcEvent.getYOnScreen(),4777srcEvent.getClickCount(),4778srcEvent.isPopupTrigger(),4779srcEvent.getButton());4780MouseEventAccessor meAccessor = AWTAccessor.getMouseEventAccessor();4781meAccessor.setCausedByTouchEvent(me,4782meAccessor.isCausedByTouchEvent(srcEvent));4783((AWTEvent)srcEvent).copyPrivateDataInto(me);4784// translate coordinates to this native container4785final Point ptSrcOrigin = srcComponent.getLocationOnScreen();47864787if (AppContext.getAppContext() != nativeContainer.appContext) {4788final MouseEvent mouseEvent = me;4789Runnable r = new Runnable() {4790public void run() {4791if (!nativeContainer.isShowing() ) {4792return;4793}47944795Point ptDstOrigin = nativeContainer.getLocationOnScreen();4796mouseEvent.translatePoint(ptSrcOrigin.x - ptDstOrigin.x,4797ptSrcOrigin.y - ptDstOrigin.y );4798Component targetOver =4799nativeContainer.getMouseEventTarget(mouseEvent.getX(),4800mouseEvent.getY(),4801Container.INCLUDE_SELF);4802trackMouseEnterExit(targetOver, mouseEvent);4803}4804};4805SunToolkit.executeOnEventHandlerThread(nativeContainer, r);4806return;4807} else {4808if (!nativeContainer.isShowing() ) {4809return;4810}48114812Point ptDstOrigin = nativeContainer.getLocationOnScreen();4813me.translatePoint( ptSrcOrigin.x - ptDstOrigin.x, ptSrcOrigin.y - ptDstOrigin.y );4814}4815}4816//System.out.println("Track event: " + me);4817// feed the 'dragged-over' event directly to the enter/exit4818// code (not a real event so don't pass it to dispatchEvent)4819Component targetOver =4820nativeContainer.getMouseEventTarget(me.getX(), me.getY(),4821Container.INCLUDE_SELF);4822trackMouseEnterExit(targetOver, me);4823}48244825/**4826* Sends a mouse event to the current mouse event recipient using4827* the given event (sent to the windowed host) as a srcEvent. If4828* the mouse event target is still in the component tree, the4829* coordinates of the event are translated to those of the target.4830* If the target has been removed, we don't bother to send the4831* message.4832*/4833void retargetMouseEvent(Component target, int id, MouseEvent e) {4834if (target == null) {4835return; // mouse is over another hw component or target is disabled4836}48374838int x = e.getX(), y = e.getY();4839Component component;48404841for(component = target;4842component != null && component != nativeContainer;4843component = component.getParent()) {4844x -= component.x;4845y -= component.y;4846}4847MouseEvent retargeted;4848if (component != null) {4849if (e instanceof SunDropTargetEvent) {4850retargeted = new SunDropTargetEvent(target,4851id,4852x,4853y,4854((SunDropTargetEvent)e).getDispatcher());4855} else if (id == MouseEvent.MOUSE_WHEEL) {4856retargeted = new MouseWheelEvent(target,4857id,4858e.getWhen(),4859e.getModifiersEx() | e.getModifiers(),4860x,4861y,4862e.getXOnScreen(),4863e.getYOnScreen(),4864e.getClickCount(),4865e.isPopupTrigger(),4866((MouseWheelEvent)e).getScrollType(),4867((MouseWheelEvent)e).getScrollAmount(),4868((MouseWheelEvent)e).getWheelRotation(),4869((MouseWheelEvent)e).getPreciseWheelRotation());4870}4871else {4872retargeted = new MouseEvent(target,4873id,4874e.getWhen(),4875e.getModifiersEx() | e.getModifiers(),4876x,4877y,4878e.getXOnScreen(),4879e.getYOnScreen(),4880e.getClickCount(),4881e.isPopupTrigger(),4882e.getButton());4883MouseEventAccessor meAccessor = AWTAccessor.getMouseEventAccessor();4884meAccessor.setCausedByTouchEvent(retargeted,4885meAccessor.isCausedByTouchEvent(e));4886}48874888((AWTEvent)e).copyPrivateDataInto(retargeted);48894890if (target == nativeContainer) {4891// avoid recursively calling LightweightDispatcher...4892((Container)target).dispatchEventToSelf(retargeted);4893} else {4894assert AppContext.getAppContext() == target.appContext;48954896if (nativeContainer.modalComp != null) {4897if (((Container)nativeContainer.modalComp).isAncestorOf(target)) {4898target.dispatchEvent(retargeted);4899} else {4900e.consume();4901}4902} else {4903target.dispatchEvent(retargeted);4904}4905}4906if (id == MouseEvent.MOUSE_WHEEL && retargeted.isConsumed()) {4907//An exception for wheel bubbling to the native system.4908//In "processMouseEvent" total event consuming for wheel events is skipped.4909//Protection from bubbling of Java-accepted wheel events.4910e.consume();4911}4912}4913}49144915// --- member variables -------------------------------49164917/**4918* The windowed container that might be hosting events for4919* subcomponents.4920*/4921private Container nativeContainer;49224923/**4924* This variable is not used, but kept for serialization compatibility4925*/4926private Component focus;49274928/**4929* The current subcomponent being hosted by this windowed4930* component that has events being forwarded to it. If this4931* is null, there are currently no events being forwarded to4932* a subcomponent.4933*/4934private transient WeakReference<Component> mouseEventTarget;49354936/**4937* The last component entered by the {@code MouseEvent}.4938*/4939private transient WeakReference<Component> targetLastEntered;49404941/**4942* The last component entered by the {@code SunDropTargetEvent}.4943*/4944private transient WeakReference<Component> targetLastEnteredDT;49454946/**4947* Is the mouse over the native container.4948*/4949private transient boolean isMouseInNativeContainer = false;49504951/**4952* Is DnD over the native container.4953*/4954private transient boolean isMouseDTInNativeContainer = false;49554956/**4957* This variable is not used, but kept for serialization compatibility4958*/4959private Cursor nativeCursor;49604961/**4962* The event mask for contained lightweight components. Lightweight4963* components need a windowed container to host window-related4964* events. This separate mask indicates events that have been4965* requested by contained lightweight components without effecting4966* the mask of the windowed component itself.4967*/4968private long eventMask;49694970/**4971* The kind of events routed to lightweight components from windowed4972* hosts.4973*/4974private static final long PROXY_EVENT_MASK =4975AWTEvent.FOCUS_EVENT_MASK |4976AWTEvent.KEY_EVENT_MASK |4977AWTEvent.MOUSE_EVENT_MASK |4978AWTEvent.MOUSE_MOTION_EVENT_MASK |4979AWTEvent.MOUSE_WHEEL_EVENT_MASK;49804981private static final long MOUSE_MASK =4982AWTEvent.MOUSE_EVENT_MASK |4983AWTEvent.MOUSE_MOTION_EVENT_MASK |4984AWTEvent.MOUSE_WHEEL_EVENT_MASK;4985}498649874988