src/share/classes/java/awt/DefaultKeyboardFocusManager.java

Print this page




 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();