1. /*
  2. * @(#)DefaultKeyboardFocusManager.java 1.31 03/12/19
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package java.awt;
  8. import java.awt.event.FocusEvent;
  9. import java.awt.event.KeyEvent;
  10. import java.awt.event.WindowEvent;
  11. import java.awt.peer.ComponentPeer;
  12. import java.awt.peer.LightweightPeer;
  13. import java.beans.PropertyChangeListener;
  14. import java.util.LinkedList;
  15. import java.util.Iterator;
  16. import java.util.ListIterator;
  17. import java.util.Set;
  18. import java.util.logging.*;
  19. import sun.awt.AppContext;
  20. import sun.awt.SunToolkit;
  21. /**
  22. * The default KeyboardFocusManager for AWT applications. Focus traversal is
  23. * done in response to a Component's focus traversal keys, and using a
  24. * Container's FocusTraversalPolicy.
  25. * <p>
  26. * Please see
  27. * <a href="http://java.sun.com/docs/books/tutorial/uiswing/misc/focus.html">
  28. * How to Use the Focus Subsystem</a>,
  29. * a section in <em>The Java Tutorial</em>, and the
  30. * <a href="../../java/awt/doc-files/FocusSpec.html">Focus Specification</a>
  31. * for more information.
  32. *
  33. * @author David Mendenhall
  34. * @version 1.31, 12/19/03
  35. *
  36. * @see FocusTraversalPolicy
  37. * @see Component#setFocusTraversalKeys
  38. * @see Component#getFocusTraversalKeys
  39. * @since 1.4
  40. */
  41. public class DefaultKeyboardFocusManager extends KeyboardFocusManager {
  42. private static final Logger focusLog = Logger.getLogger("java.awt.focus.DefaultKeyboardFocusManager");
  43. private Window realOppositeWindow;
  44. private Component realOppositeComponent;
  45. private int inSendMessage;
  46. private LinkedList enqueuedKeyEvents = new LinkedList(),
  47. typeAheadMarkers = new LinkedList();
  48. private boolean consumeNextKeyTyped;
  49. private static class TypeAheadMarker {
  50. long after;
  51. Component untilFocused;
  52. TypeAheadMarker(long after, Component untilFocused) {
  53. this.after = after;
  54. this.untilFocused = untilFocused;
  55. }
  56. /**
  57. * Returns string representation of the marker
  58. */
  59. public String toString() {
  60. return ">>> Marker after " + after + " on " + untilFocused;
  61. }
  62. }
  63. private Window getOwningFrameDialog(Window window) {
  64. while (window != null && !(window instanceof Frame ||
  65. window instanceof Dialog)) {
  66. window = (Window)window.getParent();
  67. }
  68. return window;
  69. }
  70. /*
  71. * This series of restoreFocus methods is used for recovering from a
  72. * rejected focus or activation change. Rejections typically occur when
  73. * the user attempts to focus a non-focusable Component or Window.
  74. */
  75. private void restoreFocus(FocusEvent fe, Window newFocusedWindow) {
  76. Component realOppositeComponent = this.realOppositeComponent;
  77. Component vetoedComponent = fe.getComponent();
  78. if (newFocusedWindow != null && restoreFocus(newFocusedWindow,
  79. vetoedComponent, false))
  80. {
  81. } else if (realOppositeComponent != null &&
  82. restoreFocus(realOppositeComponent, false)) {
  83. } else if (fe.getOppositeComponent() != null &&
  84. restoreFocus(fe.getOppositeComponent(), false)) {
  85. } else {
  86. clearGlobalFocusOwner();
  87. }
  88. }
  89. private void restoreFocus(WindowEvent we) {
  90. Window realOppositeWindow = this.realOppositeWindow;
  91. if (realOppositeWindow != null && restoreFocus(realOppositeWindow,
  92. null, false)) {
  93. } else if (we.getOppositeWindow() != null &&
  94. restoreFocus(we.getOppositeWindow(), null, false)) {
  95. } else {
  96. clearGlobalFocusOwner();
  97. }
  98. }
  99. private boolean restoreFocus(Window aWindow, Component vetoedComponent,
  100. boolean clearOnFailure) {
  101. Component toFocus =
  102. KeyboardFocusManager.getMostRecentFocusOwner(aWindow);
  103. if (toFocus != null && toFocus != vetoedComponent && restoreFocus(toFocus, false)) {
  104. return true;
  105. } else if (clearOnFailure) {
  106. clearGlobalFocusOwner();
  107. return true;
  108. } else {
  109. return false;
  110. }
  111. }
  112. private boolean restoreFocus(Component toFocus, boolean clearOnFailure) {
  113. if (toFocus.isShowing() && toFocus.isFocusable() &&
  114. toFocus.requestFocus(false)) {
  115. return true;
  116. } else if (toFocus.nextFocusHelper()) {
  117. return true;
  118. } else if (clearOnFailure) {
  119. clearGlobalFocusOwner();
  120. return true;
  121. } else {
  122. return false;
  123. }
  124. }
  125. /**
  126. * A special type of SentEvent which updates a counter in the target
  127. * KeyboardFocusManager if it is an instance of
  128. * DefaultKeyboardFocusManager.
  129. */
  130. private static class DefaultKeyboardFocusManagerSentEvent
  131. extends SentEvent
  132. {
  133. public DefaultKeyboardFocusManagerSentEvent(AWTEvent nested,
  134. AppContext toNotify) {
  135. super(nested, toNotify);
  136. }
  137. public final void dispatch() {
  138. KeyboardFocusManager manager =
  139. KeyboardFocusManager.getCurrentKeyboardFocusManager();
  140. DefaultKeyboardFocusManager defaultManager =
  141. (manager instanceof DefaultKeyboardFocusManager)
  142. ? (DefaultKeyboardFocusManager)manager
  143. : null;
  144. if (defaultManager != null) {
  145. synchronized (defaultManager) {
  146. defaultManager.inSendMessage++;
  147. }
  148. }
  149. super.dispatch();
  150. if (defaultManager != null) {
  151. synchronized (defaultManager) {
  152. defaultManager.inSendMessage--;
  153. }
  154. }
  155. }
  156. }
  157. /**
  158. * Sends a synthetic AWTEvent to a Component. If the Component is in
  159. * the current AppContext, then the event is immediately dispatched.
  160. * If the Component is in a different AppContext, then the event is
  161. * posted to the other AppContext's EventQueue, and this method blocks
  162. * until the event is handled or target AppContext is disposed.
  163. * Returns true if successfuly dispatched event, false if failed
  164. * to dispatch.
  165. */
  166. static boolean sendMessage(Component target, AWTEvent e) {
  167. e.isPosted = true;
  168. AppContext myAppContext = AppContext.getAppContext();
  169. final AppContext targetAppContext = target.appContext;
  170. final SentEvent se =
  171. new DefaultKeyboardFocusManagerSentEvent(e, myAppContext);
  172. if (myAppContext == targetAppContext) {
  173. se.dispatch();
  174. } else {
  175. if (targetAppContext.isDisposed()) {
  176. return false;
  177. }
  178. SunToolkit.postEvent(targetAppContext, se);
  179. if (EventQueue.isDispatchThread()) {
  180. EventDispatchThread edt = (EventDispatchThread)
  181. Thread.currentThread();
  182. edt.pumpEvents(SentEvent.ID, new Conditional() {
  183. public boolean evaluate() {
  184. return !se.dispatched && !targetAppContext.isDisposed();
  185. }
  186. });
  187. } else {
  188. synchronized (se) {
  189. while (!se.dispatched && !targetAppContext.isDisposed()) {
  190. try {
  191. se.wait(1000);
  192. } catch (InterruptedException ie) {
  193. break;
  194. }
  195. }
  196. }
  197. }
  198. }
  199. return se.dispatched;
  200. }
  201. /**
  202. * This method is called by the AWT event dispatcher requesting that the
  203. * current KeyboardFocusManager dispatch the specified event on its behalf.
  204. * DefaultKeyboardFocusManagers dispatch all FocusEvents, all WindowEvents
  205. * related to focus, and all KeyEvents. These events are dispatched based
  206. * on the KeyboardFocusManager's notion of the focus owner and the focused
  207. * and active Windows, sometimes overriding the source of the specified
  208. * AWTEvent. If this method returns <code>false</code>, then the AWT event
  209. * dispatcher will attempt to dispatch the event itself.
  210. *
  211. * @param e the AWTEvent to be dispatched
  212. * @return <code>true</code> if this method dispatched the event;
  213. * <code>false</code> otherwise
  214. */
  215. public boolean dispatchEvent(AWTEvent e) {
  216. if (focusLog.isLoggable(Level.FINE) && (e instanceof WindowEvent || e instanceof FocusEvent)) focusLog.fine("" + e);
  217. switch (e.getID()) {
  218. case WindowEvent.WINDOW_GAINED_FOCUS: {
  219. WindowEvent we = (WindowEvent)e;
  220. Window oldFocusedWindow = getGlobalFocusedWindow();
  221. Window newFocusedWindow = we.getWindow();
  222. if (newFocusedWindow == oldFocusedWindow) {
  223. break;
  224. }
  225. // If there exists a current focused window, then notify it
  226. // that it has lost focus.
  227. if (oldFocusedWindow != null) {
  228. boolean isEventDispatched =
  229. sendMessage(oldFocusedWindow,
  230. new WindowEvent(oldFocusedWindow,
  231. WindowEvent.WINDOW_LOST_FOCUS,
  232. newFocusedWindow));
  233. // Failed to dispatch, clear by ourselfves
  234. if (!isEventDispatched) {
  235. setGlobalFocusOwner(null);
  236. setGlobalFocusedWindow(null);
  237. }
  238. }
  239. // Because the native libraries do not post WINDOW_ACTIVATED
  240. // events, we need to synthesize one if the active Window
  241. // changed.
  242. Window newActiveWindow =
  243. getOwningFrameDialog(newFocusedWindow);
  244. Window currentActiveWindow = getGlobalActiveWindow();
  245. if (newActiveWindow != currentActiveWindow) {
  246. sendMessage(newActiveWindow,
  247. new WindowEvent(newActiveWindow,
  248. WindowEvent.WINDOW_ACTIVATED,
  249. currentActiveWindow));
  250. if (newActiveWindow != getGlobalActiveWindow()) {
  251. // Activation change was rejected. Unlikely, but
  252. // possible.
  253. restoreFocus(we);
  254. break;
  255. }
  256. }
  257. setGlobalFocusedWindow(newFocusedWindow);
  258. if (newFocusedWindow != getGlobalFocusedWindow()) {
  259. // Focus change was rejected. Will happen if
  260. // newFocusedWindow is not a focusable Window.
  261. restoreFocus(we);
  262. break;
  263. }
  264. setNativeFocusedWindow(newFocusedWindow);
  265. // Restore focus to the Component which last held it. We do
  266. // this here so that client code can override our choice in
  267. // a WINDOW_GAINED_FOCUS handler.
  268. //
  269. // Make sure that the focus change request doesn't change the
  270. // focused Window in case we are no longer the focused Window
  271. // when the request is handled.
  272. if (inSendMessage == 0) {
  273. // Identify which Component should initially gain focus
  274. // in the Window.
  275. //
  276. // * If we're in SendMessage, then this is a synthetic
  277. // WINDOW_GAINED_FOCUS message which was generated by a
  278. // the FOCUS_GAINED handler. Allow the Component to
  279. // which the FOCUS_GAINED message was targeted to
  280. // receive the focus.
  281. // * Otherwise, look up the correct Component here.
  282. // We don't use Window.getMostRecentFocusOwner because
  283. // window is focused now and 'null' will be returned
  284. // Calculating of most recent focus owner and focus
  285. // request should be synchronized on KeyboardFocusManager.class
  286. // to prevent from thread race when user will request
  287. // focus between calculation and our request.
  288. // But if focus transfer is synchronous, this synchronization
  289. // may cause deadlock, thus we don't synchronize this block.
  290. Component toFocus = KeyboardFocusManager.
  291. getMostRecentFocusOwner(newFocusedWindow);
  292. if ((toFocus == null) &&
  293. newFocusedWindow.isFocusableWindow())
  294. {
  295. toFocus = newFocusedWindow.getFocusTraversalPolicy().
  296. getInitialComponent(newFocusedWindow);
  297. }
  298. Component tempLost = null;
  299. synchronized(KeyboardFocusManager.class) {
  300. tempLost = newFocusedWindow.setTemporaryLostComponent(null);
  301. }
  302. // The component which last has the focus when this window was focused
  303. // should receive focus first
  304. if (focusLog.isLoggable(Level.FINER)) {
  305. focusLog.log(Level.FINER, "tempLost {0}, toFocus {1}",
  306. new Object[]{tempLost, toFocus});
  307. }
  308. if (tempLost != null) {
  309. tempLost.requestFocusInWindow();
  310. }
  311. if (toFocus != null && toFocus != tempLost) {
  312. // If there is a component which requested focus when this window
  313. // was inactive it expects to receive focus after activation.
  314. toFocus.requestFocusInWindow();
  315. }
  316. }
  317. Window realOppositeWindow = this.realOppositeWindow;
  318. if (realOppositeWindow != we.getOppositeWindow()) {
  319. we = new WindowEvent(newFocusedWindow,
  320. WindowEvent.WINDOW_GAINED_FOCUS,
  321. realOppositeWindow);
  322. }
  323. return typeAheadAssertions(newFocusedWindow, we);
  324. }
  325. case WindowEvent.WINDOW_ACTIVATED: {
  326. WindowEvent we = (WindowEvent)e;
  327. Window oldActiveWindow = getGlobalActiveWindow();
  328. Window newActiveWindow = we.getWindow();
  329. if (oldActiveWindow == newActiveWindow) {
  330. break;
  331. }
  332. // If there exists a current active window, then notify it that
  333. // it has lost activation.
  334. if (oldActiveWindow != null) {
  335. boolean isEventDispatched =
  336. sendMessage(oldActiveWindow,
  337. new WindowEvent(oldActiveWindow,
  338. WindowEvent.WINDOW_DEACTIVATED,
  339. newActiveWindow));
  340. // Failed to dispatch, clear by ourselfves
  341. if (!isEventDispatched) {
  342. setGlobalActiveWindow(null);
  343. }
  344. if (getGlobalActiveWindow() != null) {
  345. // Activation change was rejected. Unlikely, but
  346. // possible.
  347. break;
  348. }
  349. }
  350. setGlobalActiveWindow(newActiveWindow);
  351. if (newActiveWindow != getGlobalActiveWindow()) {
  352. // Activation change was rejected. Unlikely, but
  353. // possible.
  354. break;
  355. }
  356. return typeAheadAssertions(newActiveWindow, we);
  357. }
  358. case FocusEvent.FOCUS_GAINED: {
  359. FocusEvent fe = (FocusEvent)e;
  360. Component oldFocusOwner = getGlobalFocusOwner();
  361. Component newFocusOwner = fe.getComponent();
  362. if (oldFocusOwner == newFocusOwner) {
  363. if (focusLog.isLoggable(Level.FINE)) focusLog.log(Level.FINE, "Skipping {0} because focus owner is the same",
  364. new Object[] {e});
  365. break;
  366. }
  367. // If there exists a current focus owner, then notify it that
  368. // it has lost focus.
  369. if (oldFocusOwner != null) {
  370. boolean isEventDispatched =
  371. sendMessage(oldFocusOwner,
  372. new FocusEvent(oldFocusOwner,
  373. FocusEvent.FOCUS_LOST,
  374. fe.isTemporary(),
  375. newFocusOwner));
  376. // Failed to dispatch, clear by ourselfves
  377. if (!isEventDispatched) {
  378. setGlobalFocusOwner(null);
  379. if (!fe.isTemporary()) {
  380. setGlobalPermanentFocusOwner(null);
  381. }
  382. }
  383. }
  384. // Because the native windowing system has a different notion
  385. // of the current focus and activation states, it is possible
  386. // that a Component outside of the focused Window receives a
  387. // FOCUS_GAINED event. We synthesize a WINDOW_GAINED_FOCUS
  388. // event in that case.
  389. Component newFocusedWindow = newFocusOwner;
  390. while (newFocusedWindow != null &&
  391. !(newFocusedWindow instanceof Window)) {
  392. newFocusedWindow = newFocusedWindow.parent;
  393. }
  394. Window currentFocusedWindow = getGlobalFocusedWindow();
  395. if (newFocusedWindow != null &&
  396. newFocusedWindow != currentFocusedWindow)
  397. {
  398. sendMessage(newFocusedWindow,
  399. new WindowEvent((Window)newFocusedWindow,
  400. WindowEvent.WINDOW_GAINED_FOCUS,
  401. currentFocusedWindow));
  402. if (newFocusedWindow != getGlobalFocusedWindow()) {
  403. // Focus change was rejected. Will happen if
  404. // newFocusedWindow is not a focusable Window.
  405. // Need to recover type-ahead, but don't bother
  406. // restoring focus. That was done by the
  407. // WINDOW_GAINED_FOCUS handler
  408. dequeueKeyEvents(-1, newFocusOwner);
  409. break;
  410. }
  411. }
  412. setGlobalFocusOwner(newFocusOwner);
  413. if (newFocusOwner != getGlobalFocusOwner()) {
  414. // Focus change was rejected. Will happen if
  415. // newFocusOwner is not focus traversable.
  416. dequeueKeyEvents(-1, newFocusOwner);
  417. restoreFocus(fe, (Window)newFocusedWindow);
  418. break;
  419. }
  420. if (!fe.isTemporary()) {
  421. setGlobalPermanentFocusOwner(newFocusOwner);
  422. if (newFocusOwner != getGlobalPermanentFocusOwner()) {
  423. // Focus change was rejected. Unlikely, but possible.
  424. dequeueKeyEvents(-1, newFocusOwner);
  425. restoreFocus(fe, (Window)newFocusedWindow);
  426. break;
  427. }
  428. }
  429. Component realOppositeComponent = this.realOppositeComponent;
  430. if (realOppositeComponent != null &&
  431. realOppositeComponent != fe.getOppositeComponent()) {
  432. fe = new FocusEvent(newFocusOwner,
  433. FocusEvent.FOCUS_GAINED,
  434. fe.isTemporary(),
  435. realOppositeComponent);
  436. ((AWTEvent) fe).isPosted = true;
  437. }
  438. return typeAheadAssertions(newFocusOwner, fe);
  439. }
  440. case FocusEvent.FOCUS_LOST: {
  441. FocusEvent fe = (FocusEvent)e;
  442. Component currentFocusOwner = getGlobalFocusOwner();
  443. if (currentFocusOwner == null) {
  444. if (focusLog.isLoggable(Level.FINE)) focusLog.log(Level.FINE, "Skipping {0} because focus owner is null",
  445. new Object[] {e});
  446. break;
  447. }
  448. // Ignore cases where a Component loses focus to itself.
  449. // If we make a mistake because of retargeting, then the
  450. // FOCUS_GAINED handler will correct it.
  451. if (currentFocusOwner == fe.getOppositeComponent()) {
  452. if (focusLog.isLoggable(Level.FINE)) focusLog.log(Level.FINE, "Skipping {0} because current focus owner is equal to opposite",
  453. new Object[] {e});
  454. break;
  455. }
  456. setGlobalFocusOwner(null);
  457. if (getGlobalFocusOwner() != null) {
  458. // Focus change was rejected. Unlikely, but possible.
  459. restoreFocus(currentFocusOwner, true);
  460. break;
  461. }
  462. if (!fe.isTemporary()) {
  463. setGlobalPermanentFocusOwner(null);
  464. if (getGlobalPermanentFocusOwner() != null) {
  465. // Focus change was rejected. Unlikely, but possible.
  466. restoreFocus(currentFocusOwner, true);
  467. break;
  468. }
  469. } else {
  470. Window owningWindow = currentFocusOwner.getContainingWindow();
  471. if (owningWindow != null) {
  472. owningWindow.setTemporaryLostComponent(currentFocusOwner);
  473. }
  474. }
  475. fe.setSource(currentFocusOwner);
  476. realOppositeComponent = (fe.getOppositeComponent() != null)
  477. ? currentFocusOwner : null;
  478. return typeAheadAssertions(currentFocusOwner, fe);
  479. }
  480. case WindowEvent.WINDOW_DEACTIVATED: {
  481. WindowEvent we = (WindowEvent)e;
  482. Window currentActiveWindow = getGlobalActiveWindow();
  483. if (currentActiveWindow == null) {
  484. break;
  485. }
  486. if (currentActiveWindow != e.getSource()) {
  487. // The event is lost in time.
  488. // Allow listeners to precess the event but do not
  489. // change any global states
  490. break;
  491. }
  492. setGlobalActiveWindow(null);
  493. if (getGlobalActiveWindow() != null) {
  494. // Activation change was rejected. Unlikely, but possible.
  495. break;
  496. }
  497. we.setSource(currentActiveWindow);
  498. return typeAheadAssertions(currentActiveWindow, we);
  499. }
  500. case WindowEvent.WINDOW_LOST_FOCUS: {
  501. WindowEvent we = (WindowEvent)e;
  502. Window currentFocusedWindow = getGlobalFocusedWindow();
  503. Window losingFocusWindow = we.getWindow();
  504. Window activeWindow = getGlobalActiveWindow();
  505. Window oppositeWindow = we.getOppositeWindow();
  506. if (focusLog.isLoggable(Level.FINE)) focusLog.log(Level.FINE, "Active {0}, Current focused {1}, losing focus {2} opposite {3}",
  507. new Object[] {activeWindow, currentFocusedWindow,
  508. losingFocusWindow, oppositeWindow});
  509. if (currentFocusedWindow == null) {
  510. break;
  511. }
  512. // Special case -- if the native windowing system posts an
  513. // event claiming that the active Window has lost focus to the
  514. // focused Window, then discard the event. This is an artifact
  515. // of the native windowing system not knowing which Window is
  516. // really focused.
  517. if (inSendMessage == 0 && losingFocusWindow == activeWindow &&
  518. oppositeWindow == currentFocusedWindow)
  519. {
  520. break;
  521. }
  522. Component currentFocusOwner = getGlobalFocusOwner();
  523. if (currentFocusOwner != null) {
  524. // The focus owner should always receive a FOCUS_LOST event
  525. // before the Window is defocused.
  526. Component oppositeComp = null;
  527. if (oppositeWindow != null) {
  528. oppositeComp = oppositeWindow.getTemporaryLostComponent();
  529. if (oppositeComp == null) {
  530. oppositeComp = oppositeWindow.getMostRecentFocusOwner();
  531. }
  532. }
  533. if (oppositeComp == null) {
  534. oppositeComp = oppositeWindow;
  535. }
  536. sendMessage(currentFocusOwner,
  537. new FocusEvent(currentFocusOwner,
  538. FocusEvent.FOCUS_LOST,
  539. true,
  540. oppositeComp));
  541. }
  542. setGlobalFocusedWindow(null);
  543. if (getGlobalFocusedWindow() != null) {
  544. // Focus change was rejected. Unlikely, but possible.
  545. restoreFocus(currentFocusedWindow, null, true);
  546. break;
  547. }
  548. setNativeFocusedWindow(null);
  549. we.setSource(currentFocusedWindow);
  550. realOppositeWindow = (oppositeWindow != null)
  551. ? currentFocusedWindow
  552. : null;
  553. typeAheadAssertions(currentFocusedWindow, we);
  554. if (oppositeWindow == null) {
  555. // Then we need to deactive the active Window as well.
  556. // No need to synthesize in other cases, because
  557. // WINDOW_ACTIVATED will handle it if necessary.
  558. sendMessage(activeWindow,
  559. new WindowEvent(activeWindow,
  560. WindowEvent.WINDOW_DEACTIVATED,
  561. null));
  562. if (getGlobalActiveWindow() != null) {
  563. // Activation change was rejected. Unlikely,
  564. // but possible.
  565. restoreFocus(currentFocusedWindow, null, true);
  566. }
  567. }
  568. break;
  569. }
  570. case KeyEvent.KEY_TYPED:
  571. case KeyEvent.KEY_PRESSED:
  572. case KeyEvent.KEY_RELEASED:
  573. return typeAheadAssertions(null, e);
  574. default:
  575. return false;
  576. }
  577. return true;
  578. }
  579. /**
  580. * Called by <code>dispatchEvent</code> if no other
  581. * KeyEventDispatcher in the dispatcher chain dispatched the KeyEvent, or
  582. * if no other KeyEventDispatchers are registered. If the event has not
  583. * been consumed, its target is enabled, and the focus owner is not null,
  584. * this method dispatches the event to its target. This method will also
  585. * subsequently dispatch the event to all registered
  586. * KeyEventPostProcessors. After all this operations are finished,
  587. * the event is passed to peers for processing.
  588. * <p>
  589. * In all cases, this method returns <code>true</code>, since
  590. * DefaultKeyboardFocusManager is designed so that neither
  591. * <code>dispatchEvent</code>, nor the AWT event dispatcher, should take
  592. * further action on the event in any situation.
  593. *
  594. * @param e the KeyEvent to be dispatched
  595. * @return <code>true</code>
  596. * @see Component#dispatchEvent
  597. */
  598. public boolean dispatchKeyEvent(KeyEvent e) {
  599. Component focusOwner = (((AWTEvent)e).isPosted) ? getFocusOwner() : e.getComponent();
  600. if (focusOwner != null && focusOwner.isShowing() &&
  601. focusOwner.isFocusable() && focusOwner.isEnabled()) {
  602. if (!e.isConsumed()) {
  603. Component comp = e.getComponent();
  604. if (comp != null && comp.isEnabled()) {
  605. redispatchEvent(comp, e);
  606. }
  607. }
  608. }
  609. boolean stopPostProcessing = false;
  610. java.util.List processors = getKeyEventPostProcessors();
  611. if (processors != null) {
  612. for (java.util.Iterator iter = processors.iterator();
  613. !stopPostProcessing && iter.hasNext(); )
  614. {
  615. stopPostProcessing = (((KeyEventPostProcessor)(iter.next())).
  616. postProcessKeyEvent(e));
  617. }
  618. }
  619. if (!stopPostProcessing) {
  620. postProcessKeyEvent(e);
  621. }
  622. // Allow the peer to process KeyEvent
  623. Component source = e.getComponent();
  624. ComponentPeer peer = source.getPeer();
  625. if (peer == null || peer instanceof LightweightPeer) {
  626. // if focus owner is lightweight then its native container
  627. // processes event
  628. Container target = source.getNativeContainer();
  629. if (target != null) {
  630. peer = target.getPeer();
  631. }
  632. }
  633. if (peer != null) {
  634. peer.handleEvent(e);
  635. }
  636. return true;
  637. }
  638. /**
  639. * This method will be called by <code>dispatchKeyEvent</code>. It will
  640. * handle any unconsumed KeyEvents that map to an AWT
  641. * <code>MenuShortcut</code> by consuming the event and activating the
  642. * shortcut.
  643. *
  644. * @param e the KeyEvent to post-process
  645. * @return <code>true</code>
  646. * @see #dispatchKeyEvent
  647. * @see MenuShortcut
  648. */
  649. public boolean postProcessKeyEvent(KeyEvent e) {
  650. if (!e.isConsumed()) {
  651. Component target = e.getComponent();
  652. Container p = (Container)
  653. (target instanceof Container ? target : target.getParent());
  654. if (p != null) {
  655. p.postProcessKeyEvent(e);
  656. }
  657. }
  658. return true;
  659. }
  660. private void pumpApprovedKeyEvents() {
  661. KeyEvent ke;
  662. do {
  663. ke = null;
  664. synchronized (this) {
  665. if (enqueuedKeyEvents.size() != 0) {
  666. ke = (KeyEvent)enqueuedKeyEvents.getFirst();
  667. if (typeAheadMarkers.size() != 0) {
  668. TypeAheadMarker marker = (TypeAheadMarker)
  669. typeAheadMarkers.getFirst();
  670. if (ke.getWhen() > marker.after) {
  671. ke = null;
  672. }
  673. }
  674. if (ke != null) {
  675. enqueuedKeyEvents.removeFirst();
  676. }
  677. }
  678. }
  679. if (ke != null) {
  680. preDispatchKeyEvent(ke);
  681. }
  682. } while (ke != null);
  683. }
  684. /**
  685. * Dumps the list of type-ahead queue markers to stderr
  686. */
  687. void dumpMarkers() {
  688. System.err.println(">>> Markers dump, time: " + System.currentTimeMillis());
  689. synchronized (this) {
  690. if (typeAheadMarkers.size() != 0) {
  691. Iterator iter = typeAheadMarkers.iterator();
  692. while (iter.hasNext()) {
  693. TypeAheadMarker marker = (TypeAheadMarker)iter.next();
  694. System.err.println(marker);
  695. }
  696. }
  697. }
  698. System.err.println("");
  699. }
  700. private boolean typeAheadAssertions(Component target, AWTEvent e) {
  701. // Clear any pending events here as well as in the FOCUS_GAINED
  702. // handler. We need this call here in case a marker was removed in
  703. // response to a call to dequeueKeyEvents.
  704. pumpApprovedKeyEvents();
  705. switch (e.getID()) {
  706. case KeyEvent.KEY_TYPED:
  707. case KeyEvent.KEY_PRESSED:
  708. case KeyEvent.KEY_RELEASED: {
  709. KeyEvent ke = (KeyEvent)e;
  710. synchronized (this) {
  711. if (e.isPosted && typeAheadMarkers.size() != 0) {
  712. TypeAheadMarker marker = (TypeAheadMarker)
  713. typeAheadMarkers.getFirst();
  714. if (ke.getWhen() > marker.after) {
  715. enqueuedKeyEvents.addLast(ke);
  716. return true;
  717. }
  718. }
  719. }
  720. // KeyEvent was posted before focus change request
  721. return preDispatchKeyEvent(ke);
  722. }
  723. case FocusEvent.FOCUS_GAINED:
  724. // Search the marker list for the first marker tied to
  725. // the Component which just gained focus. Then remove
  726. // that marker, any markers which immediately follow
  727. // and are tied to the same component, and all markers
  728. // that preceed it. This handles the case where
  729. // multiple focus requests were made for the same
  730. // Component in a row and when we lost some of the
  731. // earlier requests. Since FOCUS_GAINED events will
  732. // not be generated for these additional requests, we
  733. // need to clear those markers too.
  734. synchronized (this) {
  735. boolean found = false;
  736. if (hasMarker(target)) {
  737. for (Iterator iter = typeAheadMarkers.iterator();
  738. iter.hasNext(); )
  739. {
  740. if (((TypeAheadMarker)iter.next()).untilFocused ==
  741. target)
  742. {
  743. found = true;
  744. } else if (found) {
  745. break;
  746. }
  747. iter.remove();
  748. }
  749. }
  750. }
  751. redispatchEvent(target, e);
  752. // Now, dispatch any pending KeyEvents which have been
  753. // released because of the FOCUS_GAINED event so that we don't
  754. // have to wait for another event to be posted to the queue.
  755. pumpApprovedKeyEvents();
  756. return true;
  757. default:
  758. redispatchEvent(target, e);
  759. return true;
  760. }
  761. }
  762. /**
  763. * Returns true if there are some marker associated with component <code>comp</code>
  764. * in a markers' queue
  765. * @since 1.5
  766. */
  767. private boolean hasMarker(Component comp) {
  768. for (Iterator iter = typeAheadMarkers.iterator(); iter.hasNext(); ) {
  769. if (((TypeAheadMarker)iter.next()).untilFocused == comp) {
  770. return true;
  771. }
  772. }
  773. return false;
  774. }
  775. /**
  776. * Clears markers queue
  777. * @since 1.5
  778. */
  779. void clearMarkers() {
  780. synchronized(this) {
  781. typeAheadMarkers.clear();
  782. }
  783. }
  784. private boolean preDispatchKeyEvent(KeyEvent ke) {
  785. if (((AWTEvent) ke).isPosted) {
  786. Component focusOwner = getFocusOwner();
  787. ke.setSource(((focusOwner != null) ? focusOwner : getFocusedWindow()));
  788. }
  789. if (ke.getSource() == null) {
  790. return true;
  791. }
  792. // Explicitly set the current event and most recent timestamp here in
  793. // addition to the call in Component.dispatchEventImpl. Because
  794. // KeyEvents can be delivered in response to a FOCUS_GAINED event, the
  795. // current timestamp may be incorrect. We need to set it here so that
  796. // KeyEventDispatchers will use the correct time.
  797. EventQueue.setCurrentEventAndMostRecentTime(ke);
  798. /**
  799. * Fix for 4495473.
  800. * This fix allows to correctly dispatch events when native
  801. * event proxying mechanism is active.
  802. * If it is active we should redispatch key events after
  803. * we detected its correct target.
  804. */
  805. if (KeyboardFocusManager.isProxyActive(ke)) {
  806. Component source = (Component)ke.getSource();
  807. Container target = source.getNativeContainer();
  808. if (target != null) {
  809. ComponentPeer peer = target.getPeer();
  810. if (peer != null) {
  811. peer.handleEvent(ke);
  812. /**
  813. * Fix for 4478780 - consume event after it was dispatched by peer.
  814. */
  815. ke.consume();
  816. }
  817. }
  818. return true;
  819. }
  820. java.util.List dispatchers = getKeyEventDispatchers();
  821. if (dispatchers != null) {
  822. for (java.util.Iterator iter = dispatchers.iterator();
  823. iter.hasNext(); )
  824. {
  825. if (((KeyEventDispatcher)(iter.next())).
  826. dispatchKeyEvent(ke))
  827. {
  828. return true;
  829. }
  830. }
  831. }
  832. return dispatchKeyEvent(ke);
  833. }
  834. private void consumeTraversalKey(KeyEvent e) {
  835. e.consume();
  836. consumeNextKeyTyped = (e.getID() == KeyEvent.KEY_PRESSED) &&
  837. !e.isActionKey();
  838. }
  839. /*
  840. * return true if event was consumed
  841. */
  842. private boolean consumeProcessedKeyEvent(KeyEvent e) {
  843. if ((e.getID() == KeyEvent.KEY_TYPED) && consumeNextKeyTyped) {
  844. e.consume();
  845. consumeNextKeyTyped = false;
  846. return true;
  847. }
  848. return false;
  849. }
  850. /**
  851. * This method initiates a focus traversal operation if and only if the
  852. * KeyEvent represents a focus traversal key for the specified
  853. * focusedComponent. It is expected that focusedComponent is the current
  854. * focus owner, although this need not be the case. If it is not,
  855. * focus traversal will nevertheless proceed as if focusedComponent
  856. * were the focus owner.
  857. *
  858. * @param focusedComponent the Component that is the basis for a focus
  859. * traversal operation if the specified event represents a focus
  860. * traversal key for the Component
  861. * @param e the event that may represent a focus traversal key
  862. */
  863. public void processKeyEvent(Component focusedComponent, KeyEvent e) {
  864. // consume processed event if needed
  865. if (consumeProcessedKeyEvent(e)) {
  866. return;
  867. }
  868. // KEY_TYPED events cannot be focus traversal keys
  869. if (e.getID() == KeyEvent.KEY_TYPED) {
  870. return;
  871. }
  872. if (focusedComponent.getFocusTraversalKeysEnabled() &&
  873. !e.isConsumed())
  874. {
  875. AWTKeyStroke stroke = AWTKeyStroke.getAWTKeyStrokeForEvent(e),
  876. oppStroke = AWTKeyStroke.getAWTKeyStroke(stroke.getKeyCode(),
  877. stroke.getModifiers(),
  878. !stroke.isOnKeyRelease());
  879. Set toTest;
  880. boolean contains, containsOpp;
  881. toTest = focusedComponent.getFocusTraversalKeys(
  882. KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
  883. contains = toTest.contains(stroke);
  884. containsOpp = toTest.contains(oppStroke);
  885. if (contains || containsOpp) {
  886. consumeTraversalKey(e);
  887. if (contains) {
  888. focusNextComponent(focusedComponent);
  889. }
  890. return;
  891. }
  892. toTest = focusedComponent.getFocusTraversalKeys(
  893. KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);
  894. contains = toTest.contains(stroke);
  895. containsOpp = toTest.contains(oppStroke);
  896. if (contains || containsOpp) {
  897. consumeTraversalKey(e);
  898. if (contains) {
  899. focusPreviousComponent(focusedComponent);
  900. }
  901. return;
  902. }
  903. toTest = focusedComponent.getFocusTraversalKeys(
  904. KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS);
  905. contains = toTest.contains(stroke);
  906. containsOpp = toTest.contains(oppStroke);
  907. if (contains || containsOpp) {
  908. consumeTraversalKey(e);
  909. if (contains) {
  910. upFocusCycle(focusedComponent);
  911. }
  912. return;
  913. }
  914. if (!((focusedComponent instanceof Container) &&
  915. ((Container)focusedComponent).isFocusCycleRoot())) {
  916. return;
  917. }
  918. toTest = focusedComponent.getFocusTraversalKeys(
  919. KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS);
  920. contains = toTest.contains(stroke);
  921. containsOpp = toTest.contains(oppStroke);
  922. if (contains || containsOpp) {
  923. consumeTraversalKey(e);
  924. if (contains) {
  925. downFocusCycle((Container)focusedComponent);
  926. }
  927. }
  928. }
  929. }
  930. /**
  931. * Delays dispatching of KeyEvents until the specified Component becomes
  932. * the focus owner. KeyEvents with timestamps later than the specified
  933. * timestamp will be enqueued until the specified Component receives a
  934. * FOCUS_GAINED event, or the AWT cancels the delay request by invoking
  935. * <code>dequeueKeyEvents</code> or <code>discardKeyEvents</code>.
  936. *
  937. * @param after timestamp of current event, or the current, system time if
  938. * the current event has no timestamp, or the AWT cannot determine
  939. * which event is currently being handled
  940. * @param untilFocused Component which will receive a FOCUS_GAINED event
  941. * before any pending KeyEvents
  942. * @see #dequeueKeyEvents
  943. * @see #discardKeyEvents
  944. */
  945. protected synchronized void enqueueKeyEvents(long after,
  946. Component untilFocused) {
  947. if (untilFocused == null) {
  948. return;
  949. }
  950. int insertionIndex = 0,
  951. i = typeAheadMarkers.size();
  952. ListIterator iter = typeAheadMarkers.listIterator(i);
  953. for (; i > 0; i--) {
  954. TypeAheadMarker marker = (TypeAheadMarker)iter.previous();
  955. if (marker.after <= after) {
  956. insertionIndex = i;
  957. break;
  958. }
  959. }
  960. typeAheadMarkers.add(insertionIndex,
  961. new TypeAheadMarker(after, untilFocused));
  962. }
  963. /**
  964. * Releases for normal dispatching to the current focus owner all
  965. * KeyEvents which were enqueued because of a call to
  966. * <code>enqueueKeyEvents</code> with the same timestamp and Component.
  967. * If the given timestamp is less than zero, the outstanding enqueue
  968. * request for the given Component with the <b>oldest</b> timestamp (if
  969. * any) should be cancelled.
  970. *
  971. * @param after the timestamp specified in the call to
  972. * <code>enqueueKeyEvents</code>, or any value < 0
  973. * @param untilFocused the Component specified in the call to
  974. * <code>enqueueKeyEvents</code>
  975. * @see #enqueueKeyEvents
  976. * @see #discardKeyEvents
  977. */
  978. protected synchronized void dequeueKeyEvents(long after,
  979. Component untilFocused) {
  980. if (untilFocused == null) {
  981. return;
  982. }
  983. TypeAheadMarker marker;
  984. ListIterator iter = typeAheadMarkers.listIterator
  985. ((after >= 0) ? typeAheadMarkers.size() : 0);
  986. if (after < 0) {
  987. while (iter.hasNext()) {
  988. marker = (TypeAheadMarker)iter.next();
  989. if (marker.untilFocused == untilFocused)
  990. {
  991. iter.remove();
  992. return;
  993. }
  994. }
  995. } else {
  996. while (iter.hasPrevious()) {
  997. marker = (TypeAheadMarker)iter.previous();
  998. if (marker.untilFocused == untilFocused &&
  999. marker.after == after)
  1000. {
  1001. iter.remove();
  1002. return;
  1003. }
  1004. }
  1005. }
  1006. }
  1007. /**
  1008. * Discards all KeyEvents which were enqueued because of one or more calls
  1009. * to <code>enqueueKeyEvents</code> with the specified Component, or one of
  1010. * its descendants.
  1011. *
  1012. * @param comp the Component specified in one or more calls to
  1013. * <code>enqueueKeyEvents</code>, or a parent of such a Component
  1014. * @see #enqueueKeyEvents
  1015. * @see #dequeueKeyEvents
  1016. */
  1017. protected synchronized void discardKeyEvents(Component comp) {
  1018. if (comp == null) {
  1019. return;
  1020. }
  1021. long start = -1;
  1022. for (Iterator iter = typeAheadMarkers.iterator(); iter.hasNext(); ) {
  1023. TypeAheadMarker marker = (TypeAheadMarker)iter.next();
  1024. Component toTest = marker.untilFocused;
  1025. boolean match = (toTest == comp);
  1026. while (!match && toTest != null && !(toTest instanceof Window)) {
  1027. toTest = toTest.getParent();
  1028. match = (toTest == comp);
  1029. }
  1030. if (match) {
  1031. if (start < 0) {
  1032. start = marker.after;
  1033. }
  1034. iter.remove();
  1035. } else if (start >= 0) {
  1036. purgeStampedEvents(start, marker.after);
  1037. start = -1;
  1038. }
  1039. }
  1040. purgeStampedEvents(start, -1);
  1041. }
  1042. // Notes:
  1043. // * must be called inside a synchronized block
  1044. // * if 'start' is < 0, then this function does nothing
  1045. // * if 'end' is < 0, then all KeyEvents from 'start' to the end of the
  1046. // queue will be removed
  1047. private void purgeStampedEvents(long start, long end) {
  1048. if (start < 0) {
  1049. return;
  1050. }
  1051. for (Iterator iter = enqueuedKeyEvents.iterator(); iter.hasNext(); ) {
  1052. KeyEvent ke = (KeyEvent)iter.next();
  1053. long time = ke.getWhen();
  1054. if (start < time && (end < 0 || time <= end)) {
  1055. iter.remove();
  1056. }
  1057. if (end >= 0 && time > end) {
  1058. break;
  1059. }
  1060. }
  1061. }
  1062. /**
  1063. * Focuses the Component before aComponent, typically based on a
  1064. * FocusTraversalPolicy.
  1065. *
  1066. * @param aComponent the Component that is the basis for the focus
  1067. * traversal operation
  1068. * @see FocusTraversalPolicy
  1069. * @see Component#transferFocusBackward
  1070. */
  1071. public void focusPreviousComponent(Component aComponent) {
  1072. if (aComponent != null) {
  1073. aComponent.transferFocusBackward();
  1074. }
  1075. }
  1076. /**
  1077. * Focuses the Component after aComponent, typically based on a
  1078. * FocusTraversalPolicy.
  1079. *
  1080. * @param aComponent the Component that is the basis for the focus
  1081. * traversal operation
  1082. * @see FocusTraversalPolicy
  1083. * @see Component#transferFocus
  1084. */
  1085. public void focusNextComponent(Component aComponent) {
  1086. if (aComponent != null) {
  1087. aComponent.transferFocus();
  1088. }
  1089. }
  1090. /**
  1091. * Moves the focus up one focus traversal cycle. Typically, the focus owner
  1092. * is set to aComponent's focus cycle root, and the current focus cycle
  1093. * root is set to the new focus owner's focus cycle root. If, however,
  1094. * aComponent's focus cycle root is a Window, then the focus owner is set
  1095. * to the focus cycle root's default Component to focus, and the current
  1096. * focus cycle root is unchanged.
  1097. *
  1098. * @param aComponent the Component that is the basis for the focus
  1099. * traversal operation
  1100. * @see Component#transferFocusUpCycle
  1101. */
  1102. public void upFocusCycle(Component aComponent) {
  1103. if (aComponent != null) {
  1104. aComponent.transferFocusUpCycle();
  1105. }
  1106. }
  1107. /**
  1108. * Moves the focus down one focus traversal cycle. If aContainer is a focus
  1109. * cycle root, then the focus owner is set to aContainer's default
  1110. * Component to focus, and the current focus cycle root is set to
  1111. * aContainer. If aContainer is not a focus cycle root, then no focus
  1112. * traversal operation occurs.
  1113. *
  1114. * @param aContainer the Container that is the basis for the focus
  1115. * traversal operation
  1116. * @see Container#transferFocusDownCycle
  1117. */
  1118. public void downFocusCycle(Container aContainer) {
  1119. if (aContainer != null && aContainer.isFocusCycleRoot()) {
  1120. aContainer.transferFocusDownCycle();
  1121. }
  1122. }
  1123. }