8159432: [PIT][macosx] StackOverflow in closed/java/awt/Dialog/DialogDeadlock/DialogDeadlockTest
authorssadetsky
Thu, 03 Nov 2016 11:51:31 +0300
changeset 42191 e5ba7d74e3c6
parent 42190 26d4a824fdea
child 42192 35a00ea5c65d
8159432: [PIT][macosx] StackOverflow in closed/java/awt/Dialog/DialogDeadlock/DialogDeadlockTest Reviewed-by: serb, azvegint
jdk/src/java.desktop/share/classes/java/awt/DefaultKeyboardFocusManager.java
--- a/jdk/src/java.desktop/share/classes/java/awt/DefaultKeyboardFocusManager.java	Thu Nov 03 03:49:42 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/java/awt/DefaultKeyboardFocusManager.java	Thu Nov 03 11:51:31 2016 +0300
@@ -75,6 +75,7 @@
     private LinkedList<KeyEvent> enqueuedKeyEvents = new LinkedList<KeyEvent>();
     private LinkedList<TypeAheadMarker> typeAheadMarkers = new LinkedList<TypeAheadMarker>();
     private boolean consumeNextKeyTyped;
+    private Component restoreFocusTo;
 
     static {
         AWTAccessor.setDefaultKeyboardFocusManagerAccessor(
@@ -145,19 +146,24 @@
     }
     private boolean restoreFocus(Window aWindow, Component vetoedComponent,
                                  boolean clearOnFailure) {
+        restoreFocusTo = null;
         Component toFocus =
             KeyboardFocusManager.getMostRecentFocusOwner(aWindow);
 
         if (toFocus != null && toFocus != vetoedComponent) {
-            Component heavyweight = getHeavyweight(aWindow);
-            if (heavyweight != null) {
-                setNativeFocusOwner(heavyweight);
-                Toolkit.getEventQueue().createSecondaryLoop(
-                        () -> getGlobalFocusedWindow() != aWindow, null, 50)
-                        .enter();
-            }
-            if (getGlobalFocusedWindow() == aWindow &&
-                              doRestoreFocus(toFocus, vetoedComponent, false)) {
+            if (getHeavyweight(aWindow) != getNativeFocusOwner()) {
+                // cannot restore focus synchronously
+                if (!toFocus.isShowing() || !toFocus.canBeFocusOwner()) {
+                    toFocus = toFocus.getNextFocusCandidate();
+                }
+                if (toFocus != null && toFocus != vetoedComponent) {
+                    if (!toFocus.requestFocus(false,
+                                                   FocusEvent.Cause.ROLLBACK)) {
+                        restoreFocusTo = toFocus;
+                    }
+                    return true;
+                }
+            } else if (doRestoreFocus(toFocus, vetoedComponent, false)) {
                 return true;
             }
         }
@@ -423,6 +429,8 @@
                     // may cause deadlock, thus we don't synchronize this block.
                     Component toFocus = KeyboardFocusManager.
                         getMostRecentFocusOwner(newFocusedWindow);
+                    boolean isFocusRestore = restoreFocusTo != null &&
+                                                      toFocus == restoreFocusTo;
                     if ((toFocus == null) &&
                         newFocusedWindow.isFocusableWindow())
                     {
@@ -441,7 +449,10 @@
                                        tempLost, toFocus);
                     }
                     if (tempLost != null) {
-                        tempLost.requestFocusInWindow(FocusEvent.Cause.ACTIVATION);
+                        tempLost.requestFocusInWindow(
+                                    isFocusRestore && tempLost == toFocus ?
+                                                FocusEvent.Cause.ROLLBACK :
+                                                FocusEvent.Cause.ACTIVATION);
                     }
 
                     if (toFocus != null && toFocus != tempLost) {
@@ -450,6 +461,7 @@
                         toFocus.requestFocusInWindow(FocusEvent.Cause.ACTIVATION);
                     }
                 }
+                restoreFocusTo = null;
 
                 Window realOppositeWindow = this.realOppositeWindowWR.get();
                 if (realOppositeWindow != we.getOppositeWindow()) {
@@ -499,6 +511,7 @@
             }
 
             case FocusEvent.FOCUS_GAINED: {
+                restoreFocusTo = null;
                 FocusEvent fe = (FocusEvent)e;
                 Component oldFocusOwner = getGlobalFocusOwner();
                 Component newFocusOwner = fe.getComponent();