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