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