changeset 11190:c8bb215eb1a5 12+11

8205092: NullPointerException in PickResultChooser.processOffer when using viewOrder Summary: Added dirty check for viewOrderChildren Reviewed-by: kcr, aghaisas Contributed-by: wookey.dean@gmail.com
author kcr
date Wed, 30 Jan 2019 14:33:43 -0800
parents dbc803ab09d8
children a22ff97ad01c
files modules/javafx.graphics/src/main/java/javafx/scene/Parent.java modules/javafx.graphics/src/test/java/test/javafx/scene/ParentTest.java
diffstat 2 files changed, 106 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/modules/javafx.graphics/src/main/java/javafx/scene/Parent.java	Wed Jan 30 14:24:22 2019 +0530
+++ b/modules/javafx.graphics/src/main/java/javafx/scene/Parent.java	Wed Jan 30 14:33:43 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2019, 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
@@ -194,7 +194,8 @@
         }
 
         if (isDirty(DirtyBits.PARENT_CHILDREN_VIEW_ORDER)) {
-            computeViewOrderChidrenAndUpdatePeer();
+            computeViewOrderChildren();
+            peer.setViewOrderChildren(viewOrderChildren);
         }
 
         if (Utils.assertionEnabled()) validatePG();
@@ -265,7 +266,7 @@
         NodeHelper.markDirty(this, DirtyBits.PARENT_CHILDREN_VIEW_ORDER);
     }
 
-    private void computeViewOrderChidrenAndUpdatePeer() {
+    private void computeViewOrderChildren() {
         boolean viewOrderSet = false;
         for (Node child : children) {
             double vo = child.getViewOrder();
@@ -284,14 +285,15 @@
                     -> a.getViewOrder() < b.getViewOrder() ? 1
                             : a.getViewOrder() == b.getViewOrder() ? 0 : -1);
         }
-
-        final NGGroup peer = getPeer();
-        peer.setViewOrderChildren(viewOrderChildren);
     }
 
     // Call this method if children view order is needed for picking.
     // The returned list should be treated as read only.
     private List<Node> getOrderedChildren() {
+        if (isDirty(DirtyBits.PARENT_CHILDREN_VIEW_ORDER)) {
+            //Fix for JDK-8205092
+            computeViewOrderChildren();
+        }
         if (!viewOrderChildren.isEmpty()) {
             return viewOrderChildren;
         }
--- a/modules/javafx.graphics/src/test/java/test/javafx/scene/ParentTest.java	Wed Jan 30 14:24:22 2019 +0530
+++ b/modules/javafx.graphics/src/test/java/test/javafx/scene/ParentTest.java	Wed Jan 30 14:33:43 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2019, 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
@@ -29,6 +29,8 @@
 import test.com.sun.javafx.pgstub.StubToolkit;
 import com.sun.javafx.sg.prism.NGGroup;
 import com.sun.javafx.tk.Toolkit;
+import com.sun.javafx.geom.PickRay;
+import com.sun.javafx.scene.input.PickResultChooser;
 import java.util.concurrent.atomic.AtomicBoolean;
 import javafx.scene.Group;
 import javafx.scene.GroupShim;
@@ -741,6 +743,101 @@
         assertSame(scene, ParentShim.getChildren(child).get(3).getScene());
     }
 
+    @Test
+    public void testPickingChildNode() {
+        Rectangle rect1 = new Rectangle();
+        rect1.setX(10);
+        rect1.setY(10);
+        rect1.setWidth(100);
+        rect1.setHeight(100);
+
+        Rectangle rect2 = new Rectangle();
+        rect2.setX(10);
+        rect2.setY(10);
+        rect2.setWidth(100);
+        rect2.setHeight(100);
+        Group g = new Group();
+
+        // needed since picking doesn't work unless rooted in a scene and visible
+        Scene scene = new Scene(g);
+        stage.setScene(scene);
+        stage.show();
+        ParentShim.getChildren(g).addAll(rect1, rect2);
+        toolkit.fireTestPulse();
+
+        PickResultChooser res = new PickResultChooser();
+        NodeHelper.pickNode(g, new PickRay(50, 50, 1, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY), res);
+        assertSame(rect2, res.getIntersectedNode());
+        res = new PickResultChooser();
+        NodeHelper.pickNode(g, new PickRay(0, 0, 1, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY), res);
+        assertNull(res.getIntersectedNode());
+    }
+
+    @Test
+    public void testPickingChildNodeWithViewOrderSet() {
+        Rectangle rect1 = new Rectangle();
+        rect1.setX(10);
+        rect1.setY(10);
+        rect1.setWidth(100);
+        rect1.setHeight(100);
+        rect1.setViewOrder(-1);
+
+        Rectangle rect2 = new Rectangle();
+        rect2.setX(10);
+        rect2.setY(10);
+        rect2.setWidth(100);
+        rect2.setHeight(100);
+        Group g = new Group();
+
+        // needed since picking doesn't work unless rooted in a scene and visible
+        Scene scene = new Scene(g);
+        stage.setScene(scene);
+        stage.show();
+        ParentShim.getChildren(g).addAll(rect1, rect2);
+        toolkit.fireTestPulse();
+
+        PickResultChooser res = new PickResultChooser();
+        NodeHelper.pickNode(g, new PickRay(50, 50, 1, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY), res);
+        assertSame(rect1, res.getIntersectedNode());
+        res = new PickResultChooser();
+        NodeHelper.pickNode(g, new PickRay(0, 0, 1, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY), res);
+        assertNull(res.getIntersectedNode());
+    }
+
+    @Test
+    public void testPickingChildNodeWithDirtyViewOrder() {
+        //JDK-8205092
+        Rectangle rect1 = new Rectangle();
+        rect1.setX(10);
+        rect1.setY(10);
+        rect1.setWidth(100);
+        rect1.setHeight(100);
+        rect1.setViewOrder(-1);
+
+        Rectangle rect2 = new Rectangle();
+        rect2.setX(10);
+        rect2.setY(10);
+        rect2.setWidth(100);
+        rect2.setHeight(100);
+        Group g = new Group();
+
+        // needed since picking doesn't work unless rooted in a scene and visible
+        Scene scene = new Scene(g);
+        stage.setScene(scene);
+        stage.show();
+        ParentShim.getChildren(g).addAll(rect1, rect2);
+        toolkit.fireTestPulse();
+
+        ParentShim.getChildren(g).remove(rect1);
+
+        PickResultChooser res = new PickResultChooser();
+        NodeHelper.pickNode(g, new PickRay(50, 50, 1, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY), res);
+        assertSame(rect2, res.getIntersectedNode());
+        res = new PickResultChooser();
+        NodeHelper.pickNode(g, new PickRay(0, 0, 1, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY), res);
+        assertNull(res.getIntersectedNode());
+    }
+
     public static class MockParent extends Parent {
         public MockParent(Node... children) {
             ParentShim.getChildren(this).addAll(children);