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

Print this page




  23  * questions.
  24  */
  25 package java.awt;
  26 
  27 import java.awt.event.FocusEvent;
  28 import java.awt.event.KeyEvent;
  29 import java.awt.event.WindowEvent;
  30 import java.awt.peer.ComponentPeer;
  31 import java.awt.peer.LightweightPeer;
  32 import java.lang.ref.WeakReference;
  33 import java.util.LinkedList;
  34 import java.util.Iterator;
  35 import java.util.ListIterator;
  36 import java.util.Set;
  37 
  38 import sun.util.logging.PlatformLogger;
  39 
  40 import sun.awt.AppContext;
  41 import sun.awt.SunToolkit;
  42 import sun.awt.CausedFocusEvent;

  43 
  44 /**
  45  * The default KeyboardFocusManager for AWT applications. Focus traversal is
  46  * done in response to a Component's focus traversal keys, and using a
  47  * Container's FocusTraversalPolicy.
  48  * <p>
  49  * Please see
  50  * <a href="http://java.sun.com/docs/books/tutorial/uiswing/misc/focus.html">
  51  * How to Use the Focus Subsystem</a>,
  52  * a section in <em>The Java Tutorial</em>, and the
  53  * <a href="../../java/awt/doc-files/FocusSpec.html">Focus Specification</a>
  54  * for more information.
  55  *
  56  * @author David Mendenhall
  57  *
  58  * @see FocusTraversalPolicy
  59  * @see Component#setFocusTraversalKeys
  60  * @see Component#getFocusTraversalKeys
  61  * @since 1.4
  62  */
  63 public class DefaultKeyboardFocusManager extends KeyboardFocusManager {
  64     private static final PlatformLogger focusLog = PlatformLogger.getLogger("java.awt.focus.DefaultKeyboardFocusManager");
  65 
  66     // null weak references to not create too many objects
  67     private static final WeakReference<Window> NULL_WINDOW_WR =
  68         new WeakReference<Window>(null);
  69     private static final WeakReference<Component> NULL_COMPONENT_WR =
  70         new WeakReference<Component>(null);
  71     private WeakReference<Window> realOppositeWindowWR = NULL_WINDOW_WR;
  72     private WeakReference<Component> realOppositeComponentWR = NULL_COMPONENT_WR;
  73     private int inSendMessage;
  74     private LinkedList enqueuedKeyEvents = new LinkedList(),
  75         typeAheadMarkers = new LinkedList();
  76     private boolean consumeNextKeyTyped;
  77 
  78     private static class TypeAheadMarker {
  79         long after;
  80         Component untilFocused;
  81 
  82         TypeAheadMarker(long after, Component untilFocused) {
  83             this.after = after;
  84             this.untilFocused = untilFocused;
  85         }
  86         /**
  87          * Returns string representation of the marker
  88          */
  89         public String toString() {
  90             return ">>> Marker after " + after + " on " + untilFocused;
  91         }
  92     }
  93 
  94     private Window getOwningFrameDialog(Window window) {
  95         while (window != null && !(window instanceof Frame ||


 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(PlatformLogger.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,


 619                 }
 620 
 621                 if (currentActiveWindow != e.getSource()) {
 622                     // The event is lost in time.
 623                     // Allow listeners to precess the event but do not
 624                     // change any global states
 625                     break;
 626                 }
 627 
 628                 setGlobalActiveWindow(null);
 629                 if (getGlobalActiveWindow() != null) {
 630                     // Activation change was rejected. Unlikely, but possible.
 631                     break;
 632                 }
 633 
 634                 we.setSource(currentActiveWindow);
 635                 return typeAheadAssertions(currentActiveWindow, we);
 636             }
 637 
 638             case WindowEvent.WINDOW_LOST_FOCUS: {




 639                 WindowEvent we = (WindowEvent)e;
 640                 Window currentFocusedWindow = getGlobalFocusedWindow();
 641                 Window losingFocusWindow = we.getWindow();
 642                 Window activeWindow = getGlobalActiveWindow();
 643                 Window oppositeWindow = we.getOppositeWindow();
 644                 if (focusLog.isLoggable(PlatformLogger.FINE))
 645                     focusLog.fine("Active {0}, Current focused {1}, losing focus {2} opposite {3}",
 646                                   activeWindow, currentFocusedWindow,
 647                                   losingFocusWindow, oppositeWindow);
 648                 if (currentFocusedWindow == null) {
 649                     break;
 650                 }
 651 
 652                 // Special case -- if the native windowing system posts an
 653                 // event claiming that the active Window has lost focus to the
 654                 // focused Window, then discard the event. This is an artifact
 655                 // of the native windowing system not knowing which Window is
 656                 // really focused.
 657                 if (inSendMessage == 0 && losingFocusWindow == activeWindow &&
 658                     oppositeWindow == currentFocusedWindow)


 798      * @see MenuShortcut
 799      */
 800     public boolean postProcessKeyEvent(KeyEvent e) {
 801         if (!e.isConsumed()) {
 802             Component target = e.getComponent();
 803             Container p = (Container)
 804                 (target instanceof Container ? target : target.getParent());
 805             if (p != null) {
 806                 p.postProcessKeyEvent(e);
 807             }
 808         }
 809         return true;
 810     }
 811 
 812     private void pumpApprovedKeyEvents() {
 813         KeyEvent ke;
 814         do {
 815             ke = null;
 816             synchronized (this) {
 817                 if (enqueuedKeyEvents.size() != 0) {
 818                     ke = (KeyEvent)enqueuedKeyEvents.getFirst();
 819                     if (typeAheadMarkers.size() != 0) {
 820                         TypeAheadMarker marker = (TypeAheadMarker)
 821                             typeAheadMarkers.getFirst();
 822                         // Fixed 5064013: may appears that the events have the same time
 823                         // if (ke.getWhen() >= marker.after) {
 824                         // The fix is rolled out.
 825 
 826                         if (ke.getWhen() > marker.after) {
 827                             ke = null;
 828                         }
 829                     }
 830                     if (ke != null) {
 831                         focusLog.finer("Pumping approved event {0}", ke);
 832                         enqueuedKeyEvents.removeFirst();
 833                     }
 834                 }
 835             }
 836             if (ke != null) {
 837                 preDispatchKeyEvent(ke);
 838             }
 839         } while (ke != null);
 840     }
 841 
 842     /**
 843      * Dumps the list of type-ahead queue markers to stderr
 844      */
 845     void dumpMarkers() {
 846         if (focusLog.isLoggable(PlatformLogger.FINEST)) {
 847             focusLog.finest(">>> Markers dump, time: {0}", System.currentTimeMillis());
 848             synchronized (this) {
 849                 if (typeAheadMarkers.size() != 0) {
 850                     Iterator iter = typeAheadMarkers.iterator();
 851                     while (iter.hasNext()) {
 852                         TypeAheadMarker marker = (TypeAheadMarker)iter.next();
 853                         focusLog.finest("    {0}", marker);
 854                     }
 855                 }
 856             }
 857         }
 858     }
 859 
 860     private boolean typeAheadAssertions(Component target, AWTEvent e) {
 861 
 862         // Clear any pending events here as well as in the FOCUS_GAINED
 863         // handler. We need this call here in case a marker was removed in
 864         // response to a call to dequeueKeyEvents.
 865         pumpApprovedKeyEvents();
 866 
 867         switch (e.getID()) {
 868             case KeyEvent.KEY_TYPED:
 869             case KeyEvent.KEY_PRESSED:
 870             case KeyEvent.KEY_RELEASED: {
 871                 KeyEvent ke = (KeyEvent)e;
 872                 synchronized (this) {
 873                     if (e.isPosted && typeAheadMarkers.size() != 0) {
 874                         TypeAheadMarker marker = (TypeAheadMarker)
 875                             typeAheadMarkers.getFirst();
 876                         // Fixed 5064013: may appears that the events have the same time
 877                         // if (ke.getWhen() >= marker.after) {
 878                         // The fix is rolled out.
 879 
 880                         if (ke.getWhen() > marker.after) {
 881                             focusLog.finer("Storing event {0} because of marker {1}", ke, marker);
 882                             enqueuedKeyEvents.addLast(ke);
 883                             return true;
 884                         }
 885                     }
 886                 }
 887 
 888                 // KeyEvent was posted before focus change request
 889                 return preDispatchKeyEvent(ke);
 890             }
 891 
 892             case FocusEvent.FOCUS_GAINED:
 893                 focusLog.finest("Markers before FOCUS_GAINED on {0}", target);
 894                 dumpMarkers();
 895                 // Search the marker list for the first marker tied to
 896                 // the Component which just gained focus. Then remove
 897                 // that marker, any markers which immediately follow
 898                 // and are tied to the same component, and all markers
 899                 // that preceed it. This handles the case where
 900                 // multiple focus requests were made for the same
 901                 // Component in a row and when we lost some of the
 902                 // earlier requests. Since FOCUS_GAINED events will
 903                 // not be generated for these additional requests, we
 904                 // need to clear those markers too.
 905                 synchronized (this) {
 906                     boolean found = false;
 907                     if (hasMarker(target)) {
 908                         for (Iterator iter = typeAheadMarkers.iterator();
 909                              iter.hasNext(); )
 910                         {
 911                             if (((TypeAheadMarker)iter.next()).untilFocused ==
 912                                 target)
 913                             {
 914                                 found = true;
 915                             } else if (found) {
 916                                 break;
 917                             }
 918                             iter.remove();
 919                         }
 920                     } else {
 921                         // Exception condition - event without marker
 922                         focusLog.finer("Event without marker {0}", e);
 923                     }
 924                 }
 925                 focusLog.finest("Markers after FOCUS_GAINED");
 926                 dumpMarkers();
 927 
 928                 redispatchEvent(target, e);
 929 
 930                 // Now, dispatch any pending KeyEvents which have been
 931                 // released because of the FOCUS_GAINED event so that we don't
 932                 // have to wait for another event to be posted to the queue.
 933                 pumpApprovedKeyEvents();
 934                 return true;
 935 
 936             default:
 937                 redispatchEvent(target, e);
 938                 return true;
 939         }
 940     }
 941 
 942     /**
 943      * Returns true if there are some marker associated with component <code>comp</code>
 944      * in a markers' queue
 945      * @since 1.5
 946      */
 947     private boolean hasMarker(Component comp) {
 948         for (Iterator iter = typeAheadMarkers.iterator(); iter.hasNext(); ) {
 949             if (((TypeAheadMarker)iter.next()).untilFocused == comp) {
 950                 return true;
 951             }
 952         }
 953         return false;
 954     }
 955 
 956     /**
 957      * Clears markers queue
 958      * @since 1.5
 959      */
 960     void clearMarkers() {
 961         synchronized(this) {
 962             typeAheadMarkers.clear();
 963         }
 964     }
 965 
 966     private boolean preDispatchKeyEvent(KeyEvent ke) {
 967         if (((AWTEvent) ke).isPosted) {
 968             Component focusOwner = getFocusOwner();
 969             ke.setSource(((focusOwner != null) ? focusOwner : getFocusedWindow()));
 970         }
 971         if (ke.getSource() == null) {
 972             return true;
 973         }
 974 
 975         // Explicitly set the current event and most recent timestamp here in
 976         // addition to the call in Component.dispatchEventImpl. Because
 977         // KeyEvents can be delivered in response to a FOCUS_GAINED event, the
 978         // current timestamp may be incorrect. We need to set it here so that
 979         // KeyEventDispatchers will use the correct time.
 980         EventQueue.setCurrentEventAndMostRecentTime(ke);
 981 
 982         /**
 983          * Fix for 4495473.
 984          * This fix allows to correctly dispatch events when native
 985          * event proxying mechanism is active.
 986          * If it is active we should redispatch key events after
 987          * we detected its correct target.
 988          */
 989         if (KeyboardFocusManager.isProxyActive(ke)) {
 990             Component source = (Component)ke.getSource();
 991             Container target = source.getNativeContainer();
 992             if (target != null) {
 993                 ComponentPeer peer = target.getPeer();
 994                 if (peer != null) {
 995                     peer.handleEvent(ke);
 996                     /**
 997                      * Fix for 4478780 - consume event after it was dispatched by peer.
 998                      */
 999                     ke.consume();


1147      *
1148      * @param after timestamp of current event, or the current, system time if
1149      *        the current event has no timestamp, or the AWT cannot determine
1150      *        which event is currently being handled
1151      * @param untilFocused Component which will receive a FOCUS_GAINED event
1152      *        before any pending KeyEvents
1153      * @see #dequeueKeyEvents
1154      * @see #discardKeyEvents
1155      */
1156     protected synchronized void enqueueKeyEvents(long after,
1157                                                  Component untilFocused) {
1158         if (untilFocused == null) {
1159             return;
1160         }
1161 
1162         focusLog.finer("Enqueue at {0} for {1}",
1163                        after, untilFocused);
1164 
1165         int insertionIndex = 0,
1166             i = typeAheadMarkers.size();
1167         ListIterator iter = typeAheadMarkers.listIterator(i);
1168 
1169         for (; i > 0; i--) {
1170             TypeAheadMarker marker = (TypeAheadMarker)iter.previous();
1171             if (marker.after <= after) {
1172                 insertionIndex = i;
1173                 break;
1174             }
1175         }
1176 
1177         typeAheadMarkers.add(insertionIndex,
1178                              new TypeAheadMarker(after, untilFocused));
1179     }
1180 
1181     /**
1182      * Releases for normal dispatching to the current focus owner all
1183      * KeyEvents which were enqueued because of a call to
1184      * <code>enqueueKeyEvents</code> with the same timestamp and Component.
1185      * If the given timestamp is less than zero, the outstanding enqueue
1186      * request for the given Component with the <b>oldest</b> timestamp (if
1187      * any) should be cancelled.
1188      *
1189      * @param after the timestamp specified in the call to
1190      *        <code>enqueueKeyEvents</code>, or any value < 0
1191      * @param untilFocused the Component specified in the call to
1192      *        <code>enqueueKeyEvents</code>
1193      * @see #enqueueKeyEvents
1194      * @see #discardKeyEvents
1195      */
1196     protected synchronized void dequeueKeyEvents(long after,
1197                                                  Component untilFocused) {
1198         if (untilFocused == null) {
1199             return;
1200         }
1201 
1202         focusLog.finer("Dequeue at {0} for {1}",
1203                        after, untilFocused);
1204 
1205         TypeAheadMarker marker;
1206         ListIterator iter = typeAheadMarkers.listIterator
1207             ((after >= 0) ? typeAheadMarkers.size() : 0);
1208 
1209         if (after < 0) {
1210             while (iter.hasNext()) {
1211                 marker = (TypeAheadMarker)iter.next();
1212                 if (marker.untilFocused == untilFocused)
1213                 {
1214                     iter.remove();
1215                     return;
1216                 }
1217             }
1218         } else {
1219             while (iter.hasPrevious()) {
1220                 marker = (TypeAheadMarker)iter.previous();
1221                 if (marker.untilFocused == untilFocused &&
1222                     marker.after == after)
1223                 {
1224                     iter.remove();
1225                     return;
1226                 }
1227             }
1228         }
1229     }
1230 
1231     /**
1232      * Discards all KeyEvents which were enqueued because of one or more calls
1233      * to <code>enqueueKeyEvents</code> with the specified Component, or one of
1234      * its descendants.
1235      *
1236      * @param comp the Component specified in one or more calls to
1237      *        <code>enqueueKeyEvents</code>, or a parent of such a Component
1238      * @see #enqueueKeyEvents
1239      * @see #dequeueKeyEvents
1240      */
1241     protected synchronized void discardKeyEvents(Component comp) {
1242         if (comp == null) {
1243             return;
1244         }
1245 
1246         long start = -1;
1247 
1248         for (Iterator iter = typeAheadMarkers.iterator(); iter.hasNext(); ) {
1249             TypeAheadMarker marker = (TypeAheadMarker)iter.next();
1250             Component toTest = marker.untilFocused;
1251             boolean match = (toTest == comp);
1252             while (!match && toTest != null && !(toTest instanceof Window)) {
1253                 toTest = toTest.getParent();
1254                 match = (toTest == comp);
1255             }
1256             if (match) {
1257                 if (start < 0) {
1258                     start = marker.after;
1259                 }
1260                 iter.remove();
1261             } else if (start >= 0) {
1262                 purgeStampedEvents(start, marker.after);
1263                 start = -1;
1264             }
1265         }
1266 
1267         purgeStampedEvents(start, -1);
1268     }
1269 
1270     // Notes:
1271     //   * must be called inside a synchronized block
1272     //   * if 'start' is < 0, then this function does nothing
1273     //   * if 'end' is < 0, then all KeyEvents from 'start' to the end of the
1274     //     queue will be removed
1275     private void purgeStampedEvents(long start, long end) {
1276         if (start < 0) {
1277             return;
1278         }
1279 
1280         for (Iterator iter = enqueuedKeyEvents.iterator(); iter.hasNext(); ) {
1281             KeyEvent ke = (KeyEvent)iter.next();
1282             long time = ke.getWhen();
1283 
1284             if (start < time && (end < 0 || time <= end)) {
1285                 iter.remove();
1286             }
1287 
1288             if (end >= 0 && time > end) {
1289                 break;
1290             }
1291         }
1292     }
1293 
1294     /**
1295      * Focuses the Component before aComponent, typically based on a
1296      * FocusTraversalPolicy.
1297      *
1298      * @param aComponent the Component that is the basis for the focus
1299      *        traversal operation
1300      * @see FocusTraversalPolicy
1301      * @see Component#transferFocusBackward




  23  * questions.
  24  */
  25 package java.awt;
  26 
  27 import java.awt.event.FocusEvent;
  28 import java.awt.event.KeyEvent;
  29 import java.awt.event.WindowEvent;
  30 import java.awt.peer.ComponentPeer;
  31 import java.awt.peer.LightweightPeer;
  32 import java.lang.ref.WeakReference;
  33 import java.util.LinkedList;
  34 import java.util.Iterator;
  35 import java.util.ListIterator;
  36 import java.util.Set;
  37 
  38 import sun.util.logging.PlatformLogger;
  39 
  40 import sun.awt.AppContext;
  41 import sun.awt.SunToolkit;
  42 import sun.awt.CausedFocusEvent;
  43 import sun.awt.TimedWindowEvent;
  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  */
  64 public class DefaultKeyboardFocusManager extends KeyboardFocusManager {
  65     private static final PlatformLogger focusLog = PlatformLogger.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<KeyEvent> enqueuedKeyEvents = new LinkedList<KeyEvent>();
  76     private LinkedList<TypeAheadMarker> typeAheadMarkers = new LinkedList<TypeAheadMarker>();
  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 ||


 243                 edt.pumpEvents(SentEvent.ID, new Conditional() {
 244                         public boolean evaluate() {
 245                             return !se.dispatched && !targetAppContext.isDisposed();
 246                         }
 247                     });
 248             } else {
 249                 synchronized (se) {
 250                     while (!se.dispatched && !targetAppContext.isDisposed()) {
 251                         try {
 252                             se.wait(1000);
 253                         } catch (InterruptedException ie) {
 254                             break;
 255                         }
 256                     }
 257                 }
 258             }
 259         }
 260         return se.dispatched;
 261     }
 262 
 263     /*
 264      * Checks if the focus window event follows key events waiting in the type-ahead
 265      * queue (if any). This may happen when a user types ahead in the window, the client
 266      * listeners hang EDT for a while, and the user switches b/w toplevels. In that
 267      * case the focus window events may be dispatched before the type-ahead events
 268      * get handled. This may lead to wrong focus behavior and in order to avoid it,
 269      * the focus window events are reposted to the end of the event queue. See 6981400.
 270      */
 271     private boolean repostIfFollowsKeyEvents(WindowEvent e) {
 272         if (!(e instanceof TimedWindowEvent)) {
 273             return false;
 274         }
 275         TimedWindowEvent we = (TimedWindowEvent)e;
 276         long time = we.getWhen();
 277         synchronized (this) {
 278             for (KeyEvent ke: enqueuedKeyEvents) {
 279                 if (time >= ke.getWhen()) {
 280                     SunToolkit.postEvent(AppContext.getAppContext(), new SequencedEvent(e));
 281                     return true;
 282                 }
 283             }
 284         }
 285         return false;
 286     }
 287     
 288     /**
 289      * This method is called by the AWT event dispatcher requesting that the
 290      * current KeyboardFocusManager dispatch the specified event on its behalf.
 291      * DefaultKeyboardFocusManagers dispatch all FocusEvents, all WindowEvents
 292      * related to focus, and all KeyEvents. These events are dispatched based
 293      * on the KeyboardFocusManager's notion of the focus owner and the focused
 294      * and active Windows, sometimes overriding the source of the specified
 295      * AWTEvent. If this method returns <code>false</code>, then the AWT event
 296      * dispatcher will attempt to dispatch the event itself.
 297      *
 298      * @param e the AWTEvent to be dispatched
 299      * @return <code>true</code> if this method dispatched the event;
 300      *         <code>false</code> otherwise
 301      */
 302     public boolean dispatchEvent(AWTEvent e) {
 303         if (focusLog.isLoggable(PlatformLogger.FINE) && (e instanceof WindowEvent || e instanceof FocusEvent)) focusLog.fine("" + e);
 304         switch (e.getID()) {
 305             case WindowEvent.WINDOW_GAINED_FOCUS: {
 306                 if (repostIfFollowsKeyEvents((WindowEvent)e)) {
 307                     break;
 308                 }
 309                 
 310                 WindowEvent we = (WindowEvent)e;
 311                 Window oldFocusedWindow = getGlobalFocusedWindow();
 312                 Window newFocusedWindow = we.getWindow();
 313                 if (newFocusedWindow == oldFocusedWindow) {
 314                     break;
 315                 }
 316 
 317                 if (!(newFocusedWindow.isFocusableWindow()
 318                       && newFocusedWindow.isVisible()
 319                       && newFocusedWindow.isDisplayable()))
 320                 {
 321                     // we can not accept focus on such window, so reject it.
 322                     restoreFocus(we);
 323                     break;
 324                 }
 325                 // If there exists a current focused window, then notify it
 326                 // that it has lost focus.
 327                 if (oldFocusedWindow != null) {
 328                     boolean isEventDispatched =
 329                         sendMessage(oldFocusedWindow,


 649                 }
 650 
 651                 if (currentActiveWindow != e.getSource()) {
 652                     // The event is lost in time.
 653                     // Allow listeners to precess the event but do not
 654                     // change any global states
 655                     break;
 656                 }
 657 
 658                 setGlobalActiveWindow(null);
 659                 if (getGlobalActiveWindow() != null) {
 660                     // Activation change was rejected. Unlikely, but possible.
 661                     break;
 662                 }
 663 
 664                 we.setSource(currentActiveWindow);
 665                 return typeAheadAssertions(currentActiveWindow, we);
 666             }
 667 
 668             case WindowEvent.WINDOW_LOST_FOCUS: {
 669                 if (repostIfFollowsKeyEvents((WindowEvent)e)) {
 670                     break;
 671                 }
 672                 
 673                 WindowEvent we = (WindowEvent)e;
 674                 Window currentFocusedWindow = getGlobalFocusedWindow();
 675                 Window losingFocusWindow = we.getWindow();
 676                 Window activeWindow = getGlobalActiveWindow();
 677                 Window oppositeWindow = we.getOppositeWindow();
 678                 if (focusLog.isLoggable(PlatformLogger.FINE))
 679                     focusLog.fine("Active {0}, Current focused {1}, losing focus {2} opposite {3}",
 680                                   activeWindow, currentFocusedWindow,
 681                                   losingFocusWindow, oppositeWindow);
 682                 if (currentFocusedWindow == null) {
 683                     break;
 684                 }
 685 
 686                 // Special case -- if the native windowing system posts an
 687                 // event claiming that the active Window has lost focus to the
 688                 // focused Window, then discard the event. This is an artifact
 689                 // of the native windowing system not knowing which Window is
 690                 // really focused.
 691                 if (inSendMessage == 0 && losingFocusWindow == activeWindow &&
 692                     oppositeWindow == currentFocusedWindow)


 832      * @see MenuShortcut
 833      */
 834     public boolean postProcessKeyEvent(KeyEvent e) {
 835         if (!e.isConsumed()) {
 836             Component target = e.getComponent();
 837             Container p = (Container)
 838                 (target instanceof Container ? target : target.getParent());
 839             if (p != null) {
 840                 p.postProcessKeyEvent(e);
 841             }
 842         }
 843         return true;
 844     }
 845 
 846     private void pumpApprovedKeyEvents() {
 847         KeyEvent ke;
 848         do {
 849             ke = null;
 850             synchronized (this) {
 851                 if (enqueuedKeyEvents.size() != 0) {
 852                     ke = enqueuedKeyEvents.getFirst();
 853                     if (typeAheadMarkers.size() != 0) {
 854                         TypeAheadMarker marker = typeAheadMarkers.getFirst();

 855                         // Fixed 5064013: may appears that the events have the same time
 856                         // if (ke.getWhen() >= marker.after) {
 857                         // The fix is rolled out.
 858 
 859                         if (ke.getWhen() > marker.after) {
 860                             ke = null;
 861                         }
 862                     }
 863                     if (ke != null) {
 864                         focusLog.finer("Pumping approved event {0}", ke);
 865                         enqueuedKeyEvents.removeFirst();
 866                     }
 867                 }
 868             }
 869             if (ke != null) {
 870                 preDispatchKeyEvent(ke);
 871             }
 872         } while (ke != null);
 873     }
 874 
 875     /**
 876      * Dumps the list of type-ahead queue markers to stderr
 877      */
 878     void dumpMarkers() {
 879         if (focusLog.isLoggable(PlatformLogger.FINEST)) {
 880             focusLog.finest(">>> Markers dump, time: {0}", System.currentTimeMillis());
 881             synchronized (this) {
 882                 if (typeAheadMarkers.size() != 0) {
 883                     Iterator<TypeAheadMarker> iter = typeAheadMarkers.iterator();
 884                     while (iter.hasNext()) {
 885                         TypeAheadMarker marker = iter.next();
 886                         focusLog.finest("    {0}", marker);
 887                     }
 888                 }
 889             }
 890         }
 891     }
 892 
 893     private boolean typeAheadAssertions(Component target, AWTEvent e) {
 894 
 895         // Clear any pending events here as well as in the FOCUS_GAINED
 896         // handler. We need this call here in case a marker was removed in
 897         // response to a call to dequeueKeyEvents.
 898         pumpApprovedKeyEvents();
 899 
 900         switch (e.getID()) {
 901             case KeyEvent.KEY_TYPED:
 902             case KeyEvent.KEY_PRESSED:
 903             case KeyEvent.KEY_RELEASED: {
 904                 KeyEvent ke = (KeyEvent)e;
 905                 synchronized (this) {
 906                     if (e.isPosted && typeAheadMarkers.size() != 0) {
 907                         TypeAheadMarker marker = typeAheadMarkers.getFirst();

 908                         // Fixed 5064013: may appears that the events have the same time
 909                         // if (ke.getWhen() >= marker.after) {
 910                         // The fix is rolled out.
 911 
 912                         if (ke.getWhen() > marker.after) {
 913                             focusLog.finer("Storing event {0} because of marker {1}", ke, marker);
 914                             enqueuedKeyEvents.addLast(ke);
 915                             return true;
 916                         }
 917                     }
 918                 }
 919 
 920                 // KeyEvent was posted before focus change request
 921                 return preDispatchKeyEvent(ke);
 922             }
 923 
 924             case FocusEvent.FOCUS_GAINED:
 925                 focusLog.finest("Markers before FOCUS_GAINED on {0}", target);
 926                 dumpMarkers();
 927                 // Search the marker list for the first marker tied to
 928                 // the Component which just gained focus. Then remove
 929                 // that marker, any markers which immediately follow
 930                 // and are tied to the same component, and all markers
 931                 // that preceed it. This handles the case where
 932                 // multiple focus requests were made for the same
 933                 // Component in a row and when we lost some of the
 934                 // earlier requests. Since FOCUS_GAINED events will
 935                 // not be generated for these additional requests, we
 936                 // need to clear those markers too.
 937                 synchronized (this) {
 938                     boolean found = false;
 939                     if (hasMarker(target)) {
 940                         for (Iterator<TypeAheadMarker> iter = typeAheadMarkers.iterator();
 941                              iter.hasNext(); )
 942                         {
 943                             if (iter.next().untilFocused == target) {


 944                                 found = true;
 945                             } else if (found) {
 946                                 break;
 947                             }
 948                             iter.remove();
 949                         }
 950                     } else {
 951                         // Exception condition - event without marker
 952                         focusLog.finer("Event without marker {0}", e);
 953                     }
 954                 }
 955                 focusLog.finest("Markers after FOCUS_GAINED");
 956                 dumpMarkers();
 957 
 958                 redispatchEvent(target, e);
 959 
 960                 // Now, dispatch any pending KeyEvents which have been
 961                 // released because of the FOCUS_GAINED event so that we don't
 962                 // have to wait for another event to be posted to the queue.
 963                 pumpApprovedKeyEvents();
 964                 return true;
 965 
 966             default:
 967                 redispatchEvent(target, e);
 968                 return true;
 969         }
 970     }
 971 
 972     /**
 973      * Returns true if there are some marker associated with component <code>comp</code>
 974      * in a markers' queue
 975      * @since 1.5
 976      */
 977     private boolean hasMarker(Component comp) {
 978         for (Iterator<TypeAheadMarker> iter = typeAheadMarkers.iterator(); iter.hasNext(); ) {
 979             if (iter.next().untilFocused == comp) {
 980                 return true;
 981             }
 982         }
 983         return false;
 984     }
 985 
 986     /**
 987      * Clears markers queue
 988      * @since 1.5
 989      */
 990     void clearMarkers() {
 991         synchronized(this) {
 992             typeAheadMarkers.clear();
 993         }
 994     }
 995 
 996     private boolean preDispatchKeyEvent(KeyEvent ke) {
 997         if (((AWTEvent) ke).isPosted) {
 998             Component focusOwner = getFocusOwner();
 999             ke.setSource(((focusOwner != null) ? focusOwner : getFocusedWindow()));
1000         }
1001         if (ke.getSource() == null) {
1002             return true;
1003         }
1004 
1005         // Explicitly set the key event timestamp here (not in Component.dispatchEventImpl):
1006         // - A key event is anyway passed to this method which starts its actual dispatching.
1007         // - If a key event is put to the type ahead queue, its time stamp should not be registered
1008         //   until its dispatching actually starts (by this method).

1009         EventQueue.setCurrentEventAndMostRecentTime(ke);
1010 
1011         /**
1012          * Fix for 4495473.
1013          * This fix allows to correctly dispatch events when native
1014          * event proxying mechanism is active.
1015          * If it is active we should redispatch key events after
1016          * we detected its correct target.
1017          */
1018         if (KeyboardFocusManager.isProxyActive(ke)) {
1019             Component source = (Component)ke.getSource();
1020             Container target = source.getNativeContainer();
1021             if (target != null) {
1022                 ComponentPeer peer = target.getPeer();
1023                 if (peer != null) {
1024                     peer.handleEvent(ke);
1025                     /**
1026                      * Fix for 4478780 - consume event after it was dispatched by peer.
1027                      */
1028                     ke.consume();


1176      *
1177      * @param after timestamp of current event, or the current, system time if
1178      *        the current event has no timestamp, or the AWT cannot determine
1179      *        which event is currently being handled
1180      * @param untilFocused Component which will receive a FOCUS_GAINED event
1181      *        before any pending KeyEvents
1182      * @see #dequeueKeyEvents
1183      * @see #discardKeyEvents
1184      */
1185     protected synchronized void enqueueKeyEvents(long after,
1186                                                  Component untilFocused) {
1187         if (untilFocused == null) {
1188             return;
1189         }
1190 
1191         focusLog.finer("Enqueue at {0} for {1}",
1192                        after, untilFocused);
1193 
1194         int insertionIndex = 0,
1195             i = typeAheadMarkers.size();
1196         ListIterator<TypeAheadMarker> iter = typeAheadMarkers.listIterator(i);
1197 
1198         for (; i > 0; i--) {
1199             TypeAheadMarker marker = iter.previous();
1200             if (marker.after <= after) {
1201                 insertionIndex = i;
1202                 break;
1203             }
1204         }
1205 
1206         typeAheadMarkers.add(insertionIndex,
1207                              new TypeAheadMarker(after, untilFocused));
1208     }
1209 
1210     /**
1211      * Releases for normal dispatching to the current focus owner all
1212      * KeyEvents which were enqueued because of a call to
1213      * <code>enqueueKeyEvents</code> with the same timestamp and Component.
1214      * If the given timestamp is less than zero, the outstanding enqueue
1215      * request for the given Component with the <b>oldest</b> timestamp (if
1216      * any) should be cancelled.
1217      *
1218      * @param after the timestamp specified in the call to
1219      *        <code>enqueueKeyEvents</code>, or any value < 0
1220      * @param untilFocused the Component specified in the call to
1221      *        <code>enqueueKeyEvents</code>
1222      * @see #enqueueKeyEvents
1223      * @see #discardKeyEvents
1224      */
1225     protected synchronized void dequeueKeyEvents(long after,
1226                                                  Component untilFocused) {
1227         if (untilFocused == null) {
1228             return;
1229         }
1230 
1231         focusLog.finer("Dequeue at {0} for {1}",
1232                        after, untilFocused);
1233 
1234         TypeAheadMarker marker;
1235         ListIterator<TypeAheadMarker> iter = typeAheadMarkers.listIterator
1236             ((after >= 0) ? typeAheadMarkers.size() : 0);
1237 
1238         if (after < 0) {
1239             while (iter.hasNext()) {
1240                 marker = iter.next();
1241                 if (marker.untilFocused == untilFocused)
1242                 {
1243                     iter.remove();
1244                     return;
1245                 }
1246             }
1247         } else {
1248             while (iter.hasPrevious()) {
1249                 marker = iter.previous();
1250                 if (marker.untilFocused == untilFocused &&
1251                     marker.after == after)
1252                 {
1253                     iter.remove();
1254                     return;
1255                 }
1256             }
1257         }
1258     }
1259 
1260     /**
1261      * Discards all KeyEvents which were enqueued because of one or more calls
1262      * to <code>enqueueKeyEvents</code> with the specified Component, or one of
1263      * its descendants.
1264      *
1265      * @param comp the Component specified in one or more calls to
1266      *        <code>enqueueKeyEvents</code>, or a parent of such a Component
1267      * @see #enqueueKeyEvents
1268      * @see #dequeueKeyEvents
1269      */
1270     protected synchronized void discardKeyEvents(Component comp) {
1271         if (comp == null) {
1272             return;
1273         }
1274 
1275         long start = -1;
1276 
1277         for (Iterator<TypeAheadMarker> iter = typeAheadMarkers.iterator(); iter.hasNext(); ) {
1278             TypeAheadMarker marker = iter.next();
1279             Component toTest = marker.untilFocused;
1280             boolean match = (toTest == comp);
1281             while (!match && toTest != null && !(toTest instanceof Window)) {
1282                 toTest = toTest.getParent();
1283                 match = (toTest == comp);
1284             }
1285             if (match) {
1286                 if (start < 0) {
1287                     start = marker.after;
1288                 }
1289                 iter.remove();
1290             } else if (start >= 0) {
1291                 purgeStampedEvents(start, marker.after);
1292                 start = -1;
1293             }
1294         }
1295 
1296         purgeStampedEvents(start, -1);
1297     }
1298 
1299     // Notes:
1300     //   * must be called inside a synchronized block
1301     //   * if 'start' is < 0, then this function does nothing
1302     //   * if 'end' is < 0, then all KeyEvents from 'start' to the end of the
1303     //     queue will be removed
1304     private void purgeStampedEvents(long start, long end) {
1305         if (start < 0) {
1306             return;
1307         }
1308 
1309         for (Iterator<KeyEvent> iter = enqueuedKeyEvents.iterator(); iter.hasNext(); ) {
1310             KeyEvent ke = iter.next();
1311             long time = ke.getWhen();
1312 
1313             if (start < time && (end < 0 || time <= end)) {
1314                 iter.remove();
1315             }
1316 
1317             if (end >= 0 && time > end) {
1318                 break;
1319             }
1320         }
1321     }
1322 
1323     /**
1324      * Focuses the Component before aComponent, typically based on a
1325      * FocusTraversalPolicy.
1326      *
1327      * @param aComponent the Component that is the basis for the focus
1328      *        traversal operation
1329      * @see FocusTraversalPolicy
1330      * @see Component#transferFocusBackward