Path: blob/master/src/java.desktop/share/classes/java/awt/Container.java
41152 views
/*1* Copyright (c) 1995, 2021, 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*/2425package java.awt;2627import java.awt.dnd.DropTarget;28import java.awt.event.AWTEventListener;29import java.awt.event.ComponentEvent;30import java.awt.event.ContainerEvent;31import java.awt.event.ContainerListener;32import java.awt.event.FocusEvent;33import java.awt.event.HierarchyEvent;34import java.awt.event.InputEvent;35import java.awt.event.KeyEvent;36import java.awt.event.MouseEvent;37import java.awt.event.MouseWheelEvent;38import java.awt.peer.ComponentPeer;39import java.awt.peer.ContainerPeer;40import java.awt.peer.LightweightPeer;41import java.beans.PropertyChangeListener;42import java.io.IOException;43import java.io.InvalidObjectException;44import java.io.ObjectInputStream;45import java.io.ObjectOutputStream;46import java.io.ObjectStreamField;47import java.io.PrintStream;48import java.io.PrintWriter;49import java.io.Serial;50import java.io.Serializable;51import java.lang.ref.WeakReference;52import java.security.AccessController;53import java.util.ArrayList;54import java.util.EventListener;55import java.util.HashSet;56import java.util.Set;5758import javax.accessibility.Accessible;59import javax.accessibility.AccessibleComponent;60import javax.accessibility.AccessibleContext;6162import sun.awt.AWTAccessor;63import sun.awt.AWTAccessor.MouseEventAccessor;64import sun.awt.AppContext;65import sun.awt.PeerEvent;66import sun.awt.SunToolkit;67import sun.awt.dnd.SunDropTargetEvent;68import sun.java2d.pipe.Region;69import sun.security.action.GetBooleanAction;70import sun.util.logging.PlatformLogger;7172/**73* A generic Abstract Window Toolkit(AWT) container object is a component74* that can contain other AWT components.75* <p>76* Components added to a container are tracked in a list. The order77* of the list will define the components' front-to-back stacking order78* within the container. If no index is specified when adding a79* component to a container, it will be added to the end of the list80* (and hence to the bottom of the stacking order).81* <p>82* <b>Note</b>: For details on the focus subsystem, see83* <a href="https://docs.oracle.com/javase/tutorial/uiswing/misc/focus.html">84* How to Use the Focus Subsystem</a>,85* a section in <em>The Java Tutorial</em>, and the86* <a href="doc-files/FocusSpec.html">Focus Specification</a>87* for more information.88*89* @author Arthur van Hoff90* @author Sami Shaio91* @see #add(java.awt.Component, int)92* @see #getComponent(int)93* @see LayoutManager94* @since 1.095*/96public class Container extends Component {9798private static final PlatformLogger log = PlatformLogger.getLogger("java.awt.Container");99private static final PlatformLogger eventLog = PlatformLogger.getLogger("java.awt.event.Container");100101private static final Component[] EMPTY_ARRAY = new Component[0];102103/**104* The components in this container.105* @see #add106* @see #getComponents107*/108private java.util.List<Component> component = new ArrayList<>();109110/**111* Layout manager for this container.112* @see #doLayout113* @see #setLayout114* @see #getLayout115*/116LayoutManager layoutMgr;117118/**119* Event router for lightweight components. If this container120* is native, this dispatcher takes care of forwarding and121* retargeting the events to lightweight components contained122* (if any).123*/124private LightweightDispatcher dispatcher;125126/**127* The focus traversal policy that will manage keyboard traversal of this128* Container's children, if this Container is a focus cycle root. If the129* value is null, this Container inherits its policy from its focus-cycle-130* root ancestor. If all such ancestors of this Container have null131* policies, then the current KeyboardFocusManager's default policy is132* used. If the value is non-null, this policy will be inherited by all133* focus-cycle-root children that have no keyboard-traversal policy of134* their own (as will, recursively, their focus-cycle-root children).135* <p>136* If this Container is not a focus cycle root, the value will be137* remembered, but will not be used or inherited by this or any other138* Containers until this Container is made a focus cycle root.139*140* @see #setFocusTraversalPolicy141* @see #getFocusTraversalPolicy142* @since 1.4143*/144private transient FocusTraversalPolicy focusTraversalPolicy;145146/**147* Indicates whether this Component is the root of a focus traversal cycle.148* Once focus enters a traversal cycle, typically it cannot leave it via149* focus traversal unless one of the up- or down-cycle keys is pressed.150* Normal traversal is limited to this Container, and all of this151* Container's descendants that are not descendants of inferior focus cycle152* roots.153*154* @see #setFocusCycleRoot155* @see #isFocusCycleRoot156* @since 1.4157*/158private boolean focusCycleRoot = false;159160161/**162* Stores the value of focusTraversalPolicyProvider property.163* @since 1.5164* @see #setFocusTraversalPolicyProvider165*/166private boolean focusTraversalPolicyProvider;167168// keeps track of the threads that are printing this component169private transient Set<Thread> printingThreads;170// True if there is at least one thread that's printing this component171private transient boolean printing = false;172173transient ContainerListener containerListener;174175/* HierarchyListener and HierarchyBoundsListener support */176transient int listeningChildren;177transient int listeningBoundsChildren;178transient int descendantsCount;179180/* Non-opaque window support -- see Window.setLayersOpaque */181transient Color preserveBackgroundColor = null;182183/**184* Use serialVersionUID from JDK 1.1 for interoperability.185*/186@Serial187private static final long serialVersionUID = 4613797578919906343L;188189/**190* A constant which toggles one of the controllable behaviors191* of {@code getMouseEventTarget}. It is used to specify whether192* the method can return the Container on which it is originally called193* in case if none of its children are the current mouse event targets.194*195* @see #getMouseEventTarget(int, int, boolean)196*/197static final boolean INCLUDE_SELF = true;198199/**200* A constant which toggles one of the controllable behaviors201* of {@code getMouseEventTarget}. It is used to specify whether202* the method should search only lightweight components.203*204* @see #getMouseEventTarget(int, int, boolean)205*/206static final boolean SEARCH_HEAVYWEIGHTS = true;207208/*209* Number of HW or LW components in this container (including210* all descendant containers).211*/212private transient int numOfHWComponents = 0;213private transient int numOfLWComponents = 0;214215private static final PlatformLogger mixingLog = PlatformLogger.getLogger("java.awt.mixing.Container");216217/**218* @serialField ncomponents int219* The number of components in this container.220* This value can be null.221* @serialField component Component[]222* The components in this container.223* @serialField layoutMgr LayoutManager224* Layout manager for this container.225* @serialField dispatcher LightweightDispatcher226* Event router for lightweight components. If this container227* is native, this dispatcher takes care of forwarding and228* retargeting the events to lightweight components contained229* (if any).230* @serialField maxSize Dimension231* Maximum size of this Container.232* @serialField focusCycleRoot boolean233* Indicates whether this Component is the root of a focus traversal cycle.234* Once focus enters a traversal cycle, typically it cannot leave it via235* focus traversal unless one of the up- or down-cycle keys is pressed.236* Normal traversal is limited to this Container, and all of this237* Container's descendants that are not descendants of inferior focus cycle238* roots.239* @serialField containerSerializedDataVersion int240* Container Serial Data Version.241* @serialField focusTraversalPolicyProvider boolean242* Stores the value of focusTraversalPolicyProvider property.243*/244@Serial245private static final ObjectStreamField[] serialPersistentFields = {246new ObjectStreamField("ncomponents", Integer.TYPE),247new ObjectStreamField("component", Component[].class),248new ObjectStreamField("layoutMgr", LayoutManager.class),249new ObjectStreamField("dispatcher", LightweightDispatcher.class),250new ObjectStreamField("maxSize", Dimension.class),251new ObjectStreamField("focusCycleRoot", Boolean.TYPE),252new ObjectStreamField("containerSerializedDataVersion", Integer.TYPE),253new ObjectStreamField("focusTraversalPolicyProvider", Boolean.TYPE),254};255256static {257/* ensure that the necessary native libraries are loaded */258Toolkit.loadLibraries();259if (!GraphicsEnvironment.isHeadless()) {260initIDs();261}262263AWTAccessor.setContainerAccessor(new AWTAccessor.ContainerAccessor() {264@Override265public void validateUnconditionally(Container cont) {266cont.validateUnconditionally();267}268269@Override270public Component findComponentAt(Container cont, int x, int y,271boolean ignoreEnabled) {272return cont.findComponentAt(x, y, ignoreEnabled);273}274275@Override276public void startLWModal(Container cont) {277cont.startLWModal();278}279280@Override281public void stopLWModal(Container cont) {282cont.stopLWModal();283}284});285}286287/**288* Initialize JNI field and method IDs for fields that may be289called from C.290*/291private static native void initIDs();292293/**294* Constructs a new Container. Containers can be extended directly,295* but are lightweight in this case and must be contained by a parent296* somewhere higher up in the component tree that is native.297* (such as Frame for example).298*/299public Container() {300}301@SuppressWarnings({"unchecked","rawtypes"})302void initializeFocusTraversalKeys() {303focusTraversalKeys = new Set[4];304}305306/**307* Gets the number of components in this panel.308* <p>309* Note: This method should be called under AWT tree lock.310*311* @return the number of components in this panel.312* @see #getComponent313* @since 1.1314* @see Component#getTreeLock()315*/316public int getComponentCount() {317return countComponents();318}319320/**321* Returns the number of components in this container.322*323* @return the number of components in this container324* @deprecated As of JDK version 1.1,325* replaced by getComponentCount().326*/327@Deprecated328public int countComponents() {329// This method is not synchronized under AWT tree lock.330// Instead, the calling code is responsible for the331// synchronization. See 6784816 for details.332return component.size();333}334335/**336* Gets the nth component in this container.337* <p>338* Note: This method should be called under AWT tree lock.339*340* @param n the index of the component to get.341* @return the n<sup>th</sup> component in this container.342* @exception ArrayIndexOutOfBoundsException343* if the n<sup>th</sup> value does not exist.344* @see Component#getTreeLock()345*/346public Component getComponent(int n) {347// This method is not synchronized under AWT tree lock.348// Instead, the calling code is responsible for the349// synchronization. See 6784816 for details.350try {351return component.get(n);352} catch (IndexOutOfBoundsException z) {353throw new ArrayIndexOutOfBoundsException("No such child: " + n);354}355}356357/**358* Gets all the components in this container.359* <p>360* Note: This method should be called under AWT tree lock.361*362* @return an array of all the components in this container.363* @see Component#getTreeLock()364*/365public Component[] getComponents() {366// This method is not synchronized under AWT tree lock.367// Instead, the calling code is responsible for the368// synchronization. See 6784816 for details.369return getComponents_NoClientCode();370}371372// NOTE: This method may be called by privileged threads.373// This functionality is implemented in a package-private method374// to insure that it cannot be overridden by client subclasses.375// DO NOT INVOKE CLIENT CODE ON THIS THREAD!376final Component[] getComponents_NoClientCode() {377return component.toArray(EMPTY_ARRAY);378}379380/*381* Wrapper for getComponents() method with a proper synchronization.382*/383Component[] getComponentsSync() {384synchronized (getTreeLock()) {385return getComponents();386}387}388389/**390* Determines the insets of this container, which indicate the size391* of the container's border.392* <p>393* A {@code Frame} object, for example, has a top inset that394* corresponds to the height of the frame's title bar.395* @return the insets of this container.396* @see Insets397* @see LayoutManager398* @since 1.1399*/400public Insets getInsets() {401return insets();402}403404/**405* Returns the insets for this container.406*407* @deprecated As of JDK version 1.1,408* replaced by {@code getInsets()}.409* @return the insets for this container410*/411@Deprecated412public Insets insets() {413ComponentPeer peer = this.peer;414if (peer instanceof ContainerPeer) {415ContainerPeer cpeer = (ContainerPeer)peer;416return (Insets)cpeer.getInsets().clone();417}418return new Insets(0, 0, 0, 0);419}420421/**422* Appends the specified component to the end of this container.423* This is a convenience method for {@link #addImpl}.424* <p>425* This method changes layout-related information, and therefore,426* invalidates the component hierarchy. If the container has already been427* displayed, the hierarchy must be validated thereafter in order to428* display the added component.429*430* @param comp the component to be added431* @exception NullPointerException if {@code comp} is {@code null}432* @see #addImpl433* @see #invalidate434* @see #validate435* @see javax.swing.JComponent#revalidate()436* @return the component argument437*/438public Component add(Component comp) {439addImpl(comp, null, -1);440return comp;441}442443/**444* Adds the specified component to this container.445* This is a convenience method for {@link #addImpl}.446* <p>447* This method is obsolete as of 1.1. Please use the448* method {@code add(Component, Object)} instead.449* <p>450* This method changes layout-related information, and therefore,451* invalidates the component hierarchy. If the container has already been452* displayed, the hierarchy must be validated thereafter in order to453* display the added component.454*455* @param name the name of the component to be added456* @param comp the component to be added457* @return the component added458* @exception NullPointerException if {@code comp} is {@code null}459* @see #add(Component, Object)460* @see #invalidate461*/462public Component add(String name, Component comp) {463addImpl(comp, name, -1);464return comp;465}466467/**468* Adds the specified component to this container at the given469* position.470* This is a convenience method for {@link #addImpl}.471* <p>472* This method changes layout-related information, and therefore,473* invalidates the component hierarchy. If the container has already been474* displayed, the hierarchy must be validated thereafter in order to475* display the added component.476*477*478* @param comp the component to be added479* @param index the position at which to insert the component,480* or {@code -1} to append the component to the end481* @exception NullPointerException if {@code comp} is {@code null}482* @exception IllegalArgumentException if {@code index} is invalid (see483* {@link #addImpl} for details)484* @return the component {@code comp}485* @see #addImpl486* @see #remove487* @see #invalidate488* @see #validate489* @see javax.swing.JComponent#revalidate()490*/491public Component add(Component comp, int index) {492addImpl(comp, null, index);493return comp;494}495496/**497* Checks that the component498* isn't supposed to be added into itself.499*/500private void checkAddToSelf(Component comp){501if (comp instanceof Container) {502for (Container cn = this; cn != null; cn=cn.parent) {503if (cn == comp) {504throw new IllegalArgumentException("adding container's parent to itself");505}506}507}508}509510/**511* Checks that the component is not a Window instance.512*/513private void checkNotAWindow(Component comp){514if (comp instanceof Window) {515throw new IllegalArgumentException("adding a window to a container");516}517}518519/**520* Checks that the component comp can be added to this container521* Checks : index in bounds of container's size,522* comp is not one of this container's parents,523* and comp is not a window.524* Comp and container must be on the same GraphicsDevice.525* if comp is container, all sub-components must be on526* same GraphicsDevice.527*528* @since 1.5529*/530private void checkAdding(Component comp, int index) {531checkTreeLock();532533GraphicsConfiguration thisGC = getGraphicsConfiguration();534535if (index > component.size() || index < 0) {536throw new IllegalArgumentException("illegal component position");537}538if (comp.parent == this) {539if (index == component.size()) {540throw new IllegalArgumentException("illegal component position " +541index + " should be less than " + component.size());542}543}544checkAddToSelf(comp);545checkNotAWindow(comp);546547Window thisTopLevel = getContainingWindow();548Window compTopLevel = comp.getContainingWindow();549if (thisTopLevel != compTopLevel) {550throw new IllegalArgumentException("component and container should be in the same top-level window");551}552if (thisGC != null) {553comp.checkGD(thisGC.getDevice().getIDstring());554}555}556557/**558* Removes component comp from this container without making unnecessary changes559* and generating unnecessary events. This function intended to perform optimized560* remove, for example, if newParent and current parent are the same it just changes561* index without calling removeNotify.562* Note: Should be called while holding treeLock563* Returns whether removeNotify was invoked564* @since: 1.5565*/566private boolean removeDelicately(Component comp, Container newParent, int newIndex) {567checkTreeLock();568569int index = getComponentZOrder(comp);570boolean needRemoveNotify = isRemoveNotifyNeeded(comp, this, newParent);571if (needRemoveNotify) {572comp.removeNotify();573}574if (newParent != this) {575if (layoutMgr != null) {576layoutMgr.removeLayoutComponent(comp);577}578adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK,579-comp.numListening(AWTEvent.HIERARCHY_EVENT_MASK));580adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,581-comp.numListening(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));582adjustDescendants(-(comp.countHierarchyMembers()));583584comp.parent = null;585if (needRemoveNotify) {586comp.setGraphicsConfiguration(null);587}588component.remove(index);589590invalidateIfValid();591} else {592// We should remove component and then593// add it by the newIndex without newIndex decrement if even we shift components to the left594// after remove. Consult the rules below:595// 2->4: 012345 -> 013425, 2->5: 012345 -> 013452596// 4->2: 012345 -> 014235597component.remove(index);598component.add(newIndex, comp);599}600if (comp.parent == null) { // was actually removed601if (containerListener != null ||602(eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 ||603Toolkit.enabledOnToolkit(AWTEvent.CONTAINER_EVENT_MASK)) {604ContainerEvent e = new ContainerEvent(this,605ContainerEvent.COMPONENT_REMOVED,606comp);607dispatchEvent(e);608609}610comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, comp,611this, HierarchyEvent.PARENT_CHANGED,612Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK));613if (peer != null && layoutMgr == null && isVisible()) {614updateCursorImmediately();615}616}617return needRemoveNotify;618}619620/**621* Checks whether this container can contain component which is focus owner.622* Verifies that container is enable and showing, and if it is focus cycle root623* its FTP allows component to be focus owner624* @since 1.5625*/626boolean canContainFocusOwner(Component focusOwnerCandidate) {627if (!(isEnabled() && isDisplayable()628&& isVisible() && isFocusable()))629{630return false;631}632if (isFocusCycleRoot()) {633FocusTraversalPolicy policy = getFocusTraversalPolicy();634if (policy instanceof DefaultFocusTraversalPolicy) {635if (!((DefaultFocusTraversalPolicy)policy).accept(focusOwnerCandidate)) {636return false;637}638}639}640synchronized(getTreeLock()) {641if (parent != null) {642return parent.canContainFocusOwner(focusOwnerCandidate);643}644}645return true;646}647648/**649* Checks whether or not this container has heavyweight children.650* Note: Should be called while holding tree lock651* @return true if there is at least one heavyweight children in a container, false otherwise652* @since 1.5653*/654final boolean hasHeavyweightDescendants() {655checkTreeLock();656return numOfHWComponents > 0;657}658659/**660* Checks whether or not this container has lightweight children.661* Note: Should be called while holding tree lock662* @return true if there is at least one lightweight children in a container, false otherwise663* @since 1.7664*/665final boolean hasLightweightDescendants() {666checkTreeLock();667return numOfLWComponents > 0;668}669670/**671* Returns closest heavyweight component to this container. If this container is heavyweight672* returns this.673* @since 1.5674*/675Container getHeavyweightContainer() {676checkTreeLock();677if (peer != null && !(peer instanceof LightweightPeer)) {678return this;679} else {680return getNativeContainer();681}682}683684/**685* Detects whether or not remove from current parent and adding to new parent requires call of686* removeNotify on the component. Since removeNotify destroys native window this might (not)687* be required. For example, if new container and old containers are the same we don't need to688* destroy native window.689* @since: 1.5690*/691private static boolean isRemoveNotifyNeeded(Component comp, Container oldContainer, Container newContainer) {692if (oldContainer == null) { // Component didn't have parent - no removeNotify693return false;694}695if (comp.peer == null) { // Component didn't have peer - no removeNotify696return false;697}698if (newContainer.peer == null) {699// Component has peer but new Container doesn't - call removeNotify700return true;701}702703// If component is lightweight non-Container or lightweight Container with all but heavyweight704// children there is no need to call remove notify705if (comp.isLightweight()) {706boolean isContainer = comp instanceof Container;707708if (!isContainer || (isContainer && !((Container)comp).hasHeavyweightDescendants())) {709return false;710}711}712713// If this point is reached, then the comp is either a HW or a LW container with HW descendants.714715// All three components have peers, check for peer change716Container newNativeContainer = oldContainer.getHeavyweightContainer();717Container oldNativeContainer = newContainer.getHeavyweightContainer();718if (newNativeContainer != oldNativeContainer) {719// Native containers change - check whether or not current platform supports720// changing of widget hierarchy on native level without recreation.721// The current implementation forbids reparenting of LW containers with HW descendants722// into another native container w/o destroying the peers. Actually such an operation723// is quite rare. If we ever need to save the peers, we'll have to slightly change the724// addDelicately() method in order to handle such LW containers recursively, reparenting725// each HW descendant independently.726return !comp.peer.isReparentSupported();727} else {728return false;729}730}731732/**733* Moves the specified component to the specified z-order index in734* the container. The z-order determines the order that components735* are painted; the component with the highest z-order paints first736* and the component with the lowest z-order paints last.737* Where components overlap, the component with the lower738* z-order paints over the component with the higher z-order.739* <p>740* If the component is a child of some other container, it is741* removed from that container before being added to this container.742* The important difference between this method and743* {@code java.awt.Container.add(Component, int)} is that this method744* doesn't call {@code removeNotify} on the component while745* removing it from its previous container unless necessary and when746* allowed by the underlying native windowing system. This way, if the747* component has the keyboard focus, it maintains the focus when748* moved to the new position.749* <p>750* This property is guaranteed to apply only to lightweight751* non-{@code Container} components.752* <p>753* This method changes layout-related information, and therefore,754* invalidates the component hierarchy.755* <p>756* <b>Note</b>: Not all platforms support changing the z-order of757* heavyweight components from one container into another without758* the call to {@code removeNotify}. There is no way to detect759* whether a platform supports this, so developers shouldn't make760* any assumptions.761*762* @param comp the component to be moved763* @param index the position in the container's list to764* insert the component, where {@code getComponentCount()}765* appends to the end766* @exception NullPointerException if {@code comp} is767* {@code null}768* @exception IllegalArgumentException if {@code comp} is one of the769* container's parents770* @exception IllegalArgumentException if {@code index} is not in771* the range {@code [0, getComponentCount()]} for moving772* between containers, or not in the range773* {@code [0, getComponentCount()-1]} for moving inside774* a container775* @exception IllegalArgumentException if adding a container to itself776* @exception IllegalArgumentException if adding a {@code Window}777* to a container778* @see #getComponentZOrder(java.awt.Component)779* @see #invalidate780* @since 1.5781*/782public void setComponentZOrder(Component comp, int index) {783synchronized (getTreeLock()) {784// Store parent because remove will clear it785Container curParent = comp.parent;786int oldZindex = getComponentZOrder(comp);787788if (curParent == this && index == oldZindex) {789return;790}791checkAdding(comp, index);792793boolean peerRecreated = (curParent != null) ?794curParent.removeDelicately(comp, this, index) : false;795796addDelicately(comp, curParent, index);797798// If the oldZindex == -1, the component gets inserted,799// rather than it changes its z-order.800if (!peerRecreated && oldZindex != -1) {801// The new 'index' cannot be == -1.802// It gets checked at the checkAdding() method.803// Therefore both oldZIndex and index denote804// some existing positions at this point and805// this is actually a Z-order changing.806comp.mixOnZOrderChanging(oldZindex, index);807}808}809}810811/**812* Traverses the tree of components and reparents children heavyweight component813* to new heavyweight parent.814* @since 1.5815*/816@SuppressWarnings("deprecation")817private void reparentTraverse(ContainerPeer parentPeer, Container child) {818checkTreeLock();819820for (int i = 0; i < child.getComponentCount(); i++) {821Component comp = child.getComponent(i);822if (comp.isLightweight()) {823// If components is lightweight check if it is container824// If it is container it might contain heavyweight children we need to reparent825if (comp instanceof Container) {826reparentTraverse(parentPeer, (Container)comp);827}828} else {829// Q: Need to update NativeInLightFixer?830comp.peer.reparent(parentPeer);831}832}833}834835/**836* Reparents child component peer to this container peer.837* Container must be heavyweight.838* @since 1.5839*/840@SuppressWarnings("deprecation")841private void reparentChild(Component comp) {842checkTreeLock();843if (comp == null) {844return;845}846if (comp.isLightweight()) {847// If component is lightweight container we need to reparent all its explicit heavyweight children848if (comp instanceof Container) {849// Traverse component's tree till depth-first until encountering heavyweight component850reparentTraverse((ContainerPeer)peer, (Container)comp);851}852} else {853comp.peer.reparent((ContainerPeer) peer);854}855}856857/**858* Adds component to this container. Tries to minimize side effects of this adding -859* doesn't call remove notify if it is not required.860* @since 1.5861*/862private void addDelicately(Component comp, Container curParent, int index) {863checkTreeLock();864865// Check if moving between containers866if (curParent != this) {867//index == -1 means add to the end.868if (index == -1) {869component.add(comp);870} else {871component.add(index, comp);872}873comp.parent = this;874comp.setGraphicsConfiguration(getGraphicsConfiguration());875876adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK,877comp.numListening(AWTEvent.HIERARCHY_EVENT_MASK));878adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,879comp.numListening(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));880adjustDescendants(comp.countHierarchyMembers());881} else {882if (index < component.size()) {883component.set(index, comp);884}885}886887invalidateIfValid();888if (peer != null) {889if (comp.peer == null) { // Remove notify was called or it didn't have peer - create new one890comp.addNotify();891} else { // Both container and child have peers, it means child peer should be reparented.892// In both cases we need to reparent native widgets.893Container newNativeContainer = getHeavyweightContainer();894Container oldNativeContainer = curParent.getHeavyweightContainer();895if (oldNativeContainer != newNativeContainer) {896// Native container changed - need to reparent native widgets897newNativeContainer.reparentChild(comp);898}899comp.updateZOrder();900901if (!comp.isLightweight() && isLightweight()) {902// If component is heavyweight and one of the containers is lightweight903// the location of the component should be fixed.904comp.relocateComponent();905}906}907}908if (curParent != this) {909/* Notify the layout manager of the added component. */910if (layoutMgr != null) {911if (layoutMgr instanceof LayoutManager2) {912((LayoutManager2)layoutMgr).addLayoutComponent(comp, null);913} else {914layoutMgr.addLayoutComponent(null, comp);915}916}917if (containerListener != null ||918(eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 ||919Toolkit.enabledOnToolkit(AWTEvent.CONTAINER_EVENT_MASK)) {920ContainerEvent e = new ContainerEvent(this,921ContainerEvent.COMPONENT_ADDED,922comp);923dispatchEvent(e);924}925comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, comp,926this, HierarchyEvent.PARENT_CHANGED,927Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK));928929// If component is focus owner or parent container of focus owner check that after reparenting930// focus owner moved out if new container prohibit this kind of focus owner.931if (comp.isFocusOwner() && !comp.canBeFocusOwnerRecursively()) {932comp.transferFocus();933} else if (comp instanceof Container) {934Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();935if (focusOwner != null && isParentOf(focusOwner) && !focusOwner.canBeFocusOwnerRecursively()) {936focusOwner.transferFocus();937}938}939} else {940comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, comp,941this, HierarchyEvent.HIERARCHY_CHANGED,942Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK));943}944945if (peer != null && layoutMgr == null && isVisible()) {946updateCursorImmediately();947}948}949950/**951* Returns the z-order index of the component inside the container.952* The higher a component is in the z-order hierarchy, the lower953* its index. The component with the lowest z-order index is954* painted last, above all other child components.955*956* @param comp the component being queried957* @return the z-order index of the component; otherwise958* returns -1 if the component is {@code null}959* or doesn't belong to the container960* @see #setComponentZOrder(java.awt.Component, int)961* @since 1.5962*/963public int getComponentZOrder(Component comp) {964if (comp == null) {965return -1;966}967synchronized(getTreeLock()) {968// Quick check - container should be immediate parent of the component969if (comp.parent != this) {970return -1;971}972return component.indexOf(comp);973}974}975976/**977* Adds the specified component to the end of this container.978* Also notifies the layout manager to add the component to979* this container's layout using the specified constraints object.980* This is a convenience method for {@link #addImpl}.981* <p>982* This method changes layout-related information, and therefore,983* invalidates the component hierarchy. If the container has already been984* displayed, the hierarchy must be validated thereafter in order to985* display the added component.986*987*988* @param comp the component to be added989* @param constraints an object expressing990* layout constraints for this component991* @exception NullPointerException if {@code comp} is {@code null}992* @see #addImpl993* @see #invalidate994* @see #validate995* @see javax.swing.JComponent#revalidate()996* @see LayoutManager997* @since 1.1998*/999public void add(Component comp, Object constraints) {1000addImpl(comp, constraints, -1);1001}10021003/**1004* Adds the specified component to this container with the specified1005* constraints at the specified index. Also notifies the layout1006* manager to add the component to the this container's layout using1007* the specified constraints object.1008* This is a convenience method for {@link #addImpl}.1009* <p>1010* This method changes layout-related information, and therefore,1011* invalidates the component hierarchy. If the container has already been1012* displayed, the hierarchy must be validated thereafter in order to1013* display the added component.1014*1015*1016* @param comp the component to be added1017* @param constraints an object expressing layout constraints for this1018* @param index the position in the container's list at which to insert1019* the component; {@code -1} means insert at the end1020* component1021* @exception NullPointerException if {@code comp} is {@code null}1022* @exception IllegalArgumentException if {@code index} is invalid (see1023* {@link #addImpl} for details)1024* @see #addImpl1025* @see #invalidate1026* @see #validate1027* @see javax.swing.JComponent#revalidate()1028* @see #remove1029* @see LayoutManager1030*/1031public void add(Component comp, Object constraints, int index) {1032addImpl(comp, constraints, index);1033}10341035/**1036* Adds the specified component to this container at the specified1037* index. This method also notifies the layout manager to add1038* the component to this container's layout using the specified1039* constraints object via the {@code addLayoutComponent}1040* method.1041* <p>1042* The constraints are1043* defined by the particular layout manager being used. For1044* example, the {@code BorderLayout} class defines five1045* constraints: {@code BorderLayout.NORTH},1046* {@code BorderLayout.SOUTH}, {@code BorderLayout.EAST},1047* {@code BorderLayout.WEST}, and {@code BorderLayout.CENTER}.1048* <p>1049* The {@code GridBagLayout} class requires a1050* {@code GridBagConstraints} object. Failure to pass1051* the correct type of constraints object results in an1052* {@code IllegalArgumentException}.1053* <p>1054* If the current layout manager implements {@code LayoutManager2}, then1055* {@link LayoutManager2#addLayoutComponent(Component,Object)} is invoked on1056* it. If the current layout manager does not implement1057* {@code LayoutManager2}, and constraints is a {@code String}, then1058* {@link LayoutManager#addLayoutComponent(String,Component)} is invoked on it.1059* <p>1060* If the component is not an ancestor of this container and has a non-null1061* parent, it is removed from its current parent before it is added to this1062* container.1063* <p>1064* This is the method to override if a program needs to track1065* every add request to a container as all other add methods defer1066* to this one. An overriding method should1067* usually include a call to the superclass's version of the method:1068*1069* <blockquote>1070* {@code super.addImpl(comp, constraints, index)}1071* </blockquote>1072* <p>1073* This method changes layout-related information, and therefore,1074* invalidates the component hierarchy. If the container has already been1075* displayed, the hierarchy must be validated thereafter in order to1076* display the added component.1077*1078* @param comp the component to be added1079* @param constraints an object expressing layout constraints1080* for this component1081* @param index the position in the container's list at which to1082* insert the component, where {@code -1}1083* means append to the end1084* @exception IllegalArgumentException if {@code index} is invalid;1085* if {@code comp} is a child of this container, the valid1086* range is {@code [-1, getComponentCount()-1]}; if component is1087* not a child of this container, the valid range is1088* {@code [-1, getComponentCount()]}1089*1090* @exception IllegalArgumentException if {@code comp} is an ancestor of1091* this container1092* @exception IllegalArgumentException if adding a window to a container1093* @exception NullPointerException if {@code comp} is {@code null}1094* @see #add(Component)1095* @see #add(Component, int)1096* @see #add(Component, java.lang.Object)1097* @see #invalidate1098* @see LayoutManager1099* @see LayoutManager21100* @since 1.11101*/1102protected void addImpl(Component comp, Object constraints, int index) {1103synchronized (getTreeLock()) {1104/* Check for correct arguments: index in bounds,1105* comp cannot be one of this container's parents,1106* and comp cannot be a window.1107* comp and container must be on the same GraphicsDevice.1108* if comp is container, all sub-components must be on1109* same GraphicsDevice.1110*/1111GraphicsConfiguration thisGC = this.getGraphicsConfiguration();11121113if (index > component.size() || (index < 0 && index != -1)) {1114throw new IllegalArgumentException(1115"illegal component position");1116}1117checkAddToSelf(comp);1118checkNotAWindow(comp);1119/* Reparent the component and tidy up the tree's state. */1120if (comp.parent != null) {1121comp.parent.remove(comp);1122if (index > component.size()) {1123throw new IllegalArgumentException("illegal component position");1124}1125}1126if (thisGC != null) {1127comp.checkGD(thisGC.getDevice().getIDstring());1128}1129113011311132//index == -1 means add to the end.1133if (index == -1) {1134component.add(comp);1135} else {1136component.add(index, comp);1137}1138comp.parent = this;1139comp.setGraphicsConfiguration(thisGC);11401141adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK,1142comp.numListening(AWTEvent.HIERARCHY_EVENT_MASK));1143adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,1144comp.numListening(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));1145adjustDescendants(comp.countHierarchyMembers());11461147invalidateIfValid();1148if (peer != null) {1149comp.addNotify();1150}11511152/* Notify the layout manager of the added component. */1153if (layoutMgr != null) {1154if (layoutMgr instanceof LayoutManager2) {1155((LayoutManager2)layoutMgr).addLayoutComponent(comp, constraints);1156} else if (constraints instanceof String) {1157layoutMgr.addLayoutComponent((String)constraints, comp);1158}1159}1160if (containerListener != null ||1161(eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 ||1162Toolkit.enabledOnToolkit(AWTEvent.CONTAINER_EVENT_MASK)) {1163ContainerEvent e = new ContainerEvent(this,1164ContainerEvent.COMPONENT_ADDED,1165comp);1166dispatchEvent(e);1167}11681169comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, comp,1170this, HierarchyEvent.PARENT_CHANGED,1171Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK));1172if (peer != null && layoutMgr == null && isVisible()) {1173updateCursorImmediately();1174}1175}1176}11771178@Override1179final boolean updateChildGraphicsData(GraphicsConfiguration gc) {1180checkTreeLock();11811182boolean ret = false;11831184for (Component comp : component) {1185if (comp != null) {1186ret |= comp.updateGraphicsData(gc);1187}1188}1189return ret;1190}11911192/**1193* Checks that all Components that this Container contains are on1194* the same GraphicsDevice as this Container. If not, throws an1195* IllegalArgumentException.1196*/1197void checkGD(String stringID) {1198for (Component comp : component) {1199if (comp != null) {1200comp.checkGD(stringID);1201}1202}1203}12041205/**1206* Removes the component, specified by {@code index},1207* from this container.1208* This method also notifies the layout manager to remove the1209* component from this container's layout via the1210* {@code removeLayoutComponent} method.1211* <p>1212* This method changes layout-related information, and therefore,1213* invalidates the component hierarchy. If the container has already been1214* displayed, the hierarchy must be validated thereafter in order to1215* reflect the changes.1216*1217*1218* @param index the index of the component to be removed1219* @throws ArrayIndexOutOfBoundsException if {@code index} is not in1220* range {@code [0, getComponentCount()-1]}1221* @see #add1222* @see #invalidate1223* @see #validate1224* @see #getComponentCount1225* @since 1.11226*/1227public void remove(int index) {1228synchronized (getTreeLock()) {1229if (index < 0 || index >= component.size()) {1230throw new ArrayIndexOutOfBoundsException(index);1231}1232Component comp = component.get(index);1233if (peer != null) {1234comp.removeNotify();1235}1236if (layoutMgr != null) {1237layoutMgr.removeLayoutComponent(comp);1238}12391240adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK,1241-comp.numListening(AWTEvent.HIERARCHY_EVENT_MASK));1242adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,1243-comp.numListening(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));1244adjustDescendants(-(comp.countHierarchyMembers()));12451246comp.parent = null;1247component.remove(index);1248comp.setGraphicsConfiguration(null);12491250invalidateIfValid();1251if (containerListener != null ||1252(eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 ||1253Toolkit.enabledOnToolkit(AWTEvent.CONTAINER_EVENT_MASK)) {1254ContainerEvent e = new ContainerEvent(this,1255ContainerEvent.COMPONENT_REMOVED,1256comp);1257dispatchEvent(e);1258}12591260comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, comp,1261this, HierarchyEvent.PARENT_CHANGED,1262Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK));1263if (peer != null && layoutMgr == null && isVisible()) {1264updateCursorImmediately();1265}1266}1267}12681269/**1270* Removes the specified component from this container.1271* This method also notifies the layout manager to remove the1272* component from this container's layout via the1273* {@code removeLayoutComponent} method.1274* <p>1275* This method changes layout-related information, and therefore,1276* invalidates the component hierarchy. If the container has already been1277* displayed, the hierarchy must be validated thereafter in order to1278* reflect the changes.1279*1280* @param comp the component to be removed1281* @throws NullPointerException if {@code comp} is {@code null}1282* @see #add1283* @see #invalidate1284* @see #validate1285* @see #remove(int)1286*/1287public void remove(Component comp) {1288synchronized (getTreeLock()) {1289if (comp.parent == this) {1290int index = component.indexOf(comp);1291if (index >= 0) {1292remove(index);1293}1294}1295}1296}12971298/**1299* Removes all the components from this container.1300* This method also notifies the layout manager to remove the1301* components from this container's layout via the1302* {@code removeLayoutComponent} method.1303* <p>1304* This method changes layout-related information, and therefore,1305* invalidates the component hierarchy. If the container has already been1306* displayed, the hierarchy must be validated thereafter in order to1307* reflect the changes.1308*1309* @see #add1310* @see #remove1311* @see #invalidate1312*/1313public void removeAll() {1314synchronized (getTreeLock()) {1315adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK,1316-listeningChildren);1317adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,1318-listeningBoundsChildren);1319adjustDescendants(-descendantsCount);13201321while (!component.isEmpty()) {1322Component comp = component.remove(component.size()-1);13231324if (peer != null) {1325comp.removeNotify();1326}1327if (layoutMgr != null) {1328layoutMgr.removeLayoutComponent(comp);1329}1330comp.parent = null;1331comp.setGraphicsConfiguration(null);1332if (containerListener != null ||1333(eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 ||1334Toolkit.enabledOnToolkit(AWTEvent.CONTAINER_EVENT_MASK)) {1335ContainerEvent e = new ContainerEvent(this,1336ContainerEvent.COMPONENT_REMOVED,1337comp);1338dispatchEvent(e);1339}13401341comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED,1342comp, this,1343HierarchyEvent.PARENT_CHANGED,1344Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK));1345}1346if (peer != null && layoutMgr == null && isVisible()) {1347updateCursorImmediately();1348}1349invalidateIfValid();1350}1351}13521353// Should only be called while holding tree lock1354int numListening(long mask) {1355int superListening = super.numListening(mask);13561357if (mask == AWTEvent.HIERARCHY_EVENT_MASK) {1358if (eventLog.isLoggable(PlatformLogger.Level.FINE)) {1359// Verify listeningChildren is correct1360int sum = 0;1361for (Component comp : component) {1362sum += comp.numListening(mask);1363}1364if (listeningChildren != sum) {1365eventLog.fine("Assertion (listeningChildren == sum) failed");1366}1367}1368return listeningChildren + superListening;1369} else if (mask == AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) {1370if (eventLog.isLoggable(PlatformLogger.Level.FINE)) {1371// Verify listeningBoundsChildren is correct1372int sum = 0;1373for (Component comp : component) {1374sum += comp.numListening(mask);1375}1376if (listeningBoundsChildren != sum) {1377eventLog.fine("Assertion (listeningBoundsChildren == sum) failed");1378}1379}1380return listeningBoundsChildren + superListening;1381} else {1382// assert false;1383if (eventLog.isLoggable(PlatformLogger.Level.FINE)) {1384eventLog.fine("This code must never be reached");1385}1386return superListening;1387}1388}13891390// Should only be called while holding tree lock1391void adjustListeningChildren(long mask, int num) {1392if (eventLog.isLoggable(PlatformLogger.Level.FINE)) {1393boolean toAssert = (mask == AWTEvent.HIERARCHY_EVENT_MASK ||1394mask == AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK ||1395mask == (AWTEvent.HIERARCHY_EVENT_MASK |1396AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));1397if (!toAssert) {1398eventLog.fine("Assertion failed");1399}1400}14011402if (num == 0)1403return;14041405if ((mask & AWTEvent.HIERARCHY_EVENT_MASK) != 0) {1406listeningChildren += num;1407}1408if ((mask & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) != 0) {1409listeningBoundsChildren += num;1410}14111412adjustListeningChildrenOnParent(mask, num);1413}14141415// Should only be called while holding tree lock1416void adjustDescendants(int num) {1417if (num == 0)1418return;14191420descendantsCount += num;1421adjustDescendantsOnParent(num);1422}14231424// Should only be called while holding tree lock1425void adjustDescendantsOnParent(int num) {1426if (parent != null) {1427parent.adjustDescendants(num);1428}1429}14301431// Should only be called while holding tree lock1432int countHierarchyMembers() {1433if (log.isLoggable(PlatformLogger.Level.FINE)) {1434// Verify descendantsCount is correct1435int sum = 0;1436for (Component comp : component) {1437sum += comp.countHierarchyMembers();1438}1439if (descendantsCount != sum) {1440log.fine("Assertion (descendantsCount == sum) failed");1441}1442}1443return descendantsCount + 1;1444}14451446private int getListenersCount(int id, boolean enabledOnToolkit) {1447checkTreeLock();1448if (enabledOnToolkit) {1449return descendantsCount;1450}1451switch (id) {1452case HierarchyEvent.HIERARCHY_CHANGED:1453return listeningChildren;1454case HierarchyEvent.ANCESTOR_MOVED:1455case HierarchyEvent.ANCESTOR_RESIZED:1456return listeningBoundsChildren;1457default:1458return 0;1459}1460}14611462final int createHierarchyEvents(int id, Component changed,1463Container changedParent, long changeFlags, boolean enabledOnToolkit)1464{1465checkTreeLock();1466int listeners = getListenersCount(id, enabledOnToolkit);14671468for (int count = listeners, i = 0; count > 0; i++) {1469count -= component.get(i).createHierarchyEvents(id, changed,1470changedParent, changeFlags, enabledOnToolkit);1471}1472return listeners +1473super.createHierarchyEvents(id, changed, changedParent,1474changeFlags, enabledOnToolkit);1475}14761477final void createChildHierarchyEvents(int id, long changeFlags,1478boolean enabledOnToolkit)1479{1480checkTreeLock();1481if (component.isEmpty()) {1482return;1483}1484int listeners = getListenersCount(id, enabledOnToolkit);14851486for (int count = listeners, i = 0; count > 0; i++) {1487count -= component.get(i).createHierarchyEvents(id, this, parent,1488changeFlags, enabledOnToolkit);1489}1490}14911492/**1493* Gets the layout manager for this container.1494*1495* @see #doLayout1496* @see #setLayout1497* @return the current layout manager for this container1498*/1499public LayoutManager getLayout() {1500return layoutMgr;1501}15021503/**1504* Sets the layout manager for this container.1505* <p>1506* This method changes layout-related information, and therefore,1507* invalidates the component hierarchy.1508*1509* @param mgr the specified layout manager1510* @see #doLayout1511* @see #getLayout1512* @see #invalidate1513*/1514public void setLayout(LayoutManager mgr) {1515layoutMgr = mgr;1516invalidateIfValid();1517}15181519/**1520* Causes this container to lay out its components. Most programs1521* should not call this method directly, but should invoke1522* the {@code validate} method instead.1523* @see LayoutManager#layoutContainer1524* @see #setLayout1525* @see #validate1526* @since 1.11527*/1528public void doLayout() {1529layout();1530}15311532/**1533* @deprecated As of JDK version 1.1,1534* replaced by {@code doLayout()}.1535*/1536@Deprecated1537public void layout() {1538LayoutManager layoutMgr = this.layoutMgr;1539if (layoutMgr != null) {1540layoutMgr.layoutContainer(this);1541}1542}15431544/**1545* Indicates if this container is a <i>validate root</i>.1546* <p>1547* Layout-related changes, such as bounds of the validate root descendants,1548* do not affect the layout of the validate root parent. This peculiarity1549* enables the {@code invalidate()} method to stop invalidating the1550* component hierarchy when the method encounters a validate root. However,1551* to preserve backward compatibility this new optimized behavior is1552* enabled only when the {@code java.awt.smartInvalidate} system property1553* value is set to {@code true}.1554* <p>1555* If a component hierarchy contains validate roots and the new optimized1556* {@code invalidate()} behavior is enabled, the {@code validate()} method1557* must be invoked on the validate root of a previously invalidated1558* component to restore the validity of the hierarchy later. Otherwise,1559* calling the {@code validate()} method on the top-level container (such1560* as a {@code Frame} object) should be used to restore the validity of the1561* component hierarchy.1562* <p>1563* The {@code Window} class and the {@code Applet} class are the validate1564* roots in AWT. Swing introduces more validate roots.1565*1566* @return whether this container is a validate root1567* @see #invalidate1568* @see java.awt.Component#invalidate1569* @see javax.swing.JComponent#isValidateRoot1570* @see javax.swing.JComponent#revalidate1571* @since 1.71572*/1573public boolean isValidateRoot() {1574return false;1575}15761577// Don't lazy-read because every app uses invalidate()1578@SuppressWarnings("removal")1579private static final boolean isJavaAwtSmartInvalidate1580= AccessController.doPrivileged(1581new GetBooleanAction("java.awt.smartInvalidate"));15821583/**1584* Invalidates the parent of the container unless the container1585* is a validate root.1586*/1587@Override1588void invalidateParent() {1589if (!isJavaAwtSmartInvalidate || !isValidateRoot()) {1590super.invalidateParent();1591}1592}15931594/**1595* Invalidates the container.1596* <p>1597* If the {@code LayoutManager} installed on this container is an instance1598* of the {@code LayoutManager2} interface, then1599* the {@link LayoutManager2#invalidateLayout(Container)} method is invoked1600* on it supplying this {@code Container} as the argument.1601* <p>1602* Afterwards this method marks this container invalid, and invalidates its1603* ancestors. See the {@link Component#invalidate} method for more details.1604*1605* @see #validate1606* @see #layout1607* @see LayoutManager21608*/1609@Override1610public void invalidate() {1611LayoutManager layoutMgr = this.layoutMgr;1612if (layoutMgr instanceof LayoutManager2) {1613LayoutManager2 lm = (LayoutManager2) layoutMgr;1614lm.invalidateLayout(this);1615}1616super.invalidate();1617}16181619/**1620* Validates this container and all of its subcomponents.1621* <p>1622* Validating a container means laying out its subcomponents.1623* Layout-related changes, such as setting the bounds of a component, or1624* adding a component to the container, invalidate the container1625* automatically. Note that the ancestors of the container may be1626* invalidated also (see {@link Component#invalidate} for details.)1627* Therefore, to restore the validity of the hierarchy, the {@code1628* validate()} method should be invoked on the top-most invalid1629* container of the hierarchy.1630* <p>1631* Validating the container may be a quite time-consuming operation. For1632* performance reasons a developer may postpone the validation of the1633* hierarchy till a set of layout-related operations completes, e.g. after1634* adding all the children to the container.1635* <p>1636* If this {@code Container} is not valid, this method invokes1637* the {@code validateTree} method and marks this {@code Container}1638* as valid. Otherwise, no action is performed.1639*1640* @see #add(java.awt.Component)1641* @see #invalidate1642* @see Container#isValidateRoot1643* @see javax.swing.JComponent#revalidate()1644* @see #validateTree1645*/1646public void validate() {1647boolean updateCur = false;1648synchronized (getTreeLock()) {1649if ((!isValid() || descendUnconditionallyWhenValidating)1650&& peer != null)1651{1652ContainerPeer p = null;1653if (peer instanceof ContainerPeer) {1654p = (ContainerPeer) peer;1655}1656if (p != null) {1657p.beginValidate();1658}1659validateTree();1660if (p != null) {1661p.endValidate();1662// Avoid updating cursor if this is an internal call.1663// See validateUnconditionally() for details.1664if (!descendUnconditionallyWhenValidating) {1665updateCur = isVisible();1666}1667}1668}1669}1670if (updateCur) {1671updateCursorImmediately();1672}1673}16741675/**1676* Indicates whether valid containers should also traverse their1677* children and call the validateTree() method on them.1678*1679* Synchronization: TreeLock.1680*1681* The field is allowed to be static as long as the TreeLock itself is1682* static.1683*1684* @see #validateUnconditionally()1685*/1686private static boolean descendUnconditionallyWhenValidating = false;16871688/**1689* Unconditionally validate the component hierarchy.1690*/1691final void validateUnconditionally() {1692boolean updateCur = false;1693synchronized (getTreeLock()) {1694descendUnconditionallyWhenValidating = true;16951696validate();1697if (peer instanceof ContainerPeer) {1698updateCur = isVisible();1699}17001701descendUnconditionallyWhenValidating = false;1702}1703if (updateCur) {1704updateCursorImmediately();1705}1706}17071708/**1709* Recursively descends the container tree and recomputes the1710* layout for any subtrees marked as needing it (those marked as1711* invalid). Synchronization should be provided by the method1712* that calls this one: {@code validate}.1713*1714* @see #doLayout1715* @see #validate1716*/1717protected void validateTree() {1718checkTreeLock();1719if (!isValid() || descendUnconditionallyWhenValidating) {1720if (peer instanceof ContainerPeer) {1721((ContainerPeer)peer).beginLayout();1722}1723if (!isValid()) {1724doLayout();1725}1726for (int i = 0; i < component.size(); i++) {1727Component comp = component.get(i);1728if ( (comp instanceof Container)1729&& !(comp instanceof Window)1730&& (!comp.isValid() ||1731descendUnconditionallyWhenValidating))1732{1733((Container)comp).validateTree();1734} else {1735comp.validate();1736}1737}1738if (peer instanceof ContainerPeer) {1739((ContainerPeer)peer).endLayout();1740}1741}1742super.validate();1743}17441745/**1746* Recursively descends the container tree and invalidates all1747* contained components.1748*/1749void invalidateTree() {1750synchronized (getTreeLock()) {1751for (int i = 0; i < component.size(); i++) {1752Component comp = component.get(i);1753if (comp instanceof Container) {1754((Container)comp).invalidateTree();1755}1756else {1757comp.invalidateIfValid();1758}1759}1760invalidateIfValid();1761}1762}17631764/**1765* Sets the font of this container.1766* <p>1767* This method changes layout-related information, and therefore,1768* invalidates the component hierarchy.1769*1770* @param f The font to become this container's font.1771* @see Component#getFont1772* @see #invalidate1773* @since 1.01774*/1775public void setFont(Font f) {1776boolean shouldinvalidate = false;17771778Font oldfont = getFont();1779super.setFont(f);1780Font newfont = getFont();1781if (newfont != oldfont && (oldfont == null ||1782!oldfont.equals(newfont))) {1783invalidateTree();1784}1785}17861787/**1788* Returns the preferred size of this container. If the preferred size has1789* not been set explicitly by {@link Component#setPreferredSize(Dimension)}1790* and this {@code Container} has a {@code non-null} {@link LayoutManager},1791* then {@link LayoutManager#preferredLayoutSize(Container)}1792* is used to calculate the preferred size.1793*1794* <p>Note: some implementations may cache the value returned from the1795* {@code LayoutManager}. Implementations that cache need not invoke1796* {@code preferredLayoutSize} on the {@code LayoutManager} every time1797* this method is invoked, rather the {@code LayoutManager} will only1798* be queried after the {@code Container} becomes invalid.1799*1800* @return an instance of {@code Dimension} that represents1801* the preferred size of this container.1802* @see #getMinimumSize1803* @see #getMaximumSize1804* @see #getLayout1805* @see LayoutManager#preferredLayoutSize(Container)1806* @see Component#getPreferredSize1807*/1808public Dimension getPreferredSize() {1809return preferredSize();1810}18111812/**1813* @deprecated As of JDK version 1.1,1814* replaced by {@code getPreferredSize()}.1815*/1816@Deprecated1817public Dimension preferredSize() {1818/* Avoid grabbing the lock if a reasonable cached size value1819* is available.1820*/1821Dimension dim = prefSize;1822if (dim == null || !(isPreferredSizeSet() || isValid())) {1823synchronized (getTreeLock()) {1824prefSize = (layoutMgr != null) ?1825layoutMgr.preferredLayoutSize(this) :1826super.preferredSize();1827dim = prefSize;1828}1829}1830if (dim != null){1831return new Dimension(dim);1832}1833else{1834return dim;1835}1836}18371838/**1839* Returns the minimum size of this container. If the minimum size has1840* not been set explicitly by {@link Component#setMinimumSize(Dimension)}1841* and this {@code Container} has a {@code non-null} {@link LayoutManager},1842* then {@link LayoutManager#minimumLayoutSize(Container)}1843* is used to calculate the minimum size.1844*1845* <p>Note: some implementations may cache the value returned from the1846* {@code LayoutManager}. Implementations that cache need not invoke1847* {@code minimumLayoutSize} on the {@code LayoutManager} every time1848* this method is invoked, rather the {@code LayoutManager} will only1849* be queried after the {@code Container} becomes invalid.1850*1851* @return an instance of {@code Dimension} that represents1852* the minimum size of this container.1853* @see #getPreferredSize1854* @see #getMaximumSize1855* @see #getLayout1856* @see LayoutManager#minimumLayoutSize(Container)1857* @see Component#getMinimumSize1858* @since 1.11859*/1860public Dimension getMinimumSize() {1861return minimumSize();1862}18631864/**1865* @deprecated As of JDK version 1.1,1866* replaced by {@code getMinimumSize()}.1867*/1868@Deprecated1869public Dimension minimumSize() {1870/* Avoid grabbing the lock if a reasonable cached size value1871* is available.1872*/1873Dimension dim = minSize;1874if (dim == null || !(isMinimumSizeSet() || isValid())) {1875synchronized (getTreeLock()) {1876minSize = (layoutMgr != null) ?1877layoutMgr.minimumLayoutSize(this) :1878super.minimumSize();1879dim = minSize;1880}1881}1882if (dim != null){1883return new Dimension(dim);1884}1885else{1886return dim;1887}1888}18891890/**1891* Returns the maximum size of this container. If the maximum size has1892* not been set explicitly by {@link Component#setMaximumSize(Dimension)}1893* and the {@link LayoutManager} installed on this {@code Container}1894* is an instance of {@link LayoutManager2}, then1895* {@link LayoutManager2#maximumLayoutSize(Container)}1896* is used to calculate the maximum size.1897*1898* <p>Note: some implementations may cache the value returned from the1899* {@code LayoutManager2}. Implementations that cache need not invoke1900* {@code maximumLayoutSize} on the {@code LayoutManager2} every time1901* this method is invoked, rather the {@code LayoutManager2} will only1902* be queried after the {@code Container} becomes invalid.1903*1904* @return an instance of {@code Dimension} that represents1905* the maximum size of this container.1906* @see #getPreferredSize1907* @see #getMinimumSize1908* @see #getLayout1909* @see LayoutManager2#maximumLayoutSize(Container)1910* @see Component#getMaximumSize1911*/1912public Dimension getMaximumSize() {1913/* Avoid grabbing the lock if a reasonable cached size value1914* is available.1915*/1916Dimension dim = maxSize;1917if (dim == null || !(isMaximumSizeSet() || isValid())) {1918synchronized (getTreeLock()) {1919if (layoutMgr instanceof LayoutManager2) {1920LayoutManager2 lm = (LayoutManager2) layoutMgr;1921maxSize = lm.maximumLayoutSize(this);1922} else {1923maxSize = super.getMaximumSize();1924}1925dim = maxSize;1926}1927}1928if (dim != null){1929return new Dimension(dim);1930}1931else{1932return dim;1933}1934}19351936/**1937* Returns the alignment along the x axis. This specifies how1938* the component would like to be aligned relative to other1939* components. The value should be a number between 0 and 11940* where 0 represents alignment along the origin, 1 is aligned1941* the furthest away from the origin, 0.5 is centered, etc.1942*/1943public float getAlignmentX() {1944float xAlign;1945if (layoutMgr instanceof LayoutManager2) {1946synchronized (getTreeLock()) {1947LayoutManager2 lm = (LayoutManager2) layoutMgr;1948xAlign = lm.getLayoutAlignmentX(this);1949}1950} else {1951xAlign = super.getAlignmentX();1952}1953return xAlign;1954}19551956/**1957* Returns the alignment along the y axis. This specifies how1958* the component would like to be aligned relative to other1959* components. The value should be a number between 0 and 11960* where 0 represents alignment along the origin, 1 is aligned1961* the furthest away from the origin, 0.5 is centered, etc.1962*/1963public float getAlignmentY() {1964float yAlign;1965if (layoutMgr instanceof LayoutManager2) {1966synchronized (getTreeLock()) {1967LayoutManager2 lm = (LayoutManager2) layoutMgr;1968yAlign = lm.getLayoutAlignmentY(this);1969}1970} else {1971yAlign = super.getAlignmentY();1972}1973return yAlign;1974}19751976/**1977* Paints the container. This forwards the paint to any lightweight1978* components that are children of this container. If this method is1979* reimplemented, super.paint(g) should be called so that lightweight1980* components are properly rendered. If a child component is entirely1981* clipped by the current clipping setting in g, paint() will not be1982* forwarded to that child.1983*1984* @param g the specified Graphics window1985* @see Component#update(Graphics)1986*/1987public void paint(Graphics g) {1988if (isShowing()) {1989synchronized (getObjectLock()) {1990if (printing) {1991if (printingThreads.contains(Thread.currentThread())) {1992return;1993}1994}1995}19961997// The container is showing on screen and1998// this paint() is not called from print().1999// Paint self and forward the paint to lightweight subcomponents.20002001// super.paint(); -- Don't bother, since it's a NOP.20022003GraphicsCallback.PaintCallback.getInstance().2004runComponents(getComponentsSync(), g, GraphicsCallback.LIGHTWEIGHTS);2005}2006}20072008/**2009* Updates the container. This forwards the update to any lightweight2010* components that are children of this container. If this method is2011* reimplemented, super.update(g) should be called so that lightweight2012* components are properly rendered. If a child component is entirely2013* clipped by the current clipping setting in g, update() will not be2014* forwarded to that child.2015*2016* @param g the specified Graphics window2017* @see Component#update(Graphics)2018*/2019public void update(Graphics g) {2020if (isShowing()) {2021if (! (peer instanceof LightweightPeer)) {2022g.clearRect(0, 0, width, height);2023}2024paint(g);2025}2026}20272028/**2029* Prints the container. This forwards the print to any lightweight2030* components that are children of this container. If this method is2031* reimplemented, super.print(g) should be called so that lightweight2032* components are properly rendered. If a child component is entirely2033* clipped by the current clipping setting in g, print() will not be2034* forwarded to that child.2035*2036* @param g the specified Graphics window2037* @see Component#update(Graphics)2038*/2039public void print(Graphics g) {2040if (isShowing()) {2041Thread t = Thread.currentThread();2042try {2043synchronized (getObjectLock()) {2044if (printingThreads == null) {2045printingThreads = new HashSet<>();2046}2047printingThreads.add(t);2048printing = true;2049}2050super.print(g); // By default, Component.print() calls paint()2051} finally {2052synchronized (getObjectLock()) {2053printingThreads.remove(t);2054printing = !printingThreads.isEmpty();2055}2056}20572058GraphicsCallback.PrintCallback.getInstance().2059runComponents(getComponentsSync(), g, GraphicsCallback.LIGHTWEIGHTS);2060}2061}20622063/**2064* Paints each of the components in this container.2065* @param g the graphics context.2066* @see Component#paint2067* @see Component#paintAll2068*/2069public void paintComponents(Graphics g) {2070if (isShowing()) {2071GraphicsCallback.PaintAllCallback.getInstance().2072runComponents(getComponentsSync(), g, GraphicsCallback.TWO_PASSES);2073}2074}20752076/**2077* Simulates the peer callbacks into java.awt for printing of2078* lightweight Containers.2079* @param g the graphics context to use for printing.2080* @see Component#printAll2081* @see #printComponents2082*/2083void lightweightPaint(Graphics g) {2084super.lightweightPaint(g);2085paintHeavyweightComponents(g);2086}20872088/**2089* Prints all the heavyweight subcomponents.2090*/2091void paintHeavyweightComponents(Graphics g) {2092if (isShowing()) {2093GraphicsCallback.PaintHeavyweightComponentsCallback.getInstance().2094runComponents(getComponentsSync(), g,2095GraphicsCallback.LIGHTWEIGHTS | GraphicsCallback.HEAVYWEIGHTS);2096}2097}20982099/**2100* Prints each of the components in this container.2101* @param g the graphics context.2102* @see Component#print2103* @see Component#printAll2104*/2105public void printComponents(Graphics g) {2106if (isShowing()) {2107GraphicsCallback.PrintAllCallback.getInstance().2108runComponents(getComponentsSync(), g, GraphicsCallback.TWO_PASSES);2109}2110}21112112/**2113* Simulates the peer callbacks into java.awt for printing of2114* lightweight Containers.2115* @param g the graphics context to use for printing.2116* @see Component#printAll2117* @see #printComponents2118*/2119void lightweightPrint(Graphics g) {2120super.lightweightPrint(g);2121printHeavyweightComponents(g);2122}21232124/**2125* Prints all the heavyweight subcomponents.2126*/2127void printHeavyweightComponents(Graphics g) {2128if (isShowing()) {2129GraphicsCallback.PrintHeavyweightComponentsCallback.getInstance().2130runComponents(getComponentsSync(), g,2131GraphicsCallback.LIGHTWEIGHTS | GraphicsCallback.HEAVYWEIGHTS);2132}2133}21342135/**2136* Adds the specified container listener to receive container events2137* from this container.2138* If l is null, no exception is thrown and no action is performed.2139* <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"2140* >AWT Threading Issues</a> for details on AWT's threading model.2141*2142* @param l the container listener2143*2144* @see #removeContainerListener2145* @see #getContainerListeners2146*/2147public synchronized void addContainerListener(ContainerListener l) {2148if (l == null) {2149return;2150}2151containerListener = AWTEventMulticaster.add(containerListener, l);2152newEventsOnly = true;2153}21542155/**2156* Removes the specified container listener so it no longer receives2157* container events from this container.2158* If l is null, no exception is thrown and no action is performed.2159* <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"2160* >AWT Threading Issues</a> for details on AWT's threading model.2161*2162* @param l the container listener2163*2164* @see #addContainerListener2165* @see #getContainerListeners2166*/2167public synchronized void removeContainerListener(ContainerListener l) {2168if (l == null) {2169return;2170}2171containerListener = AWTEventMulticaster.remove(containerListener, l);2172}21732174/**2175* Returns an array of all the container listeners2176* registered on this container.2177*2178* @return all of this container's {@code ContainerListener}s2179* or an empty array if no container2180* listeners are currently registered2181*2182* @see #addContainerListener2183* @see #removeContainerListener2184* @since 1.42185*/2186public synchronized ContainerListener[] getContainerListeners() {2187return getListeners(ContainerListener.class);2188}21892190/**2191* Returns an array of all the objects currently registered2192* as <code><em>Foo</em>Listener</code>s2193* upon this {@code Container}.2194* <code><em>Foo</em>Listener</code>s are registered using the2195* <code>add<em>Foo</em>Listener</code> method.2196*2197* <p>2198* You can specify the {@code listenerType} argument2199* with a class literal, such as2200* <code><em>Foo</em>Listener.class</code>.2201* For example, you can query a2202* {@code Container c}2203* for its container listeners with the following code:2204*2205* <pre>ContainerListener[] cls = (ContainerListener[])(c.getListeners(ContainerListener.class));</pre>2206*2207* If no such listeners exist, this method returns an empty array.2208*2209* @param listenerType the type of listeners requested; this parameter2210* should specify an interface that descends from2211* {@code java.util.EventListener}2212* @return an array of all objects registered as2213* <code><em>Foo</em>Listener</code>s on this container,2214* or an empty array if no such listeners have been added2215* @exception ClassCastException if {@code listenerType}2216* doesn't specify a class or interface that implements2217* {@code java.util.EventListener}2218* @exception NullPointerException if {@code listenerType} is {@code null}2219*2220* @see #getContainerListeners2221*2222* @since 1.32223*/2224public <T extends EventListener> T[] getListeners(Class<T> listenerType) {2225EventListener l = null;2226if (listenerType == ContainerListener.class) {2227l = containerListener;2228} else {2229return super.getListeners(listenerType);2230}2231return AWTEventMulticaster.getListeners(l, listenerType);2232}22332234// REMIND: remove when filtering is done at lower level2235boolean eventEnabled(AWTEvent e) {2236int id = e.getID();22372238if (id == ContainerEvent.COMPONENT_ADDED ||2239id == ContainerEvent.COMPONENT_REMOVED) {2240if ((eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 ||2241containerListener != null) {2242return true;2243}2244return false;2245}2246return super.eventEnabled(e);2247}22482249/**2250* Processes events on this container. If the event is a2251* {@code ContainerEvent}, it invokes the2252* {@code processContainerEvent} method, else it invokes2253* its superclass's {@code processEvent}.2254* <p>Note that if the event parameter is {@code null}2255* the behavior is unspecified and may result in an2256* exception.2257*2258* @param e the event2259*/2260protected void processEvent(AWTEvent e) {2261if (e instanceof ContainerEvent) {2262processContainerEvent((ContainerEvent)e);2263return;2264}2265super.processEvent(e);2266}22672268/**2269* Processes container events occurring on this container by2270* dispatching them to any registered ContainerListener objects.2271* NOTE: This method will not be called unless container events2272* are enabled for this component; this happens when one of the2273* following occurs:2274* <ul>2275* <li>A ContainerListener object is registered via2276* {@code addContainerListener}2277* <li>Container events are enabled via {@code enableEvents}2278* </ul>2279* <p>Note that if the event parameter is {@code null}2280* the behavior is unspecified and may result in an2281* exception.2282*2283* @param e the container event2284* @see Component#enableEvents2285*/2286protected void processContainerEvent(ContainerEvent e) {2287ContainerListener listener = containerListener;2288if (listener != null) {2289switch(e.getID()) {2290case ContainerEvent.COMPONENT_ADDED:2291listener.componentAdded(e);2292break;2293case ContainerEvent.COMPONENT_REMOVED:2294listener.componentRemoved(e);2295break;2296}2297}2298}22992300/*2301* Dispatches an event to this component or one of its sub components.2302* Create ANCESTOR_RESIZED and ANCESTOR_MOVED events in response to2303* COMPONENT_RESIZED and COMPONENT_MOVED events. We have to do this2304* here instead of in processComponentEvent because ComponentEvents2305* may not be enabled for this Container.2306* @param e the event2307*/2308void dispatchEventImpl(AWTEvent e) {2309if ((dispatcher != null) && dispatcher.dispatchEvent(e)) {2310// event was sent to a lightweight component. The2311// native-produced event sent to the native container2312// must be properly disposed of by the peer, so it2313// gets forwarded. If the native host has been removed2314// as a result of the sending the lightweight event,2315// the peer reference will be null.2316e.consume();2317if (peer != null) {2318peer.handleEvent(e);2319}2320return;2321}23222323super.dispatchEventImpl(e);23242325synchronized (getTreeLock()) {2326switch (e.getID()) {2327case ComponentEvent.COMPONENT_RESIZED:2328createChildHierarchyEvents(HierarchyEvent.ANCESTOR_RESIZED, 0,2329Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));2330break;2331case ComponentEvent.COMPONENT_MOVED:2332createChildHierarchyEvents(HierarchyEvent.ANCESTOR_MOVED, 0,2333Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));2334break;2335default:2336break;2337}2338}2339}23402341/*2342* Dispatches an event to this component, without trying to forward2343* it to any subcomponents2344* @param e the event2345*/2346void dispatchEventToSelf(AWTEvent e) {2347super.dispatchEventImpl(e);2348}23492350/**2351* Fetches the top-most (deepest) lightweight component that is interested2352* in receiving mouse events.2353*/2354Component getMouseEventTarget(int x, int y, boolean includeSelf) {2355return getMouseEventTarget(x, y, includeSelf,2356MouseEventTargetFilter.FILTER,2357!SEARCH_HEAVYWEIGHTS);2358}23592360/**2361* Fetches the top-most (deepest) component to receive SunDropTargetEvents.2362*/2363Component getDropTargetEventTarget(int x, int y, boolean includeSelf) {2364return getMouseEventTarget(x, y, includeSelf,2365DropTargetEventTargetFilter.FILTER,2366SEARCH_HEAVYWEIGHTS);2367}23682369/**2370* A private version of getMouseEventTarget which has two additional2371* controllable behaviors. This method searches for the top-most2372* descendant of this container that contains the given coordinates2373* and is accepted by the given filter. The search will be constrained to2374* lightweight descendants if the last argument is {@code false}.2375*2376* @param filter EventTargetFilter instance to determine whether the2377* given component is a valid target for this event.2378* @param searchHeavyweights if {@code false}, the method2379* will bypass heavyweight components during the search.2380*/2381private Component getMouseEventTarget(int x, int y, boolean includeSelf,2382EventTargetFilter filter,2383boolean searchHeavyweights) {2384Component comp = null;2385if (searchHeavyweights) {2386comp = getMouseEventTargetImpl(x, y, includeSelf, filter,2387SEARCH_HEAVYWEIGHTS,2388searchHeavyweights);2389}23902391if (comp == null || comp == this) {2392comp = getMouseEventTargetImpl(x, y, includeSelf, filter,2393!SEARCH_HEAVYWEIGHTS,2394searchHeavyweights);2395}23962397return comp;2398}23992400/**2401* A private version of getMouseEventTarget which has three additional2402* controllable behaviors. This method searches for the top-most2403* descendant of this container that contains the given coordinates2404* and is accepted by the given filter. The search will be constrained to2405* descendants of only lightweight children or only heavyweight children2406* of this container depending on searchHeavyweightChildren. The search will2407* be constrained to only lightweight descendants of the searched children2408* of this container if searchHeavyweightDescendants is {@code false}.2409*2410* @param filter EventTargetFilter instance to determine whether the2411* selected component is a valid target for this event.2412* @param searchHeavyweightChildren if {@code true}, the method2413* will bypass immediate lightweight children during the search.2414* If {@code false}, the methods will bypass immediate2415* heavyweight children during the search.2416* @param searchHeavyweightDescendants if {@code false}, the method2417* will bypass heavyweight descendants which are not immediate2418* children during the search. If {@code true}, the method2419* will traverse both lightweight and heavyweight descendants during2420* the search.2421*/2422private Component getMouseEventTargetImpl(int x, int y, boolean includeSelf,2423EventTargetFilter filter,2424boolean searchHeavyweightChildren,2425boolean searchHeavyweightDescendants) {2426synchronized (getTreeLock()) {24272428for (int i = 0; i < component.size(); i++) {2429Component comp = component.get(i);2430if (comp != null && comp.visible &&2431((!searchHeavyweightChildren &&2432comp.peer instanceof LightweightPeer) ||2433(searchHeavyweightChildren &&2434!(comp.peer instanceof LightweightPeer))) &&2435comp.contains(x - comp.x, y - comp.y)) {24362437// found a component that intersects the point, see if there2438// is a deeper possibility.2439if (comp instanceof Container) {2440Container child = (Container) comp;2441Component deeper = child.getMouseEventTarget(2442x - child.x,2443y - child.y,2444includeSelf,2445filter,2446searchHeavyweightDescendants);2447if (deeper != null) {2448return deeper;2449}2450} else {2451if (filter.accept(comp)) {2452// there isn't a deeper target, but this component2453// is a target2454return comp;2455}2456}2457}2458}24592460boolean isPeerOK;2461boolean isMouseOverMe;24622463isPeerOK = (peer instanceof LightweightPeer) || includeSelf;2464isMouseOverMe = contains(x,y);24652466// didn't find a child target, return this component if it's2467// a possible target2468if (isMouseOverMe && isPeerOK && filter.accept(this)) {2469return this;2470}2471// no possible target2472return null;2473}2474}24752476static interface EventTargetFilter {2477boolean accept(final Component comp);2478}24792480static class MouseEventTargetFilter implements EventTargetFilter {2481static final EventTargetFilter FILTER = new MouseEventTargetFilter();24822483private MouseEventTargetFilter() {}24842485public boolean accept(final Component comp) {2486return (comp.eventMask & AWTEvent.MOUSE_MOTION_EVENT_MASK) != 02487|| (comp.eventMask & AWTEvent.MOUSE_EVENT_MASK) != 02488|| (comp.eventMask & AWTEvent.MOUSE_WHEEL_EVENT_MASK) != 02489|| comp.mouseListener != null2490|| comp.mouseMotionListener != null2491|| comp.mouseWheelListener != null;2492}2493}24942495static class DropTargetEventTargetFilter implements EventTargetFilter {2496static final EventTargetFilter FILTER = new DropTargetEventTargetFilter();24972498private DropTargetEventTargetFilter() {}24992500public boolean accept(final Component comp) {2501DropTarget dt = comp.getDropTarget();2502return dt != null && dt.isActive();2503}2504}25052506/**2507* This is called by lightweight components that want the containing2508* windowed parent to enable some kind of events on their behalf.2509* This is needed for events that are normally only dispatched to2510* windows to be accepted so that they can be forwarded downward to2511* the lightweight component that has enabled them.2512*/2513void proxyEnableEvents(long events) {2514if (peer instanceof LightweightPeer) {2515// this container is lightweight.... continue sending it2516// upward.2517if (parent != null) {2518parent.proxyEnableEvents(events);2519}2520} else {2521// This is a native container, so it needs to host2522// one of it's children. If this function is called before2523// a peer has been created we don't yet have a dispatcher2524// because it has not yet been determined if this instance2525// is lightweight.2526if (dispatcher != null) {2527dispatcher.enableEvents(events);2528}2529}2530}25312532/**2533* @deprecated As of JDK version 1.1,2534* replaced by {@code dispatchEvent(AWTEvent e)}2535*/2536@Deprecated2537public void deliverEvent(Event e) {2538Component comp = getComponentAt(e.x, e.y);2539if ((comp != null) && (comp != this)) {2540e.translate(-comp.x, -comp.y);2541comp.deliverEvent(e);2542} else {2543postEvent(e);2544}2545}25462547/**2548* Locates the component that contains the x,y position. The2549* top-most child component is returned in the case where there2550* is overlap in the components. This is determined by finding2551* the component closest to the index 0 that claims to contain2552* the given point via Component.contains(), except that Components2553* which have native peers take precedence over those which do not2554* (i.e., lightweight Components).2555*2556* @param x the <i>x</i> coordinate2557* @param y the <i>y</i> coordinate2558* @return null if the component does not contain the position.2559* If there is no child component at the requested point and the2560* point is within the bounds of the container the container itself2561* is returned; otherwise the top-most child is returned.2562* @see Component#contains2563* @since 1.12564*/2565public Component getComponentAt(int x, int y) {2566return locate(x, y);2567}25682569/**2570* @deprecated As of JDK version 1.1,2571* replaced by {@code getComponentAt(int, int)}.2572*/2573@Deprecated2574public Component locate(int x, int y) {2575if (!contains(x, y)) {2576return null;2577}2578Component lightweight = null;2579synchronized (getTreeLock()) {2580// Optimized version of two passes:2581// see comment in sun.awt.SunGraphicsCallback2582for (final Component comp : component) {2583if (comp.contains(x - comp.x, y - comp.y)) {2584if (!comp.isLightweight()) {2585// return heavyweight component as soon as possible2586return comp;2587}2588if (lightweight == null) {2589// save and return later the first lightweight component2590lightweight = comp;2591}2592}2593}2594}2595return lightweight != null ? lightweight : this;2596}25972598/**2599* Gets the component that contains the specified point.2600* @param p the point.2601* @return returns the component that contains the point,2602* or {@code null} if the component does2603* not contain the point.2604* @see Component#contains2605* @since 1.12606*/2607public Component getComponentAt(Point p) {2608return getComponentAt(p.x, p.y);2609}26102611/**2612* Returns the position of the mouse pointer in this {@code Container}'s2613* coordinate space if the {@code Container} is under the mouse pointer,2614* otherwise returns {@code null}.2615* This method is similar to {@link Component#getMousePosition()} with the exception2616* that it can take the {@code Container}'s children into account.2617* If {@code allowChildren} is {@code false}, this method will return2618* a non-null value only if the mouse pointer is above the {@code Container}2619* directly, not above the part obscured by children.2620* If {@code allowChildren} is {@code true}, this method returns2621* a non-null value if the mouse pointer is above {@code Container} or any2622* of its descendants.2623*2624* @exception HeadlessException if GraphicsEnvironment.isHeadless() returns true2625* @param allowChildren true if children should be taken into account2626* @see Component#getMousePosition2627* @return mouse coordinates relative to this {@code Component}, or null2628* @since 1.52629*/2630public Point getMousePosition(boolean allowChildren) throws HeadlessException {2631if (GraphicsEnvironment.isHeadless()) {2632throw new HeadlessException();2633}2634@SuppressWarnings("removal")2635PointerInfo pi = java.security.AccessController.doPrivileged(2636new java.security.PrivilegedAction<PointerInfo>() {2637public PointerInfo run() {2638return MouseInfo.getPointerInfo();2639}2640}2641);2642synchronized (getTreeLock()) {2643Component inTheSameWindow = findUnderMouseInWindow(pi);2644if (isSameOrAncestorOf(inTheSameWindow, allowChildren)) {2645return pointRelativeToComponent(pi.getLocation());2646}2647return null;2648}2649}26502651boolean isSameOrAncestorOf(Component comp, boolean allowChildren) {2652return this == comp || (allowChildren && isParentOf(comp));2653}26542655/**2656* Locates the visible child component that contains the specified2657* position. The top-most child component is returned in the case2658* where there is overlap in the components. If the containing child2659* component is a Container, this method will continue searching for2660* the deepest nested child component. Components which are not2661* visible are ignored during the search.<p>2662*2663* The findComponentAt method is different from getComponentAt in2664* that getComponentAt only searches the Container's immediate2665* children; if the containing component is a Container,2666* findComponentAt will search that child to find a nested component.2667*2668* @param x the <i>x</i> coordinate2669* @param y the <i>y</i> coordinate2670* @return null if the component does not contain the position.2671* If there is no child component at the requested point and the2672* point is within the bounds of the container the container itself2673* is returned.2674* @see Component#contains2675* @see #getComponentAt2676* @since 1.22677*/2678public Component findComponentAt(int x, int y) {2679return findComponentAt(x, y, true);2680}26812682/**2683* Private version of findComponentAt which has a controllable2684* behavior. Setting 'ignoreEnabled' to 'false' bypasses disabled2685* Components during the search. This behavior is used by the2686* lightweight cursor support in sun.awt.GlobalCursorManager.2687*2688* The addition of this feature is temporary, pending the2689* adoption of new, public API which exports this feature.2690*/2691final Component findComponentAt(int x, int y, boolean ignoreEnabled) {2692synchronized (getTreeLock()) {2693if (isRecursivelyVisible()){2694return findComponentAtImpl(x, y, ignoreEnabled);2695}2696}2697return null;2698}26992700final Component findComponentAtImpl(int x, int y, boolean ignoreEnabled) {2701// checkTreeLock(); commented for a performance reason27022703if (!(contains(x, y) && visible && (ignoreEnabled || enabled))) {2704return null;2705}2706Component lightweight = null;2707// Optimized version of two passes:2708// see comment in sun.awt.SunGraphicsCallback2709for (final Component comp : component) {2710final int x1 = x - comp.x;2711final int y1 = y - comp.y;2712if (!comp.contains(x1, y1)) {2713continue; // fast path2714}2715if (!comp.isLightweight()) {2716final Component child = getChildAt(comp, x1, y1, ignoreEnabled);2717if (child != null) {2718// return heavyweight component as soon as possible2719return child;2720}2721} else {2722if (lightweight == null) {2723// save and return later the first lightweight component2724lightweight = getChildAt(comp, x1, y1, ignoreEnabled);2725}2726}2727}2728return lightweight != null ? lightweight : this;2729}27302731/**2732* Helper method for findComponentAtImpl. Finds a child component using2733* findComponentAtImpl for Container and getComponentAt for Component.2734*/2735private static Component getChildAt(Component comp, int x, int y,2736boolean ignoreEnabled) {2737if (comp instanceof Container) {2738comp = ((Container) comp).findComponentAtImpl(x, y,2739ignoreEnabled);2740} else {2741comp = comp.getComponentAt(x, y);2742}2743if (comp != null && comp.visible &&2744(ignoreEnabled || comp.enabled)) {2745return comp;2746}2747return null;2748}27492750/**2751* Locates the visible child component that contains the specified2752* point. The top-most child component is returned in the case2753* where there is overlap in the components. If the containing child2754* component is a Container, this method will continue searching for2755* the deepest nested child component. Components which are not2756* visible are ignored during the search.<p>2757*2758* The findComponentAt method is different from getComponentAt in2759* that getComponentAt only searches the Container's immediate2760* children; if the containing component is a Container,2761* findComponentAt will search that child to find a nested component.2762*2763* @param p the point.2764* @return null if the component does not contain the position.2765* If there is no child component at the requested point and the2766* point is within the bounds of the container the container itself2767* is returned.2768* @throws NullPointerException if {@code p} is {@code null}2769* @see Component#contains2770* @see #getComponentAt2771* @since 1.22772*/2773public Component findComponentAt(Point p) {2774return findComponentAt(p.x, p.y);2775}27762777/**2778* Makes this Container displayable by connecting it to2779* a native screen resource. Making a container displayable will2780* cause all of its children to be made displayable.2781* This method is called internally by the toolkit and should2782* not be called directly by programs.2783* @see Component#isDisplayable2784* @see #removeNotify2785*/2786public void addNotify() {2787synchronized (getTreeLock()) {2788// addNotify() on the children may cause proxy event enabling2789// on this instance, so we first call super.addNotify() and2790// possibly create an lightweight event dispatcher before calling2791// addNotify() on the children which may be lightweight.2792super.addNotify();2793if (! (peer instanceof LightweightPeer)) {2794dispatcher = new LightweightDispatcher(this);2795}27962797// We shouldn't use iterator because of the Swing menu2798// implementation specifics:2799// the menu is being assigned as a child to JLayeredPane2800// instead of particular component so always affect2801// collection of component if menu is becoming shown or hidden.2802for (int i = 0; i < component.size(); i++) {2803component.get(i).addNotify();2804}2805}2806}28072808/**2809* Makes this Container undisplayable by removing its connection2810* to its native screen resource. Making a container undisplayable2811* will cause all of its children to be made undisplayable.2812* This method is called by the toolkit internally and should2813* not be called directly by programs.2814* @see Component#isDisplayable2815* @see #addNotify2816*/2817public void removeNotify() {2818synchronized (getTreeLock()) {2819// We shouldn't use iterator because of the Swing menu2820// implementation specifics:2821// the menu is being assigned as a child to JLayeredPane2822// instead of particular component so always affect2823// collection of component if menu is becoming shown or hidden.2824for (int i = component.size()-1 ; i >= 0 ; i--) {2825Component comp = component.get(i);2826if (comp != null) {2827// Fix for 6607170.2828// We want to suppress focus change on disposal2829// of the focused component. But because of focus2830// is asynchronous, we should suppress focus change2831// on every component in case it receives native focus2832// in the process of disposal.2833comp.setAutoFocusTransferOnDisposal(false);2834comp.removeNotify();2835comp.setAutoFocusTransferOnDisposal(true);2836}2837}2838// If some of the children had focus before disposal then it still has.2839// Auto-transfer focus to the next (or previous) component if auto-transfer2840// is enabled.2841if (containsFocus() && KeyboardFocusManager.isAutoFocusTransferEnabledFor(this)) {2842if (!transferFocus(false)) {2843transferFocusBackward(true);2844}2845}2846if ( dispatcher != null ) {2847dispatcher.dispose();2848dispatcher = null;2849}2850super.removeNotify();2851}2852}28532854/**2855* Checks if the component is contained in the component hierarchy of2856* this container.2857* @param c the component2858* @return {@code true} if it is an ancestor;2859* {@code false} otherwise.2860* @since 1.12861*/2862public boolean isAncestorOf(Component c) {2863Container p;2864if (c == null || ((p = c.getParent()) == null)) {2865return false;2866}2867while (p != null) {2868if (p == this) {2869return true;2870}2871p = p.getParent();2872}2873return false;2874}28752876/*2877* The following code was added to support modal JInternalFrames2878* Unfortunately this code has to be added here so that we can get access to2879* some private AWT classes like SequencedEvent.2880*2881* The native container of the LW component has this field set2882* to tell it that it should block Mouse events for all LW2883* children except for the modal component.2884*2885* In the case of nested Modal components, we store the previous2886* modal component in the new modal components value of modalComp;2887*/28882889transient Component modalComp;2890transient AppContext modalAppContext;28912892private void startLWModal() {2893// Store the app context on which this component is being shown.2894// Event dispatch thread of this app context will be sleeping until2895// we wake it by any event from hideAndDisposeHandler().2896modalAppContext = AppContext.getAppContext();28972898// keep the KeyEvents from being dispatched2899// until the focus has been transferred2900long time = Toolkit.getEventQueue().getMostRecentKeyEventTime();2901Component predictedFocusOwner = (Component.isInstanceOf(this, "javax.swing.JInternalFrame")) ? ((javax.swing.JInternalFrame)(this)).getMostRecentFocusOwner() : null;2902if (predictedFocusOwner != null) {2903KeyboardFocusManager.getCurrentKeyboardFocusManager().2904enqueueKeyEvents(time, predictedFocusOwner);2905}2906// We have two mechanisms for blocking: 1. If we're on the2907// EventDispatchThread, start a new event pump. 2. If we're2908// on any other thread, call wait() on the treelock.2909final Container nativeContainer;2910synchronized (getTreeLock()) {2911nativeContainer = getHeavyweightContainer();2912if (nativeContainer.modalComp != null) {2913this.modalComp = nativeContainer.modalComp;2914nativeContainer.modalComp = this;2915return;2916}2917else {2918nativeContainer.modalComp = this;2919}2920}29212922Runnable pumpEventsForHierarchy = () -> {2923EventDispatchThread dispatchThread = (EventDispatchThread)Thread.currentThread();2924dispatchThread.pumpEventsForHierarchy(() -> nativeContainer.modalComp != null,2925Container.this);2926};29272928if (EventQueue.isDispatchThread()) {2929SequencedEvent currentSequencedEvent =2930KeyboardFocusManager.getCurrentKeyboardFocusManager().2931getCurrentSequencedEvent();2932if (currentSequencedEvent != null) {2933currentSequencedEvent.dispose();2934}29352936pumpEventsForHierarchy.run();2937} else {2938synchronized (getTreeLock()) {2939Toolkit.getEventQueue().2940postEvent(new PeerEvent(this,2941pumpEventsForHierarchy,2942PeerEvent.PRIORITY_EVENT));2943while (nativeContainer.modalComp != null)2944{2945try {2946getTreeLock().wait();2947} catch (InterruptedException e) {2948break;2949}2950}2951}2952}2953if (predictedFocusOwner != null) {2954KeyboardFocusManager.getCurrentKeyboardFocusManager().2955dequeueKeyEvents(time, predictedFocusOwner);2956}2957}29582959private void stopLWModal() {2960synchronized (getTreeLock()) {2961if (modalAppContext != null) {2962Container nativeContainer = getHeavyweightContainer();2963if(nativeContainer != null) {2964if (this.modalComp != null) {2965nativeContainer.modalComp = this.modalComp;2966this.modalComp = null;2967return;2968}2969else {2970nativeContainer.modalComp = null;2971}2972}2973// Wake up event dispatch thread on which the dialog was2974// initially shown2975SunToolkit.postEvent(modalAppContext,2976new PeerEvent(this,2977new WakingRunnable(),2978PeerEvent.PRIORITY_EVENT));2979}2980EventQueue.invokeLater(new WakingRunnable());2981getTreeLock().notifyAll();2982}2983}29842985static final class WakingRunnable implements Runnable {2986public void run() {2987}2988}29892990/* End of JOptionPane support code */29912992/**2993* Returns a string representing the state of this {@code Container}.2994* This method is intended to be used only for debugging purposes, and the2995* content and format of the returned string may vary between2996* implementations. The returned string may be empty but may not be2997* {@code null}.2998*2999* @return the parameter string of this container3000*/3001protected String paramString() {3002String str = super.paramString();3003LayoutManager layoutMgr = this.layoutMgr;3004if (layoutMgr != null) {3005str += ",layout=" + layoutMgr.getClass().getName();3006}3007return str;3008}30093010/**3011* Prints a listing of this container to the specified output3012* stream. The listing starts at the specified indentation.3013* <p>3014* The immediate children of the container are printed with3015* an indentation of {@code indent+1}. The children3016* of those children are printed at {@code indent+2}3017* and so on.3018*3019* @param out a print stream3020* @param indent the number of spaces to indent3021* @throws NullPointerException if {@code out} is {@code null}3022* @see Component#list(java.io.PrintStream, int)3023* @since 1.03024*/3025public void list(PrintStream out, int indent) {3026super.list(out, indent);3027synchronized(getTreeLock()) {3028for (int i = 0; i < component.size(); i++) {3029Component comp = component.get(i);3030if (comp != null) {3031comp.list(out, indent+1);3032}3033}3034}3035}30363037/**3038* Prints out a list, starting at the specified indentation,3039* to the specified print writer.3040* <p>3041* The immediate children of the container are printed with3042* an indentation of {@code indent+1}. The children3043* of those children are printed at {@code indent+2}3044* and so on.3045*3046* @param out a print writer3047* @param indent the number of spaces to indent3048* @throws NullPointerException if {@code out} is {@code null}3049* @see Component#list(java.io.PrintWriter, int)3050* @since 1.13051*/3052public void list(PrintWriter out, int indent) {3053super.list(out, indent);3054synchronized(getTreeLock()) {3055for (int i = 0; i < component.size(); i++) {3056Component comp = component.get(i);3057if (comp != null) {3058comp.list(out, indent+1);3059}3060}3061}3062}30633064/**3065* Sets the focus traversal keys for a given traversal operation for this3066* Container.3067* <p>3068* The default values for a Container's focus traversal keys are3069* implementation-dependent. Sun recommends that all implementations for a3070* particular native platform use the same default values. The3071* recommendations for Windows and Unix are listed below. These3072* recommendations are used in the Sun AWT implementations.3073*3074* <table class="striped">3075* <caption>Recommended default values for a Container's focus traversal3076* keys</caption>3077* <thead>3078* <tr>3079* <th scope="col">Identifier3080* <th scope="col">Meaning3081* <th scope="col">Default3082* </thead>3083* <tbody>3084* <tr>3085* <th scope="row">KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS3086* <td>Normal forward keyboard traversal3087* <td>TAB on KEY_PRESSED, CTRL-TAB on KEY_PRESSED3088* <tr>3089* <th scope="row">KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS3090* <td>Normal reverse keyboard traversal3091* <td>SHIFT-TAB on KEY_PRESSED, CTRL-SHIFT-TAB on KEY_PRESSED3092* <tr>3093* <th scope="row">KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS3094* <td>Go up one focus traversal cycle3095* <td>none3096* <tr>3097* <th scope="row">KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS3098* <td>Go down one focus traversal cycle3099* <td>none3100* </tbody>3101* </table>3102*3103* To disable a traversal key, use an empty Set; Collections.EMPTY_SET is3104* recommended.3105* <p>3106* Using the AWTKeyStroke API, client code can specify on which of two3107* specific KeyEvents, KEY_PRESSED or KEY_RELEASED, the focus traversal3108* operation will occur. Regardless of which KeyEvent is specified,3109* however, all KeyEvents related to the focus traversal key, including the3110* associated KEY_TYPED event, will be consumed, and will not be dispatched3111* to any Container. It is a runtime error to specify a KEY_TYPED event as3112* mapping to a focus traversal operation, or to map the same event to3113* multiple default focus traversal operations.3114* <p>3115* If a value of null is specified for the Set, this Container inherits the3116* Set from its parent. If all ancestors of this Container have null3117* specified for the Set, then the current KeyboardFocusManager's default3118* Set is used.3119* <p>3120* This method may throw a {@code ClassCastException} if any {@code Object}3121* in {@code keystrokes} is not an {@code AWTKeyStroke}.3122*3123* @param id one of KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,3124* KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,3125* KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or3126* KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS3127* @param keystrokes the Set of AWTKeyStroke for the specified operation3128* @see #getFocusTraversalKeys3129* @see KeyboardFocusManager#FORWARD_TRAVERSAL_KEYS3130* @see KeyboardFocusManager#BACKWARD_TRAVERSAL_KEYS3131* @see KeyboardFocusManager#UP_CYCLE_TRAVERSAL_KEYS3132* @see KeyboardFocusManager#DOWN_CYCLE_TRAVERSAL_KEYS3133* @throws IllegalArgumentException if id is not one of3134* KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,3135* KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,3136* KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or3137* KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS, or if keystrokes3138* contains null, or if any keystroke represents a KEY_TYPED event,3139* or if any keystroke already maps to another focus traversal3140* operation for this Container3141* @since 1.43142*/3143public void setFocusTraversalKeys(int id,3144Set<? extends AWTKeyStroke> keystrokes)3145{3146if (id < 0 || id >= KeyboardFocusManager.TRAVERSAL_KEY_LENGTH) {3147throw new IllegalArgumentException("invalid focus traversal key identifier");3148}31493150// Don't call super.setFocusTraversalKey. The Component parameter check3151// does not allow DOWN_CYCLE_TRAVERSAL_KEYS, but we do.3152setFocusTraversalKeys_NoIDCheck(id, keystrokes);3153}31543155/**3156* Returns the Set of focus traversal keys for a given traversal operation3157* for this Container. (See3158* {@code setFocusTraversalKeys} for a full description of each key.)3159* <p>3160* If a Set of traversal keys has not been explicitly defined for this3161* Container, then this Container's parent's Set is returned. If no Set3162* has been explicitly defined for any of this Container's ancestors, then3163* the current KeyboardFocusManager's default Set is returned.3164*3165* @param id one of KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,3166* KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,3167* KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or3168* KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS3169* @return the Set of AWTKeyStrokes for the specified operation. The Set3170* will be unmodifiable, and may be empty. null will never be3171* returned.3172* @see #setFocusTraversalKeys3173* @see KeyboardFocusManager#FORWARD_TRAVERSAL_KEYS3174* @see KeyboardFocusManager#BACKWARD_TRAVERSAL_KEYS3175* @see KeyboardFocusManager#UP_CYCLE_TRAVERSAL_KEYS3176* @see KeyboardFocusManager#DOWN_CYCLE_TRAVERSAL_KEYS3177* @throws IllegalArgumentException if id is not one of3178* KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,3179* KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,3180* KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or3181* KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS3182* @since 1.43183*/3184public Set<AWTKeyStroke> getFocusTraversalKeys(int id) {3185if (id < 0 || id >= KeyboardFocusManager.TRAVERSAL_KEY_LENGTH) {3186throw new IllegalArgumentException("invalid focus traversal key identifier");3187}31883189// Don't call super.getFocusTraversalKey. The Component parameter check3190// does not allow DOWN_CYCLE_TRAVERSAL_KEY, but we do.3191return getFocusTraversalKeys_NoIDCheck(id);3192}31933194/**3195* Returns whether the Set of focus traversal keys for the given focus3196* traversal operation has been explicitly defined for this Container. If3197* this method returns {@code false}, this Container is inheriting the3198* Set from an ancestor, or from the current KeyboardFocusManager.3199*3200* @param id one of KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,3201* KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,3202* KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or3203* KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS3204* @return {@code true} if the Set of focus traversal keys for the3205* given focus traversal operation has been explicitly defined for3206* this Component; {@code false} otherwise.3207* @throws IllegalArgumentException if id is not one of3208* KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,3209* KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,3210* KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or3211* KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS3212* @since 1.43213*/3214public boolean areFocusTraversalKeysSet(int id) {3215if (id < 0 || id >= KeyboardFocusManager.TRAVERSAL_KEY_LENGTH) {3216throw new IllegalArgumentException("invalid focus traversal key identifier");3217}32183219return (focusTraversalKeys != null && focusTraversalKeys[id] != null);3220}32213222/**3223* Returns whether the specified Container is the focus cycle root of this3224* Container's focus traversal cycle. Each focus traversal cycle has only3225* a single focus cycle root and each Container which is not a focus cycle3226* root belongs to only a single focus traversal cycle. Containers which3227* are focus cycle roots belong to two cycles: one rooted at the Container3228* itself, and one rooted at the Container's nearest focus-cycle-root3229* ancestor. This method will return {@code true} for both such3230* Containers in this case.3231*3232* @param container the Container to be tested3233* @return {@code true} if the specified Container is a focus-cycle-3234* root of this Container; {@code false} otherwise3235* @see #isFocusCycleRoot()3236* @since 1.43237*/3238public boolean isFocusCycleRoot(Container container) {3239if (isFocusCycleRoot() && container == this) {3240return true;3241} else {3242return super.isFocusCycleRoot(container);3243}3244}32453246private Container findTraversalRoot() {3247// I potentially have two roots, myself and my root parent3248// If I am the current root, then use me3249// If none of my parents are roots, then use me3250// If my root parent is the current root, then use my root parent3251// If neither I nor my root parent is the current root, then3252// use my root parent (a guess)32533254Container currentFocusCycleRoot = KeyboardFocusManager.3255getCurrentKeyboardFocusManager().getCurrentFocusCycleRoot();3256Container root;32573258if (currentFocusCycleRoot == this) {3259root = this;3260} else {3261root = getFocusCycleRootAncestor();3262if (root == null) {3263root = this;3264}3265}32663267if (root != currentFocusCycleRoot) {3268KeyboardFocusManager.getCurrentKeyboardFocusManager().3269setGlobalCurrentFocusCycleRootPriv(root);3270}3271return root;3272}32733274final boolean containsFocus() {3275final Component focusOwner = KeyboardFocusManager.3276getCurrentKeyboardFocusManager().getFocusOwner();3277return isParentOf(focusOwner);3278}32793280/**3281* Check if this component is the child of this container or its children.3282* Note: this function acquires treeLock3283* Note: this function traverses children tree only in one Window.3284* @param comp a component in test, must not be null3285*/3286private boolean isParentOf(Component comp) {3287synchronized(getTreeLock()) {3288while (comp != null && comp != this && !(comp instanceof Window)) {3289comp = comp.getParent();3290}3291return (comp == this);3292}3293}32943295void clearMostRecentFocusOwnerOnHide() {3296boolean reset = false;3297Window window = null;32983299synchronized (getTreeLock()) {3300window = getContainingWindow();3301if (window != null) {3302Component comp = KeyboardFocusManager.getMostRecentFocusOwner(window);3303reset = ((comp == this) || isParentOf(comp));3304// This synchronized should always be the second in a pair3305// (tree lock, KeyboardFocusManager.class)3306synchronized(KeyboardFocusManager.class) {3307Component storedComp = window.getTemporaryLostComponent();3308if (isParentOf(storedComp) || storedComp == this) {3309window.setTemporaryLostComponent(null);3310}3311}3312}3313}33143315if (reset) {3316KeyboardFocusManager.setMostRecentFocusOwner(window, null);3317}3318}33193320void clearCurrentFocusCycleRootOnHide() {3321KeyboardFocusManager kfm =3322KeyboardFocusManager.getCurrentKeyboardFocusManager();3323Container cont = kfm.getCurrentFocusCycleRoot();33243325if (cont == this || isParentOf(cont)) {3326kfm.setGlobalCurrentFocusCycleRootPriv(null);3327}3328}33293330final Container getTraversalRoot() {3331if (isFocusCycleRoot()) {3332return findTraversalRoot();3333}33343335return super.getTraversalRoot();3336}33373338/**3339* Sets the focus traversal policy that will manage keyboard traversal of3340* this Container's children, if this Container is a focus cycle root. If3341* the argument is null, this Container inherits its policy from its focus-3342* cycle-root ancestor. If the argument is non-null, this policy will be3343* inherited by all focus-cycle-root children that have no keyboard-3344* traversal policy of their own (as will, recursively, their focus-cycle-3345* root children).3346* <p>3347* If this Container is not a focus cycle root, the policy will be3348* remembered, but will not be used or inherited by this or any other3349* Containers until this Container is made a focus cycle root.3350*3351* @param policy the new focus traversal policy for this Container3352* @see #getFocusTraversalPolicy3353* @see #setFocusCycleRoot3354* @see #isFocusCycleRoot3355* @since 1.43356*/3357public void setFocusTraversalPolicy(FocusTraversalPolicy policy) {3358FocusTraversalPolicy oldPolicy;3359synchronized (this) {3360oldPolicy = this.focusTraversalPolicy;3361this.focusTraversalPolicy = policy;3362}3363firePropertyChange("focusTraversalPolicy", oldPolicy, policy);3364}33653366/**3367* Returns the focus traversal policy that will manage keyboard traversal3368* of this Container's children, or null if this Container is not a focus3369* cycle root. If no traversal policy has been explicitly set for this3370* Container, then this Container's focus-cycle-root ancestor's policy is3371* returned.3372*3373* @return this Container's focus traversal policy, or null if this3374* Container is not a focus cycle root.3375* @see #setFocusTraversalPolicy3376* @see #setFocusCycleRoot3377* @see #isFocusCycleRoot3378* @since 1.43379*/3380public FocusTraversalPolicy getFocusTraversalPolicy() {3381if (!isFocusTraversalPolicyProvider() && !isFocusCycleRoot()) {3382return null;3383}33843385FocusTraversalPolicy policy = this.focusTraversalPolicy;3386if (policy != null) {3387return policy;3388}33893390Container rootAncestor = getFocusCycleRootAncestor();3391if (rootAncestor != null) {3392return rootAncestor.getFocusTraversalPolicy();3393} else {3394return KeyboardFocusManager.getCurrentKeyboardFocusManager().3395getDefaultFocusTraversalPolicy();3396}3397}33983399/**3400* Returns whether the focus traversal policy has been explicitly set for3401* this Container. If this method returns {@code false}, this3402* Container will inherit its focus traversal policy from an ancestor.3403*3404* @return {@code true} if the focus traversal policy has been3405* explicitly set for this Container; {@code false} otherwise.3406* @since 1.43407*/3408public boolean isFocusTraversalPolicySet() {3409return (focusTraversalPolicy != null);3410}34113412/**3413* Sets whether this Container is the root of a focus traversal cycle. Once3414* focus enters a traversal cycle, typically it cannot leave it via focus3415* traversal unless one of the up- or down-cycle keys is pressed. Normal3416* traversal is limited to this Container, and all of this Container's3417* descendants that are not descendants of inferior focus cycle roots. Note3418* that a FocusTraversalPolicy may bend these restrictions, however. For3419* example, ContainerOrderFocusTraversalPolicy supports implicit down-cycle3420* traversal.3421* <p>3422* The alternative way to specify the traversal order of this Container's3423* children is to make this Container a3424* <a href="doc-files/FocusSpec.html#FocusTraversalPolicyProviders">focus traversal policy provider</a>.3425*3426* @param focusCycleRoot indicates whether this Container is the root of a3427* focus traversal cycle3428* @see #isFocusCycleRoot()3429* @see #setFocusTraversalPolicy3430* @see #getFocusTraversalPolicy3431* @see ContainerOrderFocusTraversalPolicy3432* @see #setFocusTraversalPolicyProvider3433* @since 1.43434*/3435public void setFocusCycleRoot(boolean focusCycleRoot) {3436boolean oldFocusCycleRoot;3437synchronized (this) {3438oldFocusCycleRoot = this.focusCycleRoot;3439this.focusCycleRoot = focusCycleRoot;3440}3441firePropertyChange("focusCycleRoot", oldFocusCycleRoot,3442focusCycleRoot);3443}34443445/**3446* Returns whether this Container is the root of a focus traversal cycle.3447* Once focus enters a traversal cycle, typically it cannot leave it via3448* focus traversal unless one of the up- or down-cycle keys is pressed.3449* Normal traversal is limited to this Container, and all of this3450* Container's descendants that are not descendants of inferior focus3451* cycle roots. Note that a FocusTraversalPolicy may bend these3452* restrictions, however. For example, ContainerOrderFocusTraversalPolicy3453* supports implicit down-cycle traversal.3454*3455* @return whether this Container is the root of a focus traversal cycle3456* @see #setFocusCycleRoot3457* @see #setFocusTraversalPolicy3458* @see #getFocusTraversalPolicy3459* @see ContainerOrderFocusTraversalPolicy3460* @since 1.43461*/3462public boolean isFocusCycleRoot() {3463return focusCycleRoot;3464}34653466/**3467* Sets whether this container will be used to provide focus3468* traversal policy. Container with this property as3469* {@code true} will be used to acquire focus traversal policy3470* instead of closest focus cycle root ancestor.3471* @param provider indicates whether this container will be used to3472* provide focus traversal policy3473* @see #setFocusTraversalPolicy3474* @see #getFocusTraversalPolicy3475* @see #isFocusTraversalPolicyProvider3476* @since 1.53477*/3478public final void setFocusTraversalPolicyProvider(boolean provider) {3479boolean oldProvider;3480synchronized(this) {3481oldProvider = focusTraversalPolicyProvider;3482focusTraversalPolicyProvider = provider;3483}3484firePropertyChange("focusTraversalPolicyProvider", oldProvider, provider);3485}34863487/**3488* Returns whether this container provides focus traversal3489* policy. If this property is set to {@code true} then when3490* keyboard focus manager searches container hierarchy for focus3491* traversal policy and encounters this container before any other3492* container with this property as true or focus cycle roots then3493* its focus traversal policy will be used instead of focus cycle3494* root's policy.3495* @see #setFocusTraversalPolicy3496* @see #getFocusTraversalPolicy3497* @see #setFocusCycleRoot3498* @see #setFocusTraversalPolicyProvider3499* @return {@code true} if this container provides focus traversal3500* policy, {@code false} otherwise3501* @since 1.53502*/3503public final boolean isFocusTraversalPolicyProvider() {3504return focusTraversalPolicyProvider;3505}35063507/**3508* Transfers the focus down one focus traversal cycle. If this Container is3509* a focus cycle root, then the focus owner is set to this Container's3510* default Component to focus, and the current focus cycle root is set to3511* this Container. If this Container is not a focus cycle root, then no3512* focus traversal operation occurs.3513*3514* @see Component#requestFocus()3515* @see #isFocusCycleRoot3516* @see #setFocusCycleRoot3517* @since 1.43518*/3519public void transferFocusDownCycle() {3520if (isFocusCycleRoot()) {3521KeyboardFocusManager.getCurrentKeyboardFocusManager().3522setGlobalCurrentFocusCycleRootPriv(this);3523Component toFocus = getFocusTraversalPolicy().3524getDefaultComponent(this);3525if (toFocus != null) {3526toFocus.requestFocus(FocusEvent.Cause.TRAVERSAL_DOWN);3527}3528}3529}35303531void preProcessKeyEvent(KeyEvent e) {3532Container parent = this.parent;3533if (parent != null) {3534parent.preProcessKeyEvent(e);3535}3536}35373538void postProcessKeyEvent(KeyEvent e) {3539Container parent = this.parent;3540if (parent != null) {3541parent.postProcessKeyEvent(e);3542}3543}35443545boolean postsOldMouseEvents() {3546return true;3547}35483549/**3550* Sets the {@code ComponentOrientation} property of this container3551* and all components contained within it.3552* <p>3553* This method changes layout-related information, and therefore,3554* invalidates the component hierarchy.3555*3556* @param o the new component orientation of this container and3557* the components contained within it.3558* @exception NullPointerException if {@code orientation} is null.3559* @see Component#setComponentOrientation3560* @see Component#getComponentOrientation3561* @see #invalidate3562* @since 1.43563*/3564public void applyComponentOrientation(ComponentOrientation o) {3565super.applyComponentOrientation(o);3566synchronized (getTreeLock()) {3567for (int i = 0; i < component.size(); i++) {3568Component comp = component.get(i);3569comp.applyComponentOrientation(o);3570}3571}3572}35733574/**3575* Adds a PropertyChangeListener to the listener list. The listener is3576* registered for all bound properties of this class, including the3577* following:3578* <ul>3579* <li>this Container's font ("font")</li>3580* <li>this Container's background color ("background")</li>3581* <li>this Container's foreground color ("foreground")</li>3582* <li>this Container's focusability ("focusable")</li>3583* <li>this Container's focus traversal keys enabled state3584* ("focusTraversalKeysEnabled")</li>3585* <li>this Container's Set of FORWARD_TRAVERSAL_KEYS3586* ("forwardFocusTraversalKeys")</li>3587* <li>this Container's Set of BACKWARD_TRAVERSAL_KEYS3588* ("backwardFocusTraversalKeys")</li>3589* <li>this Container's Set of UP_CYCLE_TRAVERSAL_KEYS3590* ("upCycleFocusTraversalKeys")</li>3591* <li>this Container's Set of DOWN_CYCLE_TRAVERSAL_KEYS3592* ("downCycleFocusTraversalKeys")</li>3593* <li>this Container's focus traversal policy ("focusTraversalPolicy")3594* </li>3595* <li>this Container's focus-cycle-root state ("focusCycleRoot")</li>3596* </ul>3597* Note that if this Container is inheriting a bound property, then no3598* event will be fired in response to a change in the inherited property.3599* <p>3600* If listener is null, no exception is thrown and no action is performed.3601*3602* @param listener the PropertyChangeListener to be added3603*3604* @see Component#removePropertyChangeListener3605* @see #addPropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)3606*/3607public void addPropertyChangeListener(PropertyChangeListener listener) {3608super.addPropertyChangeListener(listener);3609}36103611/**3612* Adds a PropertyChangeListener to the listener list for a specific3613* property. The specified property may be user-defined, or one of the3614* following defaults:3615* <ul>3616* <li>this Container's font ("font")</li>3617* <li>this Container's background color ("background")</li>3618* <li>this Container's foreground color ("foreground")</li>3619* <li>this Container's focusability ("focusable")</li>3620* <li>this Container's focus traversal keys enabled state3621* ("focusTraversalKeysEnabled")</li>3622* <li>this Container's Set of FORWARD_TRAVERSAL_KEYS3623* ("forwardFocusTraversalKeys")</li>3624* <li>this Container's Set of BACKWARD_TRAVERSAL_KEYS3625* ("backwardFocusTraversalKeys")</li>3626* <li>this Container's Set of UP_CYCLE_TRAVERSAL_KEYS3627* ("upCycleFocusTraversalKeys")</li>3628* <li>this Container's Set of DOWN_CYCLE_TRAVERSAL_KEYS3629* ("downCycleFocusTraversalKeys")</li>3630* <li>this Container's focus traversal policy ("focusTraversalPolicy")3631* </li>3632* <li>this Container's focus-cycle-root state ("focusCycleRoot")</li>3633* <li>this Container's focus-traversal-policy-provider state("focusTraversalPolicyProvider")</li>3634* <li>this Container's focus-traversal-policy-provider state("focusTraversalPolicyProvider")</li>3635* </ul>3636* Note that if this Container is inheriting a bound property, then no3637* event will be fired in response to a change in the inherited property.3638* <p>3639* If listener is null, no exception is thrown and no action is performed.3640*3641* @param propertyName one of the property names listed above3642* @param listener the PropertyChangeListener to be added3643*3644* @see #addPropertyChangeListener(java.beans.PropertyChangeListener)3645* @see Component#removePropertyChangeListener3646*/3647public void addPropertyChangeListener(String propertyName,3648PropertyChangeListener listener) {3649super.addPropertyChangeListener(propertyName, listener);3650}36513652// Serialization support. A Container is responsible for restoring the3653// parent fields of its component children.36543655/**3656* Container Serial Data Version.3657*/3658private int containerSerializedDataVersion = 1;36593660/**3661* Serializes this {@code Container} to the specified3662* {@code ObjectOutputStream}.3663* <ul>3664* <li>Writes default serializable fields to the stream.</li>3665* <li>Writes a list of serializable ContainerListener(s) as optional3666* data. The non-serializable ContainerListener(s) are detected and3667* no attempt is made to serialize them.</li>3668* <li>Write this Container's FocusTraversalPolicy if and only if it3669* is Serializable; otherwise, {@code null} is written.</li>3670* </ul>3671*3672* @param s the {@code ObjectOutputStream} to write3673* @throws IOException if an I/O error occurs3674* @serialData {@code null} terminated sequence of 0 or more pairs;3675* the pair consists of a {@code String} and {@code Object};3676* the {@code String} indicates the type of object and3677* is one of the following:3678* {@code containerListenerK} indicating an3679* {@code ContainerListener} object;3680* the {@code Container}'s {@code FocusTraversalPolicy},3681* or {@code null}3682*3683* @see AWTEventMulticaster#save(java.io.ObjectOutputStream, java.lang.String, java.util.EventListener)3684* @see Container#containerListenerK3685* @see #readObject(ObjectInputStream)3686*/3687@Serial3688private void writeObject(ObjectOutputStream s) throws IOException {3689ObjectOutputStream.PutField f = s.putFields();3690f.put("ncomponents", component.size());3691f.put("component", component.toArray(EMPTY_ARRAY));3692f.put("layoutMgr", layoutMgr);3693f.put("dispatcher", dispatcher);3694f.put("maxSize", maxSize);3695f.put("focusCycleRoot", focusCycleRoot);3696f.put("containerSerializedDataVersion", containerSerializedDataVersion);3697f.put("focusTraversalPolicyProvider", focusTraversalPolicyProvider);3698s.writeFields();36993700AWTEventMulticaster.save(s, containerListenerK, containerListener);3701s.writeObject(null);37023703if (focusTraversalPolicy instanceof java.io.Serializable) {3704s.writeObject(focusTraversalPolicy);3705} else {3706s.writeObject(null);3707}3708}37093710/**3711* Deserializes this {@code Container} from the specified3712* {@code ObjectInputStream}.3713* <ul>3714* <li>Reads default serializable fields from the stream.</li>3715* <li>Reads a list of serializable ContainerListener(s) as optional3716* data. If the list is null, no Listeners are installed.</li>3717* <li>Reads this Container's FocusTraversalPolicy, which may be null,3718* as optional data.</li>3719* </ul>3720*3721* @param s the {@code ObjectInputStream} to read3722* @throws ClassNotFoundException if the class of a serialized object could3723* not be found3724* @throws IOException if an I/O error occurs3725* @serial3726* @see #addContainerListener3727* @see #writeObject(ObjectOutputStream)3728*/3729@Serial3730private void readObject(ObjectInputStream s)3731throws ClassNotFoundException, IOException3732{3733ObjectInputStream.GetField f = s.readFields();3734// array of components may not be present in the stream or may be null3735Component [] tmpComponent = (Component[])f.get("component", null);3736if (tmpComponent == null) {3737tmpComponent = EMPTY_ARRAY;3738}3739int ncomponents = (Integer) f.get("ncomponents", 0);3740if (ncomponents < 0 || ncomponents > tmpComponent.length) {3741throw new InvalidObjectException("Incorrect number of components");3742}3743component = new java.util.ArrayList<Component>(ncomponents);3744for (int i = 0; i < ncomponents; ++i) {3745component.add(tmpComponent[i]);3746}3747layoutMgr = (LayoutManager)f.get("layoutMgr", null);3748dispatcher = (LightweightDispatcher)f.get("dispatcher", null);3749// Old stream. Doesn't contain maxSize among Component's fields.3750if (maxSize == null) {3751maxSize = (Dimension)f.get("maxSize", null);3752}3753focusCycleRoot = f.get("focusCycleRoot", false);3754containerSerializedDataVersion = f.get("containerSerializedDataVersion", 1);3755focusTraversalPolicyProvider = f.get("focusTraversalPolicyProvider", false);3756java.util.List<Component> component = this.component;3757for(Component comp : component) {3758comp.parent = this;3759adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK,3760comp.numListening(AWTEvent.HIERARCHY_EVENT_MASK));3761adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,3762comp.numListening(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));3763adjustDescendants(comp.countHierarchyMembers());3764}37653766Object keyOrNull;3767while(null != (keyOrNull = s.readObject())) {3768String key = ((String)keyOrNull).intern();37693770if (containerListenerK == key) {3771addContainerListener((ContainerListener)(s.readObject()));3772} else {3773// skip value for unrecognized key3774s.readObject();3775}3776}37773778try {3779Object policy = s.readObject();3780if (policy instanceof FocusTraversalPolicy) {3781focusTraversalPolicy = (FocusTraversalPolicy)policy;3782}3783} catch (java.io.OptionalDataException e) {3784// JDK 1.1/1.2/1.3 instances will not have this optional data.3785// e.eof will be true to indicate that there is no more data3786// available for this object. If e.eof is not true, throw the3787// exception as it might have been caused by reasons unrelated to3788// focusTraversalPolicy.37893790if (!e.eof) {3791throw e;3792}3793}3794}37953796/*3797* --- Accessibility Support ---3798*/37993800/**3801* Inner class of Container used to provide default support for3802* accessibility. This class is not meant to be used directly by3803* application developers, but is instead meant only to be3804* subclassed by container developers.3805* <p>3806* The class used to obtain the accessible role for this object,3807* as well as implementing many of the methods in the3808* AccessibleContainer interface.3809* @since 1.33810*/3811protected class AccessibleAWTContainer extends AccessibleAWTComponent {38123813/**3814* Use serialVersionUID from JDK 1.3 for interoperability.3815*/3816@Serial3817private static final long serialVersionUID = 5081320404842566097L;38183819/**3820* Constructs an {@code AccessibleAWTContainer}.3821*/3822protected AccessibleAWTContainer() {}38233824/**3825* Returns the number of accessible children in the object. If all3826* of the children of this object implement {@code Accessible},3827* then this method should return the number of children of this object.3828*3829* @return the number of accessible children in the object3830*/3831public int getAccessibleChildrenCount() {3832return Container.this.getAccessibleChildrenCount();3833}38343835/**3836* Returns the nth {@code Accessible} child of the object.3837*3838* @param i zero-based index of child3839* @return the nth {@code Accessible} child of the object3840*/3841public Accessible getAccessibleChild(int i) {3842return Container.this.getAccessibleChild(i);3843}38443845/**3846* Returns the {@code Accessible} child, if one exists,3847* contained at the local coordinate {@code Point}.3848*3849* @param p the point defining the top-left corner of the3850* {@code Accessible}, given in the coordinate space3851* of the object's parent3852* @return the {@code Accessible}, if it exists,3853* at the specified location; else {@code null}3854*/3855public Accessible getAccessibleAt(Point p) {3856return Container.this.getAccessibleAt(p);3857}38583859/**3860* Number of PropertyChangeListener objects registered. It's used3861* to add/remove ContainerListener to track target Container's state.3862*/3863private transient volatile int propertyListenersCount = 0;38643865/**3866* The handler to fire {@code PropertyChange}3867* when children are added or removed3868*/3869@SuppressWarnings("serial") // Not statically typed as Serializable3870protected ContainerListener accessibleContainerHandler = null;38713872/**3873* Fire {@code PropertyChange} listener, if one is registered,3874* when children are added or removed.3875* @since 1.33876*/3877protected class AccessibleContainerHandler3878implements ContainerListener, Serializable {38793880/**3881* Use serialVersionUID from JDK 1.3 for interoperability.3882*/3883@Serial3884private static final long serialVersionUID = -480855353991814677L;38853886/**3887* Constructs an {@code AccessibleContainerHandler}.3888*/3889protected AccessibleContainerHandler() {}38903891public void componentAdded(ContainerEvent e) {3892Component c = e.getChild();3893if (c != null && c instanceof Accessible) {3894AccessibleAWTContainer.this.firePropertyChange(3895AccessibleContext.ACCESSIBLE_CHILD_PROPERTY,3896null, ((Accessible) c).getAccessibleContext());3897}3898}3899public void componentRemoved(ContainerEvent e) {3900Component c = e.getChild();3901if (c != null && c instanceof Accessible) {3902AccessibleAWTContainer.this.firePropertyChange(3903AccessibleContext.ACCESSIBLE_CHILD_PROPERTY,3904((Accessible) c).getAccessibleContext(), null);3905}3906}3907}39083909/**3910* Adds a PropertyChangeListener to the listener list.3911*3912* @param listener the PropertyChangeListener to be added3913*/3914public void addPropertyChangeListener(PropertyChangeListener listener) {3915if (accessibleContainerHandler == null) {3916accessibleContainerHandler = new AccessibleContainerHandler();3917}3918if (propertyListenersCount++ == 0) {3919Container.this.addContainerListener(accessibleContainerHandler);3920}3921super.addPropertyChangeListener(listener);3922}39233924/**3925* Remove a PropertyChangeListener from the listener list.3926* This removes a PropertyChangeListener that was registered3927* for all properties.3928*3929* @param listener the PropertyChangeListener to be removed3930*/3931public void removePropertyChangeListener(PropertyChangeListener listener) {3932if (--propertyListenersCount == 0) {3933Container.this.removeContainerListener(accessibleContainerHandler);3934}3935super.removePropertyChangeListener(listener);3936}39373938} // inner class AccessibleAWTContainer39393940/**3941* Returns the {@code Accessible} child contained at the local3942* coordinate {@code Point}, if one exists. Otherwise3943* returns {@code null}.3944*3945* @param p the point defining the top-left corner of the3946* {@code Accessible}, given in the coordinate space3947* of the object's parent3948* @return the {@code Accessible} at the specified location,3949* if it exists; otherwise {@code null}3950*/3951Accessible getAccessibleAt(Point p) {3952synchronized (getTreeLock()) {3953if (this instanceof Accessible) {3954Accessible a = (Accessible)this;3955AccessibleContext ac = a.getAccessibleContext();3956if (ac != null) {3957AccessibleComponent acmp;3958Point location;3959int nchildren = ac.getAccessibleChildrenCount();3960for (int i=0; i < nchildren; i++) {3961a = ac.getAccessibleChild(i);3962if ((a != null)) {3963ac = a.getAccessibleContext();3964if (ac != null) {3965acmp = ac.getAccessibleComponent();3966if ((acmp != null) && (acmp.isShowing())) {3967location = acmp.getLocation();3968Point np = new Point(p.x-location.x,3969p.y-location.y);3970if (acmp.contains(np)){3971return a;3972}3973}3974}3975}3976}3977}3978return (Accessible)this;3979} else {3980Component ret = this;3981if (!this.contains(p.x,p.y)) {3982ret = null;3983} else {3984int ncomponents = this.getComponentCount();3985for (int i=0; i < ncomponents; i++) {3986Component comp = this.getComponent(i);3987if ((comp != null) && comp.isShowing()) {3988Point location = comp.getLocation();3989if (comp.contains(p.x-location.x,p.y-location.y)) {3990ret = comp;3991}3992}3993}3994}3995if (ret instanceof Accessible) {3996return (Accessible) ret;3997}3998}3999return null;4000}4001}40024003/**4004* Returns the number of accessible children in the object. If all4005* of the children of this object implement {@code Accessible},4006* then this method should return the number of children of this object.4007*4008* @return the number of accessible children in the object4009*/4010int getAccessibleChildrenCount() {4011synchronized (getTreeLock()) {4012int count = 0;4013Component[] children = this.getComponents();4014for (int i = 0; i < children.length; i++) {4015if (children[i] instanceof Accessible) {4016count++;4017}4018}4019return count;4020}4021}40224023/**4024* Returns the nth {@code Accessible} child of the object.4025*4026* @param i zero-based index of child4027* @return the nth {@code Accessible} child of the object4028*/4029Accessible getAccessibleChild(int i) {4030synchronized (getTreeLock()) {4031Component[] children = this.getComponents();4032int count = 0;4033for (int j = 0; j < children.length; j++) {4034if (children[j] instanceof Accessible) {4035if (count == i) {4036return (Accessible) children[j];4037} else {4038count++;4039}4040}4041}4042return null;4043}4044}40454046// ************************** MIXING CODE *******************************40474048final void increaseComponentCount(Component c) {4049synchronized (getTreeLock()) {4050if (!c.isDisplayable()) {4051throw new IllegalStateException(4052"Peer does not exist while invoking the increaseComponentCount() method"4053);4054}40554056int addHW = 0;4057int addLW = 0;40584059if (c instanceof Container) {4060addLW = ((Container)c).numOfLWComponents;4061addHW = ((Container)c).numOfHWComponents;4062}4063if (c.isLightweight()) {4064addLW++;4065} else {4066addHW++;4067}40684069for (Container cont = this; cont != null; cont = cont.getContainer()) {4070cont.numOfLWComponents += addLW;4071cont.numOfHWComponents += addHW;4072}4073}4074}40754076final void decreaseComponentCount(Component c) {4077synchronized (getTreeLock()) {4078if (!c.isDisplayable()) {4079throw new IllegalStateException(4080"Peer does not exist while invoking the decreaseComponentCount() method"4081);4082}40834084int subHW = 0;4085int subLW = 0;40864087if (c instanceof Container) {4088subLW = ((Container)c).numOfLWComponents;4089subHW = ((Container)c).numOfHWComponents;4090}4091if (c.isLightweight()) {4092subLW++;4093} else {4094subHW++;4095}40964097for (Container cont = this; cont != null; cont = cont.getContainer()) {4098cont.numOfLWComponents -= subLW;4099cont.numOfHWComponents -= subHW;4100}4101}4102}41034104private int getTopmostComponentIndex() {4105checkTreeLock();4106if (getComponentCount() > 0) {4107return 0;4108}4109return -1;4110}41114112private int getBottommostComponentIndex() {4113checkTreeLock();4114if (getComponentCount() > 0) {4115return getComponentCount() - 1;4116}4117return -1;4118}41194120/*4121* This method is overriden to handle opaque children in non-opaque4122* containers.4123*/4124@Override4125final Region getOpaqueShape() {4126checkTreeLock();4127if (isLightweight() && isNonOpaqueForMixing()4128&& hasLightweightDescendants())4129{4130Region s = Region.EMPTY_REGION;4131for (int index = 0; index < getComponentCount(); index++) {4132Component c = getComponent(index);4133if (c.isLightweight() && c.isShowing()) {4134s = s.getUnion(c.getOpaqueShape());4135}4136}4137return s.getIntersection(getNormalShape());4138}4139return super.getOpaqueShape();4140}41414142final void recursiveSubtractAndApplyShape(Region shape) {4143recursiveSubtractAndApplyShape(shape, getTopmostComponentIndex(), getBottommostComponentIndex());4144}41454146final void recursiveSubtractAndApplyShape(Region shape, int fromZorder) {4147recursiveSubtractAndApplyShape(shape, fromZorder, getBottommostComponentIndex());4148}41494150final void recursiveSubtractAndApplyShape(Region shape, int fromZorder, int toZorder) {4151checkTreeLock();4152if (mixingLog.isLoggable(PlatformLogger.Level.FINE)) {4153mixingLog.fine("this = " + this +4154"; shape=" + shape + "; fromZ=" + fromZorder + "; toZ=" + toZorder);4155}4156if (fromZorder == -1) {4157return;4158}4159if (shape.isEmpty()) {4160return;4161}4162// An invalid container with not-null layout should be ignored4163// by the mixing code, the container will be validated later4164// and the mixing code will be executed later.4165if (getLayout() != null && !isValid()) {4166return;4167}4168for (int index = fromZorder; index <= toZorder; index++) {4169Component comp = getComponent(index);4170if (!comp.isLightweight()) {4171comp.subtractAndApplyShape(shape);4172} else if (comp instanceof Container &&4173((Container)comp).hasHeavyweightDescendants() && comp.isShowing()) {4174((Container)comp).recursiveSubtractAndApplyShape(shape);4175}4176}4177}41784179final void recursiveApplyCurrentShape() {4180recursiveApplyCurrentShape(getTopmostComponentIndex(), getBottommostComponentIndex());4181}41824183final void recursiveApplyCurrentShape(int fromZorder) {4184recursiveApplyCurrentShape(fromZorder, getBottommostComponentIndex());4185}41864187final void recursiveApplyCurrentShape(int fromZorder, int toZorder) {4188checkTreeLock();4189if (mixingLog.isLoggable(PlatformLogger.Level.FINE)) {4190mixingLog.fine("this = " + this +4191"; fromZ=" + fromZorder + "; toZ=" + toZorder);4192}4193if (fromZorder == -1) {4194return;4195}4196// An invalid container with not-null layout should be ignored4197// by the mixing code, the container will be validated later4198// and the mixing code will be executed later.4199if (getLayout() != null && !isValid()) {4200return;4201}4202for (int index = fromZorder; index <= toZorder; index++) {4203Component comp = getComponent(index);4204if (!comp.isLightweight()) {4205comp.applyCurrentShape();4206}4207if (comp instanceof Container &&4208((Container)comp).hasHeavyweightDescendants()) {4209((Container)comp).recursiveApplyCurrentShape();4210}4211}4212}42134214@SuppressWarnings("deprecation")4215private void recursiveShowHeavyweightChildren() {4216if (!hasHeavyweightDescendants() || !isVisible()) {4217return;4218}4219for (int index = 0; index < getComponentCount(); index++) {4220Component comp = getComponent(index);4221if (comp.isLightweight()) {4222if (comp instanceof Container) {4223((Container)comp).recursiveShowHeavyweightChildren();4224}4225} else {4226if (comp.isVisible()) {4227ComponentPeer peer = comp.peer;4228if (peer != null) {4229peer.setVisible(true);4230}4231}4232}4233}4234}42354236@SuppressWarnings("deprecation")4237private void recursiveHideHeavyweightChildren() {4238if (!hasHeavyweightDescendants()) {4239return;4240}4241for (int index = 0; index < getComponentCount(); index++) {4242Component comp = getComponent(index);4243if (comp.isLightweight()) {4244if (comp instanceof Container) {4245((Container)comp).recursiveHideHeavyweightChildren();4246}4247} else {4248if (comp.isVisible()) {4249ComponentPeer peer = comp.peer;4250if (peer != null) {4251peer.setVisible(false);4252}4253}4254}4255}4256}42574258@SuppressWarnings("deprecation")4259private void recursiveRelocateHeavyweightChildren(Point origin) {4260for (int index = 0; index < getComponentCount(); index++) {4261Component comp = getComponent(index);4262if (comp.isLightweight()) {4263if (comp instanceof Container &&4264((Container)comp).hasHeavyweightDescendants())4265{4266final Point newOrigin = new Point(origin);4267newOrigin.translate(comp.getX(), comp.getY());4268((Container)comp).recursiveRelocateHeavyweightChildren(newOrigin);4269}4270} else {4271ComponentPeer peer = comp.peer;4272if (peer != null) {4273peer.setBounds(origin.x + comp.getX(), origin.y + comp.getY(),4274comp.getWidth(), comp.getHeight(),4275ComponentPeer.SET_LOCATION);4276}4277}4278}4279}42804281/**4282* Checks if the container and its direct lightweight containers are4283* visible.4284*4285* Consider the heavyweight container hides or shows the HW descendants4286* automatically. Therefore we care of LW containers' visibility only.4287*4288* This method MUST be invoked under the TreeLock.4289*/4290final boolean isRecursivelyVisibleUpToHeavyweightContainer() {4291if (!isLightweight()) {4292return true;4293}42944295for (Container cont = this;4296cont != null && cont.isLightweight();4297cont = cont.getContainer())4298{4299if (!cont.isVisible()) {4300return false;4301}4302}4303return true;4304}43054306@Override4307void mixOnShowing() {4308synchronized (getTreeLock()) {4309if (mixingLog.isLoggable(PlatformLogger.Level.FINE)) {4310mixingLog.fine("this = " + this);4311}43124313boolean isLightweight = isLightweight();43144315if (isLightweight && isRecursivelyVisibleUpToHeavyweightContainer()) {4316recursiveShowHeavyweightChildren();4317}43184319if (!isMixingNeeded()) {4320return;4321}43224323if (!isLightweight || (isLightweight && hasHeavyweightDescendants())) {4324recursiveApplyCurrentShape();4325}43264327super.mixOnShowing();4328}4329}43304331@Override4332void mixOnHiding(boolean isLightweight) {4333synchronized (getTreeLock()) {4334if (mixingLog.isLoggable(PlatformLogger.Level.FINE)) {4335mixingLog.fine("this = " + this +4336"; isLightweight=" + isLightweight);4337}4338if (isLightweight) {4339recursiveHideHeavyweightChildren();4340}4341super.mixOnHiding(isLightweight);4342}4343}43444345@Override4346void mixOnReshaping() {4347synchronized (getTreeLock()) {4348if (mixingLog.isLoggable(PlatformLogger.Level.FINE)) {4349mixingLog.fine("this = " + this);4350}43514352boolean isMixingNeeded = isMixingNeeded();43534354if (isLightweight() && hasHeavyweightDescendants()) {4355final Point origin = new Point(getX(), getY());4356for (Container cont = getContainer();4357cont != null && cont.isLightweight();4358cont = cont.getContainer())4359{4360origin.translate(cont.getX(), cont.getY());4361}43624363recursiveRelocateHeavyweightChildren(origin);43644365if (!isMixingNeeded) {4366return;4367}43684369recursiveApplyCurrentShape();4370}43714372if (!isMixingNeeded) {4373return;4374}43754376super.mixOnReshaping();4377}4378}43794380@Override4381void mixOnZOrderChanging(int oldZorder, int newZorder) {4382synchronized (getTreeLock()) {4383if (mixingLog.isLoggable(PlatformLogger.Level.FINE)) {4384mixingLog.fine("this = " + this +4385"; oldZ=" + oldZorder + "; newZ=" + newZorder);4386}43874388if (!isMixingNeeded()) {4389return;4390}43914392boolean becameHigher = newZorder < oldZorder;43934394if (becameHigher && isLightweight() && hasHeavyweightDescendants()) {4395recursiveApplyCurrentShape();4396}4397super.mixOnZOrderChanging(oldZorder, newZorder);4398}4399}44004401@Override4402void mixOnValidating() {4403synchronized (getTreeLock()) {4404if (mixingLog.isLoggable(PlatformLogger.Level.FINE)) {4405mixingLog.fine("this = " + this);4406}44074408if (!isMixingNeeded()) {4409return;4410}44114412if (hasHeavyweightDescendants()) {4413recursiveApplyCurrentShape();4414}44154416if (isLightweight() && isNonOpaqueForMixing()) {4417subtractAndApplyShapeBelowMe();4418}44194420super.mixOnValidating();4421}4422}44234424// ****************** END OF MIXING CODE ********************************4425}442644274428/**4429* Class to manage the dispatching of MouseEvents to the lightweight descendants4430* and SunDropTargetEvents to both lightweight and heavyweight descendants4431* contained by a native container.4432*4433* NOTE: the class name is not appropriate anymore, but we cannot change it4434* because we must keep serialization compatibility.4435*4436* @author Timothy Prinzing4437*/4438class LightweightDispatcher implements java.io.Serializable, AWTEventListener {44394440/**4441* Use serialVersionUID from JDK 1.1 for interoperability.4442*/4443@Serial4444private static final long serialVersionUID = 5184291520170872969L;4445/*4446* Our own mouse event for when we're dragged over from another hw4447* container4448*/4449private static final int LWD_MOUSE_DRAGGED_OVER = 1500;44504451private static final PlatformLogger eventLog = PlatformLogger.getLogger("java.awt.event.LightweightDispatcher");44524453private static final int BUTTONS_DOWN_MASK;44544455static {4456int[] buttonsDownMask = AWTAccessor.getInputEventAccessor().4457getButtonDownMasks();4458int mask = 0;4459for (int buttonDownMask : buttonsDownMask) {4460mask |= buttonDownMask;4461}4462BUTTONS_DOWN_MASK = mask;4463}44644465LightweightDispatcher(Container nativeContainer) {4466this.nativeContainer = nativeContainer;4467mouseEventTarget = new WeakReference<>(null);4468targetLastEntered = new WeakReference<>(null);4469targetLastEnteredDT = new WeakReference<>(null);4470eventMask = 0;4471}44724473/*4474* Clean up any resources allocated when dispatcher was created;4475* should be called from Container.removeNotify4476*/4477void dispose() {4478//System.out.println("Disposing lw dispatcher");4479stopListeningForOtherDrags();4480mouseEventTarget.clear();4481targetLastEntered.clear();4482targetLastEnteredDT.clear();4483}44844485/**4486* Enables events to subcomponents.4487*/4488void enableEvents(long events) {4489eventMask |= events;4490}44914492/**4493* Dispatches an event to a sub-component if necessary, and4494* returns whether or not the event was forwarded to a4495* sub-component.4496*4497* @param e the event4498*/4499boolean dispatchEvent(AWTEvent e) {4500boolean ret = false;45014502/*4503* Fix for BugTraq Id 4389284.4504* Dispatch SunDropTargetEvents regardless of eventMask value.4505* Do not update cursor on dispatching SunDropTargetEvents.4506*/4507if (e instanceof SunDropTargetEvent) {45084509SunDropTargetEvent sdde = (SunDropTargetEvent) e;4510ret = processDropTargetEvent(sdde);45114512} else {4513if (e instanceof MouseEvent && (eventMask & MOUSE_MASK) != 0) {4514MouseEvent me = (MouseEvent) e;4515ret = processMouseEvent(me);4516}45174518if (e.getID() == MouseEvent.MOUSE_MOVED) {4519nativeContainer.updateCursorImmediately();4520}4521}45224523return ret;4524}45254526/* This method effectively returns whether or not a mouse button was down4527* just BEFORE the event happened. A better method name might be4528* wasAMouseButtonDownBeforeThisEvent().4529*/4530private boolean isMouseGrab(MouseEvent e) {4531int modifiers = e.getModifiersEx();45324533if (e.getID() == MouseEvent.MOUSE_PRESSED4534|| e.getID() == MouseEvent.MOUSE_RELEASED) {4535modifiers ^= InputEvent.getMaskForButton(e.getButton());4536}4537/* modifiers now as just before event */4538return ((modifiers & BUTTONS_DOWN_MASK) != 0);4539}45404541/**4542* This method attempts to distribute a mouse event to a lightweight4543* component. It tries to avoid doing any unnecessary probes down4544* into the component tree to minimize the overhead of determining4545* where to route the event, since mouse movement events tend to4546* come in large and frequent amounts.4547*/4548private boolean processMouseEvent(MouseEvent e) {4549int id = e.getID();4550Component mouseOver = // sensitive to mouse events4551nativeContainer.getMouseEventTarget(e.getX(), e.getY(),4552Container.INCLUDE_SELF);45534554trackMouseEnterExit(mouseOver, e);45554556Component met = mouseEventTarget.get();4557// 4508327 : MOUSE_CLICKED should only go to the recipient of4558// the accompanying MOUSE_PRESSED, so don't reset mouseEventTarget on a4559// MOUSE_CLICKED.4560if (!isMouseGrab(e) && id != MouseEvent.MOUSE_CLICKED) {4561met = (mouseOver != nativeContainer) ? mouseOver : null;4562mouseEventTarget = new WeakReference<>(met);4563}45644565if (met != null) {4566switch (id) {4567case MouseEvent.MOUSE_ENTERED:4568case MouseEvent.MOUSE_EXITED:4569break;4570case MouseEvent.MOUSE_PRESSED:4571retargetMouseEvent(met, id, e);4572break;4573case MouseEvent.MOUSE_RELEASED:4574retargetMouseEvent(met, id, e);4575break;4576case MouseEvent.MOUSE_CLICKED:4577// 4508327: MOUSE_CLICKED should never be dispatched to a Component4578// other than that which received the MOUSE_PRESSED event. If the4579// mouse is now over a different Component, don't dispatch the event.4580// The previous fix for a similar problem was associated with bug4581// 4155217.4582if (mouseOver == met) {4583retargetMouseEvent(mouseOver, id, e);4584}4585break;4586case MouseEvent.MOUSE_MOVED:4587retargetMouseEvent(met, id, e);4588break;4589case MouseEvent.MOUSE_DRAGGED:4590if (isMouseGrab(e)) {4591retargetMouseEvent(met, id, e);4592}4593break;4594case MouseEvent.MOUSE_WHEEL:4595// This may send it somewhere that doesn't have MouseWheelEvents4596// enabled. In this case, Component.dispatchEventImpl() will4597// retarget the event to a parent that DOES have the events enabled.4598if (eventLog.isLoggable(PlatformLogger.Level.FINEST) && (mouseOver != null)) {4599eventLog.finest("retargeting mouse wheel to " +4600mouseOver.getName() + ", " +4601mouseOver.getClass());4602}4603retargetMouseEvent(mouseOver, id, e);4604break;4605}4606//Consuming of wheel events is implemented in "retargetMouseEvent".4607if (id != MouseEvent.MOUSE_WHEEL) {4608e.consume();4609}4610}4611return e.isConsumed();4612}46134614private boolean processDropTargetEvent(SunDropTargetEvent e) {4615int id = e.getID();4616int x = e.getX();4617int y = e.getY();46184619/*4620* Fix for BugTraq ID 4395290.4621* It is possible that SunDropTargetEvent's Point is outside of the4622* native container bounds. In this case we truncate coordinates.4623*/4624if (!nativeContainer.contains(x, y)) {4625final Dimension d = nativeContainer.getSize();4626if (d.width <= x) {4627x = d.width - 1;4628} else if (x < 0) {4629x = 0;4630}4631if (d.height <= y) {4632y = d.height - 1;4633} else if (y < 0) {4634y = 0;4635}4636}4637Component mouseOver = // not necessarily sensitive to mouse events4638nativeContainer.getDropTargetEventTarget(x, y,4639Container.INCLUDE_SELF);4640trackMouseEnterExit(mouseOver, e);46414642if (mouseOver != nativeContainer && mouseOver != null) {4643switch (id) {4644case SunDropTargetEvent.MOUSE_ENTERED:4645case SunDropTargetEvent.MOUSE_EXITED:4646break;4647default:4648retargetMouseEvent(mouseOver, id, e);4649e.consume();4650break;4651}4652}4653return e.isConsumed();4654}46554656/*4657* Generates dnd enter/exit events as mouse moves over lw components4658* @param targetOver Target mouse is over (including native container)4659* @param e SunDropTarget mouse event in native container4660*/4661private void trackDropTargetEnterExit(Component targetOver, MouseEvent e) {4662int id = e.getID();4663if (id == MouseEvent.MOUSE_ENTERED && isMouseDTInNativeContainer) {4664// This can happen if a lightweight component which initiated the4665// drag has an associated drop target. MOUSE_ENTERED comes when the4666// mouse is in the native container already. To propagate this event4667// properly we should null out targetLastEntered.4668targetLastEnteredDT.clear();4669} else if (id == MouseEvent.MOUSE_ENTERED) {4670isMouseDTInNativeContainer = true;4671} else if (id == MouseEvent.MOUSE_EXITED) {4672isMouseDTInNativeContainer = false;4673}4674Component tle = retargetMouseEnterExit(targetOver, e,4675targetLastEnteredDT.get(),4676isMouseDTInNativeContainer);4677targetLastEnteredDT = new WeakReference<>(tle);4678}46794680/*4681* Generates enter/exit events as mouse moves over lw components4682* @param targetOver Target mouse is over (including native container)4683* @param e Mouse event in native container4684*/4685private void trackMouseEnterExit(Component targetOver, MouseEvent e) {4686if (e instanceof SunDropTargetEvent) {4687trackDropTargetEnterExit(targetOver, e);4688return;4689}4690int id = e.getID();46914692if ( id != MouseEvent.MOUSE_EXITED &&4693id != MouseEvent.MOUSE_DRAGGED &&4694id != LWD_MOUSE_DRAGGED_OVER &&4695!isMouseInNativeContainer) {4696// any event but an exit or drag means we're in the native container4697isMouseInNativeContainer = true;4698startListeningForOtherDrags();4699} else if (id == MouseEvent.MOUSE_EXITED) {4700isMouseInNativeContainer = false;4701stopListeningForOtherDrags();4702}4703Component tle = retargetMouseEnterExit(targetOver, e,4704targetLastEntered.get(),4705isMouseInNativeContainer);4706targetLastEntered = new WeakReference<>(tle);4707}47084709private Component retargetMouseEnterExit(Component targetOver, MouseEvent e,4710Component lastEntered,4711boolean inNativeContainer) {4712int id = e.getID();4713Component targetEnter = inNativeContainer ? targetOver : null;47144715if (lastEntered != targetEnter) {4716if (lastEntered != null) {4717retargetMouseEvent(lastEntered, MouseEvent.MOUSE_EXITED, e);4718}4719if (id == MouseEvent.MOUSE_EXITED) {4720// consume native exit event if we generate one4721e.consume();4722}47234724if (targetEnter != null) {4725retargetMouseEvent(targetEnter, MouseEvent.MOUSE_ENTERED, e);4726}4727if (id == MouseEvent.MOUSE_ENTERED) {4728// consume native enter event if we generate one4729e.consume();4730}4731}4732return targetEnter;4733}47344735/*4736* Listens to global mouse drag events so even drags originating4737* from other heavyweight containers will generate enter/exit4738* events in this container4739*/4740@SuppressWarnings("removal")4741private void startListeningForOtherDrags() {4742//System.out.println("Adding AWTEventListener");4743java.security.AccessController.doPrivileged(4744new java.security.PrivilegedAction<Object>() {4745public Object run() {4746nativeContainer.getToolkit().addAWTEventListener(4747LightweightDispatcher.this,4748AWTEvent.MOUSE_EVENT_MASK |4749AWTEvent.MOUSE_MOTION_EVENT_MASK);4750return null;4751}4752}4753);4754}47554756@SuppressWarnings("removal")4757private void stopListeningForOtherDrags() {4758//System.out.println("Removing AWTEventListener");4759java.security.AccessController.doPrivileged(4760new java.security.PrivilegedAction<Object>() {4761public Object run() {4762nativeContainer.getToolkit().removeAWTEventListener(LightweightDispatcher.this);4763return null;4764}4765}4766);4767}47684769/*4770* (Implementation of AWTEventListener)4771* Listen for drag events posted in other hw components so we can4772* track enter/exit regardless of where a drag originated4773*/4774@SuppressWarnings("deprecation")4775public void eventDispatched(AWTEvent e) {4776boolean isForeignDrag = (e instanceof MouseEvent) &&4777!(e instanceof SunDropTargetEvent) &&4778(e.id == MouseEvent.MOUSE_DRAGGED) &&4779(e.getSource() != nativeContainer);47804781if (!isForeignDrag) {4782// only interested in drags from other hw components4783return;4784}47854786MouseEvent srcEvent = (MouseEvent)e;4787MouseEvent me;47884789synchronized (nativeContainer.getTreeLock()) {4790Component srcComponent = srcEvent.getComponent();47914792// component may have disappeared since drag event posted4793// (i.e. Swing hierarchical menus)4794if ( !srcComponent.isShowing() ) {4795return;4796}47974798// see 50835554799// check if srcComponent is in any modal blocked window4800Component c = nativeContainer;4801while ((c != null) && !(c instanceof Window)) {4802c = c.getParent_NoClientCode();4803}4804if ((c == null) || ((Window)c).isModalBlocked()) {4805return;4806}48074808//4809// create an internal 'dragged-over' event indicating4810// we are being dragged over from another hw component4811//4812me = new MouseEvent(nativeContainer,4813LWD_MOUSE_DRAGGED_OVER,4814srcEvent.getWhen(),4815srcEvent.getModifiersEx() | srcEvent.getModifiers(),4816srcEvent.getX(),4817srcEvent.getY(),4818srcEvent.getXOnScreen(),4819srcEvent.getYOnScreen(),4820srcEvent.getClickCount(),4821srcEvent.isPopupTrigger(),4822srcEvent.getButton());4823MouseEventAccessor meAccessor = AWTAccessor.getMouseEventAccessor();4824meAccessor.setCausedByTouchEvent(me,4825meAccessor.isCausedByTouchEvent(srcEvent));4826((AWTEvent)srcEvent).copyPrivateDataInto(me);4827// translate coordinates to this native container4828final Point ptSrcOrigin = srcComponent.getLocationOnScreen();48294830if (AppContext.getAppContext() != nativeContainer.appContext) {4831final MouseEvent mouseEvent = me;4832Runnable r = new Runnable() {4833public void run() {4834if (!nativeContainer.isShowing() ) {4835return;4836}48374838Point ptDstOrigin = nativeContainer.getLocationOnScreen();4839mouseEvent.translatePoint(ptSrcOrigin.x - ptDstOrigin.x,4840ptSrcOrigin.y - ptDstOrigin.y );4841Component targetOver =4842nativeContainer.getMouseEventTarget(mouseEvent.getX(),4843mouseEvent.getY(),4844Container.INCLUDE_SELF);4845trackMouseEnterExit(targetOver, mouseEvent);4846}4847};4848SunToolkit.executeOnEventHandlerThread(nativeContainer, r);4849return;4850} else {4851if (!nativeContainer.isShowing() ) {4852return;4853}48544855Point ptDstOrigin = nativeContainer.getLocationOnScreen();4856me.translatePoint( ptSrcOrigin.x - ptDstOrigin.x, ptSrcOrigin.y - ptDstOrigin.y );4857}4858}4859//System.out.println("Track event: " + me);4860// feed the 'dragged-over' event directly to the enter/exit4861// code (not a real event so don't pass it to dispatchEvent)4862Component targetOver =4863nativeContainer.getMouseEventTarget(me.getX(), me.getY(),4864Container.INCLUDE_SELF);4865trackMouseEnterExit(targetOver, me);4866}48674868/**4869* Sends a mouse event to the current mouse event recipient using4870* the given event (sent to the windowed host) as a srcEvent. If4871* the mouse event target is still in the component tree, the4872* coordinates of the event are translated to those of the target.4873* If the target has been removed, we don't bother to send the4874* message.4875*/4876@SuppressWarnings("deprecation")4877void retargetMouseEvent(Component target, int id, MouseEvent e) {4878if (target == null) {4879return; // mouse is over another hw component or target is disabled4880}48814882int x = e.getX(), y = e.getY();4883Component component;48844885for(component = target;4886component != null && component != nativeContainer;4887component = component.getParent()) {4888x -= component.x;4889y -= component.y;4890}4891MouseEvent retargeted;4892if (component != null) {4893if (e instanceof SunDropTargetEvent) {4894retargeted = new SunDropTargetEvent(target,4895id,4896x,4897y,4898((SunDropTargetEvent)e).getDispatcher());4899} else if (id == MouseEvent.MOUSE_WHEEL) {4900retargeted = new MouseWheelEvent(target,4901id,4902e.getWhen(),4903e.getModifiersEx() | e.getModifiers(),4904x,4905y,4906e.getXOnScreen(),4907e.getYOnScreen(),4908e.getClickCount(),4909e.isPopupTrigger(),4910((MouseWheelEvent)e).getScrollType(),4911((MouseWheelEvent)e).getScrollAmount(),4912((MouseWheelEvent)e).getWheelRotation(),4913((MouseWheelEvent)e).getPreciseWheelRotation());4914}4915else {4916retargeted = new MouseEvent(target,4917id,4918e.getWhen(),4919e.getModifiersEx() | e.getModifiers(),4920x,4921y,4922e.getXOnScreen(),4923e.getYOnScreen(),4924e.getClickCount(),4925e.isPopupTrigger(),4926e.getButton());4927MouseEventAccessor meAccessor = AWTAccessor.getMouseEventAccessor();4928meAccessor.setCausedByTouchEvent(retargeted,4929meAccessor.isCausedByTouchEvent(e));4930}49314932((AWTEvent)e).copyPrivateDataInto(retargeted);49334934if (target == nativeContainer) {4935// avoid recursively calling LightweightDispatcher...4936((Container)target).dispatchEventToSelf(retargeted);4937} else {4938assert AppContext.getAppContext() == target.appContext;49394940if (nativeContainer.modalComp != null) {4941if (((Container)nativeContainer.modalComp).isAncestorOf(target)) {4942target.dispatchEvent(retargeted);4943} else {4944e.consume();4945}4946} else {4947target.dispatchEvent(retargeted);4948}4949}4950if (id == MouseEvent.MOUSE_WHEEL && retargeted.isConsumed()) {4951//An exception for wheel bubbling to the native system.4952//In "processMouseEvent" total event consuming for wheel events is skipped.4953//Protection from bubbling of Java-accepted wheel events.4954e.consume();4955}4956}4957}49584959// --- member variables -------------------------------49604961/**4962* The windowed container that might be hosting events for4963* subcomponents.4964*/4965private Container nativeContainer;49664967/**4968* This variable is not used, but kept for serialization compatibility4969*/4970private Component focus;49714972/**4973* The current subcomponent being hosted by this windowed4974* component that has events being forwarded to it. If this4975* is null, there are currently no events being forwarded to4976* a subcomponent.4977*/4978private transient WeakReference<Component> mouseEventTarget;49794980/**4981* The last component entered by the {@code MouseEvent}.4982*/4983private transient WeakReference<Component> targetLastEntered;49844985/**4986* The last component entered by the {@code SunDropTargetEvent}.4987*/4988private transient WeakReference<Component> targetLastEnteredDT;49894990/**4991* Is the mouse over the native container.4992*/4993private transient boolean isMouseInNativeContainer = false;49944995/**4996* Is DnD over the native container.4997*/4998private transient boolean isMouseDTInNativeContainer = false;49995000/**5001* This variable is not used, but kept for serialization compatibility5002*/5003private Cursor nativeCursor;50045005/**5006* The event mask for contained lightweight components. Lightweight5007* components need a windowed container to host window-related5008* events. This separate mask indicates events that have been5009* requested by contained lightweight components without effecting5010* the mask of the windowed component itself.5011*/5012private long eventMask;50135014/**5015* The kind of events routed to lightweight components from windowed5016* hosts.5017*/5018private static final long PROXY_EVENT_MASK =5019AWTEvent.FOCUS_EVENT_MASK |5020AWTEvent.KEY_EVENT_MASK |5021AWTEvent.MOUSE_EVENT_MASK |5022AWTEvent.MOUSE_MOTION_EVENT_MASK |5023AWTEvent.MOUSE_WHEEL_EVENT_MASK;50245025private static final long MOUSE_MASK =5026AWTEvent.MOUSE_EVENT_MASK |5027AWTEvent.MOUSE_MOTION_EVENT_MASK |5028AWTEvent.MOUSE_WHEEL_EVENT_MASK;5029}503050315032