293 }
294 }
295 return false;
296 }
297
298 /**
299 * This method is called by the AWT event dispatcher requesting that the
300 * current KeyboardFocusManager dispatch the specified event on its behalf.
301 * DefaultKeyboardFocusManagers dispatch all FocusEvents, all WindowEvents
302 * related to focus, and all KeyEvents. These events are dispatched based
303 * on the KeyboardFocusManager's notion of the focus owner and the focused
304 * and active Windows, sometimes overriding the source of the specified
305 * AWTEvent. If this method returns <code>false</code>, then the AWT event
306 * dispatcher will attempt to dispatch the event itself.
307 *
308 * @param e the AWTEvent to be dispatched
309 * @return <code>true</code> if this method dispatched the event;
310 * <code>false</code> otherwise
311 */
312 public boolean dispatchEvent(AWTEvent e) {
313 if (focusLog.isLoggable(PlatformLogger.FINE) && (e instanceof WindowEvent || e instanceof FocusEvent)) {
314 focusLog.fine("" + e);
315 }
316 switch (e.getID()) {
317 case WindowEvent.WINDOW_GAINED_FOCUS: {
318 if (repostIfFollowsKeyEvents((WindowEvent)e)) {
319 break;
320 }
321
322 WindowEvent we = (WindowEvent)e;
323 Window oldFocusedWindow = getGlobalFocusedWindow();
324 Window newFocusedWindow = we.getWindow();
325 if (newFocusedWindow == oldFocusedWindow) {
326 break;
327 }
328
329 if (!(newFocusedWindow.isFocusableWindow()
330 && newFocusedWindow.isVisible()
331 && newFocusedWindow.isDisplayable()))
332 {
333 // we can not accept focus on such window, so reject it.
402 // request should be synchronized on KeyboardFocusManager.class
403 // to prevent from thread race when user will request
404 // focus between calculation and our request.
405 // But if focus transfer is synchronous, this synchronization
406 // may cause deadlock, thus we don't synchronize this block.
407 Component toFocus = KeyboardFocusManager.
408 getMostRecentFocusOwner(newFocusedWindow);
409 if ((toFocus == null) &&
410 newFocusedWindow.isFocusableWindow())
411 {
412 toFocus = newFocusedWindow.getFocusTraversalPolicy().
413 getInitialComponent(newFocusedWindow);
414 }
415 Component tempLost = null;
416 synchronized(KeyboardFocusManager.class) {
417 tempLost = newFocusedWindow.setTemporaryLostComponent(null);
418 }
419
420 // The component which last has the focus when this window was focused
421 // should receive focus first
422 if (focusLog.isLoggable(PlatformLogger.FINER)) {
423 focusLog.finer("tempLost {0}, toFocus {1}",
424 tempLost, toFocus);
425 }
426 if (tempLost != null) {
427 tempLost.requestFocusInWindow(CausedFocusEvent.Cause.ACTIVATION);
428 }
429
430 if (toFocus != null && toFocus != tempLost) {
431 // If there is a component which requested focus when this window
432 // was inactive it expects to receive focus after activation.
433 toFocus.requestFocusInWindow(CausedFocusEvent.Cause.ACTIVATION);
434 }
435 }
436
437 Window realOppositeWindow = this.realOppositeWindowWR.get();
438 if (realOppositeWindow != we.getOppositeWindow()) {
439 we = new WindowEvent(newFocusedWindow,
440 WindowEvent.WINDOW_GAINED_FOCUS,
441 realOppositeWindow);
442 }
471 }
472
473 setGlobalActiveWindow(newActiveWindow);
474
475 if (newActiveWindow != getGlobalActiveWindow()) {
476 // Activation change was rejected. Unlikely, but
477 // possible.
478 break;
479 }
480
481 return typeAheadAssertions(newActiveWindow, we);
482 }
483
484 case FocusEvent.FOCUS_GAINED: {
485 FocusEvent fe = (FocusEvent)e;
486 CausedFocusEvent.Cause cause = (fe instanceof CausedFocusEvent) ?
487 ((CausedFocusEvent)fe).getCause() : CausedFocusEvent.Cause.UNKNOWN;
488 Component oldFocusOwner = getGlobalFocusOwner();
489 Component newFocusOwner = fe.getComponent();
490 if (oldFocusOwner == newFocusOwner) {
491 if (focusLog.isLoggable(PlatformLogger.FINE)) {
492 focusLog.fine("Skipping {0} because focus owner is the same", e);
493 }
494 // We can't just drop the event - there could be
495 // type-ahead markers associated with it.
496 dequeueKeyEvents(-1, newFocusOwner);
497 break;
498 }
499
500 // If there exists a current focus owner, then notify it that
501 // it has lost focus.
502 if (oldFocusOwner != null) {
503 boolean isEventDispatched =
504 sendMessage(oldFocusOwner,
505 new CausedFocusEvent(oldFocusOwner,
506 FocusEvent.FOCUS_LOST,
507 fe.isTemporary(),
508 newFocusOwner, cause));
509 // Failed to dispatch, clear by ourselfves
510 if (!isEventDispatched) {
511 setGlobalFocusOwner(null);
589 }
590
591 setNativeFocusOwner(getHeavyweight(newFocusOwner));
592
593 Component realOppositeComponent = this.realOppositeComponentWR.get();
594 if (realOppositeComponent != null &&
595 realOppositeComponent != fe.getOppositeComponent()) {
596 fe = new CausedFocusEvent(newFocusOwner,
597 FocusEvent.FOCUS_GAINED,
598 fe.isTemporary(),
599 realOppositeComponent, cause);
600 ((AWTEvent) fe).isPosted = true;
601 }
602 return typeAheadAssertions(newFocusOwner, fe);
603 }
604
605 case FocusEvent.FOCUS_LOST: {
606 FocusEvent fe = (FocusEvent)e;
607 Component currentFocusOwner = getGlobalFocusOwner();
608 if (currentFocusOwner == null) {
609 if (focusLog.isLoggable(PlatformLogger.FINE))
610 focusLog.fine("Skipping {0} because focus owner is null", e);
611 break;
612 }
613 // Ignore cases where a Component loses focus to itself.
614 // If we make a mistake because of retargeting, then the
615 // FOCUS_GAINED handler will correct it.
616 if (currentFocusOwner == fe.getOppositeComponent()) {
617 if (focusLog.isLoggable(PlatformLogger.FINE))
618 focusLog.fine("Skipping {0} because current focus owner is equal to opposite", e);
619 break;
620 }
621
622 setGlobalFocusOwner(null);
623
624 if (getGlobalFocusOwner() != null) {
625 // Focus change was rejected. Unlikely, but possible.
626 restoreFocus(currentFocusOwner, true);
627 break;
628 }
629
630 if (!fe.isTemporary()) {
631 setGlobalPermanentFocusOwner(null);
632
633 if (getGlobalPermanentFocusOwner() != null) {
634 // Focus change was rejected. Unlikely, but possible.
635 restoreFocus(currentFocusOwner, true);
636 break;
637 }
670 setGlobalActiveWindow(null);
671 if (getGlobalActiveWindow() != null) {
672 // Activation change was rejected. Unlikely, but possible.
673 break;
674 }
675
676 we.setSource(currentActiveWindow);
677 return typeAheadAssertions(currentActiveWindow, we);
678 }
679
680 case WindowEvent.WINDOW_LOST_FOCUS: {
681 if (repostIfFollowsKeyEvents((WindowEvent)e)) {
682 break;
683 }
684
685 WindowEvent we = (WindowEvent)e;
686 Window currentFocusedWindow = getGlobalFocusedWindow();
687 Window losingFocusWindow = we.getWindow();
688 Window activeWindow = getGlobalActiveWindow();
689 Window oppositeWindow = we.getOppositeWindow();
690 if (focusLog.isLoggable(PlatformLogger.FINE))
691 focusLog.fine("Active {0}, Current focused {1}, losing focus {2} opposite {3}",
692 activeWindow, currentFocusedWindow,
693 losingFocusWindow, oppositeWindow);
694 if (currentFocusedWindow == null) {
695 break;
696 }
697
698 // Special case -- if the native windowing system posts an
699 // event claiming that the active Window has lost focus to the
700 // focused Window, then discard the event. This is an artifact
701 // of the native windowing system not knowing which Window is
702 // really focused.
703 if (inSendMessage == 0 && losingFocusWindow == activeWindow &&
704 oppositeWindow == currentFocusedWindow)
705 {
706 break;
707 }
708
709 Component currentFocusOwner = getGlobalFocusOwner();
710 if (currentFocusOwner != null) {
856 }
857
858 private void pumpApprovedKeyEvents() {
859 KeyEvent ke;
860 do {
861 ke = null;
862 synchronized (this) {
863 if (enqueuedKeyEvents.size() != 0) {
864 ke = enqueuedKeyEvents.getFirst();
865 if (typeAheadMarkers.size() != 0) {
866 TypeAheadMarker marker = typeAheadMarkers.getFirst();
867 // Fixed 5064013: may appears that the events have the same time
868 // if (ke.getWhen() >= marker.after) {
869 // The fix is rolled out.
870
871 if (ke.getWhen() > marker.after) {
872 ke = null;
873 }
874 }
875 if (ke != null) {
876 if (focusLog.isLoggable(PlatformLogger.FINER)) {
877 focusLog.finer("Pumping approved event {0}", ke);
878 }
879 enqueuedKeyEvents.removeFirst();
880 }
881 }
882 }
883 if (ke != null) {
884 preDispatchKeyEvent(ke);
885 }
886 } while (ke != null);
887 }
888
889 /**
890 * Dumps the list of type-ahead queue markers to stderr
891 */
892 void dumpMarkers() {
893 if (focusLog.isLoggable(PlatformLogger.FINEST)) {
894 focusLog.finest(">>> Markers dump, time: {0}", System.currentTimeMillis());
895 synchronized (this) {
896 if (typeAheadMarkers.size() != 0) {
897 Iterator<TypeAheadMarker> iter = typeAheadMarkers.iterator();
898 while (iter.hasNext()) {
899 TypeAheadMarker marker = iter.next();
900 focusLog.finest(" {0}", marker);
901 }
902 }
903 }
904 }
905 }
906
907 private boolean typeAheadAssertions(Component target, AWTEvent e) {
908
909 // Clear any pending events here as well as in the FOCUS_GAINED
910 // handler. We need this call here in case a marker was removed in
911 // response to a call to dequeueKeyEvents.
912 pumpApprovedKeyEvents();
913
914 switch (e.getID()) {
915 case KeyEvent.KEY_TYPED:
916 case KeyEvent.KEY_PRESSED:
917 case KeyEvent.KEY_RELEASED: {
918 KeyEvent ke = (KeyEvent)e;
919 synchronized (this) {
920 if (e.isPosted && typeAheadMarkers.size() != 0) {
921 TypeAheadMarker marker = typeAheadMarkers.getFirst();
922 // Fixed 5064013: may appears that the events have the same time
923 // if (ke.getWhen() >= marker.after) {
924 // The fix is rolled out.
925
926 if (ke.getWhen() > marker.after) {
927 if (focusLog.isLoggable(PlatformLogger.FINER)) {
928 focusLog.finer("Storing event {0} because of marker {1}", ke, marker);
929 }
930 enqueuedKeyEvents.addLast(ke);
931 return true;
932 }
933 }
934 }
935
936 // KeyEvent was posted before focus change request
937 return preDispatchKeyEvent(ke);
938 }
939
940 case FocusEvent.FOCUS_GAINED:
941 if (focusLog.isLoggable(PlatformLogger.FINEST)) {
942 focusLog.finest("Markers before FOCUS_GAINED on {0}", target);
943 }
944 dumpMarkers();
945 // Search the marker list for the first marker tied to
946 // the Component which just gained focus. Then remove
947 // that marker, any markers which immediately follow
948 // and are tied to the same component, and all markers
949 // that preceed it. This handles the case where
950 // multiple focus requests were made for the same
951 // Component in a row and when we lost some of the
952 // earlier requests. Since FOCUS_GAINED events will
953 // not be generated for these additional requests, we
954 // need to clear those markers too.
955 synchronized (this) {
956 boolean found = false;
957 if (hasMarker(target)) {
958 for (Iterator<TypeAheadMarker> iter = typeAheadMarkers.iterator();
959 iter.hasNext(); )
960 {
961 if (iter.next().untilFocused == target) {
962 found = true;
963 } else if (found) {
964 break;
965 }
966 iter.remove();
967 }
968 } else {
969 // Exception condition - event without marker
970 if (focusLog.isLoggable(PlatformLogger.FINER)) {
971 focusLog.finer("Event without marker {0}", e);
972 }
973 }
974 }
975 focusLog.finest("Markers after FOCUS_GAINED");
976 dumpMarkers();
977
978 redispatchEvent(target, e);
979
980 // Now, dispatch any pending KeyEvents which have been
981 // released because of the FOCUS_GAINED event so that we don't
982 // have to wait for another event to be posted to the queue.
983 pumpApprovedKeyEvents();
984 return true;
985
986 default:
987 redispatchEvent(target, e);
988 return true;
989 }
990 }
1191 * Delays dispatching of KeyEvents until the specified Component becomes
1192 * the focus owner. KeyEvents with timestamps later than the specified
1193 * timestamp will be enqueued until the specified Component receives a
1194 * FOCUS_GAINED event, or the AWT cancels the delay request by invoking
1195 * <code>dequeueKeyEvents</code> or <code>discardKeyEvents</code>.
1196 *
1197 * @param after timestamp of current event, or the current, system time if
1198 * the current event has no timestamp, or the AWT cannot determine
1199 * which event is currently being handled
1200 * @param untilFocused Component which will receive a FOCUS_GAINED event
1201 * before any pending KeyEvents
1202 * @see #dequeueKeyEvents
1203 * @see #discardKeyEvents
1204 */
1205 protected synchronized void enqueueKeyEvents(long after,
1206 Component untilFocused) {
1207 if (untilFocused == null) {
1208 return;
1209 }
1210
1211 if (focusLog.isLoggable(PlatformLogger.FINER)) {
1212 focusLog.finer("Enqueue at {0} for {1}",
1213 after, untilFocused);
1214 }
1215
1216 int insertionIndex = 0,
1217 i = typeAheadMarkers.size();
1218 ListIterator<TypeAheadMarker> iter = typeAheadMarkers.listIterator(i);
1219
1220 for (; i > 0; i--) {
1221 TypeAheadMarker marker = iter.previous();
1222 if (marker.after <= after) {
1223 insertionIndex = i;
1224 break;
1225 }
1226 }
1227
1228 typeAheadMarkers.add(insertionIndex,
1229 new TypeAheadMarker(after, untilFocused));
1230 }
1231
1233 * Releases for normal dispatching to the current focus owner all
1234 * KeyEvents which were enqueued because of a call to
1235 * <code>enqueueKeyEvents</code> with the same timestamp and Component.
1236 * If the given timestamp is less than zero, the outstanding enqueue
1237 * request for the given Component with the <b>oldest</b> timestamp (if
1238 * any) should be cancelled.
1239 *
1240 * @param after the timestamp specified in the call to
1241 * <code>enqueueKeyEvents</code>, or any value < 0
1242 * @param untilFocused the Component specified in the call to
1243 * <code>enqueueKeyEvents</code>
1244 * @see #enqueueKeyEvents
1245 * @see #discardKeyEvents
1246 */
1247 protected synchronized void dequeueKeyEvents(long after,
1248 Component untilFocused) {
1249 if (untilFocused == null) {
1250 return;
1251 }
1252
1253 if (focusLog.isLoggable(PlatformLogger.FINER)) {
1254 focusLog.finer("Dequeue at {0} for {1}",
1255 after, untilFocused);
1256 }
1257
1258 TypeAheadMarker marker;
1259 ListIterator<TypeAheadMarker> iter = typeAheadMarkers.listIterator
1260 ((after >= 0) ? typeAheadMarkers.size() : 0);
1261
1262 if (after < 0) {
1263 while (iter.hasNext()) {
1264 marker = iter.next();
1265 if (marker.untilFocused == untilFocused)
1266 {
1267 iter.remove();
1268 return;
1269 }
1270 }
1271 } else {
1272 while (iter.hasPrevious()) {
1273 marker = iter.previous();
|
293 }
294 }
295 return false;
296 }
297
298 /**
299 * This method is called by the AWT event dispatcher requesting that the
300 * current KeyboardFocusManager dispatch the specified event on its behalf.
301 * DefaultKeyboardFocusManagers dispatch all FocusEvents, all WindowEvents
302 * related to focus, and all KeyEvents. These events are dispatched based
303 * on the KeyboardFocusManager's notion of the focus owner and the focused
304 * and active Windows, sometimes overriding the source of the specified
305 * AWTEvent. If this method returns <code>false</code>, then the AWT event
306 * dispatcher will attempt to dispatch the event itself.
307 *
308 * @param e the AWTEvent to be dispatched
309 * @return <code>true</code> if this method dispatched the event;
310 * <code>false</code> otherwise
311 */
312 public boolean dispatchEvent(AWTEvent e) {
313 if (focusLog.isLoggable(PlatformLogger.Level.FINE) && (e instanceof WindowEvent || e instanceof FocusEvent)) {
314 focusLog.fine("" + e);
315 }
316 switch (e.getID()) {
317 case WindowEvent.WINDOW_GAINED_FOCUS: {
318 if (repostIfFollowsKeyEvents((WindowEvent)e)) {
319 break;
320 }
321
322 WindowEvent we = (WindowEvent)e;
323 Window oldFocusedWindow = getGlobalFocusedWindow();
324 Window newFocusedWindow = we.getWindow();
325 if (newFocusedWindow == oldFocusedWindow) {
326 break;
327 }
328
329 if (!(newFocusedWindow.isFocusableWindow()
330 && newFocusedWindow.isVisible()
331 && newFocusedWindow.isDisplayable()))
332 {
333 // we can not accept focus on such window, so reject it.
402 // request should be synchronized on KeyboardFocusManager.class
403 // to prevent from thread race when user will request
404 // focus between calculation and our request.
405 // But if focus transfer is synchronous, this synchronization
406 // may cause deadlock, thus we don't synchronize this block.
407 Component toFocus = KeyboardFocusManager.
408 getMostRecentFocusOwner(newFocusedWindow);
409 if ((toFocus == null) &&
410 newFocusedWindow.isFocusableWindow())
411 {
412 toFocus = newFocusedWindow.getFocusTraversalPolicy().
413 getInitialComponent(newFocusedWindow);
414 }
415 Component tempLost = null;
416 synchronized(KeyboardFocusManager.class) {
417 tempLost = newFocusedWindow.setTemporaryLostComponent(null);
418 }
419
420 // The component which last has the focus when this window was focused
421 // should receive focus first
422 if (focusLog.isLoggable(PlatformLogger.Level.FINER)) {
423 focusLog.finer("tempLost {0}, toFocus {1}",
424 tempLost, toFocus);
425 }
426 if (tempLost != null) {
427 tempLost.requestFocusInWindow(CausedFocusEvent.Cause.ACTIVATION);
428 }
429
430 if (toFocus != null && toFocus != tempLost) {
431 // If there is a component which requested focus when this window
432 // was inactive it expects to receive focus after activation.
433 toFocus.requestFocusInWindow(CausedFocusEvent.Cause.ACTIVATION);
434 }
435 }
436
437 Window realOppositeWindow = this.realOppositeWindowWR.get();
438 if (realOppositeWindow != we.getOppositeWindow()) {
439 we = new WindowEvent(newFocusedWindow,
440 WindowEvent.WINDOW_GAINED_FOCUS,
441 realOppositeWindow);
442 }
471 }
472
473 setGlobalActiveWindow(newActiveWindow);
474
475 if (newActiveWindow != getGlobalActiveWindow()) {
476 // Activation change was rejected. Unlikely, but
477 // possible.
478 break;
479 }
480
481 return typeAheadAssertions(newActiveWindow, we);
482 }
483
484 case FocusEvent.FOCUS_GAINED: {
485 FocusEvent fe = (FocusEvent)e;
486 CausedFocusEvent.Cause cause = (fe instanceof CausedFocusEvent) ?
487 ((CausedFocusEvent)fe).getCause() : CausedFocusEvent.Cause.UNKNOWN;
488 Component oldFocusOwner = getGlobalFocusOwner();
489 Component newFocusOwner = fe.getComponent();
490 if (oldFocusOwner == newFocusOwner) {
491 if (focusLog.isLoggable(PlatformLogger.Level.FINE)) {
492 focusLog.fine("Skipping {0} because focus owner is the same", e);
493 }
494 // We can't just drop the event - there could be
495 // type-ahead markers associated with it.
496 dequeueKeyEvents(-1, newFocusOwner);
497 break;
498 }
499
500 // If there exists a current focus owner, then notify it that
501 // it has lost focus.
502 if (oldFocusOwner != null) {
503 boolean isEventDispatched =
504 sendMessage(oldFocusOwner,
505 new CausedFocusEvent(oldFocusOwner,
506 FocusEvent.FOCUS_LOST,
507 fe.isTemporary(),
508 newFocusOwner, cause));
509 // Failed to dispatch, clear by ourselfves
510 if (!isEventDispatched) {
511 setGlobalFocusOwner(null);
589 }
590
591 setNativeFocusOwner(getHeavyweight(newFocusOwner));
592
593 Component realOppositeComponent = this.realOppositeComponentWR.get();
594 if (realOppositeComponent != null &&
595 realOppositeComponent != fe.getOppositeComponent()) {
596 fe = new CausedFocusEvent(newFocusOwner,
597 FocusEvent.FOCUS_GAINED,
598 fe.isTemporary(),
599 realOppositeComponent, cause);
600 ((AWTEvent) fe).isPosted = true;
601 }
602 return typeAheadAssertions(newFocusOwner, fe);
603 }
604
605 case FocusEvent.FOCUS_LOST: {
606 FocusEvent fe = (FocusEvent)e;
607 Component currentFocusOwner = getGlobalFocusOwner();
608 if (currentFocusOwner == null) {
609 if (focusLog.isLoggable(PlatformLogger.Level.FINE))
610 focusLog.fine("Skipping {0} because focus owner is null", e);
611 break;
612 }
613 // Ignore cases where a Component loses focus to itself.
614 // If we make a mistake because of retargeting, then the
615 // FOCUS_GAINED handler will correct it.
616 if (currentFocusOwner == fe.getOppositeComponent()) {
617 if (focusLog.isLoggable(PlatformLogger.Level.FINE))
618 focusLog.fine("Skipping {0} because current focus owner is equal to opposite", e);
619 break;
620 }
621
622 setGlobalFocusOwner(null);
623
624 if (getGlobalFocusOwner() != null) {
625 // Focus change was rejected. Unlikely, but possible.
626 restoreFocus(currentFocusOwner, true);
627 break;
628 }
629
630 if (!fe.isTemporary()) {
631 setGlobalPermanentFocusOwner(null);
632
633 if (getGlobalPermanentFocusOwner() != null) {
634 // Focus change was rejected. Unlikely, but possible.
635 restoreFocus(currentFocusOwner, true);
636 break;
637 }
670 setGlobalActiveWindow(null);
671 if (getGlobalActiveWindow() != null) {
672 // Activation change was rejected. Unlikely, but possible.
673 break;
674 }
675
676 we.setSource(currentActiveWindow);
677 return typeAheadAssertions(currentActiveWindow, we);
678 }
679
680 case WindowEvent.WINDOW_LOST_FOCUS: {
681 if (repostIfFollowsKeyEvents((WindowEvent)e)) {
682 break;
683 }
684
685 WindowEvent we = (WindowEvent)e;
686 Window currentFocusedWindow = getGlobalFocusedWindow();
687 Window losingFocusWindow = we.getWindow();
688 Window activeWindow = getGlobalActiveWindow();
689 Window oppositeWindow = we.getOppositeWindow();
690 if (focusLog.isLoggable(PlatformLogger.Level.FINE))
691 focusLog.fine("Active {0}, Current focused {1}, losing focus {2} opposite {3}",
692 activeWindow, currentFocusedWindow,
693 losingFocusWindow, oppositeWindow);
694 if (currentFocusedWindow == null) {
695 break;
696 }
697
698 // Special case -- if the native windowing system posts an
699 // event claiming that the active Window has lost focus to the
700 // focused Window, then discard the event. This is an artifact
701 // of the native windowing system not knowing which Window is
702 // really focused.
703 if (inSendMessage == 0 && losingFocusWindow == activeWindow &&
704 oppositeWindow == currentFocusedWindow)
705 {
706 break;
707 }
708
709 Component currentFocusOwner = getGlobalFocusOwner();
710 if (currentFocusOwner != null) {
856 }
857
858 private void pumpApprovedKeyEvents() {
859 KeyEvent ke;
860 do {
861 ke = null;
862 synchronized (this) {
863 if (enqueuedKeyEvents.size() != 0) {
864 ke = enqueuedKeyEvents.getFirst();
865 if (typeAheadMarkers.size() != 0) {
866 TypeAheadMarker marker = typeAheadMarkers.getFirst();
867 // Fixed 5064013: may appears that the events have the same time
868 // if (ke.getWhen() >= marker.after) {
869 // The fix is rolled out.
870
871 if (ke.getWhen() > marker.after) {
872 ke = null;
873 }
874 }
875 if (ke != null) {
876 if (focusLog.isLoggable(PlatformLogger.Level.FINER)) {
877 focusLog.finer("Pumping approved event {0}", ke);
878 }
879 enqueuedKeyEvents.removeFirst();
880 }
881 }
882 }
883 if (ke != null) {
884 preDispatchKeyEvent(ke);
885 }
886 } while (ke != null);
887 }
888
889 /**
890 * Dumps the list of type-ahead queue markers to stderr
891 */
892 void dumpMarkers() {
893 if (focusLog.isLoggable(PlatformLogger.Level.FINEST)) {
894 focusLog.finest(">>> Markers dump, time: {0}", System.currentTimeMillis());
895 synchronized (this) {
896 if (typeAheadMarkers.size() != 0) {
897 Iterator<TypeAheadMarker> iter = typeAheadMarkers.iterator();
898 while (iter.hasNext()) {
899 TypeAheadMarker marker = iter.next();
900 focusLog.finest(" {0}", marker);
901 }
902 }
903 }
904 }
905 }
906
907 private boolean typeAheadAssertions(Component target, AWTEvent e) {
908
909 // Clear any pending events here as well as in the FOCUS_GAINED
910 // handler. We need this call here in case a marker was removed in
911 // response to a call to dequeueKeyEvents.
912 pumpApprovedKeyEvents();
913
914 switch (e.getID()) {
915 case KeyEvent.KEY_TYPED:
916 case KeyEvent.KEY_PRESSED:
917 case KeyEvent.KEY_RELEASED: {
918 KeyEvent ke = (KeyEvent)e;
919 synchronized (this) {
920 if (e.isPosted && typeAheadMarkers.size() != 0) {
921 TypeAheadMarker marker = typeAheadMarkers.getFirst();
922 // Fixed 5064013: may appears that the events have the same time
923 // if (ke.getWhen() >= marker.after) {
924 // The fix is rolled out.
925
926 if (ke.getWhen() > marker.after) {
927 if (focusLog.isLoggable(PlatformLogger.Level.FINER)) {
928 focusLog.finer("Storing event {0} because of marker {1}", ke, marker);
929 }
930 enqueuedKeyEvents.addLast(ke);
931 return true;
932 }
933 }
934 }
935
936 // KeyEvent was posted before focus change request
937 return preDispatchKeyEvent(ke);
938 }
939
940 case FocusEvent.FOCUS_GAINED:
941 if (focusLog.isLoggable(PlatformLogger.Level.FINEST)) {
942 focusLog.finest("Markers before FOCUS_GAINED on {0}", target);
943 }
944 dumpMarkers();
945 // Search the marker list for the first marker tied to
946 // the Component which just gained focus. Then remove
947 // that marker, any markers which immediately follow
948 // and are tied to the same component, and all markers
949 // that preceed it. This handles the case where
950 // multiple focus requests were made for the same
951 // Component in a row and when we lost some of the
952 // earlier requests. Since FOCUS_GAINED events will
953 // not be generated for these additional requests, we
954 // need to clear those markers too.
955 synchronized (this) {
956 boolean found = false;
957 if (hasMarker(target)) {
958 for (Iterator<TypeAheadMarker> iter = typeAheadMarkers.iterator();
959 iter.hasNext(); )
960 {
961 if (iter.next().untilFocused == target) {
962 found = true;
963 } else if (found) {
964 break;
965 }
966 iter.remove();
967 }
968 } else {
969 // Exception condition - event without marker
970 if (focusLog.isLoggable(PlatformLogger.Level.FINER)) {
971 focusLog.finer("Event without marker {0}", e);
972 }
973 }
974 }
975 focusLog.finest("Markers after FOCUS_GAINED");
976 dumpMarkers();
977
978 redispatchEvent(target, e);
979
980 // Now, dispatch any pending KeyEvents which have been
981 // released because of the FOCUS_GAINED event so that we don't
982 // have to wait for another event to be posted to the queue.
983 pumpApprovedKeyEvents();
984 return true;
985
986 default:
987 redispatchEvent(target, e);
988 return true;
989 }
990 }
1191 * Delays dispatching of KeyEvents until the specified Component becomes
1192 * the focus owner. KeyEvents with timestamps later than the specified
1193 * timestamp will be enqueued until the specified Component receives a
1194 * FOCUS_GAINED event, or the AWT cancels the delay request by invoking
1195 * <code>dequeueKeyEvents</code> or <code>discardKeyEvents</code>.
1196 *
1197 * @param after timestamp of current event, or the current, system time if
1198 * the current event has no timestamp, or the AWT cannot determine
1199 * which event is currently being handled
1200 * @param untilFocused Component which will receive a FOCUS_GAINED event
1201 * before any pending KeyEvents
1202 * @see #dequeueKeyEvents
1203 * @see #discardKeyEvents
1204 */
1205 protected synchronized void enqueueKeyEvents(long after,
1206 Component untilFocused) {
1207 if (untilFocused == null) {
1208 return;
1209 }
1210
1211 if (focusLog.isLoggable(PlatformLogger.Level.FINER)) {
1212 focusLog.finer("Enqueue at {0} for {1}",
1213 after, untilFocused);
1214 }
1215
1216 int insertionIndex = 0,
1217 i = typeAheadMarkers.size();
1218 ListIterator<TypeAheadMarker> iter = typeAheadMarkers.listIterator(i);
1219
1220 for (; i > 0; i--) {
1221 TypeAheadMarker marker = iter.previous();
1222 if (marker.after <= after) {
1223 insertionIndex = i;
1224 break;
1225 }
1226 }
1227
1228 typeAheadMarkers.add(insertionIndex,
1229 new TypeAheadMarker(after, untilFocused));
1230 }
1231
1233 * Releases for normal dispatching to the current focus owner all
1234 * KeyEvents which were enqueued because of a call to
1235 * <code>enqueueKeyEvents</code> with the same timestamp and Component.
1236 * If the given timestamp is less than zero, the outstanding enqueue
1237 * request for the given Component with the <b>oldest</b> timestamp (if
1238 * any) should be cancelled.
1239 *
1240 * @param after the timestamp specified in the call to
1241 * <code>enqueueKeyEvents</code>, or any value < 0
1242 * @param untilFocused the Component specified in the call to
1243 * <code>enqueueKeyEvents</code>
1244 * @see #enqueueKeyEvents
1245 * @see #discardKeyEvents
1246 */
1247 protected synchronized void dequeueKeyEvents(long after,
1248 Component untilFocused) {
1249 if (untilFocused == null) {
1250 return;
1251 }
1252
1253 if (focusLog.isLoggable(PlatformLogger.Level.FINER)) {
1254 focusLog.finer("Dequeue at {0} for {1}",
1255 after, untilFocused);
1256 }
1257
1258 TypeAheadMarker marker;
1259 ListIterator<TypeAheadMarker> iter = typeAheadMarkers.listIterator
1260 ((after >= 0) ? typeAheadMarkers.size() : 0);
1261
1262 if (after < 0) {
1263 while (iter.hasNext()) {
1264 marker = iter.next();
1265 if (marker.untilFocused == untilFocused)
1266 {
1267 iter.remove();
1268 return;
1269 }
1270 }
1271 } else {
1272 while (iter.hasPrevious()) {
1273 marker = iter.previous();
|