changeset 7922:566591f1da88

RT-38289: [Quantum] Control ActionEvent is fired on Stage closing and the App hangs if modal window is then shown Reviewed-by: anthony, felipe, snorthov
author kcr
date Fri, 29 Aug 2014 11:10:04 -0700
parents de7ad70a06f9
children 5e65b34a175b
files modules/graphics/src/main/java/com/sun/glass/ui/Accessible.java modules/graphics/src/main/java/com/sun/javafx/tk/quantum/GlassViewEventHandler.java modules/graphics/src/main/java/com/sun/javafx/tk/quantum/GlassWindowEventHandler.java modules/graphics/src/main/java/com/sun/javafx/tk/quantum/QuantumToolkit.java tests/system/src/test/java/renderlock/RenderLock1Test.java tests/system/src/test/java/renderlock/RenderLockCommon.java
diffstat 6 files changed, 514 insertions(+), 223 deletions(-) [+]
line wrap: on
line diff
--- a/modules/graphics/src/main/java/com/sun/glass/ui/Accessible.java	Fri Aug 29 17:35:30 2014 +0200
+++ b/modules/graphics/src/main/java/com/sun/glass/ui/Accessible.java	Fri Aug 29 11:10:04 2014 -0700
@@ -32,6 +32,7 @@
 import java.security.PrivilegedAction;
 import com.sun.javafx.scene.NodeHelper;
 import com.sun.javafx.scene.SceneHelper;
+import com.sun.javafx.tk.quantum.QuantumToolkit;
 import javafx.scene.AccessibleAction;
 import javafx.scene.AccessibleAttribute;
 import javafx.scene.AccessibleRole;
@@ -154,9 +155,11 @@
     private GetAttribute getAttribute = new GetAttribute();
 
     public Object getAttribute(AccessibleAttribute attribute, Object... parameters) {
-        getAttribute.attribute = attribute;
-        getAttribute.parameters = parameters;
-        return AccessController.doPrivileged(getAttribute, getAccessControlContext());
+        return QuantumToolkit.runWithoutRenderLock(() -> {
+            getAttribute.attribute = attribute;
+            getAttribute.parameters = parameters;
+            return AccessController.doPrivileged(getAttribute, getAccessControlContext());
+        });
     }
 
     private class ExecuteAction implements PrivilegedAction<Void> {
@@ -171,9 +174,11 @@
     private ExecuteAction executeAction = new ExecuteAction();
 
     public void executeAction(AccessibleAction action, Object... parameters) {
-        executeAction.action = action;
-        executeAction.parameters = parameters;
-        AccessController.doPrivileged(executeAction, getAccessControlContext());
+        QuantumToolkit.runWithoutRenderLock(() -> {
+            executeAction.action = action;
+            executeAction.parameters = parameters;
+            return AccessController.doPrivileged(executeAction, getAccessControlContext());
+        });
     }
 
     public abstract void sendNotification(AccessibleAttribute notification);
--- a/modules/graphics/src/main/java/com/sun/javafx/tk/quantum/GlassViewEventHandler.java	Fri Aug 29 17:35:30 2014 +0200
+++ b/modules/graphics/src/main/java/com/sun/javafx/tk/quantum/GlassViewEventHandler.java	Fri Aug 29 11:10:04 2014 -0700
@@ -224,7 +224,9 @@
         keyNotification.chars = chars;
         keyNotification.modifiers = modifiers;
 
-        AccessController.doPrivileged(keyNotification, scene.getAccessControlContext());
+        QuantumToolkit.runWithoutRenderLock(() -> {
+            return AccessController.doPrivileged(keyNotification, scene.getAccessControlContext());
+        });
     }
 
     private static EventType<javafx.scene.input.MouseEvent> mouseEventType(int glassType) {
@@ -379,7 +381,9 @@
         mouseNotification.isPopupTrigger = isPopupTrigger;
         mouseNotification.isSynthesized = isSynthesized;
 
-        AccessController.doPrivileged(mouseNotification, scene.getAccessControlContext());
+        QuantumToolkit.runWithoutRenderLock(() -> {
+            return AccessController.doPrivileged(mouseNotification, scene.getAccessControlContext());
+        });
     }
 
     @Override public void handleMenuEvent(final View view,
@@ -394,12 +398,14 @@
             if (stage != null) {
                 stage.setInEventHandler(true);
             }
-            AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
-                if (scene.sceneListener != null) {
-                    scene.sceneListener.menuEvent(x, y, xAbs, yAbs, isKeyboardTrigger);
-                }
-                return null;
-            }, scene.getAccessControlContext());
+            QuantumToolkit.runWithoutRenderLock(() -> {
+                return AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
+                    if (scene.sceneListener != null) {
+                        scene.sceneListener.menuEvent(x, y, xAbs, yAbs, isKeyboardTrigger);
+                    }
+                    return null;
+                }, scene.getAccessControlContext());
+            });
         } finally {
             if (stage != null) {
                 stage.setInEventHandler(false);
@@ -425,23 +431,25 @@
             if (stage != null) {
                 stage.setInEventHandler(true);
             }
-            AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
-                if (scene.sceneListener != null) {
-                    scene.sceneListener.scrollEvent(ScrollEvent.SCROLL,
-                        deltaX, deltaY, 0, 0,
-                        xMultiplier, yMultiplier,
-                        0, // touchCount
-                        chars, lines, defaultChars, defaultLines,
-                        x, y, xAbs, yAbs,
-                        (modifiers & KeyEvent.MODIFIER_SHIFT) != 0,
-                        (modifiers & KeyEvent.MODIFIER_CONTROL) != 0,
-                        (modifiers & KeyEvent.MODIFIER_ALT) != 0,
-                        (modifiers & KeyEvent.MODIFIER_WINDOWS) != 0,
-                        false, // this is always indirect
-                        false); // this has no inertia
-                }
-                return null;
-            }, scene.getAccessControlContext());
+            QuantumToolkit.runWithoutRenderLock(() -> {
+                return AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
+                    if (scene.sceneListener != null) {
+                        scene.sceneListener.scrollEvent(ScrollEvent.SCROLL,
+                            deltaX, deltaY, 0, 0,
+                            xMultiplier, yMultiplier,
+                            0, // touchCount
+                            chars, lines, defaultChars, defaultLines,
+                            x, y, xAbs, yAbs,
+                            (modifiers & KeyEvent.MODIFIER_SHIFT) != 0,
+                            (modifiers & KeyEvent.MODIFIER_CONTROL) != 0,
+                            (modifiers & KeyEvent.MODIFIER_ALT) != 0,
+                            (modifiers & KeyEvent.MODIFIER_WINDOWS) != 0,
+                            false, // this is always indirect
+                            false); // this has no inertia
+                    }
+                    return null;
+                }, scene.getAccessControlContext());
+            });
         } finally {
             if (stage != null) {
                 stage.setInEventHandler(false);
@@ -532,18 +540,20 @@
             if (stage != null) {
                 stage.setInEventHandler(true);
             }
-            AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
-                if (scene.sceneListener != null) {
-                    String t = text != null ? text : "";
-                    EventType<InputMethodEvent> eventType =
-                            InputMethodEvent.INPUT_METHOD_TEXT_CHANGED;
-                    ObservableList<InputMethodTextRun> composed = inputMethodEventComposed(
-                            t, commitCount, clauseBoundary, attrBoundary, attrValue);
-                    String committed = t.substring(0, commitCount);
-                    scene.sceneListener.inputMethodEvent(eventType, composed, committed, cursorPos);
-                }
-                return null;
-            }, scene.getAccessControlContext());
+            QuantumToolkit.runWithoutRenderLock(() -> {
+                return AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
+                    if (scene.sceneListener != null) {
+                        String t = text != null ? text : "";
+                        EventType<InputMethodEvent> eventType =
+                                InputMethodEvent.INPUT_METHOD_TEXT_CHANGED;
+                        ObservableList<InputMethodTextRun> composed = inputMethodEventComposed(
+                                t, commitCount, clauseBoundary, attrBoundary, attrValue);
+                        String committed = t.substring(0, commitCount);
+                        scene.sceneListener.inputMethodEvent(eventType, composed, committed, cursorPos);
+                    }
+                    return null;
+                }, scene.getAccessControlContext());
+            });
         } finally {
             if (stage != null) {
                 stage.setInEventHandler(false);
@@ -617,9 +627,11 @@
         }
         TransferMode action;
         try {
-            action = dndHandler.handleDragEnter(x, y, xAbs, yAbs,
-                    actionToTransferMode(recommendedDropAction),
-                    dropTargetAssistant);
+            action = QuantumToolkit.runWithoutRenderLock(() -> {
+                return dndHandler.handleDragEnter(x, y, xAbs, yAbs,
+                        actionToTransferMode(recommendedDropAction),
+                        dropTargetAssistant);
+            });
         } finally {
             if (PULSE_LOGGING_ENABLED) {
                 PulseLogger.newInput(null);
@@ -633,7 +645,10 @@
             PulseLogger.newInput("DRAG_LEAVE");
         }
         try {
-            dndHandler.handleDragLeave(dropTargetAssistant);
+            QuantumToolkit.runWithoutRenderLock(() -> {
+                dndHandler.handleDragLeave(dropTargetAssistant);
+                return null;
+            });
         } finally {
             if (PULSE_LOGGING_ENABLED) {
                 PulseLogger.newInput(null);
@@ -651,9 +666,11 @@
         }
         TransferMode action;
         try {
-            action = dndHandler.handleDragDrop(x, y, xAbs, yAbs,
+            action = QuantumToolkit.runWithoutRenderLock(() -> {
+                return dndHandler.handleDragDrop(x, y, xAbs, yAbs,
                     actionToTransferMode(recommendedDropAction),
                     dropTargetAssistant);
+            });
         } finally {
             if (PULSE_LOGGING_ENABLED) {
                 PulseLogger.newInput(null);
@@ -672,9 +689,11 @@
         }
         TransferMode action;
         try {
-            action = dndHandler.handleDragOver(x, y, xAbs, yAbs,
-                actionToTransferMode(recommendedDropAction),
-                dropTargetAssistant);
+            action = QuantumToolkit.runWithoutRenderLock(() -> {
+                return dndHandler.handleDragOver(x, y, xAbs, yAbs,
+                    actionToTransferMode(recommendedDropAction),
+                    dropTargetAssistant);
+            });
         } finally {
             if (PULSE_LOGGING_ENABLED) {
                 PulseLogger.newInput(null);
@@ -694,7 +713,10 @@
         }
         dropSourceAssistant = assistant;
         try {
-            dndHandler.handleDragStart(button, x, y, xAbs, yAbs, assistant);
+            QuantumToolkit.runWithoutRenderLock(() -> {
+                dndHandler.handleDragStart(button, x, y, xAbs, yAbs, assistant);
+                return null;
+            });
         } finally {
             if (PULSE_LOGGING_ENABLED) {
                 PulseLogger.newInput(null);
@@ -707,7 +729,10 @@
             PulseLogger.newInput("DRAG_END");
         }
         try {
-            dndHandler.handleDragEnd(actionToTransferMode(performedAction), dropSourceAssistant);
+            QuantumToolkit.runWithoutRenderLock(() -> {
+                dndHandler.handleDragEnd(actionToTransferMode(performedAction), dropSourceAssistant);
+                return null;
+            });
         } finally {
             if (PULSE_LOGGING_ENABLED) {
                 PulseLogger.newInput(null);
@@ -791,7 +816,9 @@
         viewNotification.time = time;
         viewNotification.type = type;
         try {
-            AccessController.doPrivileged(viewNotification, scene.getAccessControlContext());
+            QuantumToolkit.runWithoutRenderLock(() -> {
+                return AccessController.doPrivileged(viewNotification, scene.getAccessControlContext());
+            });
         }
         finally {
             if (PULSE_LOGGING_ENABLED) {
@@ -814,38 +841,40 @@
             if (stage != null) {
                 stage.setInEventHandler(true);
             }
-            AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
-                if (scene.sceneListener != null) {
-                    EventType<ScrollEvent> eventType;
-                    switch(type) {
-                        case GestureEvent.GESTURE_STARTED:
-                            eventType = ScrollEvent.SCROLL_STARTED;
-                            break;
-                        case GestureEvent.GESTURE_PERFORMED:
-                            eventType = ScrollEvent.SCROLL;
-                            break;
-                        case GestureEvent.GESTURE_FINISHED:
-                            eventType = ScrollEvent.SCROLL_FINISHED;
-                            break;
-                        default:
-                            throw new RuntimeException("Unknown scroll event type: " + type);
+            QuantumToolkit.runWithoutRenderLock(() -> {
+                return AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
+                    if (scene.sceneListener != null) {
+                        EventType<ScrollEvent> eventType;
+                        switch(type) {
+                            case GestureEvent.GESTURE_STARTED:
+                                eventType = ScrollEvent.SCROLL_STARTED;
+                                break;
+                            case GestureEvent.GESTURE_PERFORMED:
+                                eventType = ScrollEvent.SCROLL;
+                                break;
+                            case GestureEvent.GESTURE_FINISHED:
+                                eventType = ScrollEvent.SCROLL_FINISHED;
+                                break;
+                            default:
+                                throw new RuntimeException("Unknown scroll event type: " + type);
+                        }
+                        scene.sceneListener.scrollEvent(eventType, dx, dy, totaldx, totaldy,
+                                multiplierX, multiplierY,
+                                touchCount,
+                                0, 0, 0, 0,
+                                x == View.GESTURE_NO_VALUE ? Double.NaN : x,
+                                y == View.GESTURE_NO_VALUE ? Double.NaN : y,
+                                xAbs == View.GESTURE_NO_VALUE ? Double.NaN : xAbs,
+                                yAbs == View.GESTURE_NO_VALUE ? Double.NaN : yAbs,
+                                (modifiers & KeyEvent.MODIFIER_SHIFT) != 0,
+                                (modifiers & KeyEvent.MODIFIER_CONTROL) != 0,
+                                (modifiers & KeyEvent.MODIFIER_ALT) != 0,
+                                (modifiers & KeyEvent.MODIFIER_WINDOWS) != 0,
+                                isDirect, isInertia);
                     }
-                    scene.sceneListener.scrollEvent(eventType, dx, dy, totaldx, totaldy,
-                            multiplierX, multiplierY,
-                            touchCount,
-                            0, 0, 0, 0,
-                            x == View.GESTURE_NO_VALUE ? Double.NaN : x,
-                            y == View.GESTURE_NO_VALUE ? Double.NaN : y,
-                            xAbs == View.GESTURE_NO_VALUE ? Double.NaN : xAbs,
-                            yAbs == View.GESTURE_NO_VALUE ? Double.NaN : yAbs,
-                            (modifiers & KeyEvent.MODIFIER_SHIFT) != 0,
-                            (modifiers & KeyEvent.MODIFIER_CONTROL) != 0,
-                            (modifiers & KeyEvent.MODIFIER_ALT) != 0,
-                            (modifiers & KeyEvent.MODIFIER_WINDOWS) != 0,
-                            isDirect, isInertia);
-                }
-                return null;
-            }, scene.getAccessControlContext());
+                    return null;
+                }, scene.getAccessControlContext());
+            });
         } finally {
             if (stage != null) {
                 stage.setInEventHandler(false);
@@ -872,35 +901,37 @@
             if (stage != null) {
                 stage.setInEventHandler(true);
             }
-            AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
-                if (scene.sceneListener != null) {
-                    EventType<ZoomEvent> eventType;
-                    switch (type) {
-                        case GestureEvent.GESTURE_STARTED:
-                            eventType = ZoomEvent.ZOOM_STARTED;
-                            break;
-                        case GestureEvent.GESTURE_PERFORMED:
-                            eventType = ZoomEvent.ZOOM;
-                            break;
-                        case GestureEvent.GESTURE_FINISHED:
-                            eventType = ZoomEvent.ZOOM_FINISHED;
-                            break;
-                        default:
-                            throw new RuntimeException("Unknown scroll event type: " + type);
+            QuantumToolkit.runWithoutRenderLock(() -> {
+                return AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
+                    if (scene.sceneListener != null) {
+                        EventType<ZoomEvent> eventType;
+                        switch (type) {
+                            case GestureEvent.GESTURE_STARTED:
+                                eventType = ZoomEvent.ZOOM_STARTED;
+                                break;
+                            case GestureEvent.GESTURE_PERFORMED:
+                                eventType = ZoomEvent.ZOOM;
+                                break;
+                            case GestureEvent.GESTURE_FINISHED:
+                                eventType = ZoomEvent.ZOOM_FINISHED;
+                                break;
+                            default:
+                                throw new RuntimeException("Unknown scroll event type: " + type);
+                        }
+                        scene.sceneListener.zoomEvent(eventType, scale, totalscale,
+                                originx == View.GESTURE_NO_VALUE ? Double.NaN : originx,
+                                originy == View.GESTURE_NO_VALUE ? Double.NaN : originy,
+                                originxAbs == View.GESTURE_NO_VALUE ? Double.NaN : originxAbs,
+                                originyAbs == View.GESTURE_NO_VALUE ? Double.NaN : originyAbs,
+                                (modifiers & KeyEvent.MODIFIER_SHIFT) != 0,
+                                (modifiers & KeyEvent.MODIFIER_CONTROL) != 0,
+                                (modifiers & KeyEvent.MODIFIER_ALT) != 0,
+                                (modifiers & KeyEvent.MODIFIER_WINDOWS) != 0,
+                                isDirect, isInertia);
                     }
-                    scene.sceneListener.zoomEvent(eventType, scale, totalscale,
-                            originx == View.GESTURE_NO_VALUE ? Double.NaN : originx,
-                            originy == View.GESTURE_NO_VALUE ? Double.NaN : originy,
-                            originxAbs == View.GESTURE_NO_VALUE ? Double.NaN : originxAbs,
-                            originyAbs == View.GESTURE_NO_VALUE ? Double.NaN : originyAbs,
-                            (modifiers & KeyEvent.MODIFIER_SHIFT) != 0,
-                            (modifiers & KeyEvent.MODIFIER_CONTROL) != 0,
-                            (modifiers & KeyEvent.MODIFIER_ALT) != 0,
-                            (modifiers & KeyEvent.MODIFIER_WINDOWS) != 0,
-                            isDirect, isInertia);
-                }
-                return null;
-            }, scene.getAccessControlContext());
+                    return null;
+                }, scene.getAccessControlContext());
+            });
         } finally {
             if (stage != null) {
                 stage.setInEventHandler(false);
@@ -926,35 +957,37 @@
             if (stage != null) {
                 stage.setInEventHandler(true);
             }
-            AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
-                if (scene.sceneListener != null) {
-                    EventType<RotateEvent> eventType;
-                    switch (type) {
-                        case GestureEvent.GESTURE_STARTED:
-                            eventType = RotateEvent.ROTATION_STARTED;
-                            break;
-                        case GestureEvent.GESTURE_PERFORMED:
-                            eventType = RotateEvent.ROTATE;
-                            break;
-                        case GestureEvent.GESTURE_FINISHED:
-                            eventType = RotateEvent.ROTATION_FINISHED;
-                            break;
-                        default:
-                            throw new RuntimeException("Unknown scroll event type: " + type);
+            QuantumToolkit.runWithoutRenderLock(() -> {
+                return AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
+                    if (scene.sceneListener != null) {
+                        EventType<RotateEvent> eventType;
+                        switch (type) {
+                            case GestureEvent.GESTURE_STARTED:
+                                eventType = RotateEvent.ROTATION_STARTED;
+                                break;
+                            case GestureEvent.GESTURE_PERFORMED:
+                                eventType = RotateEvent.ROTATE;
+                                break;
+                            case GestureEvent.GESTURE_FINISHED:
+                                eventType = RotateEvent.ROTATION_FINISHED;
+                                break;
+                            default:
+                                throw new RuntimeException("Unknown scroll event type: " + type);
+                        }
+                        scene.sceneListener.rotateEvent(eventType, dangle, totalangle,
+                                originx == View.GESTURE_NO_VALUE ? Double.NaN : originx,
+                                originy == View.GESTURE_NO_VALUE ? Double.NaN : originy,
+                                originxAbs == View.GESTURE_NO_VALUE ? Double.NaN : originxAbs,
+                                originyAbs == View.GESTURE_NO_VALUE ? Double.NaN : originyAbs,
+                                (modifiers & KeyEvent.MODIFIER_SHIFT) != 0,
+                                (modifiers & KeyEvent.MODIFIER_CONTROL) != 0,
+                                (modifiers & KeyEvent.MODIFIER_ALT) != 0,
+                                (modifiers & KeyEvent.MODIFIER_WINDOWS) != 0,
+                                isDirect, isInertia);
                     }
-                    scene.sceneListener.rotateEvent(eventType, dangle, totalangle,
-                            originx == View.GESTURE_NO_VALUE ? Double.NaN : originx,
-                            originy == View.GESTURE_NO_VALUE ? Double.NaN : originy,
-                            originxAbs == View.GESTURE_NO_VALUE ? Double.NaN : originxAbs,
-                            originyAbs == View.GESTURE_NO_VALUE ? Double.NaN : originyAbs,
-                            (modifiers & KeyEvent.MODIFIER_SHIFT) != 0,
-                            (modifiers & KeyEvent.MODIFIER_CONTROL) != 0,
-                            (modifiers & KeyEvent.MODIFIER_ALT) != 0,
-                            (modifiers & KeyEvent.MODIFIER_WINDOWS) != 0,
-                            isDirect, isInertia);
-                }
-                return null;
-            }, scene.getAccessControlContext());
+                    return null;
+                }, scene.getAccessControlContext());
+            });
         } finally {
             if (stage != null) {
                 stage.setInEventHandler(false);
@@ -979,38 +1012,40 @@
             if (stage != null) {
                 stage.setInEventHandler(true);
             }
-            AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
-                if (scene.sceneListener != null) {
-                    EventType<SwipeEvent> eventType;
-                    switch (dir) {
-                        case SwipeGesture.DIR_UP:
-                            eventType = SwipeEvent.SWIPE_UP;
-                            break;
-                        case SwipeGesture.DIR_DOWN:
-                            eventType = SwipeEvent.SWIPE_DOWN;
-                            break;
-                        case SwipeGesture.DIR_LEFT:
-                            eventType = SwipeEvent.SWIPE_LEFT;
-                            break;
-                        case SwipeGesture.DIR_RIGHT:
-                            eventType = SwipeEvent.SWIPE_RIGHT;
-                            break;
-                        default:
-                            throw new RuntimeException("Unknown swipe event direction: " + dir);
+            QuantumToolkit.runWithoutRenderLock(() -> {
+                return AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
+                    if (scene.sceneListener != null) {
+                        EventType<SwipeEvent> eventType;
+                        switch (dir) {
+                            case SwipeGesture.DIR_UP:
+                                eventType = SwipeEvent.SWIPE_UP;
+                                break;
+                            case SwipeGesture.DIR_DOWN:
+                                eventType = SwipeEvent.SWIPE_DOWN;
+                                break;
+                            case SwipeGesture.DIR_LEFT:
+                                eventType = SwipeEvent.SWIPE_LEFT;
+                                break;
+                            case SwipeGesture.DIR_RIGHT:
+                                eventType = SwipeEvent.SWIPE_RIGHT;
+                                break;
+                            default:
+                                throw new RuntimeException("Unknown swipe event direction: " + dir);
+                        }
+                        scene.sceneListener.swipeEvent(eventType, touchCount,
+                                x == View.GESTURE_NO_VALUE ? Double.NaN : x,
+                                y == View.GESTURE_NO_VALUE ? Double.NaN : y,
+                                xAbs == View.GESTURE_NO_VALUE ? Double.NaN : xAbs,
+                                yAbs == View.GESTURE_NO_VALUE ? Double.NaN : yAbs,
+                                (modifiers & KeyEvent.MODIFIER_SHIFT) != 0,
+                                (modifiers & KeyEvent.MODIFIER_CONTROL) != 0,
+                                (modifiers & KeyEvent.MODIFIER_ALT) != 0,
+                                (modifiers & KeyEvent.MODIFIER_WINDOWS) != 0,
+                                isDirect);
                     }
-                    scene.sceneListener.swipeEvent(eventType, touchCount,
-                            x == View.GESTURE_NO_VALUE ? Double.NaN : x,
-                            y == View.GESTURE_NO_VALUE ? Double.NaN : y,
-                            xAbs == View.GESTURE_NO_VALUE ? Double.NaN : xAbs,
-                            yAbs == View.GESTURE_NO_VALUE ? Double.NaN : yAbs,
-                            (modifiers & KeyEvent.MODIFIER_SHIFT) != 0,
-                            (modifiers & KeyEvent.MODIFIER_CONTROL) != 0,
-                            (modifiers & KeyEvent.MODIFIER_ALT) != 0,
-                            (modifiers & KeyEvent.MODIFIER_WINDOWS) != 0,
-                            isDirect);
-                }
-                return null;
-            }, scene.getAccessControlContext());
+                    return null;
+                }, scene.getAccessControlContext());
+            });
         } finally {
             if (stage != null) {
                 stage.setInEventHandler(false);
@@ -1033,17 +1068,19 @@
             if (stage != null) {
                 stage.setInEventHandler(true);
             }
-            AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
-                if (scene.sceneListener != null) {
-                    scene.sceneListener.touchEventBegin(time, touchEventCount,
-                            isDirect,
-                            (modifiers & KeyEvent.MODIFIER_SHIFT) != 0,
-                            (modifiers & KeyEvent.MODIFIER_CONTROL) != 0,
-                            (modifiers & KeyEvent.MODIFIER_ALT) != 0,
-                            (modifiers & KeyEvent.MODIFIER_WINDOWS) != 0);
-                }
-                return null;
-            }, scene.getAccessControlContext());
+            QuantumToolkit.runWithoutRenderLock(() -> {
+                return AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
+                    if (scene.sceneListener != null) {
+                        scene.sceneListener.touchEventBegin(time, touchEventCount,
+                                isDirect,
+                                (modifiers & KeyEvent.MODIFIER_SHIFT) != 0,
+                                (modifiers & KeyEvent.MODIFIER_CONTROL) != 0,
+                                (modifiers & KeyEvent.MODIFIER_ALT) != 0,
+                                (modifiers & KeyEvent.MODIFIER_WINDOWS) != 0);
+                    }
+                    return null;
+                }, scene.getAccessControlContext());
+            });
         } finally {
             if (stage != null) {
                 stage.setInEventHandler(false);
@@ -1068,29 +1105,31 @@
             if (stage != null) {
                 stage.setInEventHandler(true);
             }
-            AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
-                if (scene.sceneListener != null) {
-                    TouchPoint.State state;
-                    switch (type) {
-                        case TouchEvent.TOUCH_PRESSED:
-                            state = TouchPoint.State.PRESSED;
-                            break;
-                        case TouchEvent.TOUCH_MOVED:
-                            state = TouchPoint.State.MOVED;
-                            break;
-                        case TouchEvent.TOUCH_STILL:
-                            state = TouchPoint.State.STATIONARY;
-                            break;
-                        case TouchEvent.TOUCH_RELEASED:
-                            state = TouchPoint.State.RELEASED;
-                            break;
-                        default:
-                            throw new RuntimeException("Unknown touch state: " + type);
+            QuantumToolkit.runWithoutRenderLock(() -> {
+                    return AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
+                    if (scene.sceneListener != null) {
+                        TouchPoint.State state;
+                        switch (type) {
+                            case TouchEvent.TOUCH_PRESSED:
+                                state = TouchPoint.State.PRESSED;
+                                break;
+                            case TouchEvent.TOUCH_MOVED:
+                                state = TouchPoint.State.MOVED;
+                                break;
+                            case TouchEvent.TOUCH_STILL:
+                                state = TouchPoint.State.STATIONARY;
+                                break;
+                            case TouchEvent.TOUCH_RELEASED:
+                                state = TouchPoint.State.RELEASED;
+                                break;
+                            default:
+                                throw new RuntimeException("Unknown touch state: " + type);
+                        }
+                        scene.sceneListener.touchEventNext(state, touchId, x, y, xAbs, yAbs);
                     }
-                    scene.sceneListener.touchEventNext(state, touchId, x, y, xAbs, yAbs);
-                }
-                return null;
-            }, scene.getAccessControlContext());
+                    return null;
+                }, scene.getAccessControlContext());
+            });
         } finally {
             if (stage != null) {
                 stage.setInEventHandler(false);
@@ -1112,12 +1151,14 @@
             if (stage != null) {
                 stage.setInEventHandler(true);
             }
-            AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
-                if (scene.sceneListener != null) {
-                    scene.sceneListener.touchEventEnd();
-                }
-                return null;
-            }, scene.getAccessControlContext());
+            QuantumToolkit.runWithoutRenderLock(() -> {
+                return AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
+                    if (scene.sceneListener != null) {
+                        scene.sceneListener.touchEventEnd();
+                    }
+                    return null;
+                }, scene.getAccessControlContext());
+            });
         } finally {
             if (stage != null) {
                 stage.setInEventHandler(false);
--- a/modules/graphics/src/main/java/com/sun/javafx/tk/quantum/GlassWindowEventHandler.java	Fri Aug 29 17:35:30 2014 +0200
+++ b/modules/graphics/src/main/java/com/sun/javafx/tk/quantum/GlassWindowEventHandler.java	Fri Aug 29 11:10:04 2014 -0700
@@ -121,11 +121,13 @@
 
     @Override
     public void handleLevelEvent(int level) {
-        AccessControlContext acc = stage.getAccessControlContext();
-        AccessController.doPrivileged((PrivilegedAction<Void>)() -> {
-            stage.stageListener.changedAlwaysOnTop(level != Level.NORMAL);
-            return (Void)null;
-        } , acc);
+        QuantumToolkit.runWithoutRenderLock(() -> {
+            AccessControlContext acc = stage.getAccessControlContext();
+            return AccessController.doPrivileged((PrivilegedAction<Void>)() -> {
+                stage.stageListener.changedAlwaysOnTop(level != Level.NORMAL);
+                return (Void)null;
+            } , acc);
+        });
     }
     
     @Override
@@ -133,8 +135,10 @@
         this.window = window;
         this.type = type;
 
-        AccessControlContext acc = stage.getAccessControlContext();
-        AccessController.doPrivileged(this, acc);
+        QuantumToolkit.runWithoutRenderLock(() -> {
+            AccessControlContext acc = stage.getAccessControlContext();
+            return AccessController.doPrivileged(this, acc);
+        });
     }
     
     @Override
@@ -150,10 +154,12 @@
             }
         }
 
-        AccessControlContext acc = stage.getAccessControlContext();
-        AccessController.doPrivileged((PrivilegedAction<Void>)() -> {
-            stage.stageListener.changedScreen(oldScreen, newScreen);
-            return (Void)null;
-        } , acc);
+        QuantumToolkit.runWithoutRenderLock(() -> {
+            AccessControlContext acc = stage.getAccessControlContext();
+            return AccessController.doPrivileged((PrivilegedAction<Void>)() -> {
+                stage.stageListener.changedScreen(oldScreen, newScreen);
+                return (Void)null;
+            } , acc);
+        });
     }
 }
--- a/modules/graphics/src/main/java/com/sun/javafx/tk/quantum/QuantumToolkit.java	Fri Aug 29 17:35:30 2014 +0200
+++ b/modules/graphics/src/main/java/com/sun/javafx/tk/quantum/QuantumToolkit.java	Fri Aug 29 11:10:04 2014 -0700
@@ -72,6 +72,7 @@
 import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.function.Supplier;
 import com.sun.glass.ui.Application;
 import com.sun.glass.ui.Clipboard;
 import com.sun.glass.ui.ClipboardAssistance;
@@ -351,6 +352,28 @@
         }
     }
 
+    /**
+     * Runs the specified supplier, releasing the renderLock if needed.
+     * This is called by glass event handlers for Window, View, and
+     * Accessible.
+     * @param <T> the type of the return value
+     * @param supplier the supplier to be run
+     * @return the return value from calling supplier.get()
+     */
+    public static <T> T runWithoutRenderLock(Supplier<T> supplier) {
+        final boolean locked = ViewPainter.renderLock.isHeldByCurrentThread();
+        try {
+            if (locked) {
+                ViewPainter.renderLock.unlock();
+            }
+            return supplier.get();
+        } finally {
+            if (locked) {
+                ViewPainter.renderLock.lock();
+            }
+        }
+    }
+
     boolean hasNativeSystemVsync() {
         return nativeSystemVsync;
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/system/src/test/java/renderlock/RenderLock1Test.java	Fri Aug 29 11:10:04 2014 -0700
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package renderlock;
+
+import org.junit.Test;
+
+public class RenderLock1Test extends RenderLockCommon {
+    @Test
+    public void windowCloseTest() throws Exception {
+        doWindowCloseTest();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/system/src/test/java/renderlock/RenderLockCommon.java	Fri Aug 29 11:10:04 2014 -0700
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package renderlock;
+
+import com.sun.javafx.PlatformUtil;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
+import javafx.animation.FillTransition;
+import javafx.animation.Timeline;
+import javafx.application.Application;
+import javafx.application.Platform;
+import javafx.scene.Group;
+import javafx.scene.Scene;
+import javafx.scene.control.Alert;
+import javafx.scene.control.Button;
+import javafx.scene.control.ButtonType;
+import javafx.scene.layout.VBox;
+import javafx.scene.paint.Color;
+import javafx.scene.shape.Rectangle;
+import javafx.stage.Stage;
+import javafx.util.Duration;
+import junit.framework.AssertionFailedError;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import util.Util;
+
+import static org.junit.Assert.*;
+import static org.junit.Assume.*;
+import static util.Util.TIMEOUT;
+
+/**
+ * Common base class for testing snapshot.
+ */
+public class RenderLockCommon {
+
+    // Sleep time showing/hiding window in milliseconds
+    private static final int SLEEP_TIME = 1000;
+
+    // Used to launch the application before running any test
+    private static final CountDownLatch launchLatch = new CountDownLatch(1);
+
+    // Singleton Application instance
+    static MyApp myApp;
+
+    // Application class. An instance is created and initialized before running
+    // the first test, and it lives through the execution of all tests.
+    public static class MyApp extends Application {
+        Stage primaryStage;
+
+        @Override public void init() {
+            RenderLockCommon.myApp = this;
+        }
+
+        @Override public void start(Stage primaryStage) throws Exception {
+            assertTrue(Platform.isFxApplicationThread());
+            primaryStage.setTitle("Primary stage");
+            Rectangle rect = new Rectangle(100, 50);
+            FillTransition trans = new FillTransition(Duration.millis(500),
+                    rect, Color.BLUE, Color.VIOLET);
+            trans.setCycleCount(Timeline.INDEFINITE);
+            trans.setAutoReverse(true);
+            trans.play();
+            Group root = new Group(rect);
+            Scene scene = new Scene(root);
+            scene.setFill(Color.LIGHTYELLOW);
+            primaryStage.setScene(scene);
+            primaryStage.setX(0);
+            primaryStage.setY(0);
+            primaryStage.setWidth(210);
+            primaryStage.setHeight(180);
+            assertFalse(primaryStage.isShowing());
+            primaryStage.show();
+            assertTrue(primaryStage.isShowing());
+
+            this.primaryStage = primaryStage;
+            launchLatch.countDown();
+        }
+    }
+
+    @BeforeClass
+    public static void doSetupOnce() throws Exception {
+        // These tests are only valid on Windows and Mac.
+        // On Linux the closing of the window does not trigger a
+        // focusLost event with the lock held
+        assumeTrue(PlatformUtil.isMac() || PlatformUtil.isWindows());
+
+        // Start the Application
+        new Thread(() -> Application.launch(MyApp.class, (String[])null)).start();
+
+        if (!launchLatch.await(TIMEOUT, TimeUnit.MILLISECONDS)) {
+            fail("Timeout waiting for Application to launch");
+        }
+
+        assertEquals(0, launchLatch.getCount());
+    }
+
+    @AfterClass
+    public static void doTeardownOnce() {
+        Platform.exit();
+    }
+
+    // ========================== TEST CASES ==========================
+
+    private Stage testStage;
+
+    protected void doWindowCloseTest() throws Exception {
+        final CountDownLatch alertDoneLatch = new CountDownLatch(1);
+        final AtomicReference<ButtonType> alertResult = new AtomicReference<>();
+
+        Util.runAndWait(() -> {
+            Button button1 = new Button("The Button");
+            button1.focusedProperty().addListener((obs, oldValue, newValue) -> {
+                if (!newValue) {
+                    //System.err.println("lost focus");
+                    final Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
+                    Thread t = new Thread(() -> {
+                        Util.sleep(SLEEP_TIME);
+                        //System.err.println("scheduling runLater to hide alert");
+                        Platform.runLater(() -> {
+                            //System.err.println("Calling alert.hide");
+                            alert.hide();
+                        });
+                    });
+                    t.start();
+                    ButtonType result = alert.showAndWait().get();
+                    alertResult.set(result);
+                    alertDoneLatch.countDown();
+                    //System.err.println("result = " + result);
+                    //System.err.println("focus listener exit");
+                }
+            });
+
+            Button button2 = new Button("Other Button");
+
+            testStage = new Stage();
+            testStage.setScene(new Scene(new VBox(button1, button2), 400, 300));
+            button1.requestFocus();
+            testStage.requestFocus();
+            testStage.show();
+        });
+
+        Util.sleep(SLEEP_TIME);
+        //System.err.println("scheduling runLater to hide otherStage");
+        Platform.runLater(() -> {
+            //System.err.println("Calling otherStage.hide");
+            testStage.hide();
+        });
+
+        // Wait for results
+        if (!alertDoneLatch.await(TIMEOUT, TimeUnit.MILLISECONDS)) {
+            fail("Timeout waiting for alert to be hidden");
+        }
+
+        assertSame(ButtonType.CANCEL, alertResult.get());
+    }
+
+}