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

Print this page

        

*** 38,47 **** --- 38,48 ---- import sun.util.logging.PlatformLogger; import sun.awt.AppContext; import sun.awt.SunToolkit; import sun.awt.CausedFocusEvent; + import sun.awt.TimedWindowEvent; /** * The default KeyboardFocusManager for AWT applications. Focus traversal is * done in response to a Component's focus traversal keys, and using a * Container's FocusTraversalPolicy.
*** 69,80 **** private static final WeakReference<Component> NULL_COMPONENT_WR = new WeakReference<Component>(null); private WeakReference<Window> realOppositeWindowWR = NULL_WINDOW_WR; private WeakReference<Component> realOppositeComponentWR = NULL_COMPONENT_WR; private int inSendMessage; ! private LinkedList enqueuedKeyEvents = new LinkedList(), ! typeAheadMarkers = new LinkedList(); private boolean consumeNextKeyTyped; private static class TypeAheadMarker { long after; Component untilFocused; --- 70,81 ---- private static final WeakReference<Component> NULL_COMPONENT_WR = new WeakReference<Component>(null); private WeakReference<Window> realOppositeWindowWR = NULL_WINDOW_WR; private WeakReference<Component> realOppositeComponentWR = NULL_COMPONENT_WR; private int inSendMessage; ! private LinkedList<KeyEvent> enqueuedKeyEvents = new LinkedList<KeyEvent>(); ! private LinkedList<TypeAheadMarker> typeAheadMarkers = new LinkedList<TypeAheadMarker>(); private boolean consumeNextKeyTyped; private static class TypeAheadMarker { long after; Component untilFocused;
*** 257,266 **** --- 258,292 ---- } } return se.dispatched; } + /* + * Checks if the focus window event follows key events waiting in the type-ahead + * queue (if any). This may happen when a user types ahead in the window, the client + * listeners hang EDT for a while, and the user switches b/w toplevels. In that + * case the focus window events may be dispatched before the type-ahead events + * get handled. This may lead to wrong focus behavior and in order to avoid it, + * the focus window events are reposted to the end of the event queue. See 6981400. + */ + private boolean repostIfFollowsKeyEvents(WindowEvent e) { + if (!(e instanceof TimedWindowEvent)) { + return false; + } + TimedWindowEvent we = (TimedWindowEvent)e; + long time = we.getWhen(); + synchronized (this) { + for (KeyEvent ke: enqueuedKeyEvents) { + if (time >= ke.getWhen()) { + SunToolkit.postEvent(AppContext.getAppContext(), new SequencedEvent(e)); + return true; + } + } + } + return false; + } + /** * This method is called by the AWT event dispatcher requesting that the * current KeyboardFocusManager dispatch the specified event on its behalf. * DefaultKeyboardFocusManagers dispatch all FocusEvents, all WindowEvents * related to focus, and all KeyEvents. These events are dispatched based
*** 275,284 **** --- 301,314 ---- */ public boolean dispatchEvent(AWTEvent e) { if (focusLog.isLoggable(PlatformLogger.FINE) && (e instanceof WindowEvent || e instanceof FocusEvent)) focusLog.fine("" + e); switch (e.getID()) { case WindowEvent.WINDOW_GAINED_FOCUS: { + if (repostIfFollowsKeyEvents((WindowEvent)e)) { + break; + } + WindowEvent we = (WindowEvent)e; Window oldFocusedWindow = getGlobalFocusedWindow(); Window newFocusedWindow = we.getWindow(); if (newFocusedWindow == oldFocusedWindow) { break;
*** 634,643 **** --- 664,677 ---- we.setSource(currentActiveWindow); return typeAheadAssertions(currentActiveWindow, we); } case WindowEvent.WINDOW_LOST_FOCUS: { + if (repostIfFollowsKeyEvents((WindowEvent)e)) { + break; + } + WindowEvent we = (WindowEvent)e; Window currentFocusedWindow = getGlobalFocusedWindow(); Window losingFocusWindow = we.getWindow(); Window activeWindow = getGlobalActiveWindow(); Window oppositeWindow = we.getOppositeWindow();
*** 813,826 **** KeyEvent ke; do { ke = null; synchronized (this) { if (enqueuedKeyEvents.size() != 0) { ! ke = (KeyEvent)enqueuedKeyEvents.getFirst(); if (typeAheadMarkers.size() != 0) { ! TypeAheadMarker marker = (TypeAheadMarker) ! typeAheadMarkers.getFirst(); // Fixed 5064013: may appears that the events have the same time // if (ke.getWhen() >= marker.after) { // The fix is rolled out. if (ke.getWhen() > marker.after) { --- 847,859 ---- KeyEvent ke; do { ke = null; synchronized (this) { if (enqueuedKeyEvents.size() != 0) { ! ke = enqueuedKeyEvents.getFirst(); if (typeAheadMarkers.size() != 0) { ! TypeAheadMarker marker = typeAheadMarkers.getFirst(); // Fixed 5064013: may appears that the events have the same time // if (ke.getWhen() >= marker.after) { // The fix is rolled out. if (ke.getWhen() > marker.after) {
*** 845,857 **** void dumpMarkers() { if (focusLog.isLoggable(PlatformLogger.FINEST)) { focusLog.finest(">>> Markers dump, time: {0}", System.currentTimeMillis()); synchronized (this) { if (typeAheadMarkers.size() != 0) { ! Iterator iter = typeAheadMarkers.iterator(); while (iter.hasNext()) { ! TypeAheadMarker marker = (TypeAheadMarker)iter.next(); focusLog.finest(" {0}", marker); } } } } --- 878,890 ---- void dumpMarkers() { if (focusLog.isLoggable(PlatformLogger.FINEST)) { focusLog.finest(">>> Markers dump, time: {0}", System.currentTimeMillis()); synchronized (this) { if (typeAheadMarkers.size() != 0) { ! Iterator<TypeAheadMarker> iter = typeAheadMarkers.iterator(); while (iter.hasNext()) { ! TypeAheadMarker marker = iter.next(); focusLog.finest(" {0}", marker); } } } }
*** 869,880 **** case KeyEvent.KEY_PRESSED: case KeyEvent.KEY_RELEASED: { KeyEvent ke = (KeyEvent)e; synchronized (this) { if (e.isPosted && typeAheadMarkers.size() != 0) { ! TypeAheadMarker marker = (TypeAheadMarker) ! typeAheadMarkers.getFirst(); // Fixed 5064013: may appears that the events have the same time // if (ke.getWhen() >= marker.after) { // The fix is rolled out. if (ke.getWhen() > marker.after) { --- 902,912 ---- case KeyEvent.KEY_PRESSED: case KeyEvent.KEY_RELEASED: { KeyEvent ke = (KeyEvent)e; synchronized (this) { if (e.isPosted && typeAheadMarkers.size() != 0) { ! TypeAheadMarker marker = typeAheadMarkers.getFirst(); // Fixed 5064013: may appears that the events have the same time // if (ke.getWhen() >= marker.after) { // The fix is rolled out. if (ke.getWhen() > marker.after) {
*** 903,918 **** // not be generated for these additional requests, we // need to clear those markers too. synchronized (this) { boolean found = false; if (hasMarker(target)) { ! for (Iterator iter = typeAheadMarkers.iterator(); iter.hasNext(); ) { ! if (((TypeAheadMarker)iter.next()).untilFocused == ! target) ! { found = true; } else if (found) { break; } iter.remove(); --- 935,948 ---- // not be generated for these additional requests, we // need to clear those markers too. synchronized (this) { boolean found = false; if (hasMarker(target)) { ! for (Iterator<TypeAheadMarker> iter = typeAheadMarkers.iterator(); iter.hasNext(); ) { ! if (iter.next().untilFocused == target) { found = true; } else if (found) { break; } iter.remove();
*** 943,954 **** * Returns true if there are some marker associated with component <code>comp</code> * in a markers' queue * @since 1.5 */ private boolean hasMarker(Component comp) { ! for (Iterator iter = typeAheadMarkers.iterator(); iter.hasNext(); ) { ! if (((TypeAheadMarker)iter.next()).untilFocused == comp) { return true; } } return false; } --- 973,984 ---- * Returns true if there are some marker associated with component <code>comp</code> * in a markers' queue * @since 1.5 */ private boolean hasMarker(Component comp) { ! for (Iterator<TypeAheadMarker> iter = typeAheadMarkers.iterator(); iter.hasNext(); ) { ! if (iter.next().untilFocused == comp) { return true; } } return false; }
*** 970,984 **** } if (ke.getSource() == null) { return true; } ! // Explicitly set the current event and most recent timestamp here in ! // addition to the call in Component.dispatchEventImpl. Because ! // KeyEvents can be delivered in response to a FOCUS_GAINED event, the ! // current timestamp may be incorrect. We need to set it here so that ! // KeyEventDispatchers will use the correct time. EventQueue.setCurrentEventAndMostRecentTime(ke); /** * Fix for 4495473. * This fix allows to correctly dispatch events when native --- 1000,1013 ---- } if (ke.getSource() == null) { return true; } ! // Explicitly set the key event timestamp here (not in Component.dispatchEventImpl): ! // - A key event is anyway passed to this method which starts its actual dispatching. ! // - If a key event is put to the type ahead queue, its time stamp should not be registered ! // until its dispatching actually starts (by this method). EventQueue.setCurrentEventAndMostRecentTime(ke); /** * Fix for 4495473. * This fix allows to correctly dispatch events when native
*** 1162,1175 **** focusLog.finer("Enqueue at {0} for {1}", after, untilFocused); int insertionIndex = 0, i = typeAheadMarkers.size(); ! ListIterator iter = typeAheadMarkers.listIterator(i); for (; i > 0; i--) { ! TypeAheadMarker marker = (TypeAheadMarker)iter.previous(); if (marker.after <= after) { insertionIndex = i; break; } } --- 1191,1204 ---- focusLog.finer("Enqueue at {0} for {1}", after, untilFocused); int insertionIndex = 0, i = typeAheadMarkers.size(); ! ListIterator<TypeAheadMarker> iter = typeAheadMarkers.listIterator(i); for (; i > 0; i--) { ! TypeAheadMarker marker = iter.previous(); if (marker.after <= after) { insertionIndex = i; break; } }
*** 1201,1225 **** focusLog.finer("Dequeue at {0} for {1}", after, untilFocused); TypeAheadMarker marker; ! ListIterator iter = typeAheadMarkers.listIterator ((after >= 0) ? typeAheadMarkers.size() : 0); if (after < 0) { while (iter.hasNext()) { ! marker = (TypeAheadMarker)iter.next(); if (marker.untilFocused == untilFocused) { iter.remove(); return; } } } else { while (iter.hasPrevious()) { ! marker = (TypeAheadMarker)iter.previous(); if (marker.untilFocused == untilFocused && marker.after == after) { iter.remove(); return; --- 1230,1254 ---- focusLog.finer("Dequeue at {0} for {1}", after, untilFocused); TypeAheadMarker marker; ! ListIterator<TypeAheadMarker> iter = typeAheadMarkers.listIterator ((after >= 0) ? typeAheadMarkers.size() : 0); if (after < 0) { while (iter.hasNext()) { ! marker = iter.next(); if (marker.untilFocused == untilFocused) { iter.remove(); return; } } } else { while (iter.hasPrevious()) { ! marker = iter.previous(); if (marker.untilFocused == untilFocused && marker.after == after) { iter.remove(); return;
*** 1243,1254 **** return; } long start = -1; ! for (Iterator iter = typeAheadMarkers.iterator(); iter.hasNext(); ) { ! TypeAheadMarker marker = (TypeAheadMarker)iter.next(); Component toTest = marker.untilFocused; boolean match = (toTest == comp); while (!match && toTest != null && !(toTest instanceof Window)) { toTest = toTest.getParent(); match = (toTest == comp); --- 1272,1283 ---- return; } long start = -1; ! for (Iterator<TypeAheadMarker> iter = typeAheadMarkers.iterator(); iter.hasNext(); ) { ! TypeAheadMarker marker = iter.next(); Component toTest = marker.untilFocused; boolean match = (toTest == comp); while (!match && toTest != null && !(toTest instanceof Window)) { toTest = toTest.getParent(); match = (toTest == comp);
*** 1275,1286 **** private void purgeStampedEvents(long start, long end) { if (start < 0) { return; } ! for (Iterator iter = enqueuedKeyEvents.iterator(); iter.hasNext(); ) { ! KeyEvent ke = (KeyEvent)iter.next(); long time = ke.getWhen(); if (start < time && (end < 0 || time <= end)) { iter.remove(); } --- 1304,1315 ---- private void purgeStampedEvents(long start, long end) { if (start < 0) { return; } ! for (Iterator<KeyEvent> iter = enqueuedKeyEvents.iterator(); iter.hasNext(); ) { ! KeyEvent ke = iter.next(); long time = ke.getWhen(); if (start < time && (end < 0 || time <= end)) { iter.remove(); }