1 /*
   2  * Copyright (c) 2000, 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;
  27 
  28 import com.sun.javafx.scene.SceneHelper;
  29 import test.com.sun.javafx.test.MouseEventGenerator;
  30 import static org.junit.Assert.*;
  31 import javafx.event.EventHandler;
  32 import javafx.scene.input.MouseEvent;
  33 import javafx.scene.shape.Rectangle;
  34 import javafx.stage.Stage;
  35 
  36 import org.junit.Assert;
  37 import org.junit.Test;
  38 
  39 import test.com.sun.javafx.pgstub.StubScene;
  40 import test.com.sun.javafx.pgstub.StubToolkit;
  41 import com.sun.javafx.tk.Toolkit;
  42 import javafx.event.EventTarget;
  43 import javafx.event.EventType;
  44 import javafx.scene.Cursor;
  45 import javafx.scene.CursorShim;
  46 import javafx.scene.Group;
  47 import javafx.scene.Node;
  48 import javafx.scene.ParentShim;
  49 import javafx.scene.PerspectiveCamera;
  50 import javafx.scene.Scene;
  51 import javafx.scene.SubScene;
  52 import javafx.scene.input.MouseDragEvent;
  53 import javafx.scene.input.PickResult;
  54 import javafx.scene.paint.Color;
  55 import javafx.scene.transform.Rotate;
  56 
  57 public class MouseTest {
  58 
  59     private static final double DONT_TEST = 0.0;
  60 
  61     @Test
  62     public void moveShouldBubbleToParent() {
  63         SimpleTestScene scene = new SimpleTestScene();
  64         MouseEventGenerator generator = new MouseEventGenerator();
  65 
  66         scene.processEvent(generator.generateMouseEvent(
  67                 MouseEvent.MOUSE_MOVED, 250, 250));
  68 
  69         assertTrue(scene.smallSquareTracker.wasMoved());
  70         assertFalse(scene.bigSquareTracker.wasMoved());
  71         assertTrue(scene.groupTracker.wasMoved());
  72     }
  73 
  74     @Test
  75     public void moveOutsideNodesShouldntBeNoticed() {
  76         SimpleTestScene scene = new SimpleTestScene();
  77         MouseEventGenerator generator = new MouseEventGenerator();
  78 
  79         scene.processEvent(generator.generateMouseEvent(
  80                 MouseEvent.MOUSE_MOVED, 350, 350));
  81 
  82         assertFalse(scene.smallSquareTracker.wasMoved());
  83         assertFalse(scene.bigSquareTracker.wasMoved());
  84         assertFalse(scene.groupTracker.wasMoved());
  85     }
  86 
  87     @Test
  88     public void moveOutsideNodesShouldGoToScene() {
  89         SimpleTestScene scene = new SimpleTestScene();
  90         MouseEventGenerator generator = new MouseEventGenerator();
  91 
  92         scene.processEvent(generator.generateMouseEvent(
  93                 MouseEvent.MOUSE_MOVED, 350, 350));
  94 
  95         assertTrue(scene.wasMoused());
  96     }
  97 
  98     @Test
  99     public void ImpossibleToComputeCoordsShouldResultInNaNs() {
 100         final SimpleTestScene scene = new SimpleTestScene();
 101 
 102         scene.smallSquareTracker.node.setOnMouseMoved(event -> scene.smallSquareTracker.node.setScaleX(0));
 103 
 104         scene.smallSquareTracker.node.setOnMouseExited(event -> {
 105             assertTrue(Double.isNaN(event.getX()));
 106             assertTrue(Double.isNaN(event.getY()));
 107             assertTrue(Double.isNaN(event.getZ()));
 108         });
 109 
 110         scene.processEvent(MouseEventGenerator.generateMouseEvent(
 111                 MouseEvent.MOUSE_MOVED, 250, 250));
 112         scene.processEvent(MouseEventGenerator.generateMouseEvent(
 113                 MouseEvent.MOUSE_MOVED, 260, 260));
 114         assertTrue(scene.smallSquareTracker.enteredMe);
 115     }
 116 
 117     @Test
 118     public void PdrGestureShouldGoToOneNode() {
 119         SimpleTestScene scene = new SimpleTestScene();
 120         MouseEventGenerator generator = new MouseEventGenerator();
 121 
 122         /* gesture */
 123         scene.processEvent(generator.generateMouseEvent(
 124                 MouseEvent.MOUSE_PRESSED, 250, 250));
 125 
 126         scene.processEvent(generator.generateMouseEvent(
 127                 MouseEvent.MOUSE_DRAGGED, 150, 150));
 128 
 129         scene.processEvent(generator.generateMouseEvent(
 130                 MouseEvent.MOUSE_RELEASED, 150, 150));
 131 
 132         assertTrue(scene.smallSquareTracker.wasPressed());
 133         assertTrue(scene.smallSquareTracker.wasDragged());
 134         assertTrue(scene.smallSquareTracker.wasReleased());
 135         assertFalse(scene.bigSquareTracker.wasPressed());
 136         assertFalse(scene.bigSquareTracker.wasDragged());
 137         assertFalse(scene.bigSquareTracker.wasReleased());
 138         assertFalse(scene.bigSquareTracker.wasMoved());
 139 
 140         /* gesture ended */
 141         scene.processEvent(generator.generateMouseEvent(
 142                 MouseEvent.MOUSE_MOVED, 140, 140));
 143 
 144         assertTrue(scene.bigSquareTracker.wasMoved());
 145     }
 146 
 147     @Test
 148     public void PdrGestureOnSceneShouldGoOnlyToScene() {
 149         SimpleTestScene scene = new SimpleTestScene();
 150         MouseEventGenerator generator = new MouseEventGenerator();
 151 
 152         /* gesture */
 153         scene.processEvent(generator.generateMouseEvent(
 154                 MouseEvent.MOUSE_PRESSED, 50, 50));
 155 
 156         assertTrue(scene.wasMoused());
 157         assertFalse(scene.smallSquareTracker.wasPressed());
 158         assertFalse(scene.smallSquareTracker.wasDragged());
 159         assertFalse(scene.smallSquareTracker.wasReleased());
 160         assertFalse(scene.bigSquareTracker.wasPressed());
 161         assertFalse(scene.bigSquareTracker.wasDragged());
 162         assertFalse(scene.bigSquareTracker.wasReleased());
 163         assertFalse(scene.bigSquareTracker.wasMoved());
 164         scene.clear();
 165 
 166         scene.processEvent(generator.generateMouseEvent(
 167                 MouseEvent.MOUSE_DRAGGED, 150, 150));
 168 
 169         assertTrue(scene.wasMoused());
 170         assertFalse(scene.smallSquareTracker.wasPressed());
 171         assertFalse(scene.smallSquareTracker.wasDragged());
 172         assertFalse(scene.smallSquareTracker.wasReleased());
 173         assertFalse(scene.bigSquareTracker.wasPressed());
 174         assertFalse(scene.bigSquareTracker.wasDragged());
 175         assertFalse(scene.bigSquareTracker.wasReleased());
 176         assertFalse(scene.bigSquareTracker.wasMoved());
 177         scene.clear();
 178 
 179         scene.processEvent(generator.generateMouseEvent(
 180                 MouseEvent.MOUSE_RELEASED, 150, 150));
 181 
 182         assertTrue(scene.wasMoused());
 183         assertFalse(scene.smallSquareTracker.wasPressed());
 184         assertFalse(scene.smallSquareTracker.wasDragged());
 185         assertFalse(scene.smallSquareTracker.wasReleased());
 186         assertFalse(scene.bigSquareTracker.wasPressed());
 187         assertFalse(scene.bigSquareTracker.wasDragged());
 188         assertFalse(scene.bigSquareTracker.wasReleased());
 189         assertFalse(scene.bigSquareTracker.wasMoved());
 190 
 191         /* gesture ended */
 192         scene.processEvent(generator.generateMouseEvent(
 193                 MouseEvent.MOUSE_MOVED, 140, 140));
 194 
 195         assertTrue(scene.bigSquareTracker.wasMoved());
 196     }
 197 
 198     @Test
 199     public void testEnteredExitedGeneration() {
 200         SimpleTestScene scene = new SimpleTestScene();
 201         MouseEventGenerator generator = new MouseEventGenerator();
 202 
 203         scene.processEvent(generator.generateMouseEvent(
 204                 MouseEvent.MOUSE_MOVED, 350, 350));
 205 
 206         assertFalse(scene.smallSquareTracker.wasEnteredMe());
 207         assertFalse(scene.bigSquareTracker.wasEnteredMe());
 208         assertFalse(scene.groupTracker.wasEnteredMe());
 209         assertFalse(scene.smallSquareTracker.wasExitedMe());
 210         assertFalse(scene.bigSquareTracker.wasExitedMe());
 211         assertFalse(scene.groupTracker.wasExitedMe());
 212         assertTrue(scene.sceneTracker.wasEnteredMe());
 213         assertFalse(scene.sceneTracker.wasExitedMe());
 214         scene.clear();
 215 
 216         scene.processEvent(generator.generateMouseEvent(
 217                 MouseEvent.MOUSE_MOVED, 250, 250));
 218 
 219         assertTrue(scene.smallSquareTracker.wasEnteredMe());
 220         assertFalse(scene.bigSquareTracker.wasEnteredMe());
 221         assertTrue(scene.groupTracker.wasEnteredMe());
 222         assertFalse(scene.smallSquareTracker.wasExitedMe());
 223         assertFalse(scene.bigSquareTracker.wasExitedMe());
 224         assertFalse(scene.groupTracker.wasExitedMe());
 225         assertFalse(scene.sceneTracker.wasEnteredMe());
 226         assertFalse(scene.sceneTracker.wasExitedMe());
 227         scene.clear();
 228 
 229         scene.processEvent(generator.generateMouseEvent(
 230                 MouseEvent.MOUSE_MOVED, 150, 150));
 231 
 232         assertFalse(scene.smallSquareTracker.wasEnteredMe());
 233         assertTrue(scene.bigSquareTracker.wasEnteredMe());
 234         assertFalse(scene.groupTracker.wasEnteredMe());
 235         assertTrue(scene.smallSquareTracker.wasExitedMe());
 236         assertFalse(scene.bigSquareTracker.wasExitedMe());
 237         assertFalse(scene.groupTracker.wasExitedMe());
 238         assertFalse(scene.sceneTracker.wasEnteredMe());
 239         assertFalse(scene.sceneTracker.wasExitedMe());
 240         scene.clear();
 241 
 242         scene.processEvent(generator.generateMouseEvent(
 243                 MouseEvent.MOUSE_MOVED, 50, 50));
 244 
 245         assertFalse(scene.smallSquareTracker.wasEnteredMe());
 246         assertFalse(scene.bigSquareTracker.wasEnteredMe());
 247         assertFalse(scene.groupTracker.wasEnteredMe());
 248         assertFalse(scene.smallSquareTracker.wasExitedMe());
 249         assertTrue(scene.bigSquareTracker.wasExitedMe());
 250         assertTrue(scene.groupTracker.wasExitedMe());
 251         assertFalse(scene.sceneTracker.wasEnteredMe());
 252         assertFalse(scene.sceneTracker.wasExitedMe());
 253         scene.clear();
 254 
 255         scene.processEvent(generator.generateMouseEvent(
 256                 MouseEvent.MOUSE_MOVED, -1, 50));
 257         assertFalse(scene.smallSquareTracker.wasEnteredMe());
 258         assertFalse(scene.bigSquareTracker.wasEnteredMe());
 259         assertFalse(scene.groupTracker.wasEnteredMe());
 260         assertFalse(scene.smallSquareTracker.wasExitedMe());
 261         assertFalse(scene.bigSquareTracker.wasExitedMe());
 262         assertFalse(scene.groupTracker.wasExitedMe());
 263         assertFalse(scene.sceneTracker.wasEnteredMe());
 264         assertTrue(scene.sceneTracker.wasExitedMe());
 265         scene.clear();
 266     }
 267 
 268     @Test
 269     public void testEnteredExitedGenerationDuringPdr() {
 270         SimpleTestScene scene = new SimpleTestScene();
 271         MouseEventGenerator generator = new MouseEventGenerator();
 272 
 273         scene.processEvent(generator.generateMouseEvent(
 274                 MouseEvent.MOUSE_PRESSED, 255, 255));
 275 
 276         scene.processEvent(generator.generateMouseEvent(
 277                 MouseEvent.MOUSE_DRAGGED, 250, 250));
 278 
 279         assertTrue(scene.smallSquareTracker.wasEnteredMe());
 280         assertFalse(scene.bigSquareTracker.wasEnteredMe());
 281         assertTrue(scene.groupTracker.wasEnteredMe());
 282         assertFalse(scene.smallSquareTracker.wasExitedMe());
 283         assertFalse(scene.bigSquareTracker.wasExitedMe());
 284         assertFalse(scene.groupTracker.wasExitedMe());
 285         assertTrue(scene.sceneTracker.wasEnteredMe());
 286         assertFalse(scene.sceneTracker.wasExitedMe());
 287         scene.clear();
 288 
 289         scene.processEvent(generator.generateMouseEvent(
 290                 MouseEvent.MOUSE_DRAGGED, 150, 150));
 291 
 292         assertFalse(scene.smallSquareTracker.wasEnteredMe());
 293         assertFalse(scene.bigSquareTracker.wasEnteredMe());
 294         assertFalse(scene.groupTracker.wasEnteredMe());
 295         assertTrue(scene.smallSquareTracker.wasExitedMe());
 296         assertFalse(scene.bigSquareTracker.wasExitedMe());
 297         assertFalse(scene.groupTracker.wasExitedMe());
 298         assertFalse(scene.sceneTracker.wasEnteredMe());
 299         assertFalse(scene.sceneTracker.wasExitedMe());
 300         scene.clear();
 301 
 302         scene.processEvent(generator.generateMouseEvent(
 303                 MouseEvent.MOUSE_DRAGGED, 50, 50));
 304 
 305         assertFalse(scene.smallSquareTracker.wasEnteredMe());
 306         assertFalse(scene.bigSquareTracker.wasEnteredMe());
 307         assertFalse(scene.groupTracker.wasEnteredMe());
 308         assertFalse(scene.smallSquareTracker.wasExitedMe());
 309         assertFalse(scene.bigSquareTracker.wasExitedMe());
 310         assertTrue(scene.groupTracker.wasExitedMe());
 311         assertFalse(scene.sceneTracker.wasEnteredMe());
 312         assertFalse(scene.sceneTracker.wasExitedMe());
 313         scene.clear();
 314 
 315         scene.processEvent(generator.generateMouseEvent(
 316                 MouseEvent.MOUSE_DRAGGED, -1, 50));
 317 
 318         assertFalse(scene.smallSquareTracker.wasEnteredMe());
 319         assertFalse(scene.bigSquareTracker.wasEnteredMe());
 320         assertFalse(scene.groupTracker.wasEnteredMe());
 321         assertFalse(scene.smallSquareTracker.wasExitedMe());
 322         assertFalse(scene.bigSquareTracker.wasExitedMe());
 323         assertFalse(scene.groupTracker.wasExitedMe());
 324         assertFalse(scene.sceneTracker.wasEnteredMe());
 325         assertTrue(scene.sceneTracker.wasExitedMe());
 326         scene.clear();
 327 
 328         scene.processEvent(generator.generateMouseEvent(
 329                 MouseEvent.MOUSE_DRAGGED, 150, 150));
 330 
 331         assertFalse(scene.smallSquareTracker.wasEnteredMe());
 332         assertFalse(scene.bigSquareTracker.wasEnteredMe());
 333         assertTrue(scene.groupTracker.wasEnteredMe());
 334         assertFalse(scene.smallSquareTracker.wasExitedMe());
 335         assertFalse(scene.bigSquareTracker.wasExitedMe());
 336         assertFalse(scene.groupTracker.wasExitedMe());
 337         assertTrue(scene.sceneTracker.wasEnteredMe());
 338         assertFalse(scene.sceneTracker.wasExitedMe());
 339         scene.clear();
 340 
 341         scene.processEvent(generator.generateMouseEvent(
 342                 MouseEvent.MOUSE_RELEASED, 350, 350));
 343 
 344         assertFalse(scene.smallSquareTracker.wasEnteredMe());
 345         assertFalse(scene.bigSquareTracker.wasEnteredMe());
 346         assertFalse(scene.groupTracker.wasEnteredMe());
 347         assertFalse(scene.smallSquareTracker.wasExitedMe());
 348         assertFalse(scene.bigSquareTracker.wasExitedMe());
 349         assertTrue(scene.groupTracker.wasExitedMe());
 350         assertFalse(scene.sceneTracker.wasEnteredMe());
 351         assertFalse(scene.sceneTracker.wasExitedMe());
 352     }
 353 
 354     @Test
 355     public void testEnteredExitedGenerationAfterPdr() {
 356         SimpleTestScene scene = new SimpleTestScene();
 357         MouseEventGenerator generator = new MouseEventGenerator();
 358 
 359         scene.processEvent(generator.generateMouseEvent(
 360                 MouseEvent.MOUSE_PRESSED, 155, 155));
 361 
 362         scene.processEvent(generator.generateMouseEvent(
 363                 MouseEvent.MOUSE_DRAGGED, 150, 150));
 364 
 365         assertFalse(scene.smallSquareTracker.wasEnteredMe());
 366         assertTrue(scene.bigSquareTracker.wasEnteredMe());
 367         assertTrue(scene.groupTracker.wasEnteredMe());
 368         assertFalse(scene.smallSquareTracker.wasExitedMe());
 369         assertFalse(scene.bigSquareTracker.wasExitedMe());
 370         assertFalse(scene.groupTracker.wasExitedMe());
 371         scene.clear();
 372 
 373         scene.processEvent(generator.generateMouseEvent(
 374                 MouseEvent.MOUSE_DRAGGED, 250, 250));
 375 
 376         assertFalse(scene.smallSquareTracker.wasEnteredMe());
 377         assertFalse(scene.bigSquareTracker.wasEnteredMe());
 378         assertFalse(scene.groupTracker.wasEnteredMe());
 379         assertFalse(scene.smallSquareTracker.wasExitedMe());
 380         assertTrue(scene.bigSquareTracker.wasExitedMe());
 381         assertFalse(scene.groupTracker.wasExitedMe());
 382         scene.clear();
 383 
 384         scene.processEvent(generator.generateMouseEvent(
 385                 MouseEvent.MOUSE_RELEASED, 250, 250));
 386 
 387         assertTrue(scene.smallSquareTracker.wasEnteredMe());
 388         assertFalse(scene.bigSquareTracker.wasEnteredMe());
 389         assertFalse(scene.groupTracker.wasEnteredMe());
 390         assertFalse(scene.smallSquareTracker.wasExitedMe());
 391         assertFalse(scene.bigSquareTracker.wasExitedMe());
 392         assertFalse(scene.groupTracker.wasExitedMe());
 393         scene.clear();
 394 
 395         scene.processEvent(generator.generateMouseEvent(
 396                 MouseEvent.MOUSE_MOVED, 250, 250));
 397 
 398         assertFalse(scene.smallSquareTracker.wasEnteredMe());
 399         assertFalse(scene.bigSquareTracker.wasEnteredMe());
 400         assertFalse(scene.groupTracker.wasEnteredMe());
 401         assertFalse(scene.smallSquareTracker.wasExitedMe());
 402         assertFalse(scene.bigSquareTracker.wasExitedMe());
 403         assertFalse(scene.groupTracker.wasExitedMe());
 404     }
 405 
 406     @Test
 407     public void testEnteredExitedGenerationDuringDndOnScene() {
 408         SimpleTestScene scene = new SimpleTestScene();
 409         MouseEventGenerator generator = new MouseEventGenerator();
 410 
 411         scene.processEvent(generator.generateMouseEvent(
 412                 MouseEvent.MOUSE_PRESSED, 50, 50));
 413 
 414         scene.processEvent(generator.generateMouseEvent(
 415                 MouseEvent.MOUSE_DRAGGED, 250, 250));
 416 
 417         assertFalse(scene.smallSquareTracker.wasEnteredMe());
 418         assertFalse(scene.bigSquareTracker.wasEnteredMe());
 419         assertFalse(scene.groupTracker.wasEnteredMe());
 420         assertFalse(scene.smallSquareTracker.wasExitedMe());
 421         assertFalse(scene.bigSquareTracker.wasExitedMe());
 422         assertFalse(scene.groupTracker.wasExitedMe());
 423         scene.clear();
 424 
 425         scene.processEvent(generator.generateMouseEvent(
 426                 MouseEvent.MOUSE_DRAGGED, 150, 150));
 427 
 428         assertFalse(scene.smallSquareTracker.wasEnteredMe());
 429         assertFalse(scene.bigSquareTracker.wasEnteredMe());
 430         assertFalse(scene.groupTracker.wasEnteredMe());
 431         assertFalse(scene.smallSquareTracker.wasExitedMe());
 432         assertFalse(scene.bigSquareTracker.wasExitedMe());
 433         assertFalse(scene.groupTracker.wasExitedMe());
 434         scene.clear();
 435 
 436         scene.processEvent(generator.generateMouseEvent(
 437                 MouseEvent.MOUSE_DRAGGED, 50, 50));
 438 
 439         assertFalse(scene.smallSquareTracker.wasEnteredMe());
 440         assertFalse(scene.bigSquareTracker.wasEnteredMe());
 441         assertFalse(scene.groupTracker.wasEnteredMe());
 442         assertFalse(scene.smallSquareTracker.wasExitedMe());
 443         assertFalse(scene.bigSquareTracker.wasExitedMe());
 444         assertFalse(scene.groupTracker.wasExitedMe());
 445         scene.clear();
 446 
 447         scene.processEvent(generator.generateMouseEvent(
 448                 MouseEvent.MOUSE_DRAGGED, 150, 150));
 449 
 450         assertFalse(scene.smallSquareTracker.wasEnteredMe());
 451         assertFalse(scene.bigSquareTracker.wasEnteredMe());
 452         assertFalse(scene.groupTracker.wasEnteredMe());
 453         assertFalse(scene.smallSquareTracker.wasExitedMe());
 454         assertFalse(scene.bigSquareTracker.wasExitedMe());
 455         assertFalse(scene.groupTracker.wasExitedMe());
 456         scene.clear();
 457 
 458         scene.processEvent(generator.generateMouseEvent(
 459                 MouseEvent.MOUSE_RELEASED, 350, 350));
 460 
 461         assertFalse(scene.smallSquareTracker.wasEnteredMe());
 462         assertFalse(scene.bigSquareTracker.wasEnteredMe());
 463         assertFalse(scene.groupTracker.wasEnteredMe());
 464         assertFalse(scene.smallSquareTracker.wasExitedMe());
 465         assertFalse(scene.bigSquareTracker.wasExitedMe());
 466         assertFalse(scene.groupTracker.wasExitedMe());
 467     }
 468 
 469     @Test
 470     public void testEnteredExitedMeChildSwitching() {
 471         SimpleTestScene scene = new SimpleTestScene();
 472         MouseEventGenerator generator = new MouseEventGenerator();
 473 
 474         scene.processEvent(generator.generateMouseEvent(
 475                 MouseEvent.MOUSE_MOVED, 150, 150));
 476 
 477         assertFalse(scene.smallSquareTracker.wasEnteredMe());
 478         assertTrue(scene.bigSquareTracker.wasEnteredMe());
 479         assertTrue(scene.groupTracker.wasEnteredMe());
 480         assertFalse(scene.smallSquareTracker.wasExitedMe());
 481         assertFalse(scene.bigSquareTracker.wasExitedMe());
 482         assertFalse(scene.groupTracker.wasExitedMe());
 483         assertFalse(scene.smallSquareTracker.wasEnteredChild());
 484         assertFalse(scene.bigSquareTracker.wasEnteredChild());
 485         assertTrue(scene.groupTracker.wasEnteredChild());
 486         assertFalse(scene.smallSquareTracker.wasExitedChild());
 487         assertFalse(scene.bigSquareTracker.wasExitedChild());
 488         assertFalse(scene.groupTracker.wasExitedChild());
 489         scene.clear();
 490 
 491         scene.processEvent(generator.generateMouseEvent(
 492                 MouseEvent.MOUSE_MOVED, 250, 250));
 493 
 494         assertTrue(scene.smallSquareTracker.wasEnteredMe());
 495         assertFalse(scene.bigSquareTracker.wasEnteredMe());
 496         assertFalse(scene.groupTracker.wasEnteredMe());
 497         assertFalse(scene.smallSquareTracker.wasExitedMe());
 498         assertTrue(scene.bigSquareTracker.wasExitedMe());
 499         assertFalse(scene.groupTracker.wasExitedMe());
 500         assertFalse(scene.smallSquareTracker.wasEnteredChild());
 501         assertFalse(scene.bigSquareTracker.wasEnteredChild());
 502         assertTrue(scene.groupTracker.wasEnteredChild());
 503         assertFalse(scene.smallSquareTracker.wasExitedChild());
 504         assertFalse(scene.bigSquareTracker.wasExitedChild());
 505         assertTrue(scene.groupTracker.wasExitedChild());
 506         scene.clear();
 507 
 508         scene.processEvent(generator.generateMouseEvent(
 509                 MouseEvent.MOUSE_MOVED, 350, 350));
 510 
 511         assertFalse(scene.smallSquareTracker.wasEnteredMe());
 512         assertFalse(scene.bigSquareTracker.wasEnteredMe());
 513         assertFalse(scene.groupTracker.wasEnteredMe());
 514         assertTrue(scene.smallSquareTracker.wasExitedMe());
 515         assertFalse(scene.bigSquareTracker.wasExitedMe());
 516         assertTrue(scene.groupTracker.wasExitedMe());
 517         assertFalse(scene.smallSquareTracker.wasEnteredChild());
 518         assertFalse(scene.bigSquareTracker.wasEnteredChild());
 519         assertFalse(scene.groupTracker.wasEnteredChild());
 520         assertFalse(scene.smallSquareTracker.wasExitedChild());
 521         assertFalse(scene.bigSquareTracker.wasExitedChild());
 522         assertTrue(scene.groupTracker.wasExitedChild());
 523     }
 524 
 525     @Test
 526     public void platformCursorShouldBeUpdated() {
 527         SimpleTestScene scene = new SimpleTestScene();
 528         MouseEventGenerator generator = new MouseEventGenerator();
 529 
 530         scene.processEvent(generator.generateMouseEvent(
 531                 MouseEvent.MOUSE_MOVED, 250, 250));
 532 
 533         assertSame(CursorShim.getCurrentFrame(Cursor.HAND), scene.getCursorFrame());
 534 
 535         scene.processEvent(generator.generateMouseEvent(
 536                 MouseEvent.MOUSE_MOVED, 150, 150));
 537 
 538         assertSame(CursorShim.getCurrentFrame(Cursor.TEXT), scene.getCursorFrame());
 539 
 540         scene.processEvent(generator.generateMouseEvent(
 541                 MouseEvent.MOUSE_MOVED, 50, 50));
 542 
 543         assertSame(CursorShim.getCurrentFrame(Cursor.DEFAULT),
 544                    scene.getCursorFrame());
 545     }
 546 
 547     @Test
 548     public void platformCursorShouldBeUpdatedOnPulse() {
 549 
 550         final StubToolkit toolkit = (StubToolkit) Toolkit.getToolkit();
 551         SimpleTestScene scene = new SimpleTestScene();
 552         MouseEventGenerator generator = new MouseEventGenerator();
 553 
 554         scene.processEvent(generator.generateMouseEvent(
 555                 MouseEvent.MOUSE_MOVED, 250, 250));
 556 
 557         assertSame(CursorShim.getCurrentFrame(Cursor.HAND), scene.getCursorFrame());
 558 
 559         scene.scene.setCursor(Cursor.TEXT);
 560         toolkit.firePulse();
 561         assertSame(CursorShim.getCurrentFrame(Cursor.TEXT), scene.getCursorFrame());
 562 
 563     }
 564 
 565     @Test
 566     public void testHover() {
 567         SimpleTestScene scene = new SimpleTestScene();
 568         MouseEventGenerator generator = new MouseEventGenerator();
 569 
 570         scene.processEvent(generator.generateMouseEvent(
 571                 MouseEvent.MOUSE_MOVED, 250, 250));
 572 
 573         assertTrue(scene.smallSquareTracker.isHover());
 574         assertFalse(scene.bigSquareTracker.isHover());
 575         assertTrue(scene.groupTracker.isHover());
 576 
 577         scene.processEvent(generator.generateMouseEvent(
 578                 MouseEvent.MOUSE_MOVED, 150, 150));
 579 
 580         assertFalse(scene.smallSquareTracker.isHover());
 581         assertTrue(scene.bigSquareTracker.isHover());
 582         assertTrue(scene.groupTracker.isHover());
 583 
 584         scene.processEvent(generator.generateMouseEvent(
 585                 MouseEvent.MOUSE_MOVED, 50, 50));
 586 
 587         assertFalse(scene.smallSquareTracker.isHover());
 588         assertFalse(scene.bigSquareTracker.isHover());
 589         assertFalse(scene.groupTracker.isHover());
 590     }
 591 
 592     @Test
 593     public void clickShouldBeGeneratedFromPressRelease() {
 594         SimpleTestScene scene = new SimpleTestScene();
 595         MouseEventGenerator generator = new MouseEventGenerator();
 596 
 597         scene.processEvent(generator.generateMouseEvent(
 598                 MouseEvent.MOUSE_PRESSED, 250, 250));
 599         scene.processEvent(generator.generateMouseEvent(
 600                 MouseEvent.MOUSE_RELEASED, 250, 250));
 601 
 602         assertTrue(scene.smallSquareTracker.wasClicked());
 603         assertFalse(scene.bigSquareTracker.wasClicked());
 604         assertTrue(scene.groupTracker.wasClicked());
 605     }
 606 
 607     @Test
 608     public void clickShouldBeGeneratedWhenReleasedOnTheSameNode() {
 609         SimpleTestScene scene = new SimpleTestScene();
 610         MouseEventGenerator generator = new MouseEventGenerator();
 611 
 612         scene.processEvent(generator.generateMouseEvent(
 613                 MouseEvent.MOUSE_PRESSED, 250, 250));
 614         scene.processEvent(generator.generateMouseEvent(
 615                 MouseEvent.MOUSE_DRAGGED, 50, 50));
 616         scene.processEvent(generator.generateMouseEvent(
 617                 MouseEvent.MOUSE_DRAGGED, 270, 270));
 618         scene.processEvent(generator.generateMouseEvent(
 619                 MouseEvent.MOUSE_RELEASED, 270, 270));
 620 
 621         assertTrue(scene.smallSquareTracker.wasClicked());
 622         assertFalse(scene.bigSquareTracker.wasClicked());
 623         assertTrue(scene.groupTracker.wasClicked());
 624     }
 625 
 626     @Test
 627     public void clickShouldBeGeneratedWhenReleasedOnParent() {
 628         SimpleTestScene scene = new SimpleTestScene();
 629         MouseEventGenerator generator = new MouseEventGenerator();
 630 
 631         scene.processEvent(generator.generateMouseEvent(
 632                 MouseEvent.MOUSE_PRESSED, 250, 250));
 633         scene.processEvent(generator.generateMouseEvent(
 634                 MouseEvent.MOUSE_DRAGGED, 150, 150));
 635         scene.processEvent(generator.generateMouseEvent(
 636                 MouseEvent.MOUSE_RELEASED, 150, 150));
 637 
 638         assertFalse(scene.smallSquareTracker.wasClicked());
 639         assertFalse(scene.bigSquareTracker.wasClicked());
 640         assertTrue(scene.groupTracker.wasClicked());
 641     }
 642 
 643     @Test
 644     public void doubleClickShouldBeGeneratedFromPressedReleasedTwoTimes() {
 645         SimpleTestScene scene = new SimpleTestScene();
 646         MouseEventGenerator generator = new MouseEventGenerator();
 647 
 648         scene.processEvent(generator.generateMouseEvent(
 649                 MouseEvent.MOUSE_PRESSED, 250, 250));
 650         scene.processEvent(generator.generateMouseEvent(
 651                 MouseEvent.MOUSE_RELEASED, 250, 250));
 652         scene.processEvent(generator.generateMouseEvent(
 653                 MouseEvent.MOUSE_PRESSED, 250, 250));
 654         scene.processEvent(generator.generateMouseEvent(
 655                 MouseEvent.MOUSE_RELEASED, 250, 250));
 656 
 657         assertTrue(scene.smallSquareTracker.wasDoubleClicked());
 658         assertFalse(scene.bigSquareTracker.wasDoubleClicked());
 659         assertTrue(scene.groupTracker.wasDoubleClicked());
 660     }
 661 
 662     @Test
 663     public void doubleClickShouldBeGeneratedEvenIfNodeChangesInBetween() {
 664         SimpleTestScene scene = new SimpleTestScene();
 665         MouseEventGenerator generator = new MouseEventGenerator();
 666 
 667         scene.processEvent(generator.generateMouseEvent(
 668                 MouseEvent.MOUSE_PRESSED, 199, 250));
 669         scene.processEvent(generator.generateMouseEvent(
 670                 MouseEvent.MOUSE_RELEASED, 199, 250));
 671         scene.processEvent(generator.generateMouseEvent(
 672                 MouseEvent.MOUSE_PRESSED, 201, 250));
 673         scene.processEvent(generator.generateMouseEvent(
 674                 MouseEvent.MOUSE_RELEASED, 201, 250));
 675 
 676         assertTrue(scene.smallSquareTracker.wasDoubleClicked());
 677         assertFalse(scene.bigSquareTracker.wasDoubleClicked());
 678         assertTrue(scene.bigSquareTracker.wasClicked());
 679     }
 680 
 681     @Test
 682     public void doubleClickShouldBeGeneratedFromPressedReleasedTwoTimesWithHysteresis() {
 683         SimpleTestScene scene = new SimpleTestScene();
 684         MouseEventGenerator generator = new MouseEventGenerator();
 685 
 686         scene.processEvent(generator.generateMouseEvent(
 687                 MouseEvent.MOUSE_PRESSED, 250, 250));
 688         scene.processEvent(generator.generateMouseEvent(
 689                 MouseEvent.MOUSE_DRAGGED, 251, 251));
 690         scene.processEvent(generator.generateMouseEvent(
 691                 MouseEvent.MOUSE_RELEASED, 251, 251));
 692         scene.processEvent(generator.generateMouseEvent(
 693                 MouseEvent.MOUSE_DRAGGED, 252, 252));
 694         scene.processEvent(generator.generateMouseEvent(
 695                 MouseEvent.MOUSE_PRESSED, 252, 252));
 696         scene.processEvent(generator.generateMouseEvent(
 697                 MouseEvent.MOUSE_DRAGGED, 253, 253));
 698         scene.processEvent(generator.generateMouseEvent(
 699                 MouseEvent.MOUSE_RELEASED, 253, 253));
 700 
 701         assertTrue(scene.smallSquareTracker.wasDoubleClicked());
 702         assertFalse(scene.bigSquareTracker.wasDoubleClicked());
 703         assertTrue(scene.groupTracker.wasDoubleClicked());
 704     }
 705 
 706     @Test
 707     public void doubleClickShouldNotBeGeneratedWhenMovedFarAwayBetweenClick() {
 708         SimpleTestScene scene = new SimpleTestScene();
 709         MouseEventGenerator generator = new MouseEventGenerator();
 710 
 711         scene.processEvent(generator.generateMouseEvent(
 712                 MouseEvent.MOUSE_PRESSED, 250, 250));
 713         scene.processEvent(generator.generateMouseEvent(
 714                 MouseEvent.MOUSE_RELEASED, 250, 250));
 715         scene.processEvent(generator.generateMouseEvent(
 716                 MouseEvent.MOUSE_DRAGGED, 258, 258));
 717         scene.processEvent(generator.generateMouseEvent(
 718                 MouseEvent.MOUSE_PRESSED, 258, 258));
 719         scene.processEvent(generator.generateMouseEvent(
 720                 MouseEvent.MOUSE_RELEASED, 258, 258));
 721 
 722         assertTrue(scene.smallSquareTracker.wasClicked());
 723         assertFalse(scene.bigSquareTracker.wasClicked());
 724         assertTrue(scene.groupTracker.wasClicked());
 725         assertFalse(scene.smallSquareTracker.wasDoubleClicked());
 726         assertFalse(scene.bigSquareTracker.wasDoubleClicked());
 727         assertFalse(scene.groupTracker.wasDoubleClicked());
 728     }
 729 
 730     @Test
 731     public void doubleClickShouldNotBeGeneratedWhenMovedFarAwayInFirstClick() {
 732         SimpleTestScene scene = new SimpleTestScene();
 733         MouseEventGenerator generator = new MouseEventGenerator();
 734 
 735         scene.processEvent(generator.generateMouseEvent(
 736                 MouseEvent.MOUSE_PRESSED, 250, 250));
 737         scene.processEvent(generator.generateMouseEvent(
 738                 MouseEvent.MOUSE_DRAGGED, 258, 258));
 739         scene.processEvent(generator.generateMouseEvent(
 740                 MouseEvent.MOUSE_RELEASED, 258, 258));
 741         scene.processEvent(generator.generateMouseEvent(
 742                 MouseEvent.MOUSE_PRESSED, 258, 258));
 743         scene.processEvent(generator.generateMouseEvent(
 744                 MouseEvent.MOUSE_RELEASED, 258, 258));
 745 
 746         assertTrue(scene.smallSquareTracker.wasClicked());
 747         assertFalse(scene.bigSquareTracker.wasClicked());
 748         assertTrue(scene.groupTracker.wasClicked());
 749         assertFalse(scene.smallSquareTracker.wasDoubleClicked());
 750         assertFalse(scene.bigSquareTracker.wasDoubleClicked());
 751         assertFalse(scene.groupTracker.wasDoubleClicked());
 752     }
 753 
 754     @Test
 755     public void doubleClickShouldBeGeneratedWhenMovedFarAwayInSecondClick() {
 756         SimpleTestScene scene = new SimpleTestScene();
 757         MouseEventGenerator generator = new MouseEventGenerator();
 758 
 759         scene.processEvent(generator.generateMouseEvent(
 760                 MouseEvent.MOUSE_PRESSED, 250, 250));
 761         scene.processEvent(generator.generateMouseEvent(
 762                 MouseEvent.MOUSE_RELEASED, 250, 250));
 763         scene.processEvent(generator.generateMouseEvent(
 764                 MouseEvent.MOUSE_PRESSED, 250, 250));
 765         scene.processEvent(generator.generateMouseEvent(
 766                 MouseEvent.MOUSE_DRAGGED, 258, 258));
 767         scene.processEvent(generator.generateMouseEvent(
 768                 MouseEvent.MOUSE_RELEASED, 258, 258));
 769 
 770         assertTrue(scene.smallSquareTracker.wasDoubleClicked());
 771         assertFalse(scene.bigSquareTracker.wasDoubleClicked());
 772         assertTrue(scene.groupTracker.wasDoubleClicked());
 773     }
 774 
 775     @Test
 776     public void doubleClickShouldNotBeGeneratedWithLongTimeBetweenClicks() {
 777         SimpleTestScene scene = new SimpleTestScene();
 778         MouseEventGenerator generator = new MouseEventGenerator();
 779 
 780         ((StubToolkit) Toolkit.getToolkit()).setAnimationTime(0);
 781 
 782         scene.processEvent(generator.generateMouseEvent(
 783                 MouseEvent.MOUSE_PRESSED, 250, 250));
 784         scene.processEvent(generator.generateMouseEvent(
 785                 MouseEvent.MOUSE_RELEASED, 250, 250));
 786 
 787         ((StubToolkit) Toolkit.getToolkit()).setAnimationTime(2000);
 788 
 789         scene.processEvent(generator.generateMouseEvent(
 790                 MouseEvent.MOUSE_PRESSED, 250, 250));
 791         scene.processEvent(generator.generateMouseEvent(
 792                 MouseEvent.MOUSE_RELEASED, 250, 250));
 793 
 794         assertTrue(scene.smallSquareTracker.wasClicked());
 795         assertFalse(scene.bigSquareTracker.wasClicked());
 796         assertTrue(scene.groupTracker.wasClicked());
 797         assertFalse(scene.smallSquareTracker.wasDoubleClicked());
 798         assertFalse(scene.bigSquareTracker.wasDoubleClicked());
 799         assertFalse(scene.groupTracker.wasDoubleClicked());
 800     }
 801 
 802     @Test
 803     public void doubleClickShouldNotBeGeneratedWithLongTimeInFirstClick() {
 804         SimpleTestScene scene = new SimpleTestScene();
 805         MouseEventGenerator generator = new MouseEventGenerator();
 806 
 807         ((StubToolkit) Toolkit.getToolkit()).setAnimationTime(0);
 808 
 809         scene.processEvent(generator.generateMouseEvent(
 810                 MouseEvent.MOUSE_PRESSED, 250, 250));
 811 
 812         ((StubToolkit) Toolkit.getToolkit()).setAnimationTime(2000);
 813 
 814         scene.processEvent(generator.generateMouseEvent(
 815                 MouseEvent.MOUSE_RELEASED, 250, 250));
 816         scene.processEvent(generator.generateMouseEvent(
 817                 MouseEvent.MOUSE_PRESSED, 250, 250));
 818         scene.processEvent(generator.generateMouseEvent(
 819                 MouseEvent.MOUSE_RELEASED, 250, 250));
 820 
 821         assertTrue(scene.smallSquareTracker.wasClicked());
 822         assertFalse(scene.bigSquareTracker.wasClicked());
 823         assertTrue(scene.groupTracker.wasClicked());
 824         assertFalse(scene.smallSquareTracker.wasDoubleClicked());
 825         assertFalse(scene.bigSquareTracker.wasDoubleClicked());
 826         assertFalse(scene.groupTracker.wasDoubleClicked());
 827     }
 828 
 829     @Test
 830     public void doubleClickShouldBeGeneratedWithLongTimeInSecondClick() {
 831         SimpleTestScene scene = new SimpleTestScene();
 832         MouseEventGenerator generator = new MouseEventGenerator();
 833 
 834         ((StubToolkit) Toolkit.getToolkit()).setAnimationTime(0);
 835 
 836         scene.processEvent(generator.generateMouseEvent(
 837                 MouseEvent.MOUSE_PRESSED, 250, 250));
 838         scene.processEvent(generator.generateMouseEvent(
 839                 MouseEvent.MOUSE_RELEASED, 250, 250));
 840         scene.processEvent(generator.generateMouseEvent(
 841                 MouseEvent.MOUSE_PRESSED, 250, 250));
 842 
 843         ((StubToolkit) Toolkit.getToolkit()).setAnimationTime(2000);
 844 
 845         scene.processEvent(generator.generateMouseEvent(
 846                 MouseEvent.MOUSE_RELEASED, 250, 250));
 847 
 848         assertTrue(scene.smallSquareTracker.wasDoubleClicked());
 849         assertFalse(scene.bigSquareTracker.wasDoubleClicked());
 850         assertTrue(scene.groupTracker.wasDoubleClicked());
 851     }
 852 
 853     @Test
 854     public void testClickCountOfMouseEvents() {
 855         SimpleTestScene scene = new SimpleTestScene();
 856         MouseEventGenerator generator = new MouseEventGenerator();
 857 
 858         scene.processEvent(generator.generateMouseEvent(
 859                 MouseEvent.MOUSE_MOVED, 250, 250));
 860         assertEquals(0, scene.smallSquareTracker.getLastClickCount());
 861         scene.smallSquareTracker.clear();
 862 
 863         scene.processEvent(generator.generateMouseEvent(
 864                 MouseEvent.MOUSE_PRESSED, 250, 250));
 865         assertEquals(1, scene.smallSquareTracker.getLastClickCount());
 866         scene.smallSquareTracker.clear();
 867 
 868         scene.processEvent(generator.generateMouseEvent(
 869                 MouseEvent.MOUSE_DRAGGED, 251, 251));
 870         assertEquals(1, scene.smallSquareTracker.getLastClickCount());
 871         scene.smallSquareTracker.clear();
 872 
 873         scene.processEvent(generator.generateMouseEvent(
 874                 MouseEvent.MOUSE_RELEASED, 251, 251));
 875         assertEquals(1, scene.smallSquareTracker.getLastClickCount());
 876         scene.smallSquareTracker.clear();
 877 
 878         scene.processEvent(generator.generateMouseEvent(
 879                 MouseEvent.MOUSE_MOVED, 252, 252));
 880         assertEquals(0, scene.smallSquareTracker.getLastClickCount());
 881         scene.smallSquareTracker.clear();
 882 
 883         scene.processEvent(generator.generateMouseEvent(
 884                 MouseEvent.MOUSE_PRESSED, 252, 252));
 885         assertEquals(2, scene.smallSquareTracker.getLastClickCount());
 886         scene.smallSquareTracker.clear();
 887 
 888         scene.processEvent(generator.generateMouseEvent(
 889                 MouseEvent.MOUSE_DRAGGED, 280, 280));
 890         assertEquals(2, scene.smallSquareTracker.getLastClickCount());
 891         scene.smallSquareTracker.clear();
 892 
 893         scene.processEvent(generator.generateMouseEvent(
 894                 MouseEvent.MOUSE_RELEASED, 280, 280));
 895         assertEquals(2, scene.smallSquareTracker.getLastClickCount());
 896         scene.smallSquareTracker.clear();
 897 
 898         scene.processEvent(generator.generateMouseEvent(
 899                 MouseEvent.MOUSE_MOVED, 280, 280));
 900         assertEquals(0, scene.smallSquareTracker.getLastClickCount());
 901         scene.smallSquareTracker.clear();
 902 
 903         scene.processEvent(generator.generateMouseEvent(
 904                 MouseEvent.MOUSE_PRESSED, 280, 280));
 905         assertEquals(1, scene.smallSquareTracker.getLastClickCount());
 906         scene.smallSquareTracker.clear();
 907 
 908         scene.processEvent(generator.generateMouseEvent(
 909                 MouseEvent.MOUSE_RELEASED, 280, 280));
 910         assertEquals(1, scene.smallSquareTracker.getLastClickCount());
 911         scene.smallSquareTracker.clear();
 912     }
 913 
 914     @Test
 915     public void testIsStillOfMouseEvents() {
 916         SimpleTestScene scene = new SimpleTestScene();
 917         MouseEventGenerator generator = new MouseEventGenerator();
 918 
 919         scene.processEvent(generator.generateMouseEvent(
 920                 MouseEvent.MOUSE_MOVED, 250, 250));
 921         assertFalse(scene.smallSquareTracker.wasLastStill());
 922 
 923         scene.processEvent(generator.generateMouseEvent(
 924                 MouseEvent.MOUSE_PRESSED, 250, 250));
 925         assertFalse(scene.smallSquareTracker.wasLastStill());
 926 
 927         scene.processEvent(generator.generateMouseEvent(
 928                 MouseEvent.MOUSE_DRAGGED, 252, 252));
 929         assertTrue(scene.smallSquareTracker.wasLastStill());
 930 
 931         scene.processEvent(generator.generateMouseEvent(
 932                 MouseEvent.MOUSE_RELEASED, 252, 252));
 933         assertTrue(scene.smallSquareTracker.wasLastStill());
 934 
 935         scene.processEvent(generator.generateMouseEvent(
 936                 MouseEvent.MOUSE_MOVED, 254, 254));
 937         assertTrue(scene.smallSquareTracker.wasLastStill());
 938 
 939         scene.processEvent(generator.generateMouseEvent(
 940                 MouseEvent.MOUSE_PRESSED, 254, 254));
 941         assertTrue(scene.smallSquareTracker.wasLastStill());
 942 
 943         scene.processEvent(generator.generateMouseEvent(
 944                 MouseEvent.MOUSE_DRAGGED, 257, 257));
 945         assertTrue(scene.smallSquareTracker.wasLastStill());
 946 
 947         scene.processEvent(generator.generateMouseEvent(
 948                 MouseEvent.MOUSE_DRAGGED, 265, 265));
 949         assertFalse(scene.smallSquareTracker.wasLastStill());
 950 
 951         scene.processEvent(generator.generateMouseEvent(
 952                 MouseEvent.MOUSE_RELEASED, 265, 265));
 953         assertFalse(scene.smallSquareTracker.wasLastStill());
 954 
 955         scene.processEvent(generator.generateMouseEvent(
 956                 MouseEvent.MOUSE_MOVED, 266, 266));
 957         assertFalse(scene.smallSquareTracker.wasLastStill());
 958 
 959         scene.processEvent(generator.generateMouseEvent(
 960                 MouseEvent.MOUSE_PRESSED, 266, 266));
 961         assertFalse(scene.smallSquareTracker.wasLastStill());
 962 
 963         scene.processEvent(generator.generateMouseEvent(
 964                 MouseEvent.MOUSE_RELEASED, 266, 266));
 965         assertTrue(scene.smallSquareTracker.wasLastStill());
 966     }
 967 
 968     @Test
 969     public void nodeMovementsWithStillMouseShouldFireEnteredExited() {
 970         SimpleTestScene scene = new SimpleTestScene();
 971         MouseEventGenerator generator = new MouseEventGenerator();
 972 
 973         scene.processEvent(generator.generateMouseEvent(
 974                 MouseEvent.MOUSE_ENTERED, 250, 250));
 975         scene.processEvent(generator.generateMouseEvent(
 976                 MouseEvent.MOUSE_MOVED, 250, 250));
 977         scene.smallSquareTracker.clear();
 978 
 979         assertFalse(scene.smallSquareTracker.exitedMe);
 980         ((Rectangle) scene.smallSquareTracker.node).setX(400);
 981         ((StubToolkit) Toolkit.getToolkit()).firePulse();
 982         assertTrue(scene.smallSquareTracker.exitedMe);
 983 
 984         scene.smallSquareTracker.clear();
 985 
 986         assertFalse(scene.smallSquareTracker.enteredMe);
 987         ((Rectangle) scene.smallSquareTracker.node).setX(200);
 988         ((StubToolkit) Toolkit.getToolkit()).firePulse();
 989         assertTrue(scene.smallSquareTracker.enteredMe);
 990     }
 991 
 992     @Test
 993     public void nodeWithNoninvertibleTransformShouldGetNanCoords() {
 994         SimpleTestScene scene = new SimpleTestScene();
 995         MouseEventGenerator generator = new MouseEventGenerator();
 996 
 997         scene.processEvent(generator.generateMouseEvent(
 998                 MouseEvent.MOUSE_PRESSED, 250, 250));
 999         scene.smallSquareTracker.clear();
1000 
1001         scene.smallSquareTracker.node.addEventHandler(MouseEvent.MOUSE_RELEASED,
1002                 event -> {
1003                     Assert.assertEquals(Double.NaN, event.getX(), 0.0001);
1004                     Assert.assertEquals(Double.NaN, event.getY(), 0.0001);
1005                     Assert.assertEquals(251.0, event.getSceneX(), 0.0001);
1006                     Assert.assertEquals(251.0, event.getSceneY(), 0.0001);
1007                 }
1008         );
1009 
1010         ((Rectangle) scene.smallSquareTracker.node).setScaleX(0);
1011 
1012         scene.processEvent(generator.generateMouseEvent(
1013                 MouseEvent.MOUSE_RELEASED, 251, 251));
1014 
1015         assertTrue(scene.smallSquareTracker.released);
1016     }
1017 
1018     @Test
1019     public void topMostNodeShouldBePickedWithDepthBufferByPerspectiveCamera() {
1020         SimpleTestScene scene = new SimpleTestScene(true, true);
1021         MouseEventGenerator generator = new MouseEventGenerator();
1022 
1023         scene.processEvent(generator.generateMouseEvent(
1024                 MouseEvent.MOUSE_MOVED, 250, 250));
1025 
1026         assertFalse(scene.smallSquareTracker.wasMoved());
1027         assertTrue(scene.bigSquareTracker.wasMoved());
1028         assertTrue(scene.groupTracker.wasMoved());
1029     }
1030 
1031     @Test
1032     public void topMostNodeShouldBePickedWithDepthBufferByParallelCamera() {
1033         SimpleTestScene scene = new SimpleTestScene(true, false);
1034         MouseEventGenerator generator = new MouseEventGenerator();
1035 
1036         scene.processEvent(generator.generateMouseEvent(
1037                 MouseEvent.MOUSE_MOVED, 250, 250));
1038 
1039         assertFalse(scene.smallSquareTracker.wasMoved());
1040         assertTrue(scene.bigSquareTracker.wasMoved());
1041         assertTrue(scene.groupTracker.wasMoved());
1042     }
1043 
1044     @Test
1045     public void subSceneShouldBePickedOnFill() {
1046         final TestSceneWithSubScenes s = new TestSceneWithSubScenes();
1047 
1048         s.subScene1.setFill(Color.BLACK);
1049 
1050         s.scene.addEventFilter(MouseEvent.MOUSE_MOVED,
1051                 s.handler(s.subScene1, DONT_TEST, DONT_TEST));
1052 
1053         s.processEvent(MouseEvent.MOUSE_MOVED, 22, 12);
1054         s.assertCalled();
1055     }
1056 
1057     @Test
1058     public void subSceneShouldNotBePickedWithoutFill() {
1059         final TestSceneWithSubScenes s = new TestSceneWithSubScenes();
1060 
1061         s.scene.addEventFilter(MouseEvent.MOUSE_MOVED,
1062                 s.handler(s.scene, DONT_TEST, DONT_TEST));
1063 
1064         s.processEvent(MouseEvent.MOUSE_MOVED, 22, 12);
1065         s.assertCalled();
1066     }
1067 
1068     @Test
1069     public void eventShouldBubbleOutOfSubScene() {
1070         final TestSceneWithSubScenes s = new TestSceneWithSubScenes();
1071 
1072         s.parent1.setOnMouseMoved(s.handler(s.innerRect1, 120, 20));
1073 
1074         s.processEvent(MouseEvent.MOUSE_MOVED, 130, 30);
1075         s.assertCalled();
1076     }
1077 
1078     @Test
1079     public void enteredEventShouldBeGeneratedInsideSubScene() {
1080         final TestSceneWithSubScenes s = new TestSceneWithSubScenes();
1081 
1082         s.innerRect1.setOnMouseEntered(s.handler(s.innerRect1, 10, 10));
1083 
1084         s.processEvent(MouseEvent.MOUSE_MOVED, 130, 30);
1085         s.assertCalled();
1086     }
1087 
1088     @Test
1089     public void enteredEventShouldBubbleOutOfSubScene() {
1090         final TestSceneWithSubScenes s = new TestSceneWithSubScenes();
1091 
1092         s.parent1.addEventHandler(MouseEvent.MOUSE_ENTERED_TARGET,
1093                 event -> {
1094                     if (event.getTarget() == s.innerRect1) {
1095                         s.called = true;
1096                     }
1097                 }
1098         );
1099 
1100         s.processEvent(MouseEvent.MOUSE_MOVED, 130, 30);
1101         s.assertCalled();
1102     }
1103 
1104     @Test
1105     public void enteredEventShouldBeGeneratedOutsideSubScene() {
1106         final TestSceneWithSubScenes s = new TestSceneWithSubScenes();
1107 
1108         s.parent1.setOnMouseEntered(s.handler(s.parent1, 120, 20));
1109 
1110         s.processEvent(MouseEvent.MOUSE_MOVED, 130, 30);
1111         s.assertCalled();
1112     }
1113 
1114     @Test
1115     public void exitedEventShouldBeGeneratedInsideSubScene() {
1116         final TestSceneWithSubScenes s = new TestSceneWithSubScenes();
1117 
1118         s.innerRect1.setOnMouseExited(s.handler(s.innerRect1, 60, 10));
1119 
1120         s.processEvent(MouseEvent.MOUSE_MOVED, 130, 30);
1121         s.processEvent(MouseEvent.MOUSE_MOVED, 180, 30);
1122         s.assertCalled();
1123     }
1124 
1125     @Test
1126     public void exitedEventShouldBeGeneratedInsideSubSceneWhenMovedOut() {
1127         final TestSceneWithSubScenes s = new TestSceneWithSubScenes();
1128 
1129         s.innerRect1.setOnMouseExited(s.handler(s.innerRect1, 60, -15));
1130 
1131         s.processEvent(MouseEvent.MOUSE_MOVED, 130, 30);
1132         s.processEvent(MouseEvent.MOUSE_MOVED, 180, 5);
1133         s.assertCalled();
1134     }
1135 
1136     @Test
1137     public void exitedEventShouldBeGeneratedInsideSubSceneWhenMovedToOtherSubScene() {
1138         final TestSceneWithSubScenes s = new TestSceneWithSubScenes();
1139 
1140         s.innerRect1.setOnMouseExited(s.handler(s.innerRect1, 240, 10));
1141 
1142         s.processEvent(MouseEvent.MOUSE_MOVED, 130, 30);
1143         s.processEvent(MouseEvent.MOUSE_MOVED, 360, 30);
1144         s.assertCalled();
1145     }
1146 
1147     @Test
1148     public void cursorShouldBePropagatedFromSubScene() {
1149         final TestSceneWithSubScenes s = new TestSceneWithSubScenes();
1150 
1151         s.innerRect1.setCursor(Cursor.HAND);
1152         s.processEvent(MouseEvent.MOUSE_MOVED, 130, 30);
1153         assertSame(CursorShim.getCurrentFrame(Cursor.HAND), s.getCursorFrame());
1154     }
1155 
1156     @Test
1157     public void cursorShouldBeTakenFromOutsideOfSubScene() {
1158         final TestSceneWithSubScenes s = new TestSceneWithSubScenes();
1159 
1160         s.parent1.setCursor(Cursor.HAND);
1161         s.processEvent(MouseEvent.MOUSE_MOVED, 130, 30);
1162         assertSame(CursorShim.getCurrentFrame(Cursor.HAND), s.getCursorFrame());
1163     }
1164 
1165     @Test
1166     public void coordinatesShouldBeFineWhenDraggedOutOfSubSecne() {
1167         final TestSceneWithSubScenes s = new TestSceneWithSubScenes();
1168 
1169         s.innerRect1.setOnMouseDragged(s.handler(s.innerRect1, 60, -15));
1170 
1171         s.processEvent(MouseEvent.MOUSE_MOVED, 130, 30);
1172         s.processEvent(MouseEvent.MOUSE_PRESSED, 130, 30);
1173         s.processEvent(MouseEvent.MOUSE_DRAGGED, 180, 5);
1174         s.processEvent(MouseEvent.MOUSE_RELEASED, 180, 5);
1175 
1176         s.assertCalled();
1177         assertNotNull(s.lastPickResult);
1178         assertNull(s.lastPickResult.getIntersectedNode());
1179     }
1180 
1181     @Test
1182     public void coordinatesShouldBeFineWhenDraggedToOtherSubSecne() {
1183         final TestSceneWithSubScenes s = new TestSceneWithSubScenes();
1184 
1185         s.innerRect1.setOnMouseDragged(s.handler(s.innerRect1, 240, 10));
1186 
1187         s.processEvent(MouseEvent.MOUSE_MOVED, 130, 30);
1188         s.processEvent(MouseEvent.MOUSE_PRESSED, 130, 30);
1189         s.processEvent(MouseEvent.MOUSE_DRAGGED, 360, 30);
1190         s.processEvent(MouseEvent.MOUSE_RELEASED, 360, 30);
1191 
1192         s.assertCalled();
1193         assertNotNull(s.lastPickResult);
1194         assertSame(s.innerRect2, s.lastPickResult.getIntersectedNode());
1195     }
1196 
1197     @Test
1198     public void fullDragShouldDeliverToOtherSubScene() {
1199         final TestSceneWithSubScenes s = new TestSceneWithSubScenes();
1200 
1201         s.innerRect1.setOnDragDetected(event -> s.innerRect1.startFullDrag());
1202         s.innerRect2.setOnMouseDragOver(s.handler(s.innerRect2, 10, 10));
1203 
1204         s.processEvent(MouseEvent.MOUSE_MOVED, 130, 30);
1205         s.processEvent(MouseEvent.MOUSE_PRESSED, 130, 30);
1206         s.processEvent(MouseEvent.MOUSE_DRAGGED, 360, 29);
1207         s.processEvent(MouseEvent.MOUSE_DRAGGED, 360, 30);
1208         s.processEvent(MouseEvent.MOUSE_RELEASED, 360, 30);
1209 
1210         s.assertCalled();
1211     }
1212 
1213     @Test
1214     public void fullDragEnterShouldDeliverToOtherSubScene() {
1215         final TestSceneWithSubScenes s = new TestSceneWithSubScenes();
1216 
1217         s.innerRect1.setOnDragDetected(event -> s.innerRect1.startFullDrag());
1218         s.innerRect2.setOnMouseDragEntered(s.handler(s.innerRect2, 10, 10));
1219 
1220         s.processEvent(MouseEvent.MOUSE_MOVED, 130, 30);
1221         s.processEvent(MouseEvent.MOUSE_PRESSED, 130, 30);
1222         s.processEvent(MouseEvent.MOUSE_DRAGGED, 360, 30);
1223         s.processEvent(MouseEvent.MOUSE_RELEASED, 360, 30);
1224 
1225         s.assertCalled();
1226     }
1227 
1228     @Test
1229     public void fullDragEnterShouldDeliverToOtherSubScenesParent() {
1230         final TestSceneWithSubScenes s = new TestSceneWithSubScenes();
1231 
1232         s.innerRect1.setOnDragDetected(event -> s.innerRect1.startFullDrag());
1233         s.parent2.setOnMouseDragEntered(s.handler(s.parent2, 130, 20));
1234 
1235         s.processEvent(MouseEvent.MOUSE_MOVED, 130, 30);
1236         s.processEvent(MouseEvent.MOUSE_PRESSED, 130, 30);
1237         s.processEvent(MouseEvent.MOUSE_DRAGGED, 360, 30);
1238         s.processEvent(MouseEvent.MOUSE_RELEASED, 360, 30);
1239 
1240         s.assertCalled();
1241     }
1242 
1243     @Test
1244     public void depthBufferShouldWorkInsideSubScene() {
1245         final TestSceneWithSubScenes s = new TestSceneWithSubScenes(false, true);
1246 
1247         Rectangle r = new Rectangle(50, 50);
1248         r.setTranslateX(100);
1249         r.setTranslateY(10);
1250         r.setTranslateZ(1);
1251         ParentShim.getChildren(s.subScene1.getRoot()).add(r);
1252 
1253         s.innerRect1.addEventFilter(MouseEvent.MOUSE_MOVED,
1254                 s.handler(s.innerRect1, DONT_TEST, DONT_TEST));
1255 
1256         s.processEvent(MouseEvent.MOUSE_MOVED, 130, 30);
1257         s.assertCalled();
1258     }
1259 
1260     @Test
1261     public void sceneDepthBufferShouldNotInfluenceSubSceneDepthBuffer() {
1262         final TestSceneWithSubScenes s = new TestSceneWithSubScenes(true, false);
1263 
1264         Rectangle r = new Rectangle(50, 50);
1265         r.setTranslateX(100);
1266         r.setTranslateY(10);
1267         r.setTranslateZ(1);
1268         ParentShim.getChildren(s.subScene1.getRoot()).add(r);
1269 
1270         r.addEventFilter(MouseEvent.MOUSE_MOVED,
1271                 s.handler(r, DONT_TEST, DONT_TEST));
1272 
1273         s.processEvent(MouseEvent.MOUSE_MOVED, 130, 30);
1274         s.assertCalled();
1275     }
1276 
1277     @Test
1278     public void sceneShouldConsiderSubScenesFlat() {
1279         final TestSceneWithSubScenes s = new TestSceneWithSubScenes(false, true);
1280 
1281         s.parent2.setTranslateX(10);
1282         s.innerRect2.setTranslateZ(-10);
1283         s.parent2.setTranslateZ(1);
1284 
1285         s.innerRect2.addEventFilter(MouseEvent.MOUSE_MOVED,
1286                 s.handler(s.innerRect2, DONT_TEST, DONT_TEST));
1287 
1288         s.processEvent(MouseEvent.MOUSE_MOVED, 130, 30);
1289         s.assertCalled();
1290     }
1291 
1292     @Test
1293     public void coordinatesShouldBeFlattenedWhenBubblingOutOfSubScene() {
1294         final TestSceneWithSubScenes s = new TestSceneWithSubScenes();
1295 
1296         s.subScene1.setTranslateZ(5);
1297         s.innerRect1.setTranslateZ(10);
1298 
1299         s.parent1.setOnMouseMoved(event -> {
1300             Assert.assertEquals(5, event.getZ(), 0.00001);
1301             assertSame(s.innerRect1, event.getTarget());
1302             s.called = true;
1303         });
1304 
1305         s.processEvent(MouseEvent.MOUSE_MOVED, 130, 30);
1306         s.processEvent(MouseEvent.MOUSE_MOVED, 360, 30);
1307         s.assertCalled();
1308     }
1309 
1310     @Test
1311     public void coordinatesShouldBeReComputedToSubScenePlane() {
1312         final TestSceneWithSubScenes s = new TestSceneWithSubScenes();
1313 
1314         s.parent2.setTranslateZ(10);
1315         s.innerRect2.setTranslateZ(10);
1316 
1317         s.innerRect1.setOnMouseExited(s.handler(s.innerRect1, 240, 10));
1318 
1319         s.processEvent(MouseEvent.MOUSE_MOVED, 130, 30);
1320         s.processEvent(MouseEvent.MOUSE_MOVED, 360, 30);
1321         s.assertCalled();
1322     }
1323 
1324     @Test
1325     public void coordinatesShouldBeRecomputedToSubSceneProjectionPlane() {
1326         final TestSceneWithSubScenes s = new TestSceneWithSubScenes();
1327 
1328         s.scene.setCamera(new PerspectiveCamera());
1329         s.subScene1.setCamera(new PerspectiveCamera());
1330         s.subScene2.setCamera(new PerspectiveCamera());
1331 
1332         s.subScene1.setRotationAxis(Rotate.Y_AXIS);
1333         s.subScene1.setRotate(45);
1334         s.subScene2.setRotationAxis(Rotate.Y_AXIS);
1335         s.subScene2.setRotate(-45);
1336         ((Group) s.subScene1.getRoot()).getChildren().add(s.subScene1.getCamera());
1337         s.subScene1.getCamera().setTranslateZ(-3.0);
1338 
1339         s.innerRect1.setOnMouseExited(event -> {
1340             assertSame(s.innerRect2, event.getPickResult().getIntersectedNode());
1341             assertSame(s.innerRect1, event.getTarget());
1342             Assert.assertEquals(16.58, event.getPickResult().getIntersectedPoint().getX(), 0.1);
1343             Assert.assertEquals(7.33, event.getPickResult().getIntersectedPoint().getY(), 0.1);
1344             Assert.assertEquals(0.0, event.getPickResult().getIntersectedPoint().getZ(), 0.0001);
1345             Assert.assertEquals(295.81, event.getX(), 0.1);
1346             Assert.assertEquals(57.64, event.getY(), 0.1);
1347             Assert.assertEquals(-3.0, event.getZ(), 0.1);
1348 
1349             s.called = true;
1350         });
1351 
1352         s.processEvent(MouseEvent.MOUSE_MOVED, 130, 30);
1353         s.processEvent(MouseEvent.MOUSE_MOVED, 360, 30);
1354         s.assertCalled();
1355     }
1356 
1357     @Test
1358     public void coordinatesShouldBeRecomputedToNodeLocalCoordsOfSubSceneProjectionPlane() {
1359         final TestSceneWithSubScenes s = new TestSceneWithSubScenes();
1360 
1361         s.scene.setCamera(new PerspectiveCamera());
1362         s.subScene1.setCamera(new PerspectiveCamera());
1363         s.subScene2.setCamera(new PerspectiveCamera());
1364 
1365         s.subScene1.setRotationAxis(Rotate.Y_AXIS);
1366         s.subScene1.setRotate(45);
1367         s.innerRect1.setRotationAxis(Rotate.Y_AXIS);
1368         s.innerRect1.setRotate(-45);
1369         s.subScene2.setRotationAxis(Rotate.Y_AXIS);
1370         s.subScene2.setRotate(-45);
1371         s.innerRect2.setRotationAxis(Rotate.Y_AXIS);
1372         s.innerRect2.setRotate(45);
1373 
1374         s.innerRect1.setOnMouseExited(event -> {
1375             assertSame(s.innerRect2, event.getPickResult().getIntersectedNode());
1376             assertSame(s.innerRect1, event.getTarget());
1377             Assert.assertEquals(14.07, event.getPickResult().getIntersectedPoint().getX(), 0.1);
1378             Assert.assertEquals(5.97, event.getPickResult().getIntersectedPoint().getY(), 0.1);
1379             Assert.assertEquals(0.0, event.getPickResult().getIntersectedPoint().getZ(), 0.0001);
1380             Assert.assertEquals(216.49, event.getX(), 0.1);
1381             Assert.assertEquals(57.64, event.getY(), 0.1);
1382             Assert.assertEquals(-191.49, event.getZ(), 0.1);
1383 
1384             s.called = true;
1385         });
1386 
1387         s.processEvent(MouseEvent.MOUSE_MOVED, 130, 30);
1388         s.processEvent(MouseEvent.MOUSE_MOVED, 360, 30);
1389         s.assertCalled();
1390     }
1391 
1392     @Test
1393     public void ImpossibleToComputeSubSceneInnerNodeCoordsShouldResultInNaNs() {
1394         final TestSceneWithSubScenes s = new TestSceneWithSubScenes();
1395 
1396         s.parent2.setTranslateZ(10);
1397         s.innerRect2.setTranslateZ(10);
1398 
1399         s.innerRect1.setOnMouseMoved(event -> s.innerRect1.setScaleX(0.0));
1400 
1401         s.innerRect1.setOnMouseExited(event -> {
1402             assertSame(s.innerRect1, event.getTarget());
1403             assertTrue(Double.isNaN(event.getX()));
1404             assertTrue(Double.isNaN(event.getY()));
1405             assertTrue(Double.isNaN(event.getZ()));
1406             s.called = true;
1407         });
1408 
1409         s.processEvent(MouseEvent.MOUSE_MOVED, 130, 30);
1410         s.processEvent(MouseEvent.MOUSE_MOVED, 360, 30);
1411         s.assertCalled();
1412     }
1413 
1414     @Test
1415     public void ImpossibleToComputeSubSceneCoordsShouldResultInNaNs() {
1416         final TestSceneWithSubScenes s = new TestSceneWithSubScenes();
1417 
1418         s.parent2.setTranslateZ(10);
1419         s.innerRect2.setTranslateZ(10);
1420 
1421         s.innerRect1.setOnMouseMoved(event -> {
1422             s.subScene1.setRotationAxis(Rotate.Y_AXIS);
1423             s.subScene1.setRotate(90);
1424         });
1425 
1426         s.innerRect1.setOnMouseExited(event -> {
1427             assertSame(s.innerRect1, event.getTarget());
1428             assertTrue(Double.isNaN(event.getX()));
1429             assertTrue(Double.isNaN(event.getY()));
1430             assertTrue(Double.isNaN(event.getZ()));
1431             s.called = true;
1432         });
1433 
1434         s.processEvent(MouseEvent.MOUSE_MOVED, 130, 30);
1435         s.processEvent(MouseEvent.MOUSE_MOVED, 360, 30);
1436         s.assertCalled();
1437     }
1438 
1439     @Test
1440     public void mouseExitedShouldBeGeneratedBeforeNodeRemoval() {
1441         final SimpleTestScene s = new SimpleTestScene();
1442         s.smallSquareTracker.node.addEventHandler(MouseEvent.MOUSE_EXITED,
1443                 event -> assertNotNull(s.smallSquareTracker.node.getScene())
1444         );
1445 
1446         s.processEvent(MouseEventGenerator.generateMouseEvent(
1447                 MouseEvent.MOUSE_MOVED, 250, 250));
1448         assertTrue(s.smallSquareTracker.enteredMe);
1449         assertFalse(s.smallSquareTracker.exitedMe);
1450 
1451         ParentShim.getChildren(s.scene.getRoot()).clear();
1452 
1453         assertTrue(s.smallSquareTracker.exitedMe);
1454     }
1455 
1456     @Test
1457     public void pdrGestureShouldHandleDraggedNodeRemoval() {
1458         final SimpleTestScene s = new SimpleTestScene();
1459 
1460         s.processEvent(MouseEventGenerator.generateMouseEvent(
1461                 MouseEvent.MOUSE_MOVED, 250, 250));
1462         assertTrue(s.smallSquareTracker.node.isHover());
1463         assertFalse(s.smallSquareTracker.node.isPressed());
1464 
1465         s.processEvent(MouseEventGenerator.generateMouseEvent(
1466                 MouseEvent.MOUSE_PRESSED, 250, 250));
1467         assertTrue(s.smallSquareTracker.node.isHover());
1468         assertTrue(s.smallSquareTracker.node.isPressed());
1469         assertTrue(s.smallSquareTracker.wasPressed());
1470         assertTrue(s.groupTracker.wasPressed());
1471 
1472         s.processEvent(MouseEventGenerator.generateMouseEvent(
1473                 MouseEvent.MOUSE_DRAGGED, 255, 255));
1474         assertTrue(s.smallSquareTracker.node.isHover());
1475         assertTrue(s.smallSquareTracker.node.isPressed());
1476         assertTrue(s.smallSquareTracker.wasDragged());
1477         assertTrue(s.groupTracker.wasDragged());
1478 
1479         s.smallSquareTracker.clear();
1480         s.groupTracker.clear();
1481         s.rootTracker.clear();
1482 
1483         ParentShim.getChildren(s.scene.getRoot()).clear();
1484         assertFalse(s.smallSquareTracker.node.isHover());
1485         assertFalse(s.smallSquareTracker.node.isPressed());
1486         assertFalse(s.groupTracker.node.isHover());
1487         assertFalse(s.groupTracker.node.isPressed());
1488         assertTrue(s.rootTracker.node.isHover());
1489         assertTrue(s.rootTracker.node.isPressed());
1490         assertTrue(s.smallSquareTracker.wasExitedMe());
1491         assertTrue(s.groupTracker.wasExitedMe());
1492         assertFalse(s.rootTracker.wasExitedMe());
1493 
1494         s.processEvent(MouseEventGenerator.generateMouseEvent(
1495                 MouseEvent.MOUSE_DRAGGED, 260, 260));
1496         assertFalse(s.smallSquareTracker.wasDragged());
1497         assertFalse(s.groupTracker.wasDragged());
1498         assertTrue(s.rootTracker.wasDragged());
1499 
1500         s.processEvent(MouseEventGenerator.generateMouseEvent(
1501                 MouseEvent.MOUSE_RELEASED, 270, 270));
1502         assertFalse(s.smallSquareTracker.wasReleased());
1503         assertFalse(s.groupTracker.wasReleased());
1504         assertTrue(s.rootTracker.wasReleased());
1505     }
1506 
1507     @Test
1508     public void testMouseEventCanEditCursor() {
1509         final SimpleTestScene s = new SimpleTestScene();
1510 
1511         s.smallSquare.setOnMousePressed(event -> s.smallSquare.setCursor(Cursor.CROSSHAIR));
1512 
1513         s.smallSquare.setOnMouseReleased(event -> s.smallSquare.setCursor(Cursor.WAIT));
1514 
1515         s.processEvent(MouseEventGenerator.generateMouseEvent(MouseEvent.MOUSE_MOVED, 250, 250));
1516         assertSame(CursorShim.getCurrentFrame(Cursor.HAND), s.getCursorFrame());
1517         s.processEvent(MouseEventGenerator.generateMouseEvent(MouseEvent.MOUSE_PRESSED, 250, 250));
1518         assertSame(CursorShim.getCurrentFrame(Cursor.CROSSHAIR), s.getCursorFrame());
1519         s.processEvent(MouseEventGenerator.generateMouseEvent(MouseEvent.MOUSE_RELEASED, 250, 250));
1520         assertSame(CursorShim.getCurrentFrame(Cursor.WAIT), s.getCursorFrame());
1521 
1522         s.smallSquare.setOnMouseClicked(event -> s.smallSquare.setCursor(Cursor.TEXT));
1523 
1524         s.smallSquare.setCursor(Cursor.HAND);
1525 
1526         s.processEvent(MouseEventGenerator.generateMouseEvent(MouseEvent.MOUSE_MOVED, 250, 250));
1527         assertSame(CursorShim.getCurrentFrame(Cursor.HAND), s.getCursorFrame());
1528         s.processEvent(MouseEventGenerator.generateMouseEvent(MouseEvent.MOUSE_PRESSED, 250, 250));
1529         assertSame(CursorShim.getCurrentFrame(Cursor.CROSSHAIR), s.getCursorFrame());
1530         s.processEvent(MouseEventGenerator.generateMouseEvent(MouseEvent.MOUSE_RELEASED, 250, 250));
1531         assertSame(CursorShim.getCurrentFrame(Cursor.TEXT), s.getCursorFrame());
1532     }
1533 
1534     private static class SimpleTestScene {
1535 
1536         MouseEventTracker sceneTracker;
1537         MouseEventTracker rootTracker;
1538         MouseEventTracker groupTracker;
1539         MouseEventTracker bigSquareTracker;
1540         MouseEventTracker smallSquareTracker;
1541 
1542         Rectangle smallSquare;
1543         private boolean moused = false;
1544         private Scene scene;
1545 
1546         public SimpleTestScene() {
1547             this(false, false);
1548         }
1549 
1550         public SimpleTestScene(boolean depthBuffer, boolean perspective) {
1551             final Group root = new Group();
1552             scene = new Scene(root, 400, 400, depthBuffer);
1553             if (perspective) {
1554                 scene.setCamera(new PerspectiveCamera());
1555             }
1556 
1557             Group group = new Group();
1558             Rectangle bigSquare = new Rectangle(100, 100, 200, 200);
1559             smallSquare = new Rectangle(200, 200, 100, 100);
1560             bigSquare.setTranslateZ(-1);
1561 
1562             smallSquare.setCursor(Cursor.HAND);
1563             group.setCursor(Cursor.TEXT);
1564 
1565             ParentShim.getChildren(group).add(bigSquare);
1566             ParentShim.getChildren(group).add(smallSquare);
1567 
1568             ParentShim.getChildren(root).add(group);
1569 
1570             sceneTracker = new MouseEventTracker(scene);
1571             rootTracker = new MouseEventTracker(root);
1572             groupTracker = new MouseEventTracker(group);
1573             bigSquareTracker = new MouseEventTracker(bigSquare);
1574             smallSquareTracker = new MouseEventTracker(smallSquare);
1575 
1576             scene.addEventHandler(MouseEvent.ANY, event -> {
1577                 moused = true;
1578             });
1579 
1580             Stage stage = new Stage();
1581             stage.setScene(scene);
1582             stage.show();
1583         }
1584 
1585         public void processEvent(MouseEvent e) {
1586             SceneHelper.processMouseEvent(scene, e);
1587         }
1588 
1589         public Object getCursorFrame() {
1590             return ((StubScene) SceneHelper.getPeer(scene)).getCursor();
1591         }
1592 
1593         public boolean wasMoused() {
1594             return moused;
1595         }
1596 
1597         public void clear() {
1598             moused = false;
1599             sceneTracker.clear();
1600             groupTracker.clear();
1601             bigSquareTracker.clear();
1602             smallSquareTracker.clear();
1603         }
1604     }
1605 
1606     private static class MouseEventTracker {
1607 
1608         private Node node;
1609         private boolean pressed = false;
1610         private boolean released = false;
1611         private boolean clicked = false;
1612         private boolean doubleClicked = false;
1613         private boolean moved = false;
1614         private boolean dragged = false;
1615         private boolean enteredMe = false;
1616         private boolean exitedMe = false;
1617         private boolean enteredChild = false;
1618         private boolean exitedChild = false;
1619         private int lastClickCount = 0;
1620         private boolean lastIsStill = false;
1621 
1622         public MouseEventTracker(Node node) {
1623             this.node = node;
1624 
1625             node.setOnMousePressed(event -> {
1626                 pressed = true;
1627             });
1628 
1629             node.setOnMouseReleased(event -> {
1630                 released = true;
1631             });
1632 
1633             node.setOnMouseClicked(event -> {
1634                 if (event.getClickCount() == 1) {
1635                     clicked = true;
1636                 } else if (event.getClickCount() == 2) {
1637                     doubleClicked = true;
1638                 }
1639             });
1640 
1641             node.setOnMouseMoved(event -> {
1642                 moved = true;
1643             });
1644 
1645             node.setOnMouseDragged(event -> {
1646                 dragged = true;
1647             });
1648 
1649             node.addEventHandler(MouseEvent.MOUSE_ENTERED_TARGET, event -> {
1650                 if (event.getTarget() == MouseEventTracker.this.node) {
1651                     enteredMe = true;
1652                 } else {
1653                     enteredChild = true;
1654                 }
1655             });
1656 
1657             node.addEventHandler(MouseEvent.MOUSE_EXITED_TARGET, event -> {
1658                 if (event.getTarget() == MouseEventTracker.this.node) {
1659                     exitedMe = true;
1660                 } else {
1661                     exitedChild = true;
1662                 }
1663             });
1664 
1665             node.addEventHandler(MouseEvent.ANY, event -> {
1666                 if (event.getEventType() != MouseEvent.MOUSE_CLICKED) {
1667                     lastClickCount = event.getClickCount();
1668                     lastIsStill = event.isStillSincePress();
1669                 }
1670             });
1671         }
1672 
1673         public MouseEventTracker(Scene scene) {
1674             scene.setOnMouseEntered(event -> {
1675                 enteredMe = true;
1676             });
1677 
1678             scene.setOnMouseExited(event -> {
1679                 exitedMe = true;
1680             });
1681         }
1682 
1683         public boolean wasClicked() {
1684             return clicked;
1685         }
1686 
1687         public boolean wasDoubleClicked() {
1688             return doubleClicked;
1689         }
1690 
1691         public boolean wasDragged() {
1692             return dragged;
1693         }
1694 
1695         public boolean wasEnteredMe() {
1696             return enteredMe;
1697         }
1698 
1699         public boolean wasExitedMe() {
1700             return exitedMe;
1701         }
1702 
1703         public boolean wasMoved() {
1704             return moved;
1705         }
1706 
1707         public boolean wasPressed() {
1708             return pressed;
1709         }
1710 
1711         public boolean wasReleased() {
1712             return released;
1713         }
1714 
1715         public boolean wasEnteredChild() {
1716             return enteredChild;
1717         }
1718 
1719         public boolean wasExitedChild() {
1720             return exitedChild;
1721         }
1722 
1723         public boolean isHover() {
1724             return node.isHover();
1725         }
1726 
1727         public int getLastClickCount() {
1728             return lastClickCount;
1729         }
1730 
1731         public boolean wasLastStill() {
1732             return lastIsStill;
1733         }
1734 
1735         public void clear() {
1736             pressed = false;
1737             released = false;
1738             clicked = false;
1739             doubleClicked = false;
1740             moved = false;
1741             dragged = false;
1742             enteredMe = false;
1743             exitedMe = false;
1744             enteredChild = false;
1745             exitedChild = false;
1746             lastClickCount = 0;
1747         }
1748     }
1749 
1750     private static class TestSceneWithSubScenes {
1751         private SubScene subScene1, subScene2;
1752         private Rectangle innerRect1, innerRect2;
1753         private Group root, parent1, parent2;
1754         private Scene scene;
1755         private boolean called = false;
1756         private PickResult lastPickResult = null;
1757 
1758         public TestSceneWithSubScenes() {
1759             this(false, false);
1760         }
1761 
1762         public TestSceneWithSubScenes(boolean depthBuffer, boolean subDepthBuffer) {
1763             root = new Group();
1764             scene = new Scene(root, 500, 400, depthBuffer);
1765 
1766             innerRect1 = new Rectangle(50, 50);
1767             innerRect1.setTranslateX(100);
1768             innerRect1.setTranslateY(10);
1769             subScene1 = new SubScene(new Group(innerRect1), 200, 100,
1770                     subDepthBuffer, null);
1771             subScene1.setTranslateX(10);
1772             parent1 = new Group(subScene1);
1773             parent1.setTranslateX(10);
1774             parent1.setTranslateY(10);
1775 
1776             innerRect2 = new Rectangle(50, 50);
1777             innerRect2.setTranslateX(100);
1778             innerRect2.setTranslateY(10);
1779             subScene2 = new SubScene(new Group(innerRect2), 200, 100);
1780             subScene2.setTranslateX(20);
1781 
1782             parent2 = new Group(subScene2);
1783             parent2.setTranslateX(230);
1784             parent2.setTranslateY(10);
1785 
1786 
1787             ParentShim.getChildren(root).addAll(parent1, parent2);
1788 
1789             Stage stage = new Stage();
1790             stage.setScene(scene);
1791             stage.show();
1792         }
1793 
1794         public void processEvent(EventType<MouseEvent> type, double x, double y) {
1795             SceneHelper.processMouseEvent(scene,
1796                     MouseEventGenerator.generateMouseEvent(type, x, y));
1797         }
1798 
1799         public Object getCursorFrame() {
1800             return ((StubScene) SceneHelper.getPeer(scene)).getCursor();
1801         }
1802 
1803         public EventHandler<MouseEvent> handler(final EventTarget target,
1804                 final double x, final double y) {
1805 
1806             return event -> {
1807                 if (target != null) assertSame(target, event.getTarget());
1808                 if (x != DONT_TEST) assertEquals(x, event.getX(), 0.00001);
1809                 if (y != DONT_TEST) assertEquals(y, event.getY(), 0.00001);
1810                 assertEquals(0.0, event.getZ(), 0.00001);
1811                 lastPickResult = event.getPickResult();
1812                 called = true;
1813             };
1814         }
1815 
1816         public void assertCalled() {
1817             assertTrue(called);
1818         }
1819     }
1820 
1821 }