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