1. /*
  2. * @(#)Container.java 1.181 00/04/06
  3. *
  4. * Copyright 1995-2000 Sun Microsystems, Inc. All Rights Reserved.
  5. *
  6. * This software is the proprietary information of Sun Microsystems, Inc.
  7. * Use is subject to license terms.
  8. *
  9. */
  10. package java.awt;
  11. import java.io.PrintStream;
  12. import java.io.PrintWriter;
  13. import java.awt.peer.ContainerPeer;
  14. import java.awt.peer.ComponentPeer;
  15. import java.awt.event.ComponentEvent;
  16. import java.awt.event.ContainerEvent;
  17. import java.awt.event.FocusEvent;
  18. import java.awt.event.HierarchyEvent;
  19. import java.awt.event.InputEvent;
  20. import java.awt.event.KeyEvent;
  21. import java.awt.event.MouseEvent;
  22. import java.awt.event.ContainerListener;
  23. import java.util.EventListener;
  24. import java.io.ObjectOutputStream;
  25. import java.io.ObjectInputStream;
  26. import java.io.IOException;
  27. import java.awt.event.AWTEventListener;
  28. import java.awt.event.WindowAdapter;
  29. import java.awt.event.WindowListener;
  30. import java.awt.event.WindowEvent;
  31. import java.util.Stack;
  32. import java.util.Vector;
  33. import javax.accessibility.*;
  34. import javax.swing.JRootPane;
  35. import sun.awt.DebugHelper;
  36. import sun.awt.GlobalCursorManager;
  37. /**
  38. * A generic Abstract Window Toolkit(AWT) container object is a component
  39. * that can contain other AWT components.
  40. * <p>
  41. * Components added to a container are tracked in a list. The order
  42. * of the list will define the components' front-to-back stacking order
  43. * within the container. If no index is specified when adding a
  44. * component to a container, it will be added to the end of the list
  45. * (and hence to the bottom of the stacking order).
  46. * @version 1.181, 04/06/00
  47. * @author Arthur van Hoff
  48. * @author Sami Shaio
  49. * @see java.awt.Container#add(java.awt.Component, int)
  50. * @see java.awt.Container#getComponent(int)
  51. * @see java.awt.LayoutManager
  52. * @since JDK1.0
  53. */
  54. public class Container extends Component {
  55. /**
  56. * The number of components in this container.
  57. * This value can be null.
  58. * @serial
  59. * @see getComponent()
  60. * @see getComponents()
  61. * @see getComponentCount()
  62. */
  63. int ncomponents;
  64. /**
  65. * The components in this container.
  66. * @serial
  67. * @see add()
  68. * @see getComponents()
  69. */
  70. Component component[] = new Component[4];
  71. /**
  72. * Layout manager for this container.
  73. * @serial
  74. * @see doLayout()
  75. * @see setLayout()
  76. * @see getLayout()
  77. */
  78. LayoutManager layoutMgr;
  79. /**
  80. * Event router for lightweight components. If this container
  81. * is native, this dispatcher takes care of forwarding and
  82. * retargeting the events to lightweight components contained
  83. * (if any).
  84. * @serial
  85. */
  86. private LightweightDispatcher dispatcher;
  87. /*
  88. * Internal, cached size information.
  89. * @serial
  90. * @see getMaximumSize()
  91. * @see getPreferredSize()
  92. */
  93. private Dimension maxSize;
  94. // keeps track of the threads that are printing this component
  95. private transient Vector printingThreads = new Vector();
  96. // True if there is at least one thread that's printing this component
  97. private transient boolean printing = false;
  98. transient ContainerListener containerListener;
  99. /* HierarchyListener and HierarchyBoundsListener support */
  100. transient int listeningChildren;
  101. transient int listeningBoundsChildren;
  102. /*
  103. * JDK 1.1 serialVersionUID
  104. */
  105. private static final long serialVersionUID = 4613797578919906343L;
  106. private static final DebugHelper dbg = DebugHelper.create(Container.class);
  107. static {
  108. /* ensure that the necessary native libraries are loaded */
  109. Toolkit.loadLibraries();
  110. initIDs();
  111. }
  112. /**
  113. * Initialize JNI field and method IDs for fields that may be
  114. called from C.
  115. */
  116. private static native void initIDs();
  117. /**
  118. * Constructs a new Container. Containers can be extended directly,
  119. * but are lightweight in this case and must be contained by a parent
  120. * somewhere higher up in the component tree that is native.
  121. * (such as Frame for example).
  122. */
  123. public Container() {
  124. }
  125. /**
  126. * Gets the number of components in this panel.
  127. * @return the number of components in this panel.
  128. * @see java.awt.Container#getComponent
  129. * @since JDK1.1
  130. */
  131. public int getComponentCount() {
  132. return countComponents();
  133. }
  134. /**
  135. * @deprecated As of JDK version 1.1,
  136. * replaced by getComponentCount().
  137. */
  138. public int countComponents() {
  139. return ncomponents;
  140. }
  141. /**
  142. * Gets the nth component in this container.
  143. * @param n the index of the component to get.
  144. * @return the n<sup>th</sup> component in this container.
  145. * @exception ArrayIndexOutOfBoundsException
  146. * if the n<sup>th</sup> value does not exist.
  147. */
  148. public Component getComponent(int n) {
  149. synchronized (getTreeLock()) {
  150. if ((n < 0) || (n >= ncomponents)) {
  151. throw new ArrayIndexOutOfBoundsException("No such child: " + n);
  152. }
  153. return component[n];
  154. }
  155. }
  156. /**
  157. * Gets all the components in this container.
  158. * @return an array of all the components in this container.
  159. */
  160. public Component[] getComponents() {
  161. return getComponents_NoClientCode();
  162. }
  163. // NOTE: This method may be called by privileged threads.
  164. // This functionality is implemented in a package-private method
  165. // to insure that it cannot be overridden by client subclasses.
  166. // DO NOT INVOKE CLIENT CODE ON THIS THREAD!
  167. final Component[] getComponents_NoClientCode() {
  168. synchronized (getTreeLock()) {
  169. Component list[] = new Component[ncomponents];
  170. System.arraycopy(component, 0, list, 0, ncomponents);
  171. return list;
  172. }
  173. } // getComponents_NoClientCode()
  174. /**
  175. * Determines the insets of this container, which indicate the size
  176. * of the container's border.
  177. * <p>
  178. * A <code>Frame</code> object, for example, has a top inset that
  179. * corresponds to the height of the frame's title bar.
  180. * @return the insets of this container.
  181. * @see java.awt.Insets
  182. * @see java.awt.LayoutManager
  183. * @since JDK1.1
  184. */
  185. public Insets getInsets() {
  186. return insets();
  187. }
  188. /**
  189. * @deprecated As of JDK version 1.1,
  190. * replaced by <code>getInsets()</code>.
  191. */
  192. public Insets insets() {
  193. if (this.peer != null && this.peer instanceof ContainerPeer) {
  194. ContainerPeer peer = (ContainerPeer)this.peer;
  195. return (Insets)peer.insets().clone();
  196. }
  197. return new Insets(0, 0, 0, 0);
  198. }
  199. /**
  200. * Adds the specified component to the end of this container.
  201. * @param comp the component to be added.
  202. * @return the component argument.
  203. */
  204. public Component add(Component comp) {
  205. addImpl(comp, null, -1);
  206. return comp;
  207. }
  208. /**
  209. * Adds the specified component to this container.
  210. * It is strongly advised to use the 1.1 method, add(Component, Object),
  211. * in place of this method.
  212. */
  213. public Component add(String name, Component comp) {
  214. addImpl(comp, name, -1);
  215. return comp;
  216. }
  217. /**
  218. * Adds the specified component to this container at the given
  219. * position.
  220. * @param comp the component to be added.
  221. * @param index the position at which to insert the component,
  222. * or <code>-1</code> to insert the component at the end.
  223. * @return the component <code>comp</code>
  224. * @see #remove
  225. */
  226. public Component add(Component comp, int index) {
  227. addImpl(comp, null, index);
  228. return comp;
  229. }
  230. /**
  231. * Adds the specified component to the end of this container.
  232. * Also notifies the layout manager to add the component to
  233. * this container's layout using the specified constraints object.
  234. * @param comp the component to be added
  235. * @param constraints an object expressing
  236. * layout contraints for this component
  237. * @see java.awt.LayoutManager
  238. * @since JDK1.1
  239. */
  240. public void add(Component comp, Object constraints) {
  241. addImpl(comp, constraints, -1);
  242. }
  243. /**
  244. * Adds the specified component to this container with the specified
  245. * constraints at the specified index. Also notifies the layout
  246. * manager to add the component to the this container's layout using
  247. * the specified constraints object.
  248. * @param comp the component to be added
  249. * @param constraints an object expressing layout contraints for this
  250. * @param index the position in the container's list at which to insert
  251. * the component. -1 means insert at the end.
  252. * component
  253. * @see #remove
  254. * @see LayoutManager
  255. */
  256. public void add(Component comp, Object constraints, int index) {
  257. addImpl(comp, constraints, index);
  258. }
  259. /**
  260. * Adds the specified component to this container at the specified
  261. * index. This method also notifies the layout manager to add
  262. * the component to this container's layout using the specified
  263. * constraints object.
  264. * <p>
  265. * This is the method to override if a program needs to track
  266. * every add request to a container. An overriding method should
  267. * usually include a call to the superclass's version of the method:
  268. * <p>
  269. * <blockquote>
  270. * <code>super.addImpl(comp, constraints, index)</code>
  271. * </blockquote>
  272. * <p>
  273. * @param comp the component to be added.
  274. * @param constraints an object expressing layout contraints
  275. * for this component.
  276. * @param index the position in the container's list at which to
  277. * insert the component, where <code>-1</code>
  278. * means insert at the end.
  279. * @see java.awt.Container#add(java.awt.Component)
  280. * @see java.awt.Container#add(java.awt.Component, int)
  281. * @see java.awt.Container#add(java.awt.Component, java.lang.Object)
  282. * @see java.awt.LayoutManager
  283. * @since JDK1.1
  284. */
  285. protected void addImpl(Component comp, Object constraints, int index) {
  286. synchronized (getTreeLock()) {
  287. /* Check for correct arguments: index in bounds,
  288. * comp cannot be one of this container's parents,
  289. * and comp cannot be a window.
  290. * comp and container must be on the same GraphicsDevice.
  291. * if comp is container, all sub-components must be on
  292. * same GraphicsDevice.
  293. */
  294. GraphicsConfiguration thisGC = this.getGraphicsConfiguration();
  295. if (index > ncomponents || (index < 0 && index != -1)) {
  296. throw new IllegalArgumentException(
  297. "illegal component position");
  298. }
  299. if (comp instanceof Container) {
  300. for (Container cn = this; cn != null; cn=cn.parent) {
  301. if (cn == comp) {
  302. throw new IllegalArgumentException(
  303. "adding container's parent to itself");
  304. }
  305. }
  306. if (comp instanceof Window) {
  307. throw new IllegalArgumentException(
  308. "adding a window to a container");
  309. }
  310. }
  311. if (thisGC != null) {
  312. comp.checkGD(thisGC.getDevice().getIDstring());
  313. }
  314. /* Reparent the component and tidy up the tree's state. */
  315. if (comp.parent != null) {
  316. comp.parent.remove(comp);
  317. }
  318. /* Add component to list; allocate new array if necessary. */
  319. if (ncomponents == component.length) {
  320. Component newcomponents[] = new Component[ncomponents * 2];
  321. System.arraycopy(component, 0, newcomponents, 0, ncomponents);
  322. component = newcomponents;
  323. }
  324. if (index == -1 || index == ncomponents) {
  325. component[ncomponents++] = comp;
  326. } else {
  327. System.arraycopy(component, index, component,
  328. index + 1, ncomponents - index);
  329. component[index] = comp;
  330. ncomponents++;
  331. }
  332. comp.parent = this;
  333. adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK,
  334. comp.numListening(AWTEvent.HIERARCHY_EVENT_MASK));
  335. adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
  336. comp.numListening(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));
  337. if (valid) {
  338. invalidate();
  339. }
  340. if (peer != null) {
  341. comp.addNotify();
  342. }
  343. /* Notify the layout manager of the added component. */
  344. if (layoutMgr != null) {
  345. if (layoutMgr instanceof LayoutManager2) {
  346. ((LayoutManager2)layoutMgr).addLayoutComponent(comp, constraints);
  347. } else if (constraints instanceof String) {
  348. layoutMgr.addLayoutComponent((String)constraints, comp);
  349. }
  350. }
  351. if (containerListener != null ||
  352. (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0) {
  353. ContainerEvent e = new ContainerEvent(this,
  354. ContainerEvent.COMPONENT_ADDED,
  355. comp);
  356. dispatchEvent(e);
  357. }
  358. comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, comp,
  359. this, HierarchyEvent.PARENT_CHANGED);
  360. if (peer != null && layoutMgr == null && isVisible()) {
  361. GlobalCursorManager.updateCursorImmediately();
  362. }
  363. }
  364. }
  365. /**
  366. * Checks that all Components that this Container contains are on
  367. * the same GraphicsDevice as this Container. If not, throws an
  368. * IllegalArgumentException.
  369. */
  370. void checkGD(String stringID) {
  371. Component tempComp;
  372. for (int i = 0; i < component.length; i++) {
  373. tempComp= component[i];
  374. if (tempComp != null) {
  375. tempComp.checkGD(stringID);
  376. }
  377. }
  378. }
  379. /**
  380. * Removes the component, specified by <code>index</code>,
  381. * from this container.
  382. * @param index the index of the component to be removed.
  383. * @see #add
  384. * @since JDK1.1
  385. */
  386. public void remove(int index) {
  387. synchronized (getTreeLock()) {
  388. Component comp = component[index];
  389. if (peer != null) {
  390. comp.removeNotify();
  391. }
  392. if (layoutMgr != null) {
  393. layoutMgr.removeLayoutComponent(comp);
  394. }
  395. adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK,
  396. -comp.numListening(AWTEvent.HIERARCHY_EVENT_MASK));
  397. adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
  398. -comp.numListening(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));
  399. comp.parent = null;
  400. System.arraycopy(component, index + 1,
  401. component, index,
  402. ncomponents - index - 1);
  403. component[--ncomponents] = null;
  404. if (valid) {
  405. invalidate();
  406. }
  407. if (containerListener != null ||
  408. (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0) {
  409. ContainerEvent e = new ContainerEvent(this,
  410. ContainerEvent.COMPONENT_REMOVED,
  411. comp);
  412. dispatchEvent(e);
  413. }
  414. comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, comp,
  415. this, HierarchyEvent.PARENT_CHANGED);
  416. if (peer != null && layoutMgr == null && isVisible()) {
  417. GlobalCursorManager.updateCursorImmediately();
  418. }
  419. }
  420. }
  421. /**
  422. * Removes the specified component from this container.
  423. * @param comp the component to be removed
  424. * @see #add
  425. */
  426. public void remove(Component comp) {
  427. synchronized (getTreeLock()) {
  428. if (comp.parent == this) {
  429. /* Search backwards, expect that more recent additions
  430. * are more likely to be removed.
  431. */
  432. Component component[] = this.component;
  433. for (int i = ncomponents; --i >= 0; ) {
  434. if (component[i] == comp) {
  435. remove(i);
  436. }
  437. }
  438. }
  439. }
  440. }
  441. /**
  442. * Removes all the components from this container.
  443. * @see #add
  444. * @see #remove
  445. */
  446. public void removeAll() {
  447. synchronized (getTreeLock()) {
  448. adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK,
  449. -listeningChildren);
  450. adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
  451. -listeningBoundsChildren);
  452. while (ncomponents > 0) {
  453. Component comp = component[--ncomponents];
  454. component[ncomponents] = null;
  455. if (peer != null) {
  456. comp.removeNotify();
  457. }
  458. if (layoutMgr != null) {
  459. layoutMgr.removeLayoutComponent(comp);
  460. }
  461. comp.parent = null;
  462. if (containerListener != null ||
  463. (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0) {
  464. ContainerEvent e = new ContainerEvent(this,
  465. ContainerEvent.COMPONENT_REMOVED,
  466. comp);
  467. dispatchEvent(e);
  468. }
  469. comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED,
  470. comp, this,
  471. HierarchyEvent.PARENT_CHANGED);
  472. }
  473. if (peer != null && layoutMgr == null && isVisible()) {
  474. GlobalCursorManager.updateCursorImmediately();
  475. }
  476. if (valid) {
  477. invalidate();
  478. }
  479. }
  480. }
  481. // Should only be called while holding tree lock
  482. int numListening(long mask) {
  483. int superListening = super.numListening(mask);
  484. if (mask == AWTEvent.HIERARCHY_EVENT_MASK) {
  485. if (dbg.on) {
  486. // Verify listeningChildren is correct
  487. int sum = 0;
  488. for (int i = 0; i < ncomponents; i++) {
  489. sum += component[i].numListening(mask);
  490. }
  491. dbg.assert(listeningChildren == sum);
  492. }
  493. return listeningChildren + superListening;
  494. } else if (mask == AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) {
  495. if (dbg.on) {
  496. // Verify listeningBoundsChildren is correct
  497. int sum = 0;
  498. for (int i = 0; i < ncomponents; i++) {
  499. sum += component[i].numListening(mask);
  500. }
  501. dbg.assert(listeningBoundsChildren == sum);
  502. }
  503. return listeningBoundsChildren + superListening;
  504. } else {
  505. if (dbg.on) {
  506. dbg.assert(false);
  507. }
  508. return superListening;
  509. }
  510. }
  511. // Should only be called while holding tree lock
  512. void adjustListeningChildren(long mask, int num) {
  513. if (dbg.on) {
  514. dbg.assert(mask == AWTEvent.HIERARCHY_EVENT_MASK ||
  515. mask == AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK ||
  516. mask == (AWTEvent.HIERARCHY_EVENT_MASK |
  517. AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));
  518. }
  519. if (num == 0)
  520. return;
  521. if ((mask & AWTEvent.HIERARCHY_EVENT_MASK) != 0) {
  522. listeningChildren += num;
  523. }
  524. if ((mask & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) != 0) {
  525. listeningBoundsChildren += num;
  526. }
  527. if (parent != null) {
  528. parent.adjustListeningChildren(mask, num);
  529. }
  530. }
  531. // Should only be called while holding tree lock
  532. int createHierarchyEvents(int id, Component changed,
  533. Container changedParent, long changeFlags) {
  534. int listeners = 0;
  535. switch (id) {
  536. case HierarchyEvent.HIERARCHY_CHANGED:
  537. listeners = listeningChildren;
  538. break;
  539. case HierarchyEvent.ANCESTOR_MOVED:
  540. case HierarchyEvent.ANCESTOR_RESIZED:
  541. if (dbg.on) {
  542. dbg.assert(changeFlags == 0);
  543. }
  544. listeners = listeningBoundsChildren;
  545. break;
  546. default:
  547. if (dbg.on) {
  548. dbg.assert(false);
  549. }
  550. break;
  551. }
  552. for (int count = listeners, i = 0; count > 0; i++) {
  553. count -= component[i].createHierarchyEvents(id, changed,
  554. changedParent,
  555. changeFlags);
  556. }
  557. return listeners +
  558. super.createHierarchyEvents(id, changed, changedParent,
  559. changeFlags);
  560. }
  561. void createChildHierarchyEvents(int id, long changeFlags) {
  562. synchronized (getTreeLock()) {
  563. int listeners = 0;
  564. switch (id) {
  565. case HierarchyEvent.HIERARCHY_CHANGED:
  566. listeners = listeningChildren;
  567. break;
  568. case HierarchyEvent.ANCESTOR_MOVED:
  569. case HierarchyEvent.ANCESTOR_RESIZED:
  570. if (dbg.on) {
  571. dbg.assert(changeFlags == 0);
  572. }
  573. listeners = listeningBoundsChildren;
  574. break;
  575. default:
  576. if (dbg.on) {
  577. dbg.assert(false);
  578. }
  579. break;
  580. }
  581. for (int count = listeners, i = 0; count > 0; i++) {
  582. count -= component[i].createHierarchyEvents(id, this, parent,
  583. changeFlags);
  584. }
  585. }
  586. }
  587. /**
  588. * Gets the layout manager for this container.
  589. * @see #doLayout
  590. * @see #setLayout
  591. */
  592. public LayoutManager getLayout() {
  593. return layoutMgr;
  594. }
  595. /**
  596. * Sets the layout manager for this container.
  597. * @param mgr the specified layout manager
  598. * @see #doLayout
  599. * @see #getLayout
  600. */
  601. public void setLayout(LayoutManager mgr) {
  602. layoutMgr = mgr;
  603. if (valid) {
  604. invalidate();
  605. }
  606. }
  607. /**
  608. * Causes this container to lay out its components. Most programs
  609. * should not call this method directly, but should invoke
  610. * the <code>validate</code> method instead.
  611. * @see java.awt.LayoutManager#layoutContainer
  612. * @see #setLayout
  613. * @see #validate
  614. * @since JDK1.1
  615. */
  616. public void doLayout() {
  617. layout();
  618. }
  619. /**
  620. * @deprecated As of JDK version 1.1,
  621. * replaced by <code>doLayout()</code>.
  622. */
  623. public void layout() {
  624. LayoutManager layoutMgr = this.layoutMgr;
  625. if (layoutMgr != null) {
  626. layoutMgr.layoutContainer(this);
  627. }
  628. }
  629. /**
  630. * Invalidates the container. The container and all parents
  631. * above it are marked as needing to be laid out. This method can
  632. * be called often, so it needs to execute quickly.
  633. * @see #validate
  634. * @see #layout
  635. * @see LayoutManager
  636. */
  637. public void invalidate() {
  638. if (layoutMgr instanceof LayoutManager2) {
  639. LayoutManager2 lm = (LayoutManager2) layoutMgr;
  640. lm.invalidateLayout(this);
  641. }
  642. super.invalidate();
  643. }
  644. /**
  645. * Validates this container and all of its subcomponents.
  646. * <p>
  647. * AWT uses <code>validate</code> to cause a container to lay out
  648. * its subcomponents again after the components it contains
  649. * have been added to or modified.
  650. * @see #validate
  651. * @see Component#invalidate
  652. */
  653. public void validate() {
  654. /* Avoid grabbing lock unless really necessary. */
  655. if (!valid) {
  656. boolean updateCur = false;
  657. synchronized (getTreeLock()) {
  658. if (!valid && peer != null) {
  659. ContainerPeer p = null;
  660. if (peer instanceof ContainerPeer) {
  661. p = (ContainerPeer) peer;
  662. }
  663. if (p != null) {
  664. p.beginValidate();
  665. }
  666. validateTree();
  667. valid = true;
  668. if (p != null) {
  669. p.endValidate();
  670. updateCur = isVisible();
  671. }
  672. }
  673. }
  674. if (updateCur) {
  675. GlobalCursorManager.updateCursorImmediately();
  676. }
  677. }
  678. }
  679. /**
  680. * Recursively descends the container tree and recomputes the
  681. * layout for any subtrees marked as needing it (those marked as
  682. * invalid). Synchronization should be provided by the method
  683. * that calls this one: <code>validate</code>.
  684. */
  685. protected void validateTree() {
  686. if (!valid) {
  687. doLayout();
  688. Component component[] = this.component;
  689. for (int i = 0 ; i < ncomponents ; ++i) {
  690. Component comp = component[i];
  691. if ( (comp instanceof Container)
  692. && !(comp instanceof Window)
  693. && !comp.valid) {
  694. ((Container)comp).validateTree();
  695. } else {
  696. comp.validate();
  697. }
  698. }
  699. }
  700. valid = true;
  701. }
  702. /**
  703. * Recursively descends the container tree and invalidates all
  704. * contained components.
  705. */
  706. void invalidateTree() {
  707. synchronized (getTreeLock()) {
  708. for (int i = 0; i < ncomponents; ++i) {
  709. Component comp = component[i];
  710. if (comp instanceof Container) {
  711. ((Container)comp).invalidateTree();
  712. }
  713. else {
  714. if (comp.valid) {
  715. comp.invalidate();
  716. }
  717. }
  718. }
  719. if (valid) {
  720. invalidate();
  721. }
  722. }
  723. }
  724. /**
  725. * Sets the font of this container.
  726. * @param f The font to become this container's font.
  727. * @see Component#getFont
  728. * @since JDK1.0
  729. */
  730. public void setFont(Font f) {
  731. boolean shouldinvalidate = false;
  732. Font oldfont = getFont();
  733. super.setFont(f);
  734. Font newfont = getFont();
  735. if (newfont != oldfont && (oldfont == null ||
  736. !oldfont.equals(newfont))) {
  737. invalidateTree();
  738. }
  739. }
  740. /**
  741. * Returns the preferred size of this container.
  742. * @return an instance of <code>Dimension</code> that represents
  743. * the preferred size of this container.
  744. * @see java.awt.Container#getMinimumSize
  745. * @see java.awt.Container#getLayout
  746. * @see java.awt.LayoutManager#preferredLayoutSize(java.awt.Container)
  747. * @see java.awt.Component#getPreferredSize
  748. */
  749. public Dimension getPreferredSize() {
  750. return preferredSize();
  751. }
  752. /**
  753. * @deprecated As of JDK version 1.1,
  754. * replaced by <code>getPreferredSize()</code>.
  755. */
  756. public Dimension preferredSize() {
  757. /* Avoid grabbing the lock if a reasonable cached size value
  758. * is available.
  759. */
  760. Dimension dim = prefSize;
  761. if (dim != null && isValid()) {
  762. return dim;
  763. }
  764. synchronized (getTreeLock()) {
  765. prefSize = (layoutMgr != null) ?
  766. layoutMgr.preferredLayoutSize(this) :
  767. super.preferredSize();
  768. return prefSize;
  769. }
  770. }
  771. /**
  772. * Returns the minimum size of this container.
  773. * @return an instance of <code>Dimension</code> that represents
  774. * the minimum size of this container.
  775. * @see java.awt.Container#getPreferredSize
  776. * @see java.awt.Container#getLayout
  777. * @see java.awt.LayoutManager#minimumLayoutSize(java.awt.Container)
  778. * @see java.awt.Component#getMinimumSize
  779. * @since JDK1.1
  780. */
  781. public Dimension getMinimumSize() {
  782. return minimumSize();
  783. }
  784. /**
  785. * @deprecated As of JDK version 1.1,
  786. * replaced by <code>getMinimumSize()</code>.
  787. */
  788. public Dimension minimumSize() {
  789. /* Avoid grabbing the lock if a reasonable cached size value
  790. * is available.
  791. */
  792. Dimension dim = minSize;
  793. if (dim != null && isValid()) {
  794. return dim;
  795. }
  796. synchronized (getTreeLock()) {
  797. minSize = (layoutMgr != null) ?
  798. layoutMgr.minimumLayoutSize(this) :
  799. super.minimumSize();
  800. return minSize;
  801. }
  802. }
  803. /**
  804. * Returns the maximum size of this container.
  805. * @see #getPreferredSize
  806. */
  807. public Dimension getMaximumSize() {
  808. /* Avoid grabbing the lock if a reasonable cached size value
  809. * is available.
  810. */
  811. Dimension dim = maxSize;
  812. if (dim != null && isValid()) {
  813. return dim;
  814. }
  815. if (layoutMgr instanceof LayoutManager2) {
  816. synchronized (getTreeLock()) {
  817. LayoutManager2 lm = (LayoutManager2) layoutMgr;
  818. maxSize = lm.maximumLayoutSize(this);
  819. }
  820. } else {
  821. maxSize = super.getMaximumSize();
  822. }
  823. return maxSize;
  824. }
  825. /**
  826. * Returns the alignment along the x axis. This specifies how
  827. * the component would like to be aligned relative to other
  828. * components. The value should be a number between 0 and 1
  829. * where 0 represents alignment along the origin, 1 is aligned
  830. * the furthest away from the origin, 0.5 is centered, etc.
  831. */
  832. public float getAlignmentX() {
  833. float xAlign;
  834. if (layoutMgr instanceof LayoutManager2) {
  835. synchronized (getTreeLock()) {
  836. LayoutManager2 lm = (LayoutManager2) layoutMgr;
  837. xAlign = lm.getLayoutAlignmentX(this);
  838. }
  839. } else {
  840. xAlign = super.getAlignmentX();
  841. }
  842. return xAlign;
  843. }
  844. /**
  845. * Returns the alignment along the y axis. This specifies how
  846. * the component would like to be aligned relative to other
  847. * components. The value should be a number between 0 and 1
  848. * where 0 represents alignment along the origin, 1 is aligned
  849. * the furthest away from the origin, 0.5 is centered, etc.
  850. */
  851. public float getAlignmentY() {
  852. float yAlign;
  853. if (layoutMgr instanceof LayoutManager2) {
  854. synchronized (getTreeLock()) {
  855. LayoutManager2 lm = (LayoutManager2) layoutMgr;
  856. yAlign = lm.getLayoutAlignmentY(this);
  857. }
  858. } else {
  859. yAlign = super.getAlignmentY();
  860. }
  861. return yAlign;
  862. }
  863. /**
  864. * Paints the container. This forwards the paint to any lightweight
  865. * components that are children of this container. If this method is
  866. * reimplemented, super.paint(g) should be called so that lightweight
  867. * components are properly rendered. If a child component is entirely
  868. * clipped by the current clipping setting in g, paint() will not be
  869. * forwarded to that child.
  870. *
  871. * @param g the specified Graphics window
  872. * @see java.awt.Component#update(java.awt.Graphics)
  873. */
  874. public void paint(Graphics g) {
  875. if (isShowing() &&
  876. (!printing ||
  877. !printingThreads.contains(Thread.currentThread())) ) {
  878. // The container is showing on screen and
  879. // this paint() is not called from print().
  880. // Paint self and forward the paint to lightweight subcomponents.
  881. // super.paint(); -- Don't bother, since it's a NOP.
  882. GraphicsCallback.PaintCallback.getInstance().
  883. runComponents(component, g, GraphicsCallback.LIGHTWEIGHTS);
  884. }
  885. }
  886. /**
  887. * Updates the container. This forwards the update to any lightweight
  888. * components that are children of this container. If this method is
  889. * reimplemented, super.update(g) should be called so that lightweight
  890. * components are properly rendered. If a child component is entirely
  891. * clipped by the current clipping setting in g, update() will not be
  892. * forwarded to that child.
  893. *
  894. * @param g the specified Graphics window
  895. * @see java.awt.Component#update(java.awt.Graphics)
  896. */
  897. public void update(Graphics g) {
  898. if (isShowing()) {
  899. if (! (peer instanceof java.awt.peer.LightweightPeer)) {
  900. g.clearRect(0, 0, width, height);
  901. }
  902. paint(g);
  903. }
  904. }
  905. /**
  906. * Prints the container. This forwards the print to any lightweight
  907. * components that are children of this container. If this method is
  908. * reimplemented, super.print(g) should be called so that lightweight
  909. * components are properly rendered. If a child component is entirely
  910. * clipped by the current clipping setting in g, print() will not be
  911. * forwarded to that child.
  912. *
  913. * @param g the specified Graphics window
  914. * @see java.awt.Component#update(java.awt.Graphics)
  915. */
  916. public void print(Graphics g) {
  917. if (isShowing()) {
  918. Thread t = Thread.currentThread();
  919. try {
  920. printingThreads.addElement(t);
  921. printing = true;
  922. super.print(g); // By default, Component.print() calls paint()
  923. } finally {
  924. printingThreads.removeElement(t);
  925. printing = !printingThreads.isEmpty();
  926. }
  927. GraphicsCallback.PrintCallback.getInstance().
  928. runComponents(component, g, GraphicsCallback.LIGHTWEIGHTS);
  929. }
  930. }
  931. /**
  932. * Paints each of the components in this container.
  933. * @param g the graphics context.
  934. * @see java.awt.Component#paint
  935. * @see java.awt.Component#paintAll
  936. */
  937. public void paintComponents(Graphics g) {
  938. if (isShowing()) {
  939. GraphicsCallback.PaintAllCallback.getInstance().
  940. runComponents(component, g, GraphicsCallback.TWO_PASSES);
  941. }
  942. }
  943. /**
  944. * Simulates the peer callbacks into java.awt for printing of
  945. * lightweight Containers.
  946. * @param g the graphics context to use for printing.
  947. * @see Component#printAll
  948. * @see #printComponents
  949. */
  950. void lightweightPaint(Graphics g) {
  951. super.lightweightPaint(g);
  952. paintHeavyweightComponents(g);
  953. }
  954. /**
  955. * Prints all the heavyweight subcomponents.
  956. */
  957. void paintHeavyweightComponents(Graphics g) {
  958. if (isShowing()) {
  959. GraphicsCallback.PaintHeavyweightComponentsCallback.getInstance().
  960. runComponents(component, g, GraphicsCallback.LIGHTWEIGHTS |
  961. GraphicsCallback.HEAVYWEIGHTS);
  962. }
  963. }
  964. /**
  965. * Prints each of the components in this container.
  966. * @param g the graphics context.
  967. * @see java.awt.Component#print
  968. * @see java.awt.Component#printAll
  969. */
  970. public void printComponents(Graphics g) {
  971. if (isShowing()) {
  972. GraphicsCallback.PrintAllCallback.getInstance().
  973. runComponents(component, g, GraphicsCallback.TWO_PASSES);
  974. }
  975. }
  976. /**
  977. * Simulates the peer callbacks into java.awt for printing of
  978. * lightweight Containers.
  979. * @param g the graphics context to use for printing.
  980. * @see Component#printAll
  981. * @see #printComponents
  982. */
  983. void lightweightPrint(Graphics g) {
  984. super.lightweightPrint(g);
  985. printHeavyweightComponents(g);
  986. }
  987. /**
  988. * Prints all the heavyweight subcomponents.
  989. */
  990. void printHeavyweightComponents(Graphics g) {
  991. if (isShowing()) {
  992. GraphicsCallback.PrintHeavyweightComponentsCallback.getInstance().
  993. runComponents(component, g, GraphicsCallback.LIGHTWEIGHTS |
  994. GraphicsCallback.HEAVYWEIGHTS);
  995. }
  996. }
  997. /**
  998. * Adds the specified container listener to receive container events
  999. * from this container.
  1000. * If l is null, no exception is thrown and no action is performed.
  1001. *
  1002. * @param l the container listener
  1003. */
  1004. public synchronized void addContainerListener(ContainerListener l) {
  1005. if (l == null) {
  1006. return;
  1007. }
  1008. containerListener = AWTEventMulticaster.add(containerListener, l);
  1009. newEventsOnly = true;
  1010. }
  1011. /**
  1012. * Removes the specified container listener so it no longer receives
  1013. * container events from this container.
  1014. * If l is null, no exception is thrown and no action is performed.
  1015. *
  1016. * @param l the container listener
  1017. */
  1018. public synchronized void removeContainerListener(ContainerListener l) {
  1019. if (l == null) {
  1020. return;
  1021. }
  1022. containerListener = AWTEventMulticaster.remove(containerListener, l);
  1023. }
  1024. /**
  1025. * Return an array of all the listeners that were added to the Container
  1026. * with addXXXListener(), where XXX is the name of the <code>listenerType</code>
  1027. * argument. For example, to get all of the ContainerListener(s) for the
  1028. * given Container <code>c</code>, one would write:
  1029. * <pre>
  1030. * ContainerListener[] cls = (ContainerListener[])(c.getListeners(ContainerListener.class))
  1031. * </pre>
  1032. * If no such listener list exists, then an empty array is returned.
  1033. *
  1034. * @param listenerType Type of listeners requested
  1035. * @return all of the listeners of the specified type supported by this container
  1036. * @since 1.3
  1037. */
  1038. public EventListener[] getListeners(Class listenerType) {
  1039. EventListener l = null;
  1040. if (listenerType == ContainerListener.class) {
  1041. l = containerListener;
  1042. } else {
  1043. return super.getListeners(listenerType);
  1044. }
  1045. return AWTEventMulticaster.getListeners(l, listenerType);
  1046. }
  1047. // REMIND: remove when filtering is done at lower level
  1048. boolean eventEnabled(AWTEvent e) {
  1049. int id = e.getID();
  1050. if (id == ContainerEvent.COMPONENT_ADDED ||
  1051. id == ContainerEvent.COMPONENT_REMOVED) {
  1052. if ((eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 ||
  1053. containerListener != null) {
  1054. return true;
  1055. }
  1056. return false;
  1057. }
  1058. return super.eventEnabled(e);
  1059. }
  1060. /**
  1061. * Processes events on this container. If the event is a ContainerEvent,
  1062. * it invokes the processContainerEvent method, else it invokes its
  1063. * superclass's processEvent.
  1064. * @param e the event
  1065. */
  1066. protected void processEvent(AWTEvent e) {
  1067. if (e instanceof ContainerEvent) {
  1068. processContainerEvent((ContainerEvent)e);
  1069. return;
  1070. }
  1071. super.processEvent(e);
  1072. }
  1073. /**
  1074. * Processes container events occurring on this container by
  1075. * dispatching them to any registered ContainerListener objects.
  1076. * NOTE: This method will not be called unless container events
  1077. * are enabled for this component; this happens when one of the
  1078. * following occurs:
  1079. * a) A ContainerListener object is registered via addContainerListener()
  1080. * b) Container events are enabled via enableEvents()
  1081. * @see Component#enableEvents
  1082. * @param e the container event
  1083. */
  1084. protected void processContainerEvent(ContainerEvent e) {
  1085. if (containerListener != null) {
  1086. switch(e.getID()) {
  1087. case ContainerEvent.COMPONENT_ADDED:
  1088. containerListener.componentAdded(e);
  1089. break;
  1090. case ContainerEvent.COMPONENT_REMOVED:
  1091. containerListener.componentRemoved(e);
  1092. break;
  1093. }
  1094. }
  1095. }
  1096. /*
  1097. * Dispatches an event to this component or one of its sub components.
  1098. * Create ANCESTOR_RESIZED and ANCESTOR_MOVED events in response to
  1099. * COMPONENT_RESIZED and COMPONENT_MOVED events. We have to do this
  1100. * here instead of in processComponentEvent because ComponentEvents
  1101. * may not be enabled for this Container.
  1102. * @param e the event
  1103. */
  1104. void dispatchEventImpl(AWTEvent e) {
  1105. if ((dispatcher != null) && dispatcher.dispatchEvent(e)) {
  1106. // event was sent to a lightweight component. The
  1107. // native-produced event sent to the native container
  1108. // must be properly disposed of by the peer, so it
  1109. // gets forwarded. If the native host has been removed
  1110. // as a result of the sending the lightweight event,
  1111. // the peer reference will be null.
  1112. e.consume();
  1113. if (peer != null) {
  1114. peer.handleEvent(e);
  1115. }
  1116. return;
  1117. }
  1118. super.dispatchEventImpl(e);
  1119. switch (e.getID()) {
  1120. case ComponentEvent.COMPONENT_RESIZED:
  1121. createChildHierarchyEvents(HierarchyEvent.ANCESTOR_RESIZED, 0);
  1122. break;
  1123. case ComponentEvent.COMPONENT_MOVED:
  1124. createChildHierarchyEvents(HierarchyEvent.ANCESTOR_MOVED, 0);
  1125. break;
  1126. default:
  1127. break;
  1128. }
  1129. }
  1130. /*
  1131. * Dispatches an event to this component, without trying to forward
  1132. * it to any sub components
  1133. * @param e the event
  1134. */
  1135. void dispatchEventToSelf(AWTEvent e) {
  1136. super.dispatchEventImpl(e);
  1137. }
  1138. /**
  1139. * Fetchs the top-most (deepest) lightweight component that is interested
  1140. * in receiving mouse events.
  1141. */
  1142. Component getMouseEventTarget(int x, int y, boolean includeSelf) {
  1143. int ncomponents = this.ncomponents;
  1144. Component component[] = this.component;
  1145. for (int i = 0 ; i < ncomponents ; i++) {
  1146. Component comp = component[i];
  1147. if ((comp != null) && (comp.contains(x - comp.x, y - comp.y)) &&
  1148. (comp.peer instanceof java.awt.peer.LightweightPeer) &&
  1149. (comp.visible == true)) {
  1150. // found a component that intersects the point, see if there is
  1151. // a deeper possibility.
  1152. if (comp instanceof Container) {
  1153. Container child = (Container) comp;
  1154. Component deeper = child.getMouseEventTarget(x - child.x, y - child.y, includeSelf);
  1155. if (deeper != null) {
  1156. return deeper;
  1157. }
  1158. } else {
  1159. if ((comp.mouseListener != null) ||
  1160. ((comp.eventMask & AWTEvent.MOUSE_EVENT_MASK) != 0) ||
  1161. (comp.mouseMotionListener != null) ||
  1162. ((comp.eventMask & AWTEvent.MOUSE_MOTION_EVENT_MASK) != 0)) {
  1163. // there isn't a deeper target, but this component is a target
  1164. return comp;
  1165. }
  1166. }
  1167. }
  1168. }
  1169. boolean isPeerOK;
  1170. boolean isMouseOverMe;
  1171. boolean isMouseListener;
  1172. boolean isMotionListener;
  1173. isPeerOK = (peer instanceof java.awt.peer.LightweightPeer) || includeSelf;
  1174. isMouseOverMe = contains(x,y);
  1175. isMouseListener = (mouseListener != null) ||
  1176. ((eventMask & AWTEvent.MOUSE_EVENT_MASK) != 0);
  1177. isMotionListener = (mouseMotionListener != null) ||
  1178. ((eventMask & AWTEvent.MOUSE_MOTION_EVENT_MASK) != 0);
  1179. // didn't find a child target, return this component if it's a possible target
  1180. if ( isMouseOverMe && isPeerOK && (isMouseListener || isMotionListener) ) {
  1181. return this;
  1182. }
  1183. // no possible target
  1184. return null;
  1185. }
  1186. /**
  1187. * This is called by lightweight components that want the containing
  1188. * windowed parent to enable some kind of events on their behalf.
  1189. * This is needed for events that are normally only dispatched to
  1190. * windows to be accepted so that they can be forwarded downward to
  1191. * the lightweight component that has enabled them.
  1192. */
  1193. void proxyEnableEvents(long events) {
  1194. if (peer instanceof java.awt.peer.LightweightPeer) {
  1195. // this container is lightweight.... continue sending it
  1196. // upward.
  1197. if (parent != null) { parent.proxyEnableEvents(events); }
  1198. } else {
  1199. // This is a native container, so it needs to host
  1200. // one of it's children. If this function is called before
  1201. // a peer has been created we don't yet have a dispatcher
  1202. // because it has not yet been determined if this instance
  1203. // is lightweight.
  1204. if (dispatcher != null) {
  1205. dispatcher.enableEvents(events);
  1206. }
  1207. }
  1208. }
  1209. Window getWindow() {
  1210. Container w = this;
  1211. while( !(w instanceof Window) ) {
  1212. w = w.getParent();
  1213. }
  1214. return (Window)w;
  1215. }
  1216. /**
  1217. * This is called by lightweight components that have requested focus.
  1218. * The focus request is propagated upward until a native container is
  1219. * found, at which point the native container requests focus and records
  1220. * the component the host is requesting focus for.
  1221. */
  1222. void proxyRequestFocus(Component c) {
  1223. if (peer instanceof java.awt.peer.LightweightPeer) {
  1224. // this container is lightweight... continue sending it
  1225. // upward.
  1226. if (parent != null) { parent.proxyRequestFocus(c); }
  1227. } else {
  1228. // This is a windowed container, so record true focus
  1229. // component and request focus from the native window
  1230. // if needed.
  1231. if (dispatcher != null && dispatcher.setFocusRequest(c)) {
  1232. // If the focus is currently somewhere within this Window,
  1233. // call the peer to set focus to this Container. This way,
  1234. // we avoid activating this Window if it's not currently
  1235. // active. -fredx, 2-19-98, bug #4111098
  1236. Component window = this;
  1237. while (!(window instanceof Window) && window != null)
  1238. window = window.getParent();
  1239. if (window != null && ((Window)window).isActive()) {
  1240. peer.requestFocus();
  1241. }
  1242. Toolkit.getEventQueue().changeKeyEventFocus(this);
  1243. }
  1244. }
  1245. }
  1246. /**
  1247. * @deprecated As of JDK version 1.1,
  1248. * replaced by <code>dispatchEvent(AWTEvent e)</code>
  1249. */
  1250. public void deliverEvent(Event e) {
  1251. Component comp = getComponentAt(e.x, e.y);
  1252. if ((comp != null) && (comp != this)) {
  1253. e.translate(-comp.x, -comp.y);
  1254. comp.deliverEvent(e);
  1255. } else {
  1256. postEvent(e);
  1257. }
  1258. }
  1259. /**
  1260. * Locates the component that contains the x,y position. The
  1261. * top-most child component is returned in the case where there
  1262. * is overlap in the components. This is determined by finding
  1263. * the component closest to the index 0 that claims to contain
  1264. * the given point via Component.contains(), except that Components
  1265. * which have native peers take precedence over those which do not
  1266. * (i.e., lightweight Components).
  1267. *
  1268. * @param x the <i>x</i> coordinate
  1269. * @param y the <i>y</i> coordinate
  1270. * @return null if the component does not contain the position.
  1271. * If there is no child component at the requested point and the
  1272. * point is within the bounds of the container the container itself
  1273. * is returned; otherwise the top-most child is returned.
  1274. * @see Component#contains
  1275. * @since JDK1.1
  1276. */
  1277. public Component getComponentAt(int x, int y) {
  1278. return locate(x, y);
  1279. }
  1280. /**
  1281. * @deprecated As of JDK version 1.1,
  1282. * replaced by <code>getComponentAt(int, int)</code>.
  1283. */
  1284. public Component locate(int x, int y) {
  1285. if (!contains(x, y)) {
  1286. return null;
  1287. }
  1288. synchronized (getTreeLock()) {
  1289. // Two passes: see comment in sun.awt.SunGraphicsCallback
  1290. for (int i = 0 ; i < ncomponents ; i++) {
  1291. Component comp = component[i];
  1292. if (comp != null &&
  1293. !(comp.peer instanceof java.awt.peer.LightweightPeer)) {
  1294. if (comp.contains(x - comp.x, y - comp.y)) {
  1295. return comp;
  1296. }
  1297. }
  1298. }
  1299. for (int i = 0 ; i < ncomponents ; i++) {
  1300. Component comp = component[i];
  1301. if (comp != null &&
  1302. comp.peer instanceof java.awt.peer.LightweightPeer) {
  1303. if (comp.contains(x - comp.x, y - comp.y)) {
  1304. return comp;
  1305. }
  1306. }
  1307. }
  1308. }
  1309. return this;
  1310. }
  1311. /**
  1312. * Gets the component that contains the specified point.
  1313. * @param p the point.
  1314. * @return returns the component that contains the point,
  1315. * or <code>null</code> if the component does
  1316. * not contain the point.
  1317. * @see java.awt.Component#contains
  1318. * @since JDK1.1
  1319. */
  1320. public Component getComponentAt(Point p) {
  1321. return getComponentAt(p.x, p.y);
  1322. }
  1323. /**
  1324. * Locates the visible child component that contains the specified
  1325. * position. The top-most child component is returned in the case
  1326. * where there is overlap in the components. If the containing child
  1327. * component is a Container, this method will continue searching for
  1328. * the deepest nested child component. Components which are not
  1329. * visible are ignored during the search.<p>
  1330. *
  1331. * The findComponentAt method is different from getComponentAt in
  1332. * that getComponentAt only searches the Container's immediate
  1333. * children; if the containing component is a Container,
  1334. * findComponentAt will search that child to find a nested component.
  1335. *
  1336. * @param x the <i>x</i> coordinate
  1337. * @param y the <i>y</i> coordinate
  1338. * @return null if the component does not contain the position.
  1339. * If there is no child component at the requested point and the
  1340. * point is within the bounds of the container the container itself
  1341. * is returned.
  1342. * @see Component#contains
  1343. * @see getComponentAt
  1344. * @since 1.2
  1345. */
  1346. public Component findComponentAt(int x, int y) {
  1347. synchronized (getTreeLock()) {
  1348. return findComponentAt(x, y, true, false);
  1349. }
  1350. }
  1351. /**
  1352. * Private version of findComponentAt which has two controllable
  1353. * behaviors. Setting 'ignoreEnabled' to 'false' bypasses disabled
  1354. * Components during the serach. This behavior is used by the
  1355. * lightweight cursor support in sun.awt.GlobalCursorManager.
  1356. * Setting 'ignoreGlassPane' to 'true' bypasses the glass panes owned
  1357. * by any JRootPanes found during the search. This behavior is
  1358. * used by the DnD event targeting code. The cursor and DnD code
  1359. * both call this function directly via native code.
  1360. *
  1361. * The addition of both of these features is temporary, pending the
  1362. * adoption of new, public APIs which export these features (probably
  1363. * in merlin).
  1364. */
  1365. final Component findComponentAt(int x, int y, boolean ignoreEnabled,
  1366. boolean ignoreGlassPane)
  1367. {
  1368. if (!(contains(x, y) && visible && (ignoreEnabled || enabled))) {
  1369. return null;
  1370. }
  1371. int ncomponents = this.ncomponents;
  1372. Component component[] = this.component;
  1373. Component glassPane = null;
  1374. if (ignoreGlassPane && (this instanceof JRootPane)) {
  1375. glassPane = ((JRootPane)this).getGlassPane();
  1376. }
  1377. // Two passes: see comment in sun.awt.SunGraphicsCallback
  1378. for (int i = 0 ; i < ncomponents ; i++) {
  1379. Component comp = component[i];
  1380. if (comp != null && comp != glassPane &&
  1381. !(comp.peer instanceof java.awt.peer.LightweightPeer)) {
  1382. if (comp instanceof Container) {
  1383. comp = ((Container)comp).findComponentAt(x - comp.x,
  1384. y - comp.y,
  1385. ignoreEnabled,
  1386. ignoreGlassPane);
  1387. } else {
  1388. comp = comp.locate(x - comp.x, y - comp.y);
  1389. }
  1390. if (comp != null && comp.visible &&
  1391. (ignoreEnabled || comp.enabled))
  1392. {
  1393. return comp;
  1394. }
  1395. }
  1396. }
  1397. for (int i = 0 ; i < ncomponents ; i++) {
  1398. Component comp = component[i];
  1399. if (comp != null && comp != glassPane &&
  1400. comp.peer instanceof java.awt.peer.LightweightPeer) {
  1401. if (comp instanceof Container) {
  1402. comp = ((Container)comp).findComponentAt(x - comp.x,
  1403. y - comp.y,
  1404. ignoreEnabled,
  1405. ignoreGlassPane);
  1406. } else {
  1407. comp = comp.locate(x - comp.x, y - comp.y);
  1408. }
  1409. if (comp != null && comp.visible &&
  1410. (ignoreEnabled || comp.enabled))
  1411. {
  1412. return comp;
  1413. }
  1414. }
  1415. }
  1416. return this;
  1417. }
  1418. /**
  1419. * Locates the visible child component that contains the specified
  1420. * point. The top-most child component is returned in the case
  1421. * where there is overlap in the components. If the containing child
  1422. * component is a Container, this method will continue searching for
  1423. * the deepest nested child component. Components which are not
  1424. * visible are ignored during the search.<p>
  1425. *
  1426. * The findComponentAt method is different from getComponentAt in
  1427. * that getComponentAt only searches the Container's immediate
  1428. * children; if the containing component is a Container,
  1429. * findComponentAt will search that child to find a nested component.
  1430. *
  1431. * @param p the point.
  1432. * @return null if the component does not contain the position.
  1433. * If there is no child component at the requested point and the
  1434. * point is within the bounds of the container the container itself
  1435. * is returned.
  1436. * @see Component#contains
  1437. * @see getComponentAt
  1438. * @since 1.2
  1439. */
  1440. public Component findComponentAt(Point p) {
  1441. return findComponentAt(p.x, p.y);
  1442. }
  1443. /**
  1444. * Makes this Container displayable by connecting it to
  1445. * a native screen resource. Making a container displayable will
  1446. * cause any of its children to be made displayable.
  1447. * This method is called internally by the toolkit and should
  1448. * not be called directly by programs.
  1449. * @see Component#isDisplayable
  1450. * @see #removeNotify
  1451. */
  1452. public void addNotify() {
  1453. synchronized (getTreeLock()) {
  1454. // addNotify() on the children may cause proxy event enabling
  1455. // on this instance, so we first call super.addNotify() and
  1456. // possibly create an lightweight event dispatcher before calling
  1457. // addNotify() on the children which may be lightweight.
  1458. super.addNotify();
  1459. if (! (peer instanceof java.awt.peer.LightweightPeer)) {
  1460. dispatcher = new LightweightDispatcher(this);
  1461. }
  1462. int ncomponents = this.ncomponents;
  1463. Component component[] = this.component;
  1464. for (int i = 0 ; i < ncomponents ; i++) {
  1465. component[i].addNotify();
  1466. }
  1467. }
  1468. }
  1469. /**
  1470. * Makes this Container undisplayable by removing its connection
  1471. * to its native screen resource. Make a container undisplayable
  1472. * will cause any of its children to be made undisplayable.
  1473. * This method is called by the toolkit internally and should
  1474. * not be called directly by programs.
  1475. * @see Component#isDisplayable
  1476. * @see #addNotify
  1477. */
  1478. public void removeNotify() {
  1479. synchronized (getTreeLock()) {
  1480. int ncomponents = this.ncomponents;
  1481. Component component[] = this.component;
  1482. for (int i = 0 ; i < ncomponents ; i++) {
  1483. component[i].removeNotify();
  1484. }
  1485. if ( dispatcher != null ) {
  1486. dispatcher.dispose();
  1487. }
  1488. super.removeNotify();
  1489. }
  1490. }
  1491. /**
  1492. * Checks if the component is contained in the component hierarchy of
  1493. * this container.
  1494. * @param c the component
  1495. * @return <code>true</code> if it is an ancestor;
  1496. * <code>false</code> otherwise.
  1497. * @since JDK1.1
  1498. */
  1499. public boolean isAncestorOf(Component c) {
  1500. Container p;
  1501. if (c == null || ((p = c.getParent()) == null)) {
  1502. return false;
  1503. }
  1504. while (p != null) {
  1505. if (p == this) {
  1506. return true;
  1507. }
  1508. p = p.getParent();
  1509. }
  1510. return false;
  1511. }
  1512. /**
  1513. * Returns the parameter string representing the state of this
  1514. * container. This string is useful for debugging.
  1515. * @return the parameter string of this container.
  1516. */
  1517. protected String paramString() {
  1518. String str = super.paramString();
  1519. LayoutManager layoutMgr = this.layoutMgr;
  1520. if (layoutMgr != null) {
  1521. str += ",layout=" + layoutMgr.getClass().getName();
  1522. }
  1523. return str;
  1524. }
  1525. /**
  1526. * Prints a listing of this container to the specified output
  1527. * stream. The listing starts at the specified indentation.
  1528. * @param out a print stream.
  1529. * @param indent the number of spaces to indent.
  1530. * @see java.awt.Component#list(java.io.PrintStream, int)
  1531. * @since JDK
  1532. */
  1533. public void list(PrintStream out, int indent) {
  1534. super.list(out, indent);
  1535. int ncomponents = this.ncomponents;
  1536. Component component[] = this.component;
  1537. for (int i = 0 ; i < ncomponents ; i++) {
  1538. Component comp = component[i];
  1539. if (comp != null) {
  1540. comp.list(out, indent+1);
  1541. }
  1542. }
  1543. }
  1544. /**
  1545. * Prints out a list, starting at the specified indention, to the specified
  1546. * print writer.
  1547. */
  1548. public void list(PrintWriter out, int indent) {
  1549. super.list(out, indent);
  1550. int ncomponents = this.ncomponents;
  1551. Component component[] = this.component;
  1552. for (int i = 0 ; i < ncomponents ; i++) {
  1553. Component comp = component[i];
  1554. if (comp != null) {
  1555. comp.list(out, indent+1);
  1556. }
  1557. }
  1558. }
  1559. void setFocusOwner(Component c) {
  1560. Container parent = this.parent;
  1561. if (parent != null) {
  1562. parent.setFocusOwner(c);
  1563. }
  1564. }
  1565. void preProcessKeyEvent(KeyEvent e) {
  1566. Container parent = this.parent;
  1567. if (parent != null) {
  1568. parent.preProcessKeyEvent(e);
  1569. }
  1570. }
  1571. void postProcessKeyEvent(KeyEvent e) {
  1572. Container parent = this.parent;
  1573. if (parent != null) {
  1574. parent.postProcessKeyEvent(e);
  1575. }
  1576. }
  1577. void transferFocus(Component base) {
  1578. nextFocus(base);
  1579. }
  1580. boolean postsOldMouseEvents() {
  1581. return true;
  1582. }
  1583. /**
  1584. * @deprecated As of JDK version 1.1,
  1585. * replaced by transferFocus(Component).
  1586. */
  1587. void nextFocus(Component base) {
  1588. Container parent = this.parent;
  1589. if (parent != null) {
  1590. parent.transferFocus(base);
  1591. }
  1592. }
  1593. /**
  1594. * Package-visible utility to set the orientation of this container
  1595. * and all components contained within it.
  1596. * @since 1.2
  1597. * @see java.awt.Window#applyResourceBundle(java.util.ResourceBundle)
  1598. */
  1599. void applyOrientation(ComponentOrientation o) {
  1600. setComponentOrientation(o);
  1601. for (int i = 0 ; i < ncomponents ; ++i) {
  1602. Component comp = component[i];
  1603. if (comp instanceof Container) {
  1604. ((Container)comp).applyOrientation(o);
  1605. } else {
  1606. comp.setComponentOrientation(o);
  1607. }
  1608. }
  1609. }
  1610. /* Serialization support. A Container is responsible for
  1611. * restoring the parent fields of its component children.
  1612. */
  1613. /*
  1614. * Container Serial Data Version.
  1615. * @serial
  1616. */
  1617. private int containerSerializedDataVersion = 1;
  1618. /**
  1619. * Writes default serializable fields to stream. Writes
  1620. * a list of serializable ItemListener(s) as optional data.
  1621. * The non-serializable ItemListner(s) are detected and
  1622. * no attempt is made to serialize them.
  1623. *
  1624. * @serialData Null terminated sequence of 0 or more pairs.
  1625. * The pair consists of a String and Object.
  1626. * The String indicates the type of object and
  1627. * is one of the following :
  1628. * itemListenerK indicating and ItemListener object.
  1629. *
  1630. * @see AWTEventMulticaster.save(ObjectOutputStream, String, EventListener)
  1631. * @see java.awt.Component.itemListenerK
  1632. */
  1633. private void writeObject(ObjectOutputStream s)
  1634. throws IOException
  1635. {
  1636. s.defaultWriteObject();
  1637. AWTEventMulticaster.save(s, containerListenerK, containerListener);
  1638. s.writeObject(null);
  1639. }
  1640. /*
  1641. * Read the ObjectInputStream and if it isnt null
  1642. * add a listener to receive item events fired
  1643. * by the component in the container.
  1644. * Unrecognised keys or values will be Ignored.
  1645. * @serial
  1646. * @see removeActionListener()
  1647. * @see addActionListener()
  1648. */
  1649. private void readObject(ObjectInputStream s)
  1650. throws ClassNotFoundException, IOException
  1651. {
  1652. s.defaultReadObject();
  1653. Component component[] = this.component;
  1654. for(int i = 0; i < ncomponents; i++) {
  1655. component[i].parent = this;
  1656. adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK,
  1657. component[i].numListening(AWTEvent.HIERARCHY_EVENT_MASK));
  1658. adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
  1659. component[i].numListening(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));
  1660. }
  1661. Object keyOrNull;
  1662. while(null != (keyOrNull = s.readObject())) {
  1663. String key = ((String)keyOrNull).intern();
  1664. if (containerListenerK == key)
  1665. addContainerListener((ContainerListener)(s.readObject()));
  1666. else // skip value for unrecognized key
  1667. s.readObject();
  1668. }
  1669. }
  1670. /*
  1671. * --- Accessibility Support ---
  1672. */
  1673. /**
  1674. * Inner class of Container used to provide default support for
  1675. * accessibility. This class is not meant to be used directly by
  1676. * application developers, but is instead meant only to be
  1677. * subclassed by container developers.
  1678. * <p>
  1679. * The class used to obtain the accessible role for this object,
  1680. * as well as implementing many of the methods in the
  1681. * AccessibleContainer interface.
  1682. */
  1683. protected class AccessibleAWTContainer extends AccessibleAWTComponent {
  1684. /**
  1685. * Returns the number of accessible children in the object. If all
  1686. * of the children of this object implement Accessible, than this
  1687. * method should return the number of children of this object.
  1688. *
  1689. * @return the number of accessible children in the object.
  1690. */
  1691. public int getAccessibleChildrenCount() {
  1692. return Container.this.getAccessibleChildrenCount();
  1693. }
  1694. /**
  1695. * Return the nth Accessible child of the object.
  1696. *
  1697. * @param i zero-based index of child
  1698. * @return the nth Accessible child of the object
  1699. */
  1700. public Accessible getAccessibleChild(int i) {
  1701. return Container.this.getAccessibleChild(i);
  1702. }
  1703. /**
  1704. * Returns the Accessible child, if one exists, contained at the local
  1705. * coordinate Point.
  1706. *
  1707. * @param p The point defining the top-left corner of the Accessible,
  1708. * given in the coordinate space of the object's parent.
  1709. * @return the Accessible, if it exists, at the specified location;
  1710. * else null
  1711. */
  1712. public Accessible getAccessibleAt(Point p) {
  1713. return Container.this.getAccessibleAt(p);
  1714. }
  1715. protected ContainerListener accessibleContainerHandler = null;
  1716. /**
  1717. * Fire PropertyChange listener, if one is registered,
  1718. * when children added/removed.
  1719. */
  1720. protected class AccessibleContainerHandler
  1721. implements ContainerListener {
  1722. public void componentAdded(ContainerEvent e) {
  1723. Component c = e.getChild();
  1724. if (c != null && c instanceof Accessible) {
  1725. AccessibleAWTContainer.this.firePropertyChange(
  1726. AccessibleContext.ACCESSIBLE_CHILD_PROPERTY,
  1727. null, ((Accessible) c).getAccessibleContext());
  1728. }
  1729. }
  1730. public void componentRemoved(ContainerEvent e) {
  1731. Component c = e.getChild();
  1732. if (c != null && c instanceof Accessible) {
  1733. AccessibleAWTContainer.this.firePropertyChange(
  1734. AccessibleContext.ACCESSIBLE_CHILD_PROPERTY,
  1735. ((Accessible) c).getAccessibleContext(), null);
  1736. }
  1737. }
  1738. }
  1739. } // inner class AccessibleAWTContainer
  1740. /**
  1741. * Returns the Accessible child contained at the local coordinate
  1742. * Point, if one exists.
  1743. *
  1744. * @return the Accessible at the specified location, if it exists
  1745. */
  1746. Accessible getAccessibleAt(Point p) {
  1747. synchronized (getTreeLock()) {
  1748. if (this instanceof Accessible) {
  1749. Accessible a = (Accessible)this;
  1750. AccessibleContext ac = a.getAccessibleContext();
  1751. if (ac != null) {
  1752. AccessibleComponent acmp;
  1753. Point location;
  1754. int nchildren = ac.getAccessibleChildrenCount();
  1755. for (int i=0; i < nchildren; i++) {
  1756. a = ac.getAccessibleChild(i);
  1757. if ((a != null)) {
  1758. ac = a.getAccessibleContext();
  1759. if (ac != null) {
  1760. acmp = ac.getAccessibleComponent();
  1761. if ((acmp != null) && (acmp.isShowing())) {
  1762. location = acmp.getLocation();
  1763. Point np = new Point(p.x-location.x,
  1764. p.y-location.y);
  1765. if (acmp.contains(np)){
  1766. return a;
  1767. }
  1768. }
  1769. }
  1770. }
  1771. }
  1772. }
  1773. return (Accessible)this;
  1774. } else {
  1775. Component ret = this;
  1776. if (!this.contains(p.x,p.y)) {
  1777. ret = null;
  1778. } else {
  1779. int ncomponents = this.getComponentCount();
  1780. for (int i=0; i < ncomponents; i++) {
  1781. Component comp = this.getComponent(i);
  1782. if ((comp != null) && comp.isShowing()) {
  1783. Point location = comp.getLocation();
  1784. if (comp.contains(p.x-location.x,p.y-location.y)) {
  1785. ret = comp;
  1786. }
  1787. }
  1788. }
  1789. }
  1790. if (ret instanceof Accessible) {
  1791. return (Accessible) ret;
  1792. }
  1793. }
  1794. return null;
  1795. }
  1796. }
  1797. /**
  1798. * Returns the number of accessible children in the object. If all
  1799. * of the children of this object implement Accessible, than this
  1800. * method should return the number of children of this object.
  1801. *
  1802. * @return the number of accessible children in the object.
  1803. */
  1804. int getAccessibleChildrenCount() {
  1805. synchronized (getTreeLock()) {
  1806. int count = 0;
  1807. Component[] children = this.getComponents();
  1808. for (int i = 0; i < children.length; i++) {
  1809. if (children[i] instanceof Accessible) {
  1810. count++;
  1811. }
  1812. }
  1813. return count;
  1814. }
  1815. }
  1816. /**
  1817. * Return the nth Accessible child of the object.
  1818. *
  1819. * @param i zero-based index of child
  1820. * @return the nth Accessible child of the object
  1821. */
  1822. Accessible getAccessibleChild(int i) {
  1823. synchronized (getTreeLock()) {
  1824. Component[] children = this.getComponents();
  1825. int count = 0;
  1826. for (int j = 0; j < children.length; j++) {
  1827. if (children[j] instanceof Accessible) {
  1828. if (count == i) {
  1829. return (Accessible) children[j];
  1830. } else {
  1831. count++;
  1832. }
  1833. }
  1834. }
  1835. return null;
  1836. }
  1837. }
  1838. }
  1839. /**
  1840. * Class to manage the dispatching of events to the lightweight
  1841. * components contained by a native container.
  1842. *
  1843. * @author Timothy Prinzing
  1844. */
  1845. class LightweightDispatcher implements java.io.Serializable, AWTEventListener {
  1846. /*
  1847. * JDK 1.1 serialVersionUID
  1848. */
  1849. private static final long serialVersionUID = 5184291520170872969L;
  1850. /*
  1851. * Our own mouse event for when we're dragged over from another hw container
  1852. */
  1853. private static final int LWD_MOUSE_DRAGGED_OVER = 1500;
  1854. LightweightDispatcher(Container nativeContainer) {
  1855. this.nativeContainer = nativeContainer;
  1856. focus = null;
  1857. mouseEventTarget = null;
  1858. eventMask = 0;
  1859. }
  1860. /*
  1861. * Clean up any resources allocated when dispatcher was created;
  1862. * should be called from Container.removeNotify
  1863. */
  1864. void dispose() {
  1865. //System.out.println("Disposing lw dispatcher");
  1866. stopListeningForOtherDrags();
  1867. }
  1868. /**
  1869. * Enables events to lightweight components.
  1870. */
  1871. void enableEvents(long events) {
  1872. eventMask |= events;
  1873. }
  1874. /**
  1875. * This is called by the hosting native container on behalf of lightweight
  1876. * components that have requested focus. The focus request is propagated
  1877. * upward from the requesting lightweight component until a windowed host
  1878. * is found, at which point the windowed host calls this method. This
  1879. * method returns whether or not the peer associated with the native
  1880. * component needs to request focus from the native window system. When
  1881. * that happens, the native window system will generate the necessary focus
  1882. * events.
  1883. *
  1884. * If a lightweight component already has focus the focus events are
  1885. * synthesized, since there will be no native events to drive the focus.
  1886. * If the native host already has focus, the focus gained is synthesized
  1887. * for the lightweight component requesting focus, since it will receive no
  1888. * native focus requests.
  1889. */
  1890. boolean setFocusRequest(Component c) {
  1891. boolean peerRequest = false;
  1892. Window w = nativeContainer.getWindow();
  1893. if (w == null || c == null) {
  1894. return true;
  1895. }
  1896. // Get the current owner of the focus
  1897. Component focusOwner = w.getFocusOwner();
  1898. // Push the new component on the stack
  1899. focusStack.push(c);
  1900. // After the first component has been pushed on the stack,
  1901. // handle focus lost for the current focus owner
  1902. if (focusStack.size() == 1) {
  1903. if (focusOwner == null) {
  1904. // No container has focus, no need to send focus lost.
  1905. // Peer will need to request focus.
  1906. peerRequest = true;
  1907. } else if (focusOwner == nativeContainer) {
  1908. // The native container already has focus, so just
  1909. // send a FOCUS_LOST event to the container.
  1910. nativeContainer.dispatchEvent(
  1911. new FocusEvent(nativeContainer,
  1912. FocusEvent.FOCUS_LOST, false));
  1913. } else if (focusOwner == c) {
  1914. // The lightweight component itself already has the
  1915. // focus, no need to send focus lost.
  1916. } else if (focusOwner == focus) {
  1917. // A lightweight component has focus currently and a new one
  1918. // has been requested. There won't be any window-system events
  1919. // associated with this so we go ahead and send FOCUS_LOST for
  1920. // the old component.
  1921. if (focus != null) {
  1922. focus.dispatchEvent(new FocusEvent(focus,
  1923. FocusEvent.FOCUS_LOST, false));
  1924. }
  1925. } else {
  1926. // Fix for bug 4095214
  1927. // Paul Sheehan
  1928. // In any other case, the peer will need to request focus.
  1929. peerRequest = true;
  1930. }
  1931. }
  1932. int focusStackSize = focusStack.size();
  1933. // If there are components on the stack, we need to handle focus gained
  1934. // for the topmost component.
  1935. if (focusStackSize > 0) {
  1936. focus = (Component)focusStack.pop();
  1937. // Clear the stack so that the focus gained is not handled again.
  1938. focusStack.clear();
  1939. // Send a focus gained only when the peer does not need to
  1940. // handle the focus request.
  1941. //
  1942. // Also, if the focus owner is the component itself, we should
  1943. // send the focus gained event only if the stack depth was greater
  1944. // than 1. If it was only 1, then the component was never given
  1945. // a focus lost, so we shouldn't send a focus gained. If it was
  1946. // greater than 1, we have only gotten here through sending a
  1947. // focus lost to the component, so we need to send focus gained
  1948. // back to the component again.
  1949. if (!peerRequest && (focusOwner != c || focusStackSize > 1)) {
  1950. focus.dispatchEvent(new FocusEvent(focus,
  1951. FocusEvent.FOCUS_GAINED, false));
  1952. }
  1953. }
  1954. return peerRequest;
  1955. }
  1956. /**
  1957. * Dispatches an event to a lightweight sub-component if necessary, and
  1958. * returns whether or not the event was forwarded to a lightweight
  1959. * sub-component.
  1960. *
  1961. * @param e the event
  1962. */
  1963. boolean dispatchEvent(AWTEvent e) {
  1964. boolean ret = false;
  1965. if ((eventMask & PROXY_EVENT_MASK) != 0) {
  1966. if ((e instanceof MouseEvent) &&
  1967. ((eventMask & MOUSE_MASK) != 0)) {
  1968. MouseEvent me = (MouseEvent) e;
  1969. ret = processMouseEvent(me);
  1970. } else if (e instanceof FocusEvent) {
  1971. FocusEvent fe = (FocusEvent) e;
  1972. ret = processFocusEvent(fe);
  1973. } else if (e instanceof KeyEvent) {
  1974. KeyEvent ke = (KeyEvent) e;
  1975. ret = processKeyEvent(ke);
  1976. }
  1977. }
  1978. if (e.getID() == MouseEvent.MOUSE_MOVED) {
  1979. GlobalCursorManager.updateCursorImmediately((InputEvent)e);
  1980. }
  1981. return ret;
  1982. }
  1983. private boolean processKeyEvent(KeyEvent e) {
  1984. if (focus != null) {
  1985. // Don't duplicate the event here.
  1986. // The KeyEvent for LightWeightComponent is also passed to
  1987. // input methods and their native handlers. The native handlers
  1988. // require the original native event data to be attached to
  1989. // the KeyEvent.
  1990. Component source = e.getComponent();
  1991. e.setSource(focus);
  1992. focus.dispatchEvent(e);
  1993. e.setSource(source);
  1994. return e.isConsumed();
  1995. }
  1996. return false;
  1997. }
  1998. private boolean processFocusEvent(FocusEvent e) {
  1999. if (focus != null) {
  2000. int id = e.getID();
  2001. FocusEvent retargeted = new FocusEvent(focus, id, e.isTemporary());
  2002. ((AWTEvent)e).copyPrivateDataInto(retargeted);
  2003. focus.dispatchEvent(retargeted);
  2004. if ((id == FocusEvent.FOCUS_LOST) && (e.isTemporary() == false)) {
  2005. focus = null;
  2006. }
  2007. return true;
  2008. }
  2009. return false;
  2010. }
  2011. /**
  2012. * This method attempts to distribute a mouse event to a lightweight
  2013. * component. It tries to avoid doing any unnecessary probes down
  2014. * into the component tree to minimize the overhead of determining
  2015. * where to route the event, since mouse movement events tend to
  2016. * come in large and frequent amounts.
  2017. */
  2018. private boolean processMouseEvent(MouseEvent e) {
  2019. int id = e.getID();
  2020. Component targetOver;
  2021. Component lwOver;
  2022. targetOver = nativeContainer.getMouseEventTarget(e.getX(), e.getY(),true);
  2023. trackMouseEnterExit(targetOver, e);
  2024. if (mouseEventTarget == null) {
  2025. if ( id == MouseEvent.MOUSE_MOVED ||
  2026. id == MouseEvent.MOUSE_PRESSED ) {
  2027. lwOver = (targetOver != nativeContainer) ? targetOver : null;
  2028. setMouseTarget(lwOver,e);
  2029. }
  2030. }
  2031. if (mouseEventTarget != null) {
  2032. // we are currently forwarding to some component, check
  2033. // to see if we should continue to forward.
  2034. switch(id) {
  2035. case MouseEvent.MOUSE_DRAGGED:
  2036. if(dragging) {
  2037. retargetMouseEvent(mouseEventTarget, id, e);
  2038. }
  2039. break;
  2040. case MouseEvent.MOUSE_PRESSED:
  2041. dragging = true;
  2042. retargetMouseEvent(mouseEventTarget, id, e);
  2043. break;
  2044. case MouseEvent.MOUSE_RELEASED:
  2045. {
  2046. Component releasedTarget = mouseEventTarget;
  2047. dragging = false;
  2048. retargetMouseEvent(mouseEventTarget, id, e);
  2049. lwOver = nativeContainer.getMouseEventTarget(e.getX(), e.getY(),false);
  2050. setMouseTarget(lwOver, e);
  2051. // fix 4155217
  2052. // component was hidden or moved in user code MOUSE_RELEASED handling
  2053. isClickOrphaned = lwOver != releasedTarget;
  2054. break;
  2055. }
  2056. case MouseEvent.MOUSE_CLICKED:
  2057. if (!isClickOrphaned) {
  2058. // fix 4155217
  2059. // click event should not be redirected since component has moved or hidden
  2060. retargetMouseEvent(mouseEventTarget, id, e);
  2061. }
  2062. isClickOrphaned = false;
  2063. break;
  2064. case MouseEvent.MOUSE_ENTERED:
  2065. break;
  2066. case MouseEvent.MOUSE_EXITED:
  2067. if (!dragging) {
  2068. setMouseTarget(null, e);
  2069. }
  2070. break;
  2071. case MouseEvent.MOUSE_MOVED:
  2072. lwOver = nativeContainer.getMouseEventTarget(e.getX(), e.getY(),false);
  2073. setMouseTarget(lwOver, e);
  2074. retargetMouseEvent(mouseEventTarget, id, e);
  2075. break;
  2076. }
  2077. e.consume();
  2078. }
  2079. return e.isConsumed();
  2080. }
  2081. /**
  2082. * Change the current target of mouse events.
  2083. */
  2084. private void setMouseTarget(Component target, MouseEvent e) {
  2085. if (target != mouseEventTarget) {
  2086. //System.out.println("setMouseTarget: " + target);
  2087. mouseEventTarget = target;
  2088. }
  2089. }
  2090. /*
  2091. * Generates enter/exit events as mouse moves over lw components
  2092. * @param targetOver Target mouse is over (including native container)
  2093. * @param e Mouse event in native container
  2094. */
  2095. private void trackMouseEnterExit(Component targetOver, MouseEvent e) {
  2096. Component targetEnter = null;
  2097. int id = e.getID();
  2098. if ( id != MouseEvent.MOUSE_EXITED &&
  2099. id != MouseEvent.MOUSE_DRAGGED &&
  2100. id != LWD_MOUSE_DRAGGED_OVER &&
  2101. isMouseInNativeContainer == false ) {
  2102. // any event but an exit or drag means we're in the native container
  2103. isMouseInNativeContainer = true;
  2104. startListeningForOtherDrags();
  2105. } else if ( id == MouseEvent.MOUSE_EXITED ) {
  2106. isMouseInNativeContainer = false;
  2107. stopListeningForOtherDrags();
  2108. }
  2109. if (isMouseInNativeContainer) {
  2110. targetEnter = targetOver;
  2111. }
  2112. if (targetLastEntered == targetEnter) {
  2113. return;
  2114. }
  2115. //System.out.println("targetOver = " + targetOver);
  2116. //System.out.println("targetEnter = " + targetEnter);
  2117. //System.out.println("targetLastEntered = " + targetLastEntered);
  2118. // Fix 4150851 : if a lightweight component is on the border the
  2119. // native container does not get the event
  2120. if (targetLastEntered != null &&
  2121. targetLastEntered != nativeContainer) {
  2122. retargetMouseEvent(targetLastEntered, MouseEvent.MOUSE_EXITED, e);
  2123. }
  2124. if (nativeContainer != null &&
  2125. targetEnter == null) {
  2126. retargetMouseEvent(nativeContainer, MouseEvent.MOUSE_EXITED, e);
  2127. }
  2128. if (id == MouseEvent.MOUSE_EXITED) {
  2129. // consume native exit event if we generate one
  2130. e.consume();
  2131. }
  2132. // Fix 4150851 : if a lightweight component is on the border the
  2133. // native container does not get the event
  2134. if (nativeContainer != null &&
  2135. targetLastEntered == null) {
  2136. retargetMouseEvent(nativeContainer, MouseEvent.MOUSE_ENTERED, e);
  2137. }
  2138. if (targetEnter != null &&
  2139. targetEnter != nativeContainer) {
  2140. retargetMouseEvent(targetEnter, MouseEvent.MOUSE_ENTERED, e);
  2141. }
  2142. if (id == MouseEvent.MOUSE_ENTERED) {
  2143. // consume native enter event if we generate one
  2144. e.consume();
  2145. }
  2146. //System.out.println("targetLastEntered: " + targetLastEntered);
  2147. targetLastEntered = targetEnter;
  2148. }
  2149. /*
  2150. * Listens to global mouse drag events so even drags originating
  2151. * from other heavyweight containers will generate enter/exit
  2152. * events in this container
  2153. */
  2154. private void startListeningForOtherDrags() {
  2155. //System.out.println("Adding AWTEventListener");
  2156. java.security.AccessController.doPrivileged(
  2157. new java.security.PrivilegedAction() {
  2158. public Object run() {
  2159. nativeContainer.getToolkit().addAWTEventListener(
  2160. LightweightDispatcher.this,
  2161. AWTEvent.MOUSE_EVENT_MASK |
  2162. AWTEvent.MOUSE_MOTION_EVENT_MASK);
  2163. return null;
  2164. }
  2165. }
  2166. );
  2167. }
  2168. private void stopListeningForOtherDrags() {
  2169. //System.out.println("Removing AWTEventListener");
  2170. java.security.AccessController.doPrivileged(
  2171. new java.security.PrivilegedAction() {
  2172. public Object run() {
  2173. nativeContainer.getToolkit().removeAWTEventListener(LightweightDispatcher.this);
  2174. return null;
  2175. }
  2176. }
  2177. );
  2178. }
  2179. /*
  2180. * (Implementation of AWTEventListener)
  2181. * Listen for drag events posted in other hw components so we can
  2182. * track enter/exit regardless of where a drag originated
  2183. */
  2184. public void eventDispatched(AWTEvent e) {
  2185. boolean isForeignDrag = (e instanceof MouseEvent) &&
  2186. (e.id == MouseEvent.MOUSE_DRAGGED) &&
  2187. (e.getSource() != nativeContainer);
  2188. if (!isForeignDrag) {
  2189. // only interested in drags from other hw components
  2190. return;
  2191. }
  2192. MouseEvent srcEvent = (MouseEvent)e;
  2193. MouseEvent me;
  2194. synchronized (nativeContainer.getTreeLock()) {
  2195. Component srcComponent = srcEvent.getComponent();
  2196. // component may have disappeared since drag event posted
  2197. // (i.e. Swing hierarchical menus)
  2198. if ( !srcComponent.isShowing() ||
  2199. !nativeContainer.isShowing() ) {
  2200. return;
  2201. }
  2202. //
  2203. // create an internal 'dragged-over' event indicating
  2204. // we are being dragged over from another hw component
  2205. //
  2206. me = new MouseEvent(nativeContainer,
  2207. LWD_MOUSE_DRAGGED_OVER,
  2208. srcEvent.getWhen(),
  2209. srcEvent.getModifiers(),
  2210. srcEvent.getX(),
  2211. srcEvent.getY(),
  2212. srcEvent.getClickCount(),
  2213. srcEvent.isPopupTrigger());
  2214. ((AWTEvent)srcEvent).copyPrivateDataInto(me);
  2215. // translate coordinates to this native container
  2216. Point ptSrcOrigin = srcComponent.getLocationOnScreen();
  2217. Point ptDstOrigin = nativeContainer.getLocationOnScreen();
  2218. me.translatePoint( ptSrcOrigin.x - ptDstOrigin.x, ptSrcOrigin.y - ptDstOrigin.y );
  2219. }
  2220. //System.out.println("Track event: " + me);
  2221. // feed the 'dragged-over' event directly to the enter/exit
  2222. // code (not a real event so don't pass it to dispatchEvent)
  2223. Component targetOver = nativeContainer.getMouseEventTarget(me.getX(), me.getY(), true);
  2224. trackMouseEnterExit(targetOver, me);
  2225. }
  2226. /**
  2227. * Sends a mouse event to the current mouse event recipient using
  2228. * the given event (sent to the windowed host) as a srcEvent. If
  2229. * the mouse event target is still in the component tree, the
  2230. * coordinates of the event are translated to those of the target.
  2231. * If the target has been removed, we don't bother to send the
  2232. * message.
  2233. */
  2234. void retargetMouseEvent(Component target, int id, MouseEvent e) {
  2235. if (target == null) {
  2236. return; // mouse is over another hw component
  2237. }
  2238. int x = e.getX(), y = e.getY();
  2239. Component component;
  2240. for(component = target;
  2241. component != null && component != nativeContainer;
  2242. component = component.getParent()) {
  2243. x -= component.x;
  2244. y -= component.y;
  2245. }
  2246. if (component != null) {
  2247. MouseEvent retargeted = new MouseEvent(target,
  2248. id,
  2249. e.getWhen(),
  2250. e.getModifiers(),
  2251. x,
  2252. y,
  2253. e.getClickCount(),
  2254. e.isPopupTrigger());
  2255. ((AWTEvent)e).copyPrivateDataInto(retargeted);
  2256. if (target == nativeContainer) {
  2257. // avoid recursively calling LightweightDispatcher...
  2258. ((Container)target).dispatchEventToSelf(retargeted);
  2259. } else {
  2260. target.dispatchEvent(retargeted);
  2261. }
  2262. }
  2263. }
  2264. // --- member variables -------------------------------
  2265. /**
  2266. * The windowed container that might be hosting events for
  2267. * lightweight components.
  2268. */
  2269. private Container nativeContainer;
  2270. /**
  2271. * The current lightweight component that has focus that is being
  2272. * hosted by this container. If this is a null reference then
  2273. * there is currently no focus on a lightweight component being
  2274. * hosted by this container
  2275. */
  2276. private Component focus;
  2277. /**
  2278. * Fix for 4128659 Michael Martak, 06/29/99
  2279. * Stack of components that need the focus.
  2280. * Since focus requests may need to be issued resulting from FOCUS_LOST
  2281. * or FOCUS_GAINED events (i.e., recursively), a stack is required to
  2282. * ensure that the correct component receives the focus.
  2283. */
  2284. private transient Stack focusStack = new Stack();
  2285. /**
  2286. * The current lightweight component being hosted by this windowed
  2287. * component that has mouse events being forwarded to it. If this
  2288. * is null, there are currently no mouse events being forwarded to
  2289. * a lightweight component.
  2290. */
  2291. private transient Component mouseEventTarget;
  2292. /**
  2293. * The last component entered
  2294. */
  2295. private transient Component targetLastEntered;
  2296. /**
  2297. * Is the mouse over the native container
  2298. */
  2299. private transient boolean isMouseInNativeContainer = false;
  2300. /**
  2301. * Is the next click event orphaned because the component hid/moved
  2302. */
  2303. private transient boolean isClickOrphaned = false;
  2304. /**
  2305. * Indicates if the mouse pointer is currently being dragged...
  2306. * this is needed because we may receive exit events while dragging
  2307. * and need to keep the current mouse target in this case.
  2308. */
  2309. private boolean dragging;
  2310. /**
  2311. * This variable is not used, but kept for serialization compatibility
  2312. */
  2313. private Cursor nativeCursor;
  2314. /**
  2315. * The event mask for contained lightweight components. Lightweight
  2316. * components need a windowed container to host window-related
  2317. * events. This seperate mask indicates events that have been
  2318. * requested by contained lightweight components without effecting
  2319. * the mask of the windowed component itself.
  2320. */
  2321. private long eventMask;
  2322. /**
  2323. * The kind of events routed to lightweight components from windowed
  2324. * hosts.
  2325. */
  2326. private static final long PROXY_EVENT_MASK =
  2327. AWTEvent.FOCUS_EVENT_MASK |
  2328. AWTEvent.KEY_EVENT_MASK |
  2329. AWTEvent.MOUSE_EVENT_MASK |
  2330. AWTEvent.MOUSE_MOTION_EVENT_MASK;
  2331. private static final long MOUSE_MASK =
  2332. AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK;
  2333. }