< prev index next >

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

Print this page




 292                     Window toplevel = marker.untilFocused.getContainingWindow();
 293                     // Check that the component awaiting focus belongs to
 294                     // the current focused window. See 8015454.
 295                     if (toplevel != null && toplevel.isFocused()) {
 296                         SunToolkit.postEvent(AppContext.getAppContext(), new SequencedEvent(e));
 297                         return true;
 298                     }
 299                 }
 300             }
 301         }
 302         return false;
 303     }
 304 
 305     /**
 306      * This method is called by the AWT event dispatcher requesting that the
 307      * current KeyboardFocusManager dispatch the specified event on its behalf.
 308      * DefaultKeyboardFocusManagers dispatch all FocusEvents, all WindowEvents
 309      * related to focus, and all KeyEvents. These events are dispatched based
 310      * on the KeyboardFocusManager's notion of the focus owner and the focused
 311      * and active Windows, sometimes overriding the source of the specified
 312      * AWTEvent. If this method returns <code>false</code>, then the AWT event
 313      * dispatcher will attempt to dispatch the event itself.
 314      *
 315      * @param e the AWTEvent to be dispatched
 316      * @return <code>true</code> if this method dispatched the event;
 317      *         <code>false</code> otherwise
 318      */
 319     public boolean dispatchEvent(AWTEvent e) {
 320         if (focusLog.isLoggable(PlatformLogger.Level.FINE) && (e instanceof WindowEvent || e instanceof FocusEvent)) {
 321             focusLog.fine("" + e);
 322         }
 323         switch (e.getID()) {
 324             case WindowEvent.WINDOW_GAINED_FOCUS: {
 325                 if (repostIfFollowsKeyEvents((WindowEvent)e)) {
 326                     break;
 327                 }
 328 
 329                 WindowEvent we = (WindowEvent)e;
 330                 Window oldFocusedWindow = getGlobalFocusedWindow();
 331                 Window newFocusedWindow = we.getWindow();
 332                 if (newFocusedWindow == oldFocusedWindow) {
 333                     break;
 334                 }
 335 
 336                 if (!(newFocusedWindow.isFocusableWindow()
 337                       && newFocusedWindow.isVisible()


 761                         // but possible.
 762                         restoreFocus(currentFocusedWindow, null, true);
 763                     }
 764                 }
 765                 break;
 766             }
 767 
 768             case KeyEvent.KEY_TYPED:
 769             case KeyEvent.KEY_PRESSED:
 770             case KeyEvent.KEY_RELEASED:
 771                 return typeAheadAssertions(null, e);
 772 
 773             default:
 774                 return false;
 775         }
 776 
 777         return true;
 778     }
 779 
 780     /**
 781      * Called by <code>dispatchEvent</code> if no other
 782      * KeyEventDispatcher in the dispatcher chain dispatched the KeyEvent, or
 783      * if no other KeyEventDispatchers are registered. If the event has not
 784      * been consumed, its target is enabled, and the focus owner is not null,
 785      * this method dispatches the event to its target. This method will also
 786      * subsequently dispatch the event to all registered
 787      * KeyEventPostProcessors. After all this operations are finished,
 788      * the event is passed to peers for processing.
 789      * <p>
 790      * In all cases, this method returns <code>true</code>, since
 791      * DefaultKeyboardFocusManager is designed so that neither
 792      * <code>dispatchEvent</code>, nor the AWT event dispatcher, should take
 793      * further action on the event in any situation.
 794      *
 795      * @param e the KeyEvent to be dispatched
 796      * @return <code>true</code>
 797      * @see Component#dispatchEvent
 798      */
 799     public boolean dispatchKeyEvent(KeyEvent e) {
 800         Component focusOwner = (((AWTEvent)e).isPosted) ? getFocusOwner() : e.getComponent();
 801 
 802         if (focusOwner != null && focusOwner.isShowing() && focusOwner.canBeFocusOwner()) {
 803             if (!e.isConsumed()) {
 804                 Component comp = e.getComponent();
 805                 if (comp != null && comp.isEnabled()) {
 806                     redispatchEvent(comp, e);
 807                 }
 808             }
 809         }
 810         boolean stopPostProcessing = false;
 811         java.util.List<KeyEventPostProcessor> processors = getKeyEventPostProcessors();
 812         if (processors != null) {
 813             for (java.util.Iterator<KeyEventPostProcessor> iter = processors.iterator();
 814                  !stopPostProcessing && iter.hasNext(); )
 815             {
 816                 stopPostProcessing = iter.next().


 824         // Allow the peer to process KeyEvent
 825         Component source = e.getComponent();
 826         ComponentPeer peer = source.peer;
 827 
 828         if (peer == null || peer instanceof LightweightPeer) {
 829             // if focus owner is lightweight then its native container
 830             // processes event
 831             Container target = source.getNativeContainer();
 832             if (target != null) {
 833                 peer = target.peer;
 834             }
 835         }
 836         if (peer != null) {
 837             peer.handleEvent(e);
 838         }
 839 
 840         return true;
 841     }
 842 
 843     /**
 844      * This method will be called by <code>dispatchKeyEvent</code>. It will
 845      * handle any unconsumed KeyEvents that map to an AWT
 846      * <code>MenuShortcut</code> by consuming the event and activating the
 847      * shortcut.
 848      *
 849      * @param e the KeyEvent to post-process
 850      * @return <code>true</code>
 851      * @see #dispatchKeyEvent
 852      * @see MenuShortcut
 853      */
 854     public boolean postProcessKeyEvent(KeyEvent e) {
 855         if (!e.isConsumed()) {
 856             Component target = e.getComponent();
 857             Container p = (Container)
 858                 (target instanceof Container ? target : target.getParent());
 859             if (p != null) {
 860                 p.postProcessKeyEvent(e);
 861             }
 862         }
 863         return true;
 864     }
 865 
 866     private void pumpApprovedKeyEvents() {
 867         KeyEvent ke;
 868         do {
 869             ke = null;
 870             synchronized (this) {


 981                     }
 982                 }
 983                 focusLog.finest("Markers after FOCUS_GAINED");
 984                 dumpMarkers();
 985 
 986                 redispatchEvent(target, e);
 987 
 988                 // Now, dispatch any pending KeyEvents which have been
 989                 // released because of the FOCUS_GAINED event so that we don't
 990                 // have to wait for another event to be posted to the queue.
 991                 pumpApprovedKeyEvents();
 992                 return true;
 993 
 994             default:
 995                 redispatchEvent(target, e);
 996                 return true;
 997         }
 998     }
 999 
1000     /**
1001      * Returns true if there are some marker associated with component <code>comp</code>
1002      * in a markers' queue
1003      * @since 1.5
1004      */
1005     private boolean hasMarker(Component comp) {
1006         for (Iterator<TypeAheadMarker> iter = typeAheadMarkers.iterator(); iter.hasNext(); ) {
1007             if (iter.next().untilFocused == comp) {
1008                 return true;
1009             }
1010         }
1011         return false;
1012     }
1013 
1014     /**
1015      * Clears markers queue
1016      * @since 1.5
1017      */
1018     void clearMarkers() {
1019         synchronized(this) {
1020             typeAheadMarkers.clear();
1021         }


1184 
1185             toTest = focusedComponent.getFocusTraversalKeys(
1186                 KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS);
1187             contains = toTest.contains(stroke);
1188             containsOpp = toTest.contains(oppStroke);
1189 
1190             if (contains || containsOpp) {
1191                 consumeTraversalKey(e);
1192                 if (contains) {
1193                     downFocusCycle((Container)focusedComponent);
1194                 }
1195             }
1196         }
1197     }
1198 
1199     /**
1200      * Delays dispatching of KeyEvents until the specified Component becomes
1201      * the focus owner. KeyEvents with timestamps later than the specified
1202      * timestamp will be enqueued until the specified Component receives a
1203      * FOCUS_GAINED event, or the AWT cancels the delay request by invoking
1204      * <code>dequeueKeyEvents</code> or <code>discardKeyEvents</code>.
1205      *
1206      * @param after timestamp of current event, or the current, system time if
1207      *        the current event has no timestamp, or the AWT cannot determine
1208      *        which event is currently being handled
1209      * @param untilFocused Component which will receive a FOCUS_GAINED event
1210      *        before any pending KeyEvents
1211      * @see #dequeueKeyEvents
1212      * @see #discardKeyEvents
1213      */
1214     protected synchronized void enqueueKeyEvents(long after,
1215                                                  Component untilFocused) {
1216         if (untilFocused == null) {
1217             return;
1218         }
1219 
1220         if (focusLog.isLoggable(PlatformLogger.Level.FINER)) {
1221             focusLog.finer("Enqueue at {0} for {1}",
1222                        after, untilFocused);
1223         }
1224 
1225         int insertionIndex = 0,
1226             i = typeAheadMarkers.size();
1227         ListIterator<TypeAheadMarker> iter = typeAheadMarkers.listIterator(i);
1228 
1229         for (; i > 0; i--) {
1230             TypeAheadMarker marker = iter.previous();
1231             if (marker.after <= after) {
1232                 insertionIndex = i;
1233                 break;
1234             }
1235         }
1236 
1237         typeAheadMarkers.add(insertionIndex,
1238                              new TypeAheadMarker(after, untilFocused));
1239     }
1240 
1241     /**
1242      * Releases for normal dispatching to the current focus owner all
1243      * KeyEvents which were enqueued because of a call to
1244      * <code>enqueueKeyEvents</code> with the same timestamp and Component.
1245      * If the given timestamp is less than zero, the outstanding enqueue
1246      * request for the given Component with the <b>oldest</b> timestamp (if
1247      * any) should be cancelled.
1248      *
1249      * @param after the timestamp specified in the call to
1250      *        <code>enqueueKeyEvents</code>, or any value &lt; 0
1251      * @param untilFocused the Component specified in the call to
1252      *        <code>enqueueKeyEvents</code>
1253      * @see #enqueueKeyEvents
1254      * @see #discardKeyEvents
1255      */
1256     protected synchronized void dequeueKeyEvents(long after,
1257                                                  Component untilFocused) {
1258         if (untilFocused == null) {
1259             return;
1260         }
1261 
1262         if (focusLog.isLoggable(PlatformLogger.Level.FINER)) {
1263             focusLog.finer("Dequeue at {0} for {1}",
1264                        after, untilFocused);
1265         }
1266 
1267         TypeAheadMarker marker;
1268         ListIterator<TypeAheadMarker> iter = typeAheadMarkers.listIterator
1269             ((after >= 0) ? typeAheadMarkers.size() : 0);
1270 
1271         if (after < 0) {
1272             while (iter.hasNext()) {


1275                 {
1276                     iter.remove();
1277                     return;
1278                 }
1279             }
1280         } else {
1281             while (iter.hasPrevious()) {
1282                 marker = iter.previous();
1283                 if (marker.untilFocused == untilFocused &&
1284                     marker.after == after)
1285                 {
1286                     iter.remove();
1287                     return;
1288                 }
1289             }
1290         }
1291     }
1292 
1293     /**
1294      * Discards all KeyEvents which were enqueued because of one or more calls
1295      * to <code>enqueueKeyEvents</code> with the specified Component, or one of
1296      * its descendants.
1297      *
1298      * @param comp the Component specified in one or more calls to
1299      *        <code>enqueueKeyEvents</code>, or a parent of such a Component
1300      * @see #enqueueKeyEvents
1301      * @see #dequeueKeyEvents
1302      */
1303     protected synchronized void discardKeyEvents(Component comp) {
1304         if (comp == null) {
1305             return;
1306         }
1307 
1308         long start = -1;
1309 
1310         for (Iterator<TypeAheadMarker> iter = typeAheadMarkers.iterator(); iter.hasNext(); ) {
1311             TypeAheadMarker marker = iter.next();
1312             Component toTest = marker.untilFocused;
1313             boolean match = (toTest == comp);
1314             while (!match && toTest != null && !(toTest instanceof Window)) {
1315                 toTest = toTest.getParent();
1316                 match = (toTest == comp);
1317             }
1318             if (match) {
1319                 if (start < 0) {




 292                     Window toplevel = marker.untilFocused.getContainingWindow();
 293                     // Check that the component awaiting focus belongs to
 294                     // the current focused window. See 8015454.
 295                     if (toplevel != null && toplevel.isFocused()) {
 296                         SunToolkit.postEvent(AppContext.getAppContext(), new SequencedEvent(e));
 297                         return true;
 298                     }
 299                 }
 300             }
 301         }
 302         return false;
 303     }
 304 
 305     /**
 306      * This method is called by the AWT event dispatcher requesting that the
 307      * current KeyboardFocusManager dispatch the specified event on its behalf.
 308      * DefaultKeyboardFocusManagers dispatch all FocusEvents, all WindowEvents
 309      * related to focus, and all KeyEvents. These events are dispatched based
 310      * on the KeyboardFocusManager's notion of the focus owner and the focused
 311      * and active Windows, sometimes overriding the source of the specified
 312      * AWTEvent. If this method returns {@code false}, then the AWT event
 313      * dispatcher will attempt to dispatch the event itself.
 314      *
 315      * @param e the AWTEvent to be dispatched
 316      * @return {@code true} if this method dispatched the event;
 317      *         {@code false} otherwise
 318      */
 319     public boolean dispatchEvent(AWTEvent e) {
 320         if (focusLog.isLoggable(PlatformLogger.Level.FINE) && (e instanceof WindowEvent || e instanceof FocusEvent)) {
 321             focusLog.fine("" + e);
 322         }
 323         switch (e.getID()) {
 324             case WindowEvent.WINDOW_GAINED_FOCUS: {
 325                 if (repostIfFollowsKeyEvents((WindowEvent)e)) {
 326                     break;
 327                 }
 328 
 329                 WindowEvent we = (WindowEvent)e;
 330                 Window oldFocusedWindow = getGlobalFocusedWindow();
 331                 Window newFocusedWindow = we.getWindow();
 332                 if (newFocusedWindow == oldFocusedWindow) {
 333                     break;
 334                 }
 335 
 336                 if (!(newFocusedWindow.isFocusableWindow()
 337                       && newFocusedWindow.isVisible()


 761                         // but possible.
 762                         restoreFocus(currentFocusedWindow, null, true);
 763                     }
 764                 }
 765                 break;
 766             }
 767 
 768             case KeyEvent.KEY_TYPED:
 769             case KeyEvent.KEY_PRESSED:
 770             case KeyEvent.KEY_RELEASED:
 771                 return typeAheadAssertions(null, e);
 772 
 773             default:
 774                 return false;
 775         }
 776 
 777         return true;
 778     }
 779 
 780     /**
 781      * Called by {@code dispatchEvent} if no other
 782      * KeyEventDispatcher in the dispatcher chain dispatched the KeyEvent, or
 783      * if no other KeyEventDispatchers are registered. If the event has not
 784      * been consumed, its target is enabled, and the focus owner is not null,
 785      * this method dispatches the event to its target. This method will also
 786      * subsequently dispatch the event to all registered
 787      * KeyEventPostProcessors. After all this operations are finished,
 788      * the event is passed to peers for processing.
 789      * <p>
 790      * In all cases, this method returns {@code true}, since
 791      * DefaultKeyboardFocusManager is designed so that neither
 792      * {@code dispatchEvent}, nor the AWT event dispatcher, should take
 793      * further action on the event in any situation.
 794      *
 795      * @param e the KeyEvent to be dispatched
 796      * @return {@code true}
 797      * @see Component#dispatchEvent
 798      */
 799     public boolean dispatchKeyEvent(KeyEvent e) {
 800         Component focusOwner = (((AWTEvent)e).isPosted) ? getFocusOwner() : e.getComponent();
 801 
 802         if (focusOwner != null && focusOwner.isShowing() && focusOwner.canBeFocusOwner()) {
 803             if (!e.isConsumed()) {
 804                 Component comp = e.getComponent();
 805                 if (comp != null && comp.isEnabled()) {
 806                     redispatchEvent(comp, e);
 807                 }
 808             }
 809         }
 810         boolean stopPostProcessing = false;
 811         java.util.List<KeyEventPostProcessor> processors = getKeyEventPostProcessors();
 812         if (processors != null) {
 813             for (java.util.Iterator<KeyEventPostProcessor> iter = processors.iterator();
 814                  !stopPostProcessing && iter.hasNext(); )
 815             {
 816                 stopPostProcessing = iter.next().


 824         // Allow the peer to process KeyEvent
 825         Component source = e.getComponent();
 826         ComponentPeer peer = source.peer;
 827 
 828         if (peer == null || peer instanceof LightweightPeer) {
 829             // if focus owner is lightweight then its native container
 830             // processes event
 831             Container target = source.getNativeContainer();
 832             if (target != null) {
 833                 peer = target.peer;
 834             }
 835         }
 836         if (peer != null) {
 837             peer.handleEvent(e);
 838         }
 839 
 840         return true;
 841     }
 842 
 843     /**
 844      * This method will be called by {@code dispatchKeyEvent}. It will
 845      * handle any unconsumed KeyEvents that map to an AWT
 846      * {@code MenuShortcut} by consuming the event and activating the
 847      * shortcut.
 848      *
 849      * @param e the KeyEvent to post-process
 850      * @return {@code true}
 851      * @see #dispatchKeyEvent
 852      * @see MenuShortcut
 853      */
 854     public boolean postProcessKeyEvent(KeyEvent e) {
 855         if (!e.isConsumed()) {
 856             Component target = e.getComponent();
 857             Container p = (Container)
 858                 (target instanceof Container ? target : target.getParent());
 859             if (p != null) {
 860                 p.postProcessKeyEvent(e);
 861             }
 862         }
 863         return true;
 864     }
 865 
 866     private void pumpApprovedKeyEvents() {
 867         KeyEvent ke;
 868         do {
 869             ke = null;
 870             synchronized (this) {


 981                     }
 982                 }
 983                 focusLog.finest("Markers after FOCUS_GAINED");
 984                 dumpMarkers();
 985 
 986                 redispatchEvent(target, e);
 987 
 988                 // Now, dispatch any pending KeyEvents which have been
 989                 // released because of the FOCUS_GAINED event so that we don't
 990                 // have to wait for another event to be posted to the queue.
 991                 pumpApprovedKeyEvents();
 992                 return true;
 993 
 994             default:
 995                 redispatchEvent(target, e);
 996                 return true;
 997         }
 998     }
 999 
1000     /**
1001      * Returns true if there are some marker associated with component {@code comp}
1002      * in a markers' queue
1003      * @since 1.5
1004      */
1005     private boolean hasMarker(Component comp) {
1006         for (Iterator<TypeAheadMarker> iter = typeAheadMarkers.iterator(); iter.hasNext(); ) {
1007             if (iter.next().untilFocused == comp) {
1008                 return true;
1009             }
1010         }
1011         return false;
1012     }
1013 
1014     /**
1015      * Clears markers queue
1016      * @since 1.5
1017      */
1018     void clearMarkers() {
1019         synchronized(this) {
1020             typeAheadMarkers.clear();
1021         }


1184 
1185             toTest = focusedComponent.getFocusTraversalKeys(
1186                 KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS);
1187             contains = toTest.contains(stroke);
1188             containsOpp = toTest.contains(oppStroke);
1189 
1190             if (contains || containsOpp) {
1191                 consumeTraversalKey(e);
1192                 if (contains) {
1193                     downFocusCycle((Container)focusedComponent);
1194                 }
1195             }
1196         }
1197     }
1198 
1199     /**
1200      * Delays dispatching of KeyEvents until the specified Component becomes
1201      * the focus owner. KeyEvents with timestamps later than the specified
1202      * timestamp will be enqueued until the specified Component receives a
1203      * FOCUS_GAINED event, or the AWT cancels the delay request by invoking
1204      * {@code dequeueKeyEvents} or {@code discardKeyEvents}.
1205      *
1206      * @param after timestamp of current event, or the current, system time if
1207      *        the current event has no timestamp, or the AWT cannot determine
1208      *        which event is currently being handled
1209      * @param untilFocused Component which will receive a FOCUS_GAINED event
1210      *        before any pending KeyEvents
1211      * @see #dequeueKeyEvents
1212      * @see #discardKeyEvents
1213      */
1214     protected synchronized void enqueueKeyEvents(long after,
1215                                                  Component untilFocused) {
1216         if (untilFocused == null) {
1217             return;
1218         }
1219 
1220         if (focusLog.isLoggable(PlatformLogger.Level.FINER)) {
1221             focusLog.finer("Enqueue at {0} for {1}",
1222                        after, untilFocused);
1223         }
1224 
1225         int insertionIndex = 0,
1226             i = typeAheadMarkers.size();
1227         ListIterator<TypeAheadMarker> iter = typeAheadMarkers.listIterator(i);
1228 
1229         for (; i > 0; i--) {
1230             TypeAheadMarker marker = iter.previous();
1231             if (marker.after <= after) {
1232                 insertionIndex = i;
1233                 break;
1234             }
1235         }
1236 
1237         typeAheadMarkers.add(insertionIndex,
1238                              new TypeAheadMarker(after, untilFocused));
1239     }
1240 
1241     /**
1242      * Releases for normal dispatching to the current focus owner all
1243      * KeyEvents which were enqueued because of a call to
1244      * {@code enqueueKeyEvents} with the same timestamp and Component.
1245      * If the given timestamp is less than zero, the outstanding enqueue
1246      * request for the given Component with the <b>oldest</b> timestamp (if
1247      * any) should be cancelled.
1248      *
1249      * @param after the timestamp specified in the call to
1250      *        {@code enqueueKeyEvents}, or any value &lt; 0
1251      * @param untilFocused the Component specified in the call to
1252      *        {@code enqueueKeyEvents}
1253      * @see #enqueueKeyEvents
1254      * @see #discardKeyEvents
1255      */
1256     protected synchronized void dequeueKeyEvents(long after,
1257                                                  Component untilFocused) {
1258         if (untilFocused == null) {
1259             return;
1260         }
1261 
1262         if (focusLog.isLoggable(PlatformLogger.Level.FINER)) {
1263             focusLog.finer("Dequeue at {0} for {1}",
1264                        after, untilFocused);
1265         }
1266 
1267         TypeAheadMarker marker;
1268         ListIterator<TypeAheadMarker> iter = typeAheadMarkers.listIterator
1269             ((after >= 0) ? typeAheadMarkers.size() : 0);
1270 
1271         if (after < 0) {
1272             while (iter.hasNext()) {


1275                 {
1276                     iter.remove();
1277                     return;
1278                 }
1279             }
1280         } else {
1281             while (iter.hasPrevious()) {
1282                 marker = iter.previous();
1283                 if (marker.untilFocused == untilFocused &&
1284                     marker.after == after)
1285                 {
1286                     iter.remove();
1287                     return;
1288                 }
1289             }
1290         }
1291     }
1292 
1293     /**
1294      * Discards all KeyEvents which were enqueued because of one or more calls
1295      * to {@code enqueueKeyEvents} with the specified Component, or one of
1296      * its descendants.
1297      *
1298      * @param comp the Component specified in one or more calls to
1299      *        {@code enqueueKeyEvents}, or a parent of such a Component
1300      * @see #enqueueKeyEvents
1301      * @see #dequeueKeyEvents
1302      */
1303     protected synchronized void discardKeyEvents(Component comp) {
1304         if (comp == null) {
1305             return;
1306         }
1307 
1308         long start = -1;
1309 
1310         for (Iterator<TypeAheadMarker> iter = typeAheadMarkers.iterator(); iter.hasNext(); ) {
1311             TypeAheadMarker marker = iter.next();
1312             Component toTest = marker.untilFocused;
1313             boolean match = (toTest == comp);
1314             while (!match && toTest != null && !(toTest instanceof Window)) {
1315                 toTest = toTest.getParent();
1316                 match = (toTest == comp);
1317             }
1318             if (match) {
1319                 if (start < 0) {


< prev index next >