1 /*
   2  * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package test.javafx.scene.input;
  27 
  28 import com.sun.javafx.scene.SceneHelper;
  29 import test.com.sun.javafx.pgstub.StubScene;
  30 import java.util.ArrayList;
  31 import java.util.Arrays;
  32 import java.util.Random;
  33 import javafx.event.Event;
  34 import javafx.scene.Group;
  35 import javafx.scene.Scene;
  36 import javafx.scene.shape.Rectangle;
  37 import javafx.stage.Stage;
  38 import javafx.event.EventHandler;
  39 import javafx.geometry.Point3D;
  40 import javafx.scene.ParentShim;
  41 import javafx.scene.input.PickResult;
  42 import javafx.scene.input.TouchEvent;
  43 import javafx.scene.input.TouchPoint;
  44 import org.junit.Assert;
  45 import org.junit.Ignore;
  46 import org.junit.Test;
  47 import static org.junit.Assert.*;
  48 
  49 public class TouchEventTest {
  50     private static final int SANE_BENCHMARK_CYCLES = 1000000;
  51     private static final int CRAZY_BENCHMARK_CYCLES = 500000;
  52 
  53     private int touched;
  54 
  55     @Test public void testTouchPointConstructor() {
  56         Rectangle node = new Rectangle();
  57         node.setTranslateX(3);
  58         node.setTranslateY(2);
  59         node.setTranslateZ(50);
  60         PickResult pickRes = new PickResult(node, new Point3D(15, 25, 100), 33);
  61         TouchPoint tp = new TouchPoint(2, TouchPoint.State.STATIONARY,
  62                 10, 20, 30, 40, node, pickRes);
  63 
  64         assertEquals(2, tp.getId());
  65         assertSame(TouchPoint.State.STATIONARY, tp.getState());
  66         assertEquals(18, tp.getX(), 10e-20);
  67         assertEquals(27, tp.getY(), 10e-20);
  68         assertEquals(150, tp.getZ(), 10e-20);
  69         assertEquals(10, tp.getSceneX(), 10e-20);
  70         assertEquals(20, tp.getSceneY(), 10e-20);
  71         assertEquals(30, tp.getScreenX(), 10e-20);
  72         assertEquals(40, tp.getScreenY(), 10e-20);
  73         assertSame(node, tp.getTarget());
  74         assertSame(pickRes, tp.getPickResult());
  75     }
  76 
  77     @Test public void testTouchPointConstructorWithoutPickResult() {
  78         Rectangle node = new Rectangle();
  79         TouchPoint tp = new TouchPoint(2, TouchPoint.State.STATIONARY,
  80                 10, 20, 30, 40, node, null);
  81 
  82         assertEquals(10, tp.getX(), 10e-20);
  83         assertEquals(20, tp.getY(), 10e-20);
  84         assertEquals(0, tp.getZ(), 10e-20);
  85         assertEquals(10, tp.getSceneX(), 10e-20);
  86         assertEquals(20, tp.getSceneY(), 10e-20);
  87         assertEquals(30, tp.getScreenX(), 10e-20);
  88         assertEquals(40, tp.getScreenY(), 10e-20);
  89         assertNotNull(tp.getPickResult());
  90         assertNotNull(tp.getPickResult().getIntersectedPoint());
  91         assertEquals(10, tp.getPickResult().getIntersectedPoint().getX(), 10e-20);
  92         assertEquals(20, tp.getPickResult().getIntersectedPoint().getY(), 10e-20);
  93         assertEquals(0, tp.getPickResult().getIntersectedPoint().getZ(), 10e-20);
  94     }
  95 
  96     @Test public void testShortConstructor() {
  97         Rectangle node = new Rectangle();
  98         node.setTranslateX(3);
  99         node.setTranslateY(2);
 100         node.setTranslateZ(50);
 101 
 102         PickResult pickRes1 = new PickResult(node, new Point3D(15, 25, 100), 33);
 103         PickResult pickRes2 = new PickResult(node, new Point3D(16, 26, 101), 33);
 104         TouchPoint tp1 = new TouchPoint(2, TouchPoint.State.STATIONARY, 10, 20, 30, 40, node, pickRes1);
 105         TouchPoint tp2 = new TouchPoint(3, TouchPoint.State.PRESSED, 11, 21, 31, 41, node, pickRes2);
 106 
 107         TouchEvent e = new TouchEvent(
 108                 TouchEvent.TOUCH_PRESSED, tp2,
 109                 new ArrayList<>(Arrays.asList(tp1, tp2)), 158,
 110                 false, true, false, true);
 111 
 112         assertSame(TouchEvent.TOUCH_PRESSED, e.getEventType());
 113         assertSame(tp2, e.getTouchPoint());
 114         assertEquals(2, e.getTouchPoints().size());
 115         assertSame(tp1, e.getTouchPoints().get(0));
 116         assertSame(tp2, e.getTouchPoints().get(1));
 117         assertEquals(158, e.getEventSetId());
 118         assertFalse(e.isShiftDown());
 119         assertTrue(e.isControlDown());
 120         assertFalse(e.isAltDown());
 121         assertTrue(e.isMetaDown());
 122         assertSame(Event.NULL_SOURCE_TARGET, e.getSource());
 123         assertSame(Event.NULL_SOURCE_TARGET, e.getTarget());
 124         assertFalse(e.isConsumed());
 125 
 126         e = new TouchEvent(
 127                 TouchEvent.TOUCH_PRESSED, tp2,
 128                 new ArrayList<>(Arrays.asList(tp1, tp2)), 158,
 129                 true, false, true, false);
 130         assertTrue(e.isShiftDown());
 131         assertFalse(e.isControlDown());
 132         assertTrue(e.isAltDown());
 133         assertFalse(e.isMetaDown());
 134     }
 135 
 136     @Test public void testLongConstructor() {
 137         Rectangle node = new Rectangle(10, 10);
 138         node.setTranslateX(3);
 139         node.setTranslateY(2);
 140         node.setTranslateZ(50);
 141         Rectangle n1 = new Rectangle(10, 10);
 142         Rectangle n2 = new Rectangle(10, 10);
 143 
 144         PickResult pickRes1 = new PickResult(node, new Point3D(15, 25, 100), 33);
 145         PickResult pickRes2 = new PickResult(node, new Point3D(16, 26, 101), 33);
 146         TouchPoint tp1 = new TouchPoint(2, TouchPoint.State.STATIONARY, 10, 20, 30, 40, node, pickRes1);
 147         TouchPoint tp2 = new TouchPoint(3, TouchPoint.State.PRESSED, 11, 21, 31, 41, node, pickRes2);
 148 
 149         TouchEvent e = new TouchEvent(n1, n2,
 150                 TouchEvent.TOUCH_PRESSED, tp2,
 151                 new ArrayList<>(Arrays.asList(tp1, tp2)), 158,
 152                 false, true, false, true);
 153 
 154         assertSame(n1, e.getSource());
 155         assertSame(n2, e.getTarget());
 156         assertSame(TouchEvent.TOUCH_PRESSED, e.getEventType());
 157         assertSame(tp2, e.getTouchPoint());
 158         assertEquals(2, e.getTouchPoints().size());
 159         assertSame(tp1, e.getTouchPoints().get(0));
 160         assertSame(tp2, e.getTouchPoints().get(1));
 161         assertEquals(158, e.getEventSetId());
 162         assertFalse(e.isShiftDown());
 163         assertTrue(e.isControlDown());
 164         assertFalse(e.isAltDown());
 165         assertTrue(e.isMetaDown());
 166         assertFalse(e.isConsumed());
 167 
 168         e = new TouchEvent(n1, n2,
 169                 TouchEvent.TOUCH_PRESSED, tp2,
 170                 new ArrayList<>(Arrays.asList(tp1, tp2)), 158,
 171                 true, false, true, false);
 172         assertTrue(e.isShiftDown());
 173         assertFalse(e.isControlDown());
 174         assertTrue(e.isAltDown());
 175         assertFalse(e.isMetaDown());
 176     }
 177 
 178     @Test
 179     public void shouldPassModifiers() {
 180         Scene scene = createScene();
 181         Rectangle rect =
 182                 (Rectangle) scene.getRoot().getChildrenUnmodifiable().get(0);
 183 
 184         touched = 0;
 185         rect.addEventHandler(TouchEvent.ANY, event -> {
 186             touched++;
 187             switch(touched) {
 188                 case 1:
 189                     Assert.assertEquals(true, event.isShiftDown());
 190                     Assert.assertEquals(false, event.isControlDown());
 191                     Assert.assertEquals(true, event.isAltDown());
 192                     Assert.assertEquals(false, event.isMetaDown());
 193                     break;
 194                 case 2:
 195                     Assert.assertEquals(false, event.isShiftDown());
 196                     Assert.assertEquals(true, event.isControlDown());
 197                     Assert.assertEquals(false, event.isAltDown());
 198                     Assert.assertEquals(true, event.isMetaDown());
 199                     break;
 200                 case 3:
 201                     Assert.assertEquals(false, event.isShiftDown());
 202                     Assert.assertEquals(true, event.isControlDown());
 203                     Assert.assertEquals(true, event.isAltDown());
 204                     Assert.assertEquals(false, event.isMetaDown());
 205                     break;
 206                 default:
 207                     fail("Wrong touch point id " + event.getTouchPoint().getId());
 208             }
 209         });
 210 
 211         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventBegin(
 212                 System.currentTimeMillis(), 1, true, true, false, true, false);
 213         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
 214                 TouchPoint.State.PRESSED, 1, 110, 110, 110, 110);
 215         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventEnd();
 216 
 217         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventBegin(
 218                 System.currentTimeMillis(), 1, true, false, true, false, true);
 219         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
 220                 TouchPoint.State.STATIONARY, 1, 110, 110, 110, 110);
 221         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventEnd();
 222 
 223         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventBegin(
 224                 System.currentTimeMillis(), 1, true, false, true, true, false);
 225         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
 226                 TouchPoint.State.RELEASED, 1, 110, 110, 110, 110);
 227         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventEnd();
 228 
 229         assertEquals(3, touched);
 230     }
 231 
 232     @Test
 233     public void shouldCountTouchesCorrectly() {
 234         Scene scene = createScene();
 235         Rectangle rect =
 236                 (Rectangle) scene.getRoot().getChildrenUnmodifiable().get(0);
 237 
 238         touched = 0;
 239         rect.addEventHandler(TouchEvent.ANY, event -> {
 240             touched++;
 241             switch(touched) {
 242                 case 1:
 243                     Assert.assertEquals(1, event.getTouchCount());
 244                     Assert.assertEquals(1, event.getTouchPoints().size());
 245                     break;
 246                 case 2:
 247                 case 3:
 248                     Assert.assertEquals(2, event.getTouchCount());
 249                     Assert.assertEquals(2, event.getTouchPoints().size());
 250                     break;
 251                 case 4:
 252                 case 5:
 253                     Assert.assertEquals(2, event.getTouchCount());
 254                     Assert.assertEquals(2, event.getTouchPoints().size());
 255                     break;
 256                 case 6:
 257                     Assert.assertEquals(1, event.getTouchCount());
 258                     Assert.assertEquals(1, event.getTouchPoints().size());
 259                     break;
 260                 default:
 261                     fail("Wrong touch point id " + event.getTouchPoint().getId());
 262             }
 263         });
 264 
 265         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventBegin(
 266                 System.currentTimeMillis(), 1, true, true, false, true, false);
 267         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
 268                 TouchPoint.State.PRESSED, 1, 110, 110, 110, 110);
 269         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventEnd();
 270 
 271         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventBegin(
 272                 System.currentTimeMillis(), 2, true, false, true, false, true);
 273         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
 274                 TouchPoint.State.STATIONARY, 1, 110, 110, 110, 110);
 275         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
 276                 TouchPoint.State.PRESSED, 2, 120, 120, 110, 110);
 277         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventEnd();
 278 
 279         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventBegin(
 280                 System.currentTimeMillis(), 2, true, false, true, true, false);
 281         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
 282                 TouchPoint.State.STATIONARY, 1, 110, 110, 110, 110);
 283         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
 284                 TouchPoint.State.RELEASED, 2, 120, 120, 110, 110);
 285         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventEnd();
 286 
 287         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventBegin(
 288                 System.currentTimeMillis(), 1, true, false, true, true, false);
 289         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
 290                 TouchPoint.State.RELEASED, 1, 110, 110, 110, 110);
 291         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventEnd();
 292 
 293         assertEquals(6, touched);
 294     }
 295 
 296     @Test
 297     public void shouldGenerateCorrectEventSetIDs() {
 298         Scene scene = createScene();
 299         Rectangle rect =
 300                 (Rectangle) scene.getRoot().getChildrenUnmodifiable().get(0);
 301 
 302         touched = 0;
 303         rect.addEventHandler(TouchEvent.ANY, event -> {
 304             touched++;
 305             switch(touched) {
 306                 case 1:
 307                     Assert.assertEquals(1, event.getEventSetId());
 308                     break;
 309                 case 2:
 310                 case 3:
 311                     Assert.assertEquals(2, event.getEventSetId());
 312                     break;
 313                 case 4:
 314                 case 5:
 315                     Assert.assertEquals(3, event.getEventSetId());
 316                     break;
 317                 case 6:
 318                     Assert.assertEquals(4, event.getEventSetId());
 319                     break;
 320                 default:
 321                     fail("Wrong touch point id " + event.getTouchPoint().getId());
 322             }
 323         });
 324 
 325         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventBegin(
 326                 System.currentTimeMillis(), 1, true, true, false, true, false);
 327         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
 328                 TouchPoint.State.PRESSED, 1, 110, 110, 110, 110);
 329         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventEnd();
 330 
 331         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventBegin(
 332                 System.currentTimeMillis(), 2, true, false, true, false, true);
 333         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
 334                 TouchPoint.State.STATIONARY, 1, 110, 110, 110, 110);
 335         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
 336                 TouchPoint.State.PRESSED, 2, 120, 120, 110, 110);
 337         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventEnd();
 338 
 339         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventBegin(
 340                 System.currentTimeMillis(), 2, true, false, true, true, false);
 341         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
 342                 TouchPoint.State.STATIONARY, 1, 110, 110, 110, 110);
 343         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
 344                 TouchPoint.State.RELEASED, 2, 120, 120, 110, 110);
 345         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventEnd();
 346 
 347         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventBegin(
 348                 System.currentTimeMillis(), 1, true, false, true, true, false);
 349         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
 350                 TouchPoint.State.RELEASED, 1, 110, 110, 110, 110);
 351         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventEnd();
 352 
 353         assertEquals(6, touched);
 354     }
 355 
 356     @Test
 357     public void shouldReIDTouchPoints() {
 358         Scene scene = createScene();
 359         Rectangle rect =
 360                 (Rectangle) scene.getRoot().getChildrenUnmodifiable().get(0);
 361 
 362         touched = 0;
 363         rect.setOnTouchPressed(event -> {
 364             touched++;
 365             switch(event.getTouchPoint().getId()) {
 366                 case 1:
 367                     Assert.assertEquals(110.0, event.getTouchPoint().getX(), 0.0001);
 368                     Assert.assertEquals(110.0, event.getTouchPoint().getY(), 0.0001);
 369                     assertEquals(1, touched);
 370                     break;
 371                 case 2:
 372                     Assert.assertEquals(120.0, event.getTouchPoint().getX(), 0.0001);
 373                     Assert.assertEquals(120.0, event.getTouchPoint().getY(), 0.0001);
 374                     assertEquals(2, touched);
 375                     break;
 376                 case 3:
 377                     Assert.assertEquals(130.0, event.getTouchPoint().getX(), 0.0001);
 378                     Assert.assertEquals(130.0, event.getTouchPoint().getY(), 0.0001);
 379                     assertEquals(3, touched);
 380                     break;
 381                 default:
 382                     fail("Wrong touch point id " + event.getTouchPoint().getId());
 383             }
 384         });
 385 
 386         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventBegin(
 387                 System.currentTimeMillis(), 3, true, false, false, false, false);
 388         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
 389                 TouchPoint.State.PRESSED, 1368, 110, 110, 110, 110);
 390         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
 391                 TouchPoint.State.PRESSED, 1, 120, 120, 120, 120);
 392         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
 393                 TouchPoint.State.PRESSED, 152, 130, 130, 130, 130);
 394         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventEnd();
 395 
 396         assertEquals(3, touched);
 397     }
 398 
 399     @Test
 400     public void shouldNotReuseTouchPointID() {
 401         Scene scene = createScene();
 402         Rectangle rect =
 403                 (Rectangle) scene.getRoot().getChildrenUnmodifiable().get(0);
 404 
 405         touched = 0;
 406         rect.setOnTouchPressed(event -> {
 407             touched++;
 408             switch(event.getTouchPoint().getId()) {
 409                 case 1:
 410                     Assert.assertEquals(110.0, event.getTouchPoint().getX(), 0.0001);
 411                     Assert.assertEquals(110.0, event.getTouchPoint().getY(), 0.0001);
 412                     assertEquals(1, touched);
 413                     break;
 414                 case 2:
 415                     Assert.assertEquals(120.0, event.getTouchPoint().getX(), 0.0001);
 416                     Assert.assertEquals(120.0, event.getTouchPoint().getY(), 0.0001);
 417                     assertEquals(2, touched);
 418                     break;
 419                 case 3:
 420                     Assert.assertEquals(130.0, event.getTouchPoint().getX(), 0.0001);
 421                     Assert.assertEquals(130.0, event.getTouchPoint().getY(), 0.0001);
 422                     assertEquals(3, touched);
 423                     break;
 424                 default:
 425                     fail("Wrong touch point id " + event.getTouchPoint().getId());
 426             }
 427         });
 428 
 429         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventBegin(
 430                 System.currentTimeMillis(), 2, true, false, false, false, false);
 431         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
 432                 TouchPoint.State.PRESSED, 1368, 110, 110, 110, 110);
 433         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
 434                 TouchPoint.State.PRESSED, 1, 120, 120, 120, 120);
 435         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventEnd();
 436 
 437         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventBegin(
 438                 System.currentTimeMillis(), 2, true, false, false, false, false);
 439         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
 440                 TouchPoint.State.STATIONARY, 1368, 110, 110, 110, 110);
 441         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
 442                 TouchPoint.State.RELEASED, 1, 120, 120, 120, 120);
 443         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventEnd();
 444 
 445         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventBegin(
 446                 System.currentTimeMillis(), 2, true, false, false, false, false);
 447         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
 448                 TouchPoint.State.STATIONARY, 1368, 110, 110, 110, 110);
 449         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
 450                 TouchPoint.State.PRESSED, 1, 130, 130, 130, 130);
 451         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventEnd();
 452 
 453         assertEquals(3, touched);
 454     }
 455 
 456     @Test
 457     public void shouldMaintainPressOrder() {
 458         Scene scene = createScene();
 459         Rectangle rect =
 460                 (Rectangle) scene.getRoot().getChildrenUnmodifiable().get(0);
 461 
 462         touched = 0;
 463         rect.setOnTouchPressed(event -> {
 464             touched++;
 465             switch(event.getTouchPoint().getId()) {
 466                 case 1:
 467                     Assert.assertEquals(110.0, event.getTouchPoint().getX(), 0.0001);
 468                     Assert.assertEquals(110.0, event.getTouchPoint().getY(), 0.0001);
 469                     Assert.assertEquals(1, event.getTouchPoints().get(0).getId());
 470                     Assert.assertEquals(2, event.getTouchPoints().get(1).getId());
 471                     assertEquals(1, touched);
 472                     break;
 473                 case 2:
 474                     Assert.assertEquals(120.0, event.getTouchPoint().getX(), 0.0001);
 475                     Assert.assertEquals(120.0, event.getTouchPoint().getY(), 0.0001);
 476                     Assert.assertEquals(1, event.getTouchPoints().get(0).getId());
 477                     Assert.assertEquals(2, event.getTouchPoints().get(1).getId());
 478                     assertEquals(2, touched);
 479                     break;
 480                 case 3:
 481                     Assert.assertEquals(130.0, event.getTouchPoint().getX(), 0.0001);
 482                     Assert.assertEquals(130.0, event.getTouchPoint().getY(), 0.0001);
 483                     Assert.assertEquals(1, event.getTouchPoints().get(0).getId());
 484                     Assert.assertEquals(3, event.getTouchPoints().get(1).getId());
 485                     assertEquals(3, touched);
 486                     break;
 487                 default:
 488                     fail("Wrong touch point id " + event.getTouchPoint().getId());
 489             }
 490         });
 491 
 492         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventBegin(
 493                 System.currentTimeMillis(), 2, true, false, false, false, false);
 494         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
 495                 TouchPoint.State.PRESSED, 1368, 110, 110, 110, 110);
 496         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
 497                 TouchPoint.State.PRESSED, 1, 120, 120, 120, 120);
 498         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventEnd();
 499 
 500         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventBegin(
 501                 System.currentTimeMillis(), 2, true, false, false, false, false);
 502         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
 503                 TouchPoint.State.RELEASED, 1, 120, 120, 120, 120);
 504         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
 505                 TouchPoint.State.STATIONARY, 1368, 110, 110, 110, 110);
 506         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventEnd();
 507 
 508         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventBegin(
 509                 System.currentTimeMillis(), 2, true, false, false, false, false);
 510         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
 511                 TouchPoint.State.PRESSED, 1, 130, 130, 130, 130);
 512         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
 513                 TouchPoint.State.STATIONARY, 1368, 110, 110, 110, 110);
 514         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventEnd();
 515 
 516         assertEquals(3, touched);
 517     }
 518 
 519     @Test
 520     public void shouldMaintainIDMapping() {
 521         Scene scene = createScene();
 522         Rectangle rect =
 523                 (Rectangle) scene.getRoot().getChildrenUnmodifiable().get(0);
 524 
 525         touched = 0;
 526         rect.setOnTouchPressed(event -> {
 527             touched++;
 528             switch(event.getTouchPoint().getId()) {
 529                 case 1:
 530                     Assert.assertEquals(110.0, event.getTouchPoint().getX(), 0.0001);
 531                     Assert.assertEquals(110.0, event.getTouchPoint().getY(), 0.0001);
 532                     Assert.assertEquals(1, event.getTouchPoints().get(0).getId());
 533                     Assert.assertEquals(2, event.getTouchPoints().get(1).getId());
 534                     assertEquals(1, touched);
 535                     break;
 536                 case 2:
 537                     Assert.assertEquals(120.0, event.getTouchPoint().getX(), 0.0001);
 538                     Assert.assertEquals(120.0, event.getTouchPoint().getY(), 0.0001);
 539                     Assert.assertEquals(1, event.getTouchPoints().get(0).getId());
 540                     Assert.assertEquals(2, event.getTouchPoints().get(1).getId());
 541                     assertEquals(2, touched);
 542                     break;
 543                 default:
 544                     fail("Wrong touch point id " + event.getTouchPoint().getId());
 545             }
 546         });
 547 
 548         rect.setOnTouchMoved(event -> {
 549             touched++;
 550             switch(event.getTouchPoint().getId()) {
 551                 case 1:
 552                     Assert.assertEquals(120.0, event.getTouchPoint().getX(), 0.0001);
 553                     Assert.assertEquals(120.0, event.getTouchPoint().getY(), 0.0001);
 554                     Assert.assertEquals(1, event.getTouchPoints().get(0).getId());
 555                     Assert.assertEquals(2, event.getTouchPoints().get(1).getId());
 556                     assertEquals(3, touched);
 557                     break;
 558                 case 2:
 559                     Assert.assertEquals(110.0, event.getTouchPoint().getX(), 0.0001);
 560                     Assert.assertEquals(110.0, event.getTouchPoint().getY(), 0.0001);
 561                     Assert.assertEquals(1, event.getTouchPoints().get(0).getId());
 562                     Assert.assertEquals(2, event.getTouchPoints().get(1).getId());
 563                     assertEquals(4, touched);
 564                     break;
 565                 default:
 566                     fail("Wrong touch point id " + event.getTouchPoint().getId());
 567             }
 568         });
 569 
 570         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventBegin(
 571                 System.currentTimeMillis(), 2, true, false, false, false, false);
 572         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
 573                 TouchPoint.State.PRESSED, 1368, 110, 110, 110, 110);
 574         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
 575                 TouchPoint.State.PRESSED, 127, 120, 120, 120, 120);
 576         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventEnd();
 577 
 578         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventBegin(
 579                 System.currentTimeMillis(), 2, true, false, false, false, false);
 580         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
 581                 TouchPoint.State.MOVED, 127, 110, 110, 110, 110);
 582         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
 583                 TouchPoint.State.MOVED, 1368, 120, 120, 120, 120);
 584         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventEnd();
 585 
 586         assertEquals(4, touched);
 587     }
 588 
 589     @Test
 590     public void shouldMaintainIDMappingInDynamicConditions() {
 591         Scene scene = createScene();
 592         Rectangle rect =
 593                 (Rectangle) scene.getRoot().getChildrenUnmodifiable().get(0);
 594 
 595         touched = 0;
 596         rect.setOnTouchPressed(event -> {
 597             touched++;
 598             switch(event.getTouchPoint().getId()) {
 599                 case 1:
 600                     Assert.assertEquals(110.0, event.getTouchPoint().getX(), 0.0001);
 601                     Assert.assertEquals(110.0, event.getTouchPoint().getY(), 0.0001);
 602                     Assert.assertEquals(1, event.getTouchPoints().get(0).getId());
 603                     Assert.assertEquals(2, event.getTouchPoints().get(1).getId());
 604                     assertEquals(1, touched);
 605                     break;
 606                 case 2:
 607                     Assert.assertEquals(120.0, event.getTouchPoint().getX(), 0.0001);
 608                     Assert.assertEquals(120.0, event.getTouchPoint().getY(), 0.0001);
 609                     Assert.assertEquals(1, event.getTouchPoints().get(0).getId());
 610                     Assert.assertEquals(2, event.getTouchPoints().get(1).getId());
 611                     assertEquals(2, touched);
 612                     break;
 613                 case 3:
 614                     Assert.assertEquals(160.0, event.getTouchPoint().getX(), 0.0001);
 615                     Assert.assertEquals(160.0, event.getTouchPoint().getY(), 0.0001);
 616                     Assert.assertEquals(2, event.getTouchPoints().get(0).getId());
 617                     Assert.assertEquals(3, event.getTouchPoints().get(1).getId());
 618                     assertEquals(3, touched);
 619                     break;
 620                 default:
 621                     fail("Wrong touch point id " + event.getTouchPoint().getId());
 622             }
 623         });
 624 
 625         rect.setOnTouchMoved(event -> {
 626             touched++;
 627             switch(event.getTouchPoint().getId()) {
 628                 case 2:
 629                     Assert.assertEquals(120.0, event.getTouchPoint().getX(), 0.0001);
 630                     Assert.assertEquals(120.0, event.getTouchPoint().getY(), 0.0001);
 631                     Assert.assertEquals(2, event.getTouchPoints().get(0).getId());
 632                     Assert.assertEquals(3, event.getTouchPoints().get(1).getId());
 633                     assertEquals(4, touched);
 634                     break;
 635                 case 3:
 636                     Assert.assertEquals(160.0, event.getTouchPoint().getX(), 0.0001);
 637                     Assert.assertEquals(160.0, event.getTouchPoint().getY(), 0.0001);
 638                     Assert.assertEquals(2, event.getTouchPoints().get(0).getId());
 639                     Assert.assertEquals(3, event.getTouchPoints().get(1).getId());
 640                     assertEquals(5, touched);
 641                     break;
 642                 default:
 643                     fail("Wrong touch point id " + event.getTouchPoint().getId());
 644             }
 645         });
 646 
 647         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventBegin(
 648                 System.currentTimeMillis(), 2, true, false, false, false, false);
 649         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
 650                 TouchPoint.State.PRESSED, 1368, 110, 110, 110, 110);
 651         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
 652                 TouchPoint.State.PRESSED, 127, 120, 120, 120, 120);
 653         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventEnd();
 654 
 655         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventBegin(
 656                 System.currentTimeMillis(), 2, true, false, false, false, false);
 657         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
 658                 TouchPoint.State.STATIONARY, 127, 120, 120, 120, 120);
 659         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
 660                 TouchPoint.State.RELEASED, 1368, 120, 120, 120, 120);
 661         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventEnd();
 662 
 663         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventBegin(
 664                 System.currentTimeMillis(), 2, true, false, false, false, false);
 665         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
 666                 TouchPoint.State.PRESSED, 11, 160, 160, 160, 160);
 667         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
 668                 TouchPoint.State.STATIONARY, 127, 120, 120, 120, 120);
 669         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventEnd();
 670 
 671         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventBegin(
 672                 System.currentTimeMillis(), 2, true, false, false, false, false);
 673         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
 674                 TouchPoint.State.MOVED, 11, 160, 160, 160, 160);
 675         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
 676                 TouchPoint.State.MOVED, 127, 120, 120, 120, 120);
 677         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventEnd();
 678 
 679         assertEquals(5, touched);
 680     }
 681 
 682     @Test
 683     public void shouldResetIDsAfterGesture() {
 684         Scene scene = createScene();
 685         Rectangle rect =
 686                 (Rectangle) scene.getRoot().getChildrenUnmodifiable().get(0);
 687 
 688         touched = 0;
 689         rect.addEventHandler(TouchEvent.ANY, event -> {
 690             touched++;
 691             switch(touched) {
 692                 case 1:
 693                 case 2:
 694                     Assert.assertEquals(1, event.getEventSetId());
 695                     Assert.assertEquals(touched, event.getTouchPoint().getId());
 696                     break;
 697                 case 3:
 698                 case 4:
 699                     Assert.assertEquals(2, event.getEventSetId());
 700                     Assert.assertEquals(touched - 2, event.getTouchPoint().getId());
 701                     break;
 702                 case 5:
 703                 case 6:
 704                     Assert.assertEquals(1, event.getEventSetId());
 705                     Assert.assertEquals(touched - 4, event.getTouchPoint().getId());
 706                     break;
 707                 case 7:
 708                 case 8:
 709                     Assert.assertEquals(2, event.getEventSetId());
 710                     Assert.assertEquals(touched - 6, event.getTouchPoint().getId());
 711                     break;
 712                 default:
 713                     fail("Wrong touch point id " + event.getTouchPoint().getId());
 714             }
 715         });
 716 
 717         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventBegin(
 718                 System.currentTimeMillis(), 2, true, true, false, true, false);
 719         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
 720                 TouchPoint.State.PRESSED, 1, 110, 110, 110, 110);
 721         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
 722                 TouchPoint.State.PRESSED, 2, 120, 120, 110, 110);
 723         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventEnd();
 724 
 725         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventBegin(
 726                 System.currentTimeMillis(), 2, true, false, true, true, false);
 727         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
 728                 TouchPoint.State.RELEASED, 1, 110, 110, 110, 110);
 729         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
 730                 TouchPoint.State.RELEASED, 2, 120, 120, 110, 110);
 731         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventEnd();
 732 
 733         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventBegin(
 734                 System.currentTimeMillis(), 2, true, true, false, true, false);
 735         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
 736                 TouchPoint.State.PRESSED, 1, 110, 110, 110, 110);
 737         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
 738                 TouchPoint.State.PRESSED, 2, 120, 120, 110, 110);
 739         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventEnd();
 740 
 741         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventBegin(
 742                 System.currentTimeMillis(), 2, true, false, true, true, false);
 743         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
 744                 TouchPoint.State.RELEASED, 1, 110, 110, 110, 110);
 745         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
 746                 TouchPoint.State.RELEASED, 2, 120, 120, 110, 110);
 747         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventEnd();
 748 
 749 
 750         assertEquals(8, touched);
 751     }
 752 
 753     @Test
 754     public void touchPointsShouldContainTouchPoint() {
 755         Scene scene = createScene();
 756         Rectangle rect =
 757                 (Rectangle) scene.getRoot().getChildrenUnmodifiable().get(0);
 758 
 759         touched = 0;
 760         rect.addEventHandler(TouchEvent.ANY, event -> {
 761             touched++;
 762             switch(touched) {
 763                 case 1:
 764                 case 3:
 765                     assertSame(event.getTouchPoint(), event.getTouchPoints().get(0));
 766                     break;
 767                 case 2:
 768                 case 4:
 769                     assertSame(event.getTouchPoint(), event.getTouchPoints().get(1));
 770                     break;
 771                 default:
 772                     fail("Wrong touch point id " + event.getTouchPoint().getId());
 773             }
 774         });
 775 
 776         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventBegin(
 777                 System.currentTimeMillis(), 2, true, true, false, true, false);
 778         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
 779                 TouchPoint.State.PRESSED, 1, 110, 110, 110, 110);
 780         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
 781                 TouchPoint.State.PRESSED, 2, 120, 120, 110, 110);
 782         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventEnd();
 783 
 784         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventBegin(
 785                 System.currentTimeMillis(), 2, true, true, false, true, false);
 786         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
 787                 TouchPoint.State.RELEASED, 1, 110, 110, 110, 110);
 788         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
 789                 TouchPoint.State.RELEASED, 2, 120, 120, 110, 110);
 790         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventEnd();
 791 
 792         assertEquals(4, touched);
 793     }
 794 
 795     @Test
 796     public void touchPointsShouldHaveCorrectTarget() {
 797         Scene scene = createScene();
 798 
 799         final Rectangle rect1 =
 800                 (Rectangle) scene.getRoot().getChildrenUnmodifiable().get(0);
 801 
 802         final Rectangle rect2 =
 803                 (Rectangle) scene.getRoot().getChildrenUnmodifiable().get(1);
 804 
 805         touched = 0;
 806         rect1.addEventHandler(TouchEvent.ANY, event -> {
 807             touched++;
 808             assertSame(rect1, event.getTouchPoint().getTarget());
 809             assertSame(rect2, event.getTouchPoints().get(1).getTarget());
 810         });
 811         rect2.addEventHandler(TouchEvent.ANY, event -> {
 812             touched++;
 813             assertSame(rect2, event.getTouchPoint().getTarget());
 814             assertSame(rect1, event.getTouchPoints().get(0).getTarget());
 815         });
 816 
 817         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventBegin(
 818                 System.currentTimeMillis(), 2, true, true, false, true, false);
 819         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
 820                 TouchPoint.State.PRESSED, 1, 110, 110, 110, 110);
 821         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
 822                 TouchPoint.State.PRESSED, 2, 220, 220, 220, 220);
 823         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventEnd();
 824 
 825         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventBegin(
 826                 System.currentTimeMillis(), 2, true, true, false, true, false);
 827         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
 828                 TouchPoint.State.RELEASED, 1, 110, 110, 110, 110);
 829         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
 830                 TouchPoint.State.RELEASED, 2, 220, 220, 220, 220);
 831         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventEnd();
 832 
 833         assertEquals(4, touched);
 834     }
 835 
 836     @Test
 837     public void shouldCompute3dCoordinates() {
 838         Scene scene = createScene();
 839         Rectangle rect =
 840                 (Rectangle) scene.getRoot().getChildrenUnmodifiable().get(0);
 841         rect.setTranslateZ(50);
 842 
 843         touched = 0;
 844         rect.addEventHandler(TouchEvent.ANY, event -> {
 845             touched++;
 846             Assert.assertEquals(110, event.getTouchPoint().getX(), 0.00001);
 847             Assert.assertEquals(110, event.getTouchPoint().getY(), 0.00001);
 848             Assert.assertEquals(0, event.getTouchPoint().getZ(), 0.00001);
 849         });
 850 
 851         scene.addEventHandler(TouchEvent.ANY, event -> {
 852             touched++;
 853             Assert.assertEquals(110, event.getTouchPoint().getX(), 0.00001);
 854             Assert.assertEquals(110, event.getTouchPoint().getY(), 0.00001);
 855             Assert.assertEquals(50, event.getTouchPoint().getZ(), 0.00001);
 856         });
 857 
 858         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventBegin(
 859                 System.currentTimeMillis(), 1, true, true, false, true, false);
 860         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
 861                 TouchPoint.State.PRESSED, 1, 110, 110, 110, 110);
 862         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventEnd();
 863 
 864         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventBegin(
 865                 System.currentTimeMillis(), 1, true, false, true, false, true);
 866         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
 867                 TouchPoint.State.STATIONARY, 1, 110, 110, 110, 110);
 868         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventEnd();
 869 
 870         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventBegin(
 871                 System.currentTimeMillis(), 1, true, false, true, true, false);
 872         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
 873                 TouchPoint.State.RELEASED, 1, 110, 110, 110, 110);
 874         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventEnd();
 875 
 876         assertEquals(6, touched);
 877     }
 878 
 879     @Test
 880     public void touchPointsShouldHaveCorrectPickResult() {
 881         Scene scene = createScene();
 882 
 883         final Rectangle rect1 =
 884                 (Rectangle) scene.getRoot().getChildrenUnmodifiable().get(0);
 885 
 886         final Rectangle rect2 =
 887                 (Rectangle) scene.getRoot().getChildrenUnmodifiable().get(1);
 888 
 889         touched = 0;
 890         rect1.addEventHandler(TouchEvent.ANY, event -> {
 891             touched++;
 892             assertSame(rect1, event.getTouchPoint().getTarget());
 893             assertSame(rect2, event.getTouchPoints().get(1).getTarget());
 894             PickResult res1 = event.getTouchPoint().getPickResult();
 895             PickResult res2 = event.getTouchPoints().get(1).getPickResult();
 896             switch(touched) {
 897                 case 1:
 898                     assertNotNull(res1);
 899                     assertSame(rect1, res1.getIntersectedNode());
 900                     assertEquals(110, res1.getIntersectedPoint().getX(), 0.00001);
 901                     assertEquals(110, res1.getIntersectedPoint().getY(), 0.00001);
 902                     assertEquals(0, res1.getIntersectedPoint().getZ(), 0.00001);
 903 
 904                     assertNotNull(res2);
 905                     assertSame(rect2, res2.getIntersectedNode());
 906                     assertEquals(220, res2.getIntersectedPoint().getX(), 0.00001);
 907                     assertEquals(220, res2.getIntersectedPoint().getY(), 0.00001);
 908                     assertEquals(0, res1.getIntersectedPoint().getZ(), 0.00001);
 909                     break;
 910                 case 3:
 911                     assertNotNull(res1);
 912                     assertSame(rect2, res1.getIntersectedNode());
 913                     assertEquals(220, res1.getIntersectedPoint().getX(), 0.00001);
 914                     assertEquals(220, res1.getIntersectedPoint().getY(), 0.00001);
 915                     assertEquals(0, res1.getIntersectedPoint().getZ(), 0.00001);
 916 
 917                     assertNotNull(res2);
 918                     assertSame(rect1, res2.getIntersectedNode());
 919                     assertEquals(110, res2.getIntersectedPoint().getX(), 0.00001);
 920                     assertEquals(110, res2.getIntersectedPoint().getY(), 0.00001);
 921                     assertEquals(0, res1.getIntersectedPoint().getZ(), 0.00001);
 922                     break;
 923                 default:
 924                     fail("Wrong event delivered");
 925             }
 926         });
 927         rect2.addEventHandler(TouchEvent.ANY, event -> {
 928             touched++;
 929             assertSame(rect2, event.getTouchPoint().getTarget());
 930             assertSame(rect1, event.getTouchPoints().get(0).getTarget());
 931             PickResult res2 = event.getTouchPoint().getPickResult();
 932             PickResult res1 = event.getTouchPoints().get(0).getPickResult();
 933             switch(touched) {
 934                 case 2:
 935                     assertNotNull(res1);
 936                     assertSame(rect1, res1.getIntersectedNode());
 937                     assertEquals(110, res1.getIntersectedPoint().getX(), 0.00001);
 938                     assertEquals(110, res1.getIntersectedPoint().getY(), 0.00001);
 939                     assertEquals(0, res1.getIntersectedPoint().getZ(), 0.00001);
 940 
 941                     assertNotNull(res2);
 942                     assertSame(rect2, res2.getIntersectedNode());
 943                     assertEquals(220, res2.getIntersectedPoint().getX(), 0.00001);
 944                     assertEquals(220, res2.getIntersectedPoint().getY(), 0.00001);
 945                     assertEquals(0, res1.getIntersectedPoint().getZ(), 0.00001);
 946                     break;
 947                 case 4:
 948                     assertNotNull(res1);
 949                     assertSame(rect2, res1.getIntersectedNode());
 950                     assertEquals(220, res1.getIntersectedPoint().getX(), 0.00001);
 951                     assertEquals(220, res1.getIntersectedPoint().getY(), 0.00001);
 952                     assertEquals(0, res1.getIntersectedPoint().getZ(), 0.00001);
 953 
 954                     assertNotNull(res2);
 955                     assertSame(rect1, res2.getIntersectedNode());
 956                     assertEquals(110, res2.getIntersectedPoint().getX(), 0.00001);
 957                     assertEquals(110, res2.getIntersectedPoint().getY(), 0.00001);
 958                     assertEquals(0, res1.getIntersectedPoint().getZ(), 0.00001);
 959                     break;
 960                 default:
 961                     fail("Wrong event delivered");
 962             }
 963         });
 964 
 965         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventBegin(
 966                 System.currentTimeMillis(), 2, true, true, false, true, false);
 967         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
 968                 TouchPoint.State.PRESSED, 1, 110, 110, 110, 110);
 969         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
 970                 TouchPoint.State.PRESSED, 2, 220, 220, 220, 220);
 971         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventEnd();
 972 
 973         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventBegin(
 974                 System.currentTimeMillis(), 2, true, true, false, true, false);
 975         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
 976                 TouchPoint.State.MOVED, 1, 220, 220, 220, 220);
 977         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
 978                 TouchPoint.State.MOVED, 2, 110, 110, 110, 110);
 979         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventEnd();
 980 
 981         assertEquals(4, touched);
 982     }
 983 
 984     @Test
 985     public void testTouchPointsBelongsTo() {
 986         final Scene scene = createScene();
 987 
 988         final Rectangle rect1 =
 989                 (Rectangle) scene.getRoot().getChildrenUnmodifiable().get(0);
 990 
 991         final Rectangle rect2 =
 992                 (Rectangle) scene.getRoot().getChildrenUnmodifiable().get(1);
 993 
 994         touched = 0;
 995         rect1.addEventHandler(TouchEvent.ANY, event -> {
 996             touched++;
 997             assertTrue(event.getTouchPoint().belongsTo(rect1));
 998             assertTrue(event.getTouchPoint().belongsTo(scene.getRoot()));
 999             assertTrue(event.getTouchPoint().belongsTo(scene));
1000             assertFalse(event.getTouchPoint().belongsTo(rect2));
1001 
1002             assertFalse(event.getTouchPoints().get(1).belongsTo(rect1));
1003             assertTrue(event.getTouchPoints().get(1).belongsTo(scene.getRoot()));
1004             assertTrue(event.getTouchPoints().get(1).belongsTo(scene));
1005             assertTrue(event.getTouchPoints().get(1).belongsTo(rect2));
1006         });
1007         rect2.addEventHandler(TouchEvent.ANY, event -> {
1008             touched++;
1009             assertTrue(event.getTouchPoint().belongsTo(rect2));
1010             assertTrue(event.getTouchPoint().belongsTo(scene.getRoot()));
1011             assertTrue(event.getTouchPoint().belongsTo(scene));
1012             assertFalse(event.getTouchPoint().belongsTo(rect1));
1013 
1014             assertFalse(event.getTouchPoints().get(0).belongsTo(rect2));
1015             assertTrue(event.getTouchPoints().get(0).belongsTo(scene.getRoot()));
1016             assertTrue(event.getTouchPoints().get(0).belongsTo(scene));
1017             assertTrue(event.getTouchPoints().get(0).belongsTo(rect1));
1018         });
1019 
1020         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventBegin(
1021                 System.currentTimeMillis(), 2, true, true, false, true, false);
1022         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
1023                 TouchPoint.State.PRESSED, 1, 110, 110, 110, 110);
1024         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
1025                 TouchPoint.State.PRESSED, 2, 220, 220, 220, 220);
1026         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventEnd();
1027 
1028         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventBegin(
1029                 System.currentTimeMillis(), 2, true, true, false, true, false);
1030         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
1031                 TouchPoint.State.RELEASED, 1, 110, 110, 110, 110);
1032         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
1033                 TouchPoint.State.RELEASED, 2, 220, 220, 220, 220);
1034         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventEnd();
1035 
1036         assertEquals(4, touched);
1037     }
1038 
1039     @Test
1040     public void shouldPickAndGrabTouchPoints() {
1041         Scene scene = createScene();
1042         final Rectangle rect1 =
1043                 (Rectangle) scene.getRoot().getChildrenUnmodifiable().get(0);
1044 
1045         final Rectangle rect2 =
1046                 (Rectangle) scene.getRoot().getChildrenUnmodifiable().get(1);
1047 
1048         touched = 0;
1049         rect1.addEventHandler(TouchEvent.ANY, event -> {
1050             touched++;
1051             switch(touched) {
1052                 case 1:
1053                     Assert.assertEquals(1, event.getTouchPoint().getId());
1054                     Assert.assertEquals(150.0, event.getTouchPoint().getX(), 0.0001);
1055                     Assert.assertEquals(155.0, event.getTouchPoint().getY(), 0.0001);
1056                     Assert.assertEquals(150.0, event.getTouchPoint().getSceneX(), 0.0001);
1057                     Assert.assertEquals(155.0, event.getTouchPoint().getSceneY(), 0.0001);
1058                     Assert.assertEquals(1150.0, event.getTouchPoint().getScreenX(), 0.0001);
1059                     Assert.assertEquals(1155.0, event.getTouchPoint().getScreenY(), 0.0001);
1060                     break;
1061                 case 3:
1062                     Assert.assertEquals(1, event.getTouchPoint().getId());
1063                     Assert.assertEquals(250.0, event.getTouchPoint().getX(), 0.0001);
1064                     Assert.assertEquals(255.0, event.getTouchPoint().getY(), 0.0001);
1065                     Assert.assertEquals(250.0, event.getTouchPoint().getSceneX(), 0.0001);
1066                     Assert.assertEquals(255.0, event.getTouchPoint().getSceneY(), 0.0001);
1067                     Assert.assertEquals(1250.0, event.getTouchPoint().getScreenX(), 0.0001);
1068                     Assert.assertEquals(1255.0, event.getTouchPoint().getScreenY(), 0.0001);
1069                     break;
1070                 default:
1071                     fail("Wrong touch point delivery");
1072             }
1073         });
1074 
1075         rect2.addEventHandler(TouchEvent.ANY, event -> {
1076             touched++;
1077             switch(touched) {
1078                 case 2:
1079                     Assert.assertEquals(2, event.getTouchPoint().getId());
1080                     Assert.assertEquals(260.0, event.getTouchPoint().getX(), 0.0001);
1081                     Assert.assertEquals(265.0, event.getTouchPoint().getY(), 0.0001);
1082                     Assert.assertEquals(260.0, event.getTouchPoint().getSceneX(), 0.0001);
1083                     Assert.assertEquals(265.0, event.getTouchPoint().getSceneY(), 0.0001);
1084                     Assert.assertEquals(1260.0, event.getTouchPoint().getScreenX(), 0.0001);
1085                     Assert.assertEquals(1265.0, event.getTouchPoint().getScreenY(), 0.0001);
1086                     break;
1087                 case 4:
1088                     Assert.assertEquals(2, event.getTouchPoint().getId());
1089                     Assert.assertEquals(160.0, event.getTouchPoint().getX(), 0.0001);
1090                     Assert.assertEquals(165.0, event.getTouchPoint().getY(), 0.0001);
1091                     Assert.assertEquals(160.0, event.getTouchPoint().getSceneX(), 0.0001);
1092                     Assert.assertEquals(165.0, event.getTouchPoint().getSceneY(), 0.0001);
1093                     Assert.assertEquals(1160.0, event.getTouchPoint().getScreenX(), 0.0001);
1094                     Assert.assertEquals(1165.0, event.getTouchPoint().getScreenY(), 0.0001);
1095                     break;
1096                 default:
1097                     fail("Wrong touch point delivery");
1098             }
1099         });
1100 
1101         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventBegin(
1102                 System.currentTimeMillis(), 2, true, true, false, true, false);
1103         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
1104                 TouchPoint.State.PRESSED, 3, 150, 155, 1150, 1155);
1105         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
1106                 TouchPoint.State.PRESSED, 4, 260, 265, 1260, 1265);
1107         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventEnd();
1108 
1109         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventBegin(
1110                 System.currentTimeMillis(), 2, true, true, false, true, false);
1111         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
1112                 TouchPoint.State.MOVED, 3, 250, 255, 1250, 1255);
1113         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
1114                 TouchPoint.State.MOVED, 4, 160, 165, 1160, 1165);
1115         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventEnd();
1116 
1117         assertEquals(4, touched);
1118     }
1119 
1120     @Test
1121     public void ungrabShouldEnablePickingForTouchPoints() {
1122         Scene scene = createScene();
1123         Rectangle rect1 =
1124                 (Rectangle) scene.getRoot().getChildrenUnmodifiable().get(0);
1125 
1126         Rectangle rect2 =
1127                 (Rectangle) scene.getRoot().getChildrenUnmodifiable().get(1);
1128 
1129         touched = 0;
1130         rect1.addEventHandler(TouchEvent.ANY, event -> {
1131             touched++;
1132             switch(touched) {
1133                 case 1:
1134                     Assert.assertEquals(1, event.getTouchPoint().getId());
1135                     Assert.assertEquals(150.0, event.getTouchPoint().getX(), 0.0001);
1136                     Assert.assertEquals(155.0, event.getTouchPoint().getY(), 0.0001);
1137                     Assert.assertEquals(150.0, event.getTouchPoint().getSceneX(), 0.0001);
1138                     Assert.assertEquals(155.0, event.getTouchPoint().getSceneY(), 0.0001);
1139                     Assert.assertEquals(1150.0, event.getTouchPoint().getScreenX(), 0.0001);
1140                     Assert.assertEquals(1155.0, event.getTouchPoint().getScreenY(), 0.0001);
1141                     event.getTouchPoint().ungrab();
1142                     break;
1143                 case 4:
1144                     Assert.assertEquals(2, event.getTouchPoint().getId());
1145                     Assert.assertEquals(160.0, event.getTouchPoint().getX(), 0.0001);
1146                     Assert.assertEquals(165.0, event.getTouchPoint().getY(), 0.0001);
1147                     Assert.assertEquals(160.0, event.getTouchPoint().getSceneX(), 0.0001);
1148                     Assert.assertEquals(165.0, event.getTouchPoint().getSceneY(), 0.0001);
1149                     Assert.assertEquals(1160.0, event.getTouchPoint().getScreenX(), 0.0001);
1150                     Assert.assertEquals(1165.0, event.getTouchPoint().getScreenY(), 0.0001);
1151                     break;
1152                 default:
1153                     fail("Wrong touch point delivery");
1154             }
1155         });
1156 
1157         rect2.addEventHandler(TouchEvent.ANY, event -> {
1158             touched++;
1159             switch(touched) {
1160                 case 2:
1161                     Assert.assertEquals(2, event.getTouchPoint().getId());
1162                     Assert.assertEquals(260.0, event.getTouchPoint().getX(), 0.0001);
1163                     Assert.assertEquals(265.0, event.getTouchPoint().getY(), 0.0001);
1164                     Assert.assertEquals(260.0, event.getTouchPoint().getSceneX(), 0.0001);
1165                     Assert.assertEquals(265.0, event.getTouchPoint().getSceneY(), 0.0001);
1166                     Assert.assertEquals(1260.0, event.getTouchPoint().getScreenX(), 0.0001);
1167                     Assert.assertEquals(1265.0, event.getTouchPoint().getScreenY(), 0.0001);
1168                     event.getTouchPoint().ungrab();
1169                     break;
1170                 case 3:
1171                     Assert.assertEquals(1, event.getTouchPoint().getId());
1172                     Assert.assertEquals(250.0, event.getTouchPoint().getX(), 0.0001);
1173                     Assert.assertEquals(255.0, event.getTouchPoint().getY(), 0.0001);
1174                     Assert.assertEquals(250.0, event.getTouchPoint().getSceneX(), 0.0001);
1175                     Assert.assertEquals(255.0, event.getTouchPoint().getSceneY(), 0.0001);
1176                     Assert.assertEquals(1250.0, event.getTouchPoint().getScreenX(), 0.0001);
1177                     Assert.assertEquals(1255.0, event.getTouchPoint().getScreenY(), 0.0001);
1178                     break;
1179                 default:
1180                     fail("Wrong touch point delivery");
1181             }
1182         });
1183 
1184         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventBegin(
1185                 System.currentTimeMillis(), 2, true, true, false, true, false);
1186         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
1187                 TouchPoint.State.PRESSED, 3, 150, 155, 1150, 1155);
1188         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
1189                 TouchPoint.State.PRESSED, 4, 260, 265, 1260, 1265);
1190         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventEnd();
1191 
1192         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventBegin(
1193                 System.currentTimeMillis(), 2, true, true, false, true, false);
1194         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
1195                 TouchPoint.State.MOVED, 3, 250, 255, 1250, 1255);
1196         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
1197                 TouchPoint.State.MOVED, 4, 160, 165, 1160, 1165);
1198         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventEnd();
1199 
1200         assertEquals(4, touched);
1201     }
1202 
1203     @Test
1204     public void grabWithArgShouldAffectDelivery() {
1205         Scene scene = createScene();
1206         final Rectangle rect1 =
1207                 (Rectangle) scene.getRoot().getChildrenUnmodifiable().get(0);
1208 
1209         final Rectangle rect2 =
1210                 (Rectangle) scene.getRoot().getChildrenUnmodifiable().get(1);
1211 
1212         touched = 0;
1213         rect1.addEventHandler(TouchEvent.ANY, event -> {
1214             touched++;
1215             switch(touched) {
1216                 case 1:
1217                     Assert.assertEquals(1, event.getTouchPoint().getId());
1218                     Assert.assertEquals(150.0, event.getTouchPoint().getX(), 0.0001);
1219                     Assert.assertEquals(155.0, event.getTouchPoint().getY(), 0.0001);
1220                     Assert.assertEquals(150.0, event.getTouchPoint().getSceneX(), 0.0001);
1221                     Assert.assertEquals(155.0, event.getTouchPoint().getSceneY(), 0.0001);
1222                     Assert.assertEquals(1150.0, event.getTouchPoint().getScreenX(), 0.0001);
1223                     Assert.assertEquals(1155.0, event.getTouchPoint().getScreenY(), 0.0001);
1224                     event.getTouchPoints().get(1).grab(rect1);
1225                     break;
1226                 case 3:
1227                     Assert.assertEquals(1, event.getTouchPoint().getId());
1228                     Assert.assertEquals(250.0, event.getTouchPoint().getX(), 0.0001);
1229                     Assert.assertEquals(255.0, event.getTouchPoint().getY(), 0.0001);
1230                     Assert.assertEquals(250.0, event.getTouchPoint().getSceneX(), 0.0001);
1231                     Assert.assertEquals(255.0, event.getTouchPoint().getSceneY(), 0.0001);
1232                     Assert.assertEquals(1250.0, event.getTouchPoint().getScreenX(), 0.0001);
1233                     Assert.assertEquals(1255.0, event.getTouchPoint().getScreenY(), 0.0001);
1234                     break;
1235                 case 4:
1236                     Assert.assertEquals(2, event.getTouchPoint().getId());
1237                     Assert.assertEquals(160.0, event.getTouchPoint().getX(), 0.0001);
1238                     Assert.assertEquals(165.0, event.getTouchPoint().getY(), 0.0001);
1239                     Assert.assertEquals(160.0, event.getTouchPoint().getSceneX(), 0.0001);
1240                     Assert.assertEquals(165.0, event.getTouchPoint().getSceneY(), 0.0001);
1241                     Assert.assertEquals(1160.0, event.getTouchPoint().getScreenX(), 0.0001);
1242                     Assert.assertEquals(1165.0, event.getTouchPoint().getScreenY(), 0.0001);
1243                     break;
1244                 default:
1245                     fail("Wrong touch point delivery");
1246             }
1247         });
1248 
1249         rect2.addEventHandler(TouchEvent.ANY, event -> {
1250             touched++;
1251             switch(touched) {
1252                 case 2:
1253                     Assert.assertEquals(2, event.getTouchPoint().getId());
1254                     Assert.assertEquals(260.0, event.getTouchPoint().getX(), 0.0001);
1255                     Assert.assertEquals(265.0, event.getTouchPoint().getY(), 0.0001);
1256                     Assert.assertEquals(260.0, event.getTouchPoint().getSceneX(), 0.0001);
1257                     Assert.assertEquals(265.0, event.getTouchPoint().getSceneY(), 0.0001);
1258                     Assert.assertEquals(1260.0, event.getTouchPoint().getScreenX(), 0.0001);
1259                     Assert.assertEquals(1265.0, event.getTouchPoint().getScreenY(), 0.0001);
1260                     break;
1261                 default:
1262                     fail("Wrong touch point delivery");
1263             }
1264         });
1265 
1266         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventBegin(
1267                 System.currentTimeMillis(), 2, true, true, false, true, false);
1268         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
1269                 TouchPoint.State.PRESSED, 3, 150, 155, 1150, 1155);
1270         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
1271                 TouchPoint.State.PRESSED, 4, 260, 265, 1260, 1265);
1272         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventEnd();
1273 
1274         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventBegin(
1275                 System.currentTimeMillis(), 2, true, true, false, true, false);
1276         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
1277                 TouchPoint.State.MOVED, 3, 250, 255, 1250, 1255);
1278         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
1279                 TouchPoint.State.MOVED, 4, 160, 165, 1160, 1165);
1280         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventEnd();
1281 
1282         assertEquals(4, touched);
1283     }
1284 
1285     @Test
1286     public void grabWithoutArgShouldAffectDelivery() {
1287         Scene scene = createScene();
1288         final Rectangle rect1 =
1289                 (Rectangle) scene.getRoot().getChildrenUnmodifiable().get(0);
1290 
1291         final Rectangle rect2 =
1292                 (Rectangle) scene.getRoot().getChildrenUnmodifiable().get(1);
1293 
1294         touched = 0;
1295         rect1.addEventHandler(TouchEvent.ANY, event -> {
1296             touched++;
1297             switch(touched) {
1298                 case 1:
1299                     Assert.assertEquals(1, event.getTouchPoint().getId());
1300                     Assert.assertEquals(150.0, event.getTouchPoint().getX(), 0.0001);
1301                     Assert.assertEquals(155.0, event.getTouchPoint().getY(), 0.0001);
1302                     Assert.assertEquals(150.0, event.getTouchPoint().getSceneX(), 0.0001);
1303                     Assert.assertEquals(155.0, event.getTouchPoint().getSceneY(), 0.0001);
1304                     Assert.assertEquals(1150.0, event.getTouchPoint().getScreenX(), 0.0001);
1305                     Assert.assertEquals(1155.0, event.getTouchPoint().getScreenY(), 0.0001);
1306                     event.getTouchPoints().get(1).grab();
1307                     break;
1308                 case 3:
1309                     Assert.assertEquals(1, event.getTouchPoint().getId());
1310                     Assert.assertEquals(250.0, event.getTouchPoint().getX(), 0.0001);
1311                     Assert.assertEquals(255.0, event.getTouchPoint().getY(), 0.0001);
1312                     Assert.assertEquals(250.0, event.getTouchPoint().getSceneX(), 0.0001);
1313                     Assert.assertEquals(255.0, event.getTouchPoint().getSceneY(), 0.0001);
1314                     Assert.assertEquals(1250.0, event.getTouchPoint().getScreenX(), 0.0001);
1315                     Assert.assertEquals(1255.0, event.getTouchPoint().getScreenY(), 0.0001);
1316                     break;
1317                 case 4:
1318                     Assert.assertEquals(2, event.getTouchPoint().getId());
1319                     Assert.assertEquals(160.0, event.getTouchPoint().getX(), 0.0001);
1320                     Assert.assertEquals(165.0, event.getTouchPoint().getY(), 0.0001);
1321                     Assert.assertEquals(160.0, event.getTouchPoint().getSceneX(), 0.0001);
1322                     Assert.assertEquals(165.0, event.getTouchPoint().getSceneY(), 0.0001);
1323                     Assert.assertEquals(1160.0, event.getTouchPoint().getScreenX(), 0.0001);
1324                     Assert.assertEquals(1165.0, event.getTouchPoint().getScreenY(), 0.0001);
1325                     break;
1326                 default:
1327                     fail("Wrong touch point delivery");
1328             }
1329         });
1330 
1331         rect2.addEventHandler(TouchEvent.ANY, event -> {
1332             touched++;
1333             switch(touched) {
1334                 case 2:
1335                     Assert.assertEquals(2, event.getTouchPoint().getId());
1336                     Assert.assertEquals(260.0, event.getTouchPoint().getX(), 0.0001);
1337                     Assert.assertEquals(265.0, event.getTouchPoint().getY(), 0.0001);
1338                     Assert.assertEquals(260.0, event.getTouchPoint().getSceneX(), 0.0001);
1339                     Assert.assertEquals(265.0, event.getTouchPoint().getSceneY(), 0.0001);
1340                     Assert.assertEquals(1260.0, event.getTouchPoint().getScreenX(), 0.0001);
1341                     Assert.assertEquals(1265.0, event.getTouchPoint().getScreenY(), 0.0001);
1342                     break;
1343                 default:
1344                     fail("Wrong touch point delivery");
1345             }
1346         });
1347 
1348         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventBegin(
1349                 System.currentTimeMillis(), 2, true, true, false, true, false);
1350         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
1351                 TouchPoint.State.PRESSED, 3, 150, 155, 1150, 1155);
1352         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
1353                 TouchPoint.State.PRESSED, 4, 260, 265, 1260, 1265);
1354         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventEnd();
1355 
1356         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventBegin(
1357                 System.currentTimeMillis(), 2, true, true, false, true, false);
1358         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
1359                 TouchPoint.State.MOVED, 3, 250, 255, 1250, 1255);
1360         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
1361                 TouchPoint.State.MOVED, 4, 160, 165, 1160, 1165);
1362         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventEnd();
1363 
1364         assertEquals(4, touched);
1365     }
1366 
1367     @Test
1368     public void pointsShouldBeTransformedCorrectly() {
1369         Scene scene = createScene();
1370         Rectangle rect =
1371                 (Rectangle) scene.getRoot().getChildrenUnmodifiable().get(0);
1372         rect.setTranslateX(15);
1373         rect.setTranslateY(5);
1374 
1375         touched = 0;
1376         rect.addEventHandler(TouchEvent.ANY, event -> {
1377             touched++;
1378             switch(touched) {
1379                 case 1:
1380                     Assert.assertEquals(115.0, event.getTouchPoint().getX(), 0.0001);
1381                     Assert.assertEquals(125.0, event.getTouchPoint().getY(), 0.0001);
1382                     Assert.assertEquals(130.0, event.getTouchPoint().getSceneX(), 0.0001);
1383                     Assert.assertEquals(130.0, event.getTouchPoint().getSceneY(), 0.0001);
1384                     break;
1385                 case 2:
1386                 case 3:
1387                 case 4:
1388                 case 5:
1389                     Assert.assertEquals(115.0, event.getTouchPoints().get(0).getX(), 0.0001);
1390                     Assert.assertEquals(125.0, event.getTouchPoints().get(0).getY(), 0.0001);
1391                     Assert.assertEquals(130.0, event.getTouchPoints().get(0).getSceneX(), 0.0001);
1392                     Assert.assertEquals(130.0, event.getTouchPoints().get(0).getSceneY(), 0.0001);
1393                     Assert.assertEquals(125.0, event.getTouchPoints().get(1).getX(), 0.0001);
1394                     Assert.assertEquals(135.0, event.getTouchPoints().get(1).getY(), 0.0001);
1395                     Assert.assertEquals(140.0, event.getTouchPoints().get(1).getSceneX(), 0.0001);
1396                     Assert.assertEquals(140.0, event.getTouchPoints().get(1).getSceneY(), 0.0001);
1397                     break;
1398                 default:
1399                     fail("Wrong touch point id " + event.getTouchPoint().getId());
1400             }
1401         });
1402 
1403         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventBegin(
1404                 System.currentTimeMillis(), 1, true, true, false, true, false);
1405         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
1406                 TouchPoint.State.PRESSED, 1, 130, 130, 130, 130);
1407         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventEnd();
1408 
1409         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventBegin(
1410                 System.currentTimeMillis(), 2, true, true, false, true, false);
1411         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
1412                 TouchPoint.State.STATIONARY, 1, 130, 130, 130, 130);
1413         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
1414                 TouchPoint.State.PRESSED, 2, 140, 140, 140, 140);
1415         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventEnd();
1416 
1417         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventBegin(
1418                 System.currentTimeMillis(), 2, true, true, false, true, false);
1419         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
1420                 TouchPoint.State.RELEASED, 1, 130, 130, 130, 130);
1421         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
1422                 TouchPoint.State.RELEASED, 2, 140, 140, 140, 140);
1423         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventEnd();
1424 
1425 
1426         assertEquals(5, touched);
1427     }
1428 
1429     @Test
1430     public void shouldIgnoreIndirectTouchEvents() {
1431         Scene scene = createScene();
1432         Rectangle rect =
1433                 (Rectangle) scene.getRoot().getChildrenUnmodifiable().get(0);
1434 
1435         rect.addEventHandler(TouchEvent.ANY, event -> fail("Delivered indirect touch event"));
1436 
1437         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventBegin(
1438                 System.currentTimeMillis(), 1, false, true, false, true, false);
1439         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
1440                 TouchPoint.State.PRESSED, 1, 110, 110, 110, 110);
1441         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventEnd();
1442 
1443         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventBegin(
1444                 System.currentTimeMillis(), 1, false, true, false, true, false);
1445         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
1446                 TouchPoint.State.RELEASED, 1, 110, 110, 110, 110);
1447         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventEnd();
1448     }
1449 
1450     @Test(expected=RuntimeException.class)
1451     public void shouldThrowREOnWrongSmallId() {
1452         Scene scene = createScene();
1453         Rectangle rect =
1454                 (Rectangle) scene.getRoot().getChildrenUnmodifiable().get(0);
1455 
1456         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventBegin(
1457                 System.currentTimeMillis(), 1, true, false, false, false, false);
1458         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
1459                 TouchPoint.State.PRESSED, 1, 110, 110, 110, 110);
1460         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventEnd();
1461 
1462         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventBegin(
1463                 System.currentTimeMillis(), 1, true, false, false, false, false);
1464         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
1465                 TouchPoint.State.MOVED, 2, 110, 110, 110, 110);
1466         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventEnd();
1467     }
1468 
1469     @Test(expected=RuntimeException.class)
1470     public void shouldThrowREOnWrongLargeId() {
1471         Scene scene = createScene();
1472         Rectangle rect =
1473                 (Rectangle) scene.getRoot().getChildrenUnmodifiable().get(0);
1474 
1475         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventBegin(
1476                 System.currentTimeMillis(), 1, true, false, false, false, false);
1477         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
1478                 TouchPoint.State.PRESSED, 1368, 110, 110, 110, 110);
1479         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventEnd();
1480 
1481         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventBegin(
1482                 System.currentTimeMillis(), 1, true, false, false, false, false);
1483         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
1484                 TouchPoint.State.MOVED, 127, 110, 110, 110, 110);
1485         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventEnd();
1486     }
1487 
1488     @Test(expected=RuntimeException.class)
1489     public void shouldThrowREOnBigTPNumber() {
1490         Scene scene = createScene();
1491         Rectangle rect =
1492                 (Rectangle) scene.getRoot().getChildrenUnmodifiable().get(0);
1493 
1494         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventBegin(
1495                 System.currentTimeMillis(), 1, true, false, false, false, false);
1496         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
1497                 TouchPoint.State.PRESSED, 1368, 110, 110, 110, 110);
1498         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
1499                 TouchPoint.State.PRESSED, 1, 110, 110, 110, 110);
1500         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventEnd();
1501     }
1502 
1503     @Test(expected=RuntimeException.class)
1504     public void shouldThrowREOnSmallTPNumber() {
1505         Scene scene = createScene();
1506         Rectangle rect =
1507                 (Rectangle) scene.getRoot().getChildrenUnmodifiable().get(0);
1508 
1509         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventBegin(
1510                 System.currentTimeMillis(), 2, true, false, false, false, false);
1511         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
1512                 TouchPoint.State.PRESSED, 1368, 110, 110, 110, 110);
1513         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventEnd();
1514     }
1515 
1516     @Test(expected=RuntimeException.class)
1517     public void shouldThrowREOnLostRelease() {
1518         Scene scene = createScene();
1519         Rectangle rect =
1520                 (Rectangle) scene.getRoot().getChildrenUnmodifiable().get(0);
1521 
1522         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventBegin(
1523                 System.currentTimeMillis(), 1, true, false, false, false, false);
1524         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
1525                 TouchPoint.State.PRESSED, 1368, 110, 110, 110, 110);
1526         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventEnd();
1527 
1528         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventBegin(
1529                 System.currentTimeMillis(), 1, true, false, false, false, false);
1530         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
1531                 TouchPoint.State.PRESSED, 1, 110, 110, 110, 110);
1532         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventEnd();
1533     }
1534 
1535     // Reenable once indirect events are used
1536     @Ignore("For now we've decided to ingore indirect events completely.")
1537     @Test(expected=RuntimeException.class)
1538     public void shouldThrowREOnLostIndirectRelease() {
1539         Scene scene = createScene();
1540         Rectangle rect =
1541                 (Rectangle) scene.getRoot().getChildrenUnmodifiable().get(0);
1542 
1543         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventBegin(
1544                 System.currentTimeMillis(), 1, false, false, false, false, false);
1545         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
1546                 TouchPoint.State.PRESSED, 1368, 110, 110, 110, 110);
1547         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventEnd();
1548 
1549         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventBegin(
1550                 System.currentTimeMillis(), 1, false, false, false, false, false);
1551         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
1552                 TouchPoint.State.PRESSED, 1, 110, 110, 110, 110);
1553         ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventEnd();
1554     }
1555 
1556     private Scene createScene() {
1557         final Group root = new Group();
1558 
1559         final Scene scene = new Scene(root, 400, 400);
1560 
1561         Rectangle rect = new Rectangle(100, 100, 100, 100);
1562         Rectangle rect2 = new Rectangle(200, 200, 100, 100);
1563 
1564         ParentShim.getChildren(root).addAll(rect, rect2);
1565 
1566         Stage stage = new Stage();
1567         stage.setScene(scene);
1568         stage.show();
1569 
1570         return scene;
1571     }
1572 
1573     @Test
1574     @Ignore("This is a benchmark, not any functional test. Run it individually if you wish.")
1575     public void saneOrderingBenchmark() {
1576         long[] ids = new long[] { 2, 3, 4, 5, 6 };
1577         boolean[] active = new boolean[] { false, false, false, false, false };
1578         int count = 0;
1579         int tick = 5;
1580         int available = 5;
1581         Random rand = new Random();
1582 
1583         Scene scene = createScene();
1584 
1585 
1586         int ticker = 0;
1587         int added = -1;
1588         int removed = -1;
1589         long timer = System.currentTimeMillis();
1590         for (int i = 0; i < SANE_BENCHMARK_CYCLES; i++) {
1591             ticker++;
1592             if (ticker == tick) {
1593                 ticker = 0;
1594 
1595                 boolean up;
1596                 if (count == available) {
1597                     up = false;
1598                 } else if (count == 0) {
1599                     up = true;
1600                 } else {
1601                     up = Math.random() > 0.4;
1602                 }
1603 
1604                 if (up) {
1605                     for (int j = 0; j < available; j++) {
1606                         if (!active[j]) {
1607                             active[j] = true;
1608                             added = j;
1609                             count++;
1610                             break;
1611                         }
1612                     }
1613                 } else {
1614                     int which = rand.nextInt(count);
1615                     int k = 0;
1616                     for (int j = 0; j < available; j++) {
1617                         if (active[j]) {
1618                             k++;
1619                             if (k == which) {
1620                                 active[j] = false;
1621                                 removed = j;
1622                                 count--;
1623                                 break;
1624                             }
1625                         }
1626                     }
1627                 }
1628             }
1629 
1630             int reporting = count + (removed >= 0 ? 1 : 0);
1631 
1632             ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventBegin(
1633                     System.currentTimeMillis(), reporting, true, false, false, false, false);
1634 
1635             for (int j = 0; j < available; j++) {
1636                 if (active[j] || removed == j) {
1637                     TouchPoint.State state = TouchPoint.State.MOVED;
1638                     if (added == j) {
1639                         state = TouchPoint.State.PRESSED;
1640                     } else if (removed == j) {
1641                         state = TouchPoint.State.RELEASED;
1642                     } else {
1643                     }
1644 
1645                     ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
1646                             state, ids[j], 150, 150, 150, 150);
1647                 }
1648             }
1649 
1650             ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventEnd();
1651             removed = -1;
1652             added = -1;
1653         }
1654         long timer2 = System.currentTimeMillis();
1655         System.out.println("*************************************************");
1656         System.out.println("Benchmark1 time: " + (timer2 - timer));
1657         System.out.println("*************************************************");
1658         System.out.println("");
1659     }
1660 
1661     @Test
1662     @Ignore("This is a benchmark, not any functional test. Run it individually if you wish.")
1663     public void crazyOrderingBenchmark() {
1664         long[] ids = new long[] { 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000 };
1665         boolean[] active = new boolean[] { false, false, false, false, false,
1666                 false, false, false, false, false };
1667         int count = 0;
1668         int tick = 5;
1669         int available = 10;
1670         Random rand = new Random();
1671 
1672         Scene scene = createScene();
1673 
1674 
1675         int ticker = 0;
1676         int added = -1;
1677         int removed = -1;
1678         long timer = System.currentTimeMillis();
1679         for (int i = 0; i < CRAZY_BENCHMARK_CYCLES; i++) {
1680             ticker++;
1681             if (ticker == tick) {
1682                 ticker = 0;
1683 
1684                 boolean up;
1685                 if (count == available) {
1686                     up = false;
1687                 } else if (count == 0) {
1688                     up = true;
1689                 } else {
1690                     up = Math.random() > 0.4;
1691                 }
1692 
1693                 if (up) {
1694                     int which = rand.nextInt(available - count);
1695                     int k = 0;
1696                     for (int j = 0; j < available; j++) {
1697                         if (!active[j]) {
1698                             k++;
1699                             if (k == which) {
1700                                 active[j] = true;
1701                                 added = j;
1702                                 count++;
1703                                 ids[j] = Math.abs(rand.nextLong());
1704                                 if (ids[j] == 0) {
1705                                     ids[j] = 1;
1706                                 }
1707                                 break;
1708                             }
1709                         }
1710                     }
1711                 } else {
1712                     int which = rand.nextInt(count);
1713                     int k = 0;
1714                     for (int j = 0; j < available; j++) {
1715                         if (active[j]) {
1716                             k++;
1717                             if (k == which) {
1718                                 active[j] = false;
1719                                 removed = j;
1720                                 count--;
1721                                 break;
1722                             }
1723                         }
1724                     }
1725                 }
1726             }
1727 
1728             int reporting = count + (removed >= 0 ? 1 : 0);
1729 
1730             ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventBegin(
1731                     System.currentTimeMillis(), reporting, true, false, false, false, false);
1732 
1733             for (int j = 0; j < available; j++) {
1734                 if (active[j] || removed == j) {
1735                     TouchPoint.State state = TouchPoint.State.MOVED;
1736                     if (added == j) {
1737                         state = TouchPoint.State.PRESSED;
1738                     } else if (removed == j) {
1739                         state = TouchPoint.State.RELEASED;
1740                     }
1741 
1742                     ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventNext(
1743                             state, ids[j], 150, 150, 150, 150);
1744                 }
1745             }
1746 
1747             ((StubScene) SceneHelper.getPeer(scene)).getListener().touchEventEnd();
1748             removed = -1;
1749             added = -1;
1750         }
1751         long timer2 = System.currentTimeMillis();
1752         System.out.println("*************************************************");
1753         System.out.println("Benchmark2 time: " + (timer2 - timer));
1754         System.out.println("*************************************************");
1755         System.out.println("");
1756     }
1757 
1758 }