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