jdk Sdiff src/share/classes/java/awt (original) (raw)


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 *

49 * Please see 50 * 51 * How to Use the Focus Subsystem, 52 * a section in The Java Tutorial, and the 53 * Focus Specification 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 NULL_WINDOW_WR = 68 new WeakReference(null); 69 private static final WeakReference NULL_COMPONENT_WR = 70 new WeakReference(null); 71 private WeakReference realOppositeWindowWR = NULL_WINDOW_WR; 72 private WeakReference 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 false, then the AWT event 270 * dispatcher will attempt to dispatch the event itself. 271 * 272 * @param e the AWTEvent to be dispatched 273 * @return true if this method dispatched the event; 274 * false 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 comp 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 * enqueueKeyEvents 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 oldest timestamp (if 1187 * any) should be cancelled. 1188 * 1189 * @param after the timestamp specified in the call to 1190 * enqueueKeyEvents, or any value < 0 1191 * @param untilFocused the Component specified in the call to 1192 * enqueueKeyEvents 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 enqueueKeyEvents with the specified Component, or one of 1234 * its descendants. 1235 * 1236 * @param comp the Component specified in one or more calls to 1237 * enqueueKeyEvents, 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 *

50 * Please see 51 * 52 * How to Use the Focus Subsystem, 53 * a section in The Java Tutorial, and the 54 * Focus Specification 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 NULL_WINDOW_WR = 69 new WeakReference(null); 70 private static final WeakReference NULL_COMPONENT_WR = 71 new WeakReference(null); 72 private WeakReference realOppositeWindowWR = NULL_WINDOW_WR; 73 private WeakReference realOppositeComponentWR = NULL_COMPONENT_WR; 74 private int inSendMessage; 75 private LinkedList enqueuedKeyEvents = new LinkedList(); 76 private LinkedList typeAheadMarkers = new LinkedList(); 77 private boolean consumeNextKeyTyped; 78 79 private static class TypeAheadMarker { 80 long after; 81 Component untilFocused; 82 83 TypeAheadMarker(long after, Component untilFocused) { 84 this.after = after; 85 this.untilFocused = untilFocused; 86 } 87 /* 88 * Returns string representation of the marker 89 */ 90 public String toString() { 91 return ">>> Marker after " + after + " on " + untilFocused; 92 } 93 } 94 95 private Window getOwningFrameDialog(Window window) { 96 while (window != null && !(window instanceof Frame ||


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 false, then the AWT event 296 * dispatcher will attempt to dispatch the event itself. 297 * 298 * @param e the AWTEvent to be dispatched 299 * @return true if this method dispatched the event; 300 * false 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 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 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 comp 974 * in a markers' queue 975 * @since 1.5 976 / 977 private boolean hasMarker(Component comp) { 978 for (Iterator 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 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 * enqueueKeyEvents 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 oldest timestamp (if 1216 * any) should be cancelled. 1217 * 1218 * @param after the timestamp specified in the call to 1219 * enqueueKeyEvents, or any value < 0 1220 * @param untilFocused the Component specified in the call to 1221 * enqueueKeyEvents 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 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 enqueueKeyEvents with the specified Component, or one of 1263 * its descendants. 1264 * 1265 * @param comp the Component specified in one or more calls to 1266 * enqueueKeyEvents, 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 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 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