1 /*
   2  * Copyright (c) 2010, 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.stage;
  27 
  28 import com.sun.javafx.scene.SceneHelper;
  29 import com.sun.javafx.stage.WindowHelper;
  30 import test.com.sun.javafx.pgstub.StubPopupStage;
  31 import test.com.sun.javafx.pgstub.StubStage;
  32 import test.com.sun.javafx.pgstub.StubToolkit;
  33 import test.com.sun.javafx.pgstub.StubToolkit.ScreenConfiguration;
  34 import test.com.sun.javafx.test.MouseEventGenerator;
  35 import com.sun.javafx.tk.Toolkit;
  36 import javafx.concurrent.Task;
  37 import javafx.event.Event;
  38 import javafx.event.EventHandler;
  39 import javafx.geometry.BoundingBox;
  40 import javafx.geometry.Bounds;
  41 import javafx.geometry.Rectangle2D;
  42 import javafx.scene.Cursor;
  43 import javafx.scene.Group;
  44 import javafx.scene.Parent;
  45 import javafx.scene.Scene;
  46 import javafx.scene.input.KeyCode;
  47 import javafx.scene.input.KeyEvent;
  48 import javafx.scene.input.MouseEvent;
  49 import javafx.scene.shape.Rectangle;
  50 import junit.framework.Assert;
  51 import org.junit.After;
  52 import org.junit.Before;
  53 import org.junit.Ignore;
  54 import org.junit.Test;
  55 
  56 import java.util.concurrent.ExecutionException;
  57 import java.util.concurrent.atomic.AtomicBoolean;
  58 import javafx.scene.ParentShim;
  59 import javafx.stage.Popup;
  60 import javafx.stage.PopupWindow;
  61 import javafx.stage.Screen;
  62 import javafx.stage.Stage;
  63 import javafx.stage.Window;
  64 
  65 import static org.junit.Assert.*;
  66 
  67 public class PopupTest {
  68 
  69     private StubToolkit toolkit;
  70     private Stage stage;
  71     private Scene scene;
  72     private boolean done = false;
  73 
  74     @Before
  75     public void setUp() {
  76         stage = new Stage();
  77         scene = new Scene(new Group(), 500, 500);
  78         stage.setScene(scene);
  79         stage.show();
  80         done = false;
  81         toolkit = (StubToolkit) Toolkit.getToolkit();
  82     }
  83 
  84     @After
  85     public void tearDown() {
  86         stage.hide();
  87         toolkit.resetScreens();
  88     }
  89 
  90     private void pulse() {
  91         toolkit.fireTestPulse();
  92     }
  93 
  94     @Test
  95     public void testShow() {
  96         // test showing popup with visible parent
  97         Popup p1 = new Popup();
  98         p1.show(stage);
  99         assertTrue(p1.isShowing());
 100 
 101         // test showing popup with invisible parent
 102         stage.hide();
 103         Popup p2 = new Popup();
 104         p2.show(stage);
 105         assertFalse(p2.isShowing());
 106 
 107         // test showing popup without parent
 108         // TODO should result in an exception
 109 //        Popup p3 = new Popup();
 110 //        p3.show(null);
 111 //        assertFalse(p3.isVisible());
 112     }
 113 
 114     @Test
 115     public void testShowNoAutofix() {
 116         Popup p1 = new Popup();
 117         p1.setAutoFix(false);
 118         p1.show(stage);
 119         assertTrue(p1.isShowing());
 120     }
 121 
 122     @Test
 123     public void testShowLocation() {
 124         Popup p1 = new Popup();
 125         p1.show(stage, 10, 20);
 126         assertTrue(p1.isShowing());
 127         assertEquals(10, p1.getX(), 1e-100);
 128         assertEquals(20, p1.getY(), 1e-100);
 129         pulse();
 130         StubPopupStage peer = (StubPopupStage) WindowHelper.getPeer(p1);
 131         assertEquals(10, peer.x, 1e-100);
 132         assertEquals(20, peer.y, 1e-100);
 133     }
 134 
 135     private static final class PopupRoot extends Parent {
 136         private final Rectangle geomBoundsRect;
 137 
 138         private double layoutBoundsX;
 139         private double layoutBoundsY;
 140         private double layoutBoundsWidth;
 141         private double layoutBoundsHeight;
 142 
 143         public PopupRoot() {
 144             geomBoundsRect = new Rectangle(0, 0, 100, 100);
 145             layoutBoundsWidth = 100;
 146             layoutBoundsHeight = 100;
 147 
 148             ParentShim.getChildren(this).add(geomBoundsRect);
 149         }
 150 
 151         public void setGeomBounds(final double x, final double y,
 152                                   final double width,
 153                                   final double height) {
 154             geomBoundsRect.setX(x);
 155             geomBoundsRect.setY(y);
 156             geomBoundsRect.setWidth(width);
 157             geomBoundsRect.setHeight(height);
 158         }
 159 
 160         public void setLayoutBounds(final double x, final double y,
 161                                     final double width,
 162                                     final double height) {
 163             layoutBoundsX = x;
 164             layoutBoundsY = y;
 165             layoutBoundsWidth = width;
 166             layoutBoundsHeight = height;
 167 
 168             impl_layoutBoundsChanged();
 169         }
 170 
 171         @Override
 172         protected Bounds impl_computeLayoutBounds() {
 173             return new BoundingBox(layoutBoundsX, layoutBoundsY,
 174                                    layoutBoundsWidth, layoutBoundsHeight);
 175         }
 176     }
 177 
 178     @Test
 179     public void testAnchorPositioning() {
 180         final Popup popup = new Popup();
 181         final PopupRoot root = new PopupRoot();
 182 
 183         root.setGeomBounds(-10, 20, 120, 100);
 184         root.setLayoutBounds(0, 0, 100, 140);
 185 
 186         popup.getScene().setRoot(root);
 187 
 188         popup.setAnchorLocation(PopupWindow.AnchorLocation.WINDOW_BOTTOM_RIGHT);
 189         popup.show(stage, 400, 400);
 190 
 191         final StubPopupStage peer = (StubPopupStage) WindowHelper.getPeer(popup);
 192 
 193         pulse();
 194         assertEquals(280.0, peer.x, 1e-100);
 195         assertEquals(260.0, peer.y, 1e-100);
 196 
 197         popup.setAnchorLocation(PopupWindow.AnchorLocation.CONTENT_TOP_LEFT);
 198         assertEquals(290.0, popup.getAnchorX(), 1e-100);
 199         assertEquals(260.0, popup.getAnchorY(), 1e-100);
 200 
 201         pulse();
 202         assertEquals(280.0, peer.x, 1e-100);
 203         assertEquals(260.0, peer.y, 1e-100);
 204 
 205         popup.setAnchorX(200);
 206         popup.setAnchorY(100);
 207 
 208         pulse();
 209         assertEquals(190.0, peer.x, 1e-100);
 210         assertEquals(100.0, peer.y, 1e-100);
 211     }
 212 
 213     @Test
 214     public void testAnchorKeepsPositionOnContentChange() {
 215         final Popup popup = new Popup();
 216         final PopupRoot root = new PopupRoot();
 217 
 218         root.setGeomBounds(0, 0, 100, 140);
 219         root.setLayoutBounds(-10, 20, 120, 100);
 220 
 221         popup.getScene().setRoot(root);
 222 
 223         popup.setAnchorLocation(
 224                 PopupWindow.AnchorLocation.CONTENT_BOTTOM_RIGHT);
 225         popup.show(stage, 400, 300);
 226 
 227         final StubPopupStage peer = (StubPopupStage) WindowHelper.getPeer(popup);
 228 
 229         assertEquals(280.0, peer.x, 1e-100);
 230         assertEquals(180.0, peer.y, 1e-100);
 231 
 232         root.setLayoutBounds(10, -10, 80, 160);
 233 
 234         pulse();
 235 
 236         assertEquals(400.0, popup.getAnchorX(), 1e-100);
 237         assertEquals(300.0, popup.getAnchorY(), 1e-100);
 238         assertEquals(310.0, peer.x, 1e-100);
 239         assertEquals(140.0, peer.y, 1e-100);
 240     }
 241 
 242     @Test
 243     public void testPopupWithoutAnchorStayInTheCenter() {
 244         final Popup popup = new Popup();
 245         popup.setWidth(100);
 246         popup.setHeight(100);
 247         popup.show(stage);
 248         Rectangle2D bounds = Screen.getPrimary().getVisualBounds();
 249 
 250         double centerX = Math.ceil((bounds.getMinX() + (bounds.getWidth() - 100))/2);
 251         double centerY = Math.ceil((bounds.getMinY() + (bounds.getHeight() - 100))/3);
 252 
 253         StubPopupStage peer = (StubPopupStage) WindowHelper.getPeer(popup);
 254 
 255         assertEquals(centerX, Math.ceil(peer.x), 1e-100);
 256         assertEquals(centerY, Math.ceil(peer.y), 1e-100);
 257 
 258         popup.hide();
 259         popup.show(stage);
 260 
 261         peer = (StubPopupStage) WindowHelper.getPeer(popup);
 262 
 263         assertEquals(centerX, Math.ceil(peer.x), 1e-100);
 264         assertEquals(centerY, Math.ceil(peer.y), 1e-100);
 265     }
 266 
 267     @Test
 268     public void testHide() {
 269         Popup p1 = new Popup();
 270         p1.show(stage);
 271         assertTrue(p1.isShowing());
 272         p1.hide();
 273         assertFalse(p1.isShowing());
 274     }
 275 
 276     @Test
 277     public void testHideAll() {
 278         Popup p1 = new Popup();
 279         p1.show(stage);
 280         Popup p2 = new Popup();
 281         p2.show(p1);
 282         assertTrue(p1.isShowing());
 283         assertTrue(p2.isShowing());
 284         p1.hide();
 285         assertFalse(p1.isShowing());
 286         assertFalse(p2.isShowing());
 287         p1.show(stage);
 288         assertTrue(p1.isShowing());
 289         assertFalse(p2.isShowing());
 290         p1.hide();
 291         assertFalse(p1.isShowing());
 292         assertFalse(p2.isShowing());
 293     }
 294 
 295     @Test
 296     public void testAutoHiding() {
 297         Popup p1 = new Popup();
 298         p1.setAutoHide(true);
 299         p1.show(stage);
 300 
 301         Rectangle rect = new Rectangle();
 302         p1.getContent().add(rect);
 303         rect.requestFocus();
 304         assertTrue(p1.isShowing());
 305 
 306         // hiding popup stage removes the focus (in stubbed environment)
 307         p1.hide();
 308         assertFalse(p1.isShowing());
 309     }
 310 
 311     @Test
 312     public void testAutoHidingWithFocusedChild() {
 313         Popup p1 = new Popup();
 314         p1.setAutoHide(true);
 315         p1.show(stage);
 316         // setting initial focus
 317         Rectangle rect = new Rectangle();
 318         p1.getContent().add(rect);
 319         rect.requestFocus();
 320         assertTrue(p1.isShowing());
 321 
 322         Popup p2 = new Popup();
 323         p2.setAutoHide(true);
 324         p2.show(p1);
 325         Rectangle rect2 = new Rectangle();
 326         p2.getContent().add(rect2);
 327         rect2.requestFocus();
 328         assertTrue(p1.isShowing());
 329         assertTrue(p2.isShowing());
 330 
 331         p1.hide();
 332         // child has focus, popup should stay visible
 333         // Again this should be handled by PopupEventRedirector
 334         // all the AutoHide features are not implemented yet.
 335         //assertTrue(p1.isVisible());
 336     }
 337 
 338     @Test
 339     public void testAutoHidingTree() {
 340         Popup p0 = new Popup();
 341         p0.setAutoHide(true);
 342         p0.show(stage);
 343         // setting initial focus
 344         Rectangle rect = new Rectangle();
 345         p0.getContent().add(rect);
 346         rect.requestFocus();
 347 
 348         Popup p1 = new Popup();
 349         p1.setAutoHide(true);
 350         p1.show(p0);
 351 
 352         Popup p2 = new Popup();
 353         p2.setAutoHide(true);
 354         p2.show(p1);
 355         Rectangle rect2 = new Rectangle();
 356         p2.getContent().add(rect2);
 357         rect2.requestFocus();
 358 
 359         assertTrue(p1.isShowing());
 360         assertTrue(p2.isShowing());
 361         assertTrue(p0.isShowing());
 362 
 363         // after autohide the whole popup tree should be hidden
 364         // up to the parent popup with focus
 365         p2.hide();
 366         // Commenting this assersion for now : need to decide if
 367         // doAutoHide on popup should hide just itself or its parent popup as well.
 368         // PopupEventRedirector should probably take care of it.
 369         //assertFalse(p1.isVisible());
 370         assertFalse(p2.isShowing());
 371         assertTrue(p0.isShowing());
 372     }
 373 
 374     @Test
 375     public void testOnAutohide() {
 376         Popup p1 = new Popup();
 377         p1.setAutoHide(true);
 378         p1.show(stage);
 379         p1.setOnAutoHide(e -> {
 380             done = true;
 381         });
 382         Rectangle rect = new Rectangle(20, 20, 50, 50);
 383         p1.getContent().add(rect);
 384         assertFalse(done);
 385 
 386         final MouseEventGenerator generator = new MouseEventGenerator();
 387         SceneHelper.processMouseEvent(scene,
 388                 generator.generateMouseEvent(
 389                         MouseEvent.MOUSE_PRESSED, 0, 0));
 390 
 391         // test whether runnable ran
 392         assertTrue(done);
 393     }
 394 
 395 
 396     @Ignore ("Not sure how this ever worked, or what the point is")
 397     @Test
 398     public void testPeerListener() {
 399         Popup p = new Popup();
 400         p.setAutoHide(true);
 401         p.show(stage);
 402 
 403         StubPopupStage peer = (StubPopupStage) WindowHelper.getPeer(p);
 404         p.sizeToScene();
 405 
 406         double width = p.getWidth();
 407         double height = p.getHeight();
 408 
 409         // test changing dimensions to same values
 410         p.sizeToScene();
 411         assertEquals(width, p.getWidth(), 1e-100);
 412         assertEquals(height, p.getHeight(), 1e-100);
 413 
 414         // these methods shouldn't do anything for popups,
 415         // width and height should stay the same
 416         peer.close();
 417         assertEquals(width, p.getWidth(), 1e-100);
 418         assertEquals(height, p.getHeight(), 1e-100);
 419 
 420         peer.setFullScreen(true);
 421         assertEquals(width, p.getWidth(), 1e-100);
 422         assertEquals(height, p.getHeight(), 1e-100);
 423 
 424         peer.setIconified(true);
 425         assertEquals(width, p.getWidth(), 1e-100);
 426         assertEquals(height, p.getHeight(), 1e-100);
 427 
 428         peer.setResizable(true);
 429         assertEquals(width, p.getWidth(), 1e-100);
 430         assertEquals(height, p.getHeight(), 1e-100);
 431 
 432         peer.setLocation(0, 0);
 433         assertEquals(0, p.getX(), 1e-100);
 434         assertEquals(0, p.getY(), 1e-100);
 435         peer.setSize(100, 100);
 436         assertEquals(100, p.getWidth(), 1e-100);
 437         assertEquals(100, p.getHeight(), 1e-100);
 438     }
 439 
 440     @Test
 441     public void testDefautValueOfAutofix() {
 442         Popup p = new Popup();
 443         assertTrue(p.isAutoFix());
 444         assertTrue(p.autoFixProperty().get());
 445     }
 446 
 447     @Test
 448     public void testBasicAutofix() {
 449         toolkit.setScreens(
 450                 new ScreenConfiguration(0, 0, 1920, 1200,
 451                                         0, 200, 1920, 1000,
 452                                         96));
 453 
 454         final Popup popup = new Popup();
 455         popup.getContent().add(new Rectangle(0, 0, 50, 50));
 456         popup.show(stage, 1900, 100);
 457         assertEquals(1920, popup.getX() + popup.getWidth(), 1e-100);
 458         assertEquals(200, popup.getY(), 1e-100);
 459     }
 460 
 461     @Test
 462     public void testDoubleShowAutofix() {
 463         toolkit.setScreens(
 464                 new ScreenConfiguration(0, 0, 1920, 1200,
 465                                         0, 200, 1920, 1000,
 466                                         96));
 467 
 468         final Popup popup = new Popup();
 469         popup.getContent().add(new Rectangle(0, 0, 50, 50));
 470 
 471         popup.show(stage, 1900, 100);
 472         assertEquals(1920, popup.getX() + popup.getWidth(), 1e-100);
 473         assertEquals(200, popup.getY(), 1e-100);
 474 
 475         popup.show(stage, 1900, 100);
 476         assertEquals(1920, popup.getX() + popup.getWidth(), 1e-100);
 477         assertEquals(200, popup.getY(), 1e-100);
 478     }
 479 
 480     @Test
 481     public void testAutofixActivationAfterShow() {
 482         toolkit.setScreens(
 483                 new ScreenConfiguration(0, 0, 1920, 1200,
 484                                         0, 200, 1920, 1000,
 485                                         96));
 486 
 487         final Popup popup = new Popup();
 488         popup.setAutoFix(false);
 489         popup.getContent().add(new Rectangle(0, 0, 50, 50));
 490         popup.show(stage, 1900, 100);
 491 
 492         assertEquals(1900, popup.getX(), 1e-100);
 493         assertEquals(100, popup.getY(), 1e-100);
 494 
 495         popup.setAutoFix(true);
 496         assertEquals(1920, popup.getX() + popup.getWidth(), 1e-100);
 497         assertEquals(200, popup.getY(), 1e-100);
 498     }
 499 
 500     @Test
 501     public void testAutofixOnContentChange() {
 502         toolkit.setScreens(
 503                 new ScreenConfiguration(0, 0, 1920, 1200,
 504                                         0, 0, 1920, 1172,
 505                                         96));
 506 
 507         final Popup popup = new Popup();
 508         popup.getContent().add(new Rectangle(0, 0, 50, 50));
 509         popup.show(stage, 100, 1120);
 510         assertEquals(100, popup.getX(), 1e-100);
 511         assertEquals(1120, popup.getY(), 1e-100);
 512 
 513         popup.getContent().add(new Rectangle(0, 0, 50, 100));
 514         assertEquals(100, popup.getX(), 1e-100);
 515         assertEquals(1172, popup.getY() + popup.getHeight(), 1e-100);
 516     }
 517 
 518     @Test
 519     public void testAutofixOnScreenChange() {
 520         toolkit.setScreens(
 521                 new ScreenConfiguration(0, 0, 1920, 1200,
 522                                         0, 0, 1920, 1172,
 523                                         96));
 524 
 525         final Popup popup = new Popup();
 526         popup.getContent().add(new Rectangle(0, 0, 50, 50));
 527         popup.show(stage, 100, 1120);
 528         assertEquals(100, popup.getX(), 1e-100);
 529         assertEquals(1120, popup.getY(), 1e-100);
 530 
 531         toolkit.setScreens(
 532                 new ScreenConfiguration(0, 0, 1920, 1200,
 533                                         120, 0, 1800, 1172,
 534                                         96));
 535 
 536         assertEquals(120, popup.getX(), 1e-100);
 537         assertEquals(1120, popup.getY(), 1e-100);
 538     }
 539 
 540     @Test
 541     public void testAutofixWithFullScreen() {
 542         toolkit.setScreens(
 543                 new ScreenConfiguration(0, 0, 1920, 1200,
 544                                         0, 0, 1920, 1172,
 545                                         96));
 546 
 547         final Popup popup = new Popup();
 548         popup.getContent().add(new Rectangle(0, 0, 50, 50));
 549 
 550         stage.setFullScreen(true);
 551         popup.show(stage, 100, 1160);
 552 
 553         assertEquals(100, popup.getX(), 1e-100);
 554         assertEquals(1150, popup.getY(), 1e-100);
 555     }
 556 
 557     @Test
 558     public void testSetPopupContentByChangingRootNode() {
 559         final Popup popup = new Popup();
 560 
 561         popup.getScene().setRoot(new Group(new Rectangle(0, 0, 300, 200)));
 562         assertEquals(300, popup.getWidth(), 1e-100);
 563         assertEquals(200, popup.getHeight(), 1e-100);
 564 
 565         popup.getScene().setRoot(new Group(new Rectangle(0, 0, 200, 300)));
 566         assertEquals(200, popup.getWidth(), 1e-100);
 567         assertEquals(300, popup.getHeight(), 1e-100);
 568     }
 569 
 570     @Test
 571     public void testKeyEventTranslation() {
 572         Popup popup = new Popup();
 573         AtomicBoolean res = new AtomicBoolean(false);
 574         Rectangle rectangle = new Rectangle(0, 0, 300, 200);
 575         popup.getScene().setRoot(new Group(rectangle));
 576         popup.show(stage);
 577         rectangle.requestFocus();
 578         rectangle.setOnKeyPressed((KeyEvent e) -> {
 579             assertEquals(rectangle, e.getTarget());
 580             res.set(true);
 581         });
 582 
 583         Event.fireEvent(stage, new KeyEvent(null, stage, KeyEvent.KEY_PRESSED, "c", "c", KeyCode.C, false, false, false, false));
 584         assertTrue(res.get());
 585     }
 586 
 587     @Test
 588     public void testConsumeAutoHidingEventsProperty() {
 589         final EventCounter mouseEventCounter = new EventCounter();
 590         final EventCounter keyEventCounter = new EventCounter();
 591 
 592         stage.addEventHandler(MouseEvent.MOUSE_PRESSED, mouseEventCounter);
 593         stage.addEventHandler(KeyEvent.KEY_PRESSED, keyEventCounter);
 594         try {
 595             final MouseEventGenerator mouseEventGenerator =
 596                     new MouseEventGenerator();
 597 
 598             final Popup popup = new Popup();
 599             popup.setAutoHide(true);
 600 
 601             assertTrue(popup.getConsumeAutoHidingEvents());
 602 
 603             popup.show(stage);
 604             Event.fireEvent(stage,
 605                             mouseEventGenerator.generateMouseEvent(
 606                                 MouseEvent.MOUSE_PRESSED, 0, 0));
 607             assertEquals(0, mouseEventCounter.getValue());
 608 
 609             popup.show(stage);
 610             Event.fireEvent(stage,
 611                             new KeyEvent(null, stage,
 612                                 KeyEvent.KEY_PRESSED, KeyEvent.CHAR_UNDEFINED,
 613                                 KeyCode.ESCAPE.getName(),
 614                                 KeyCode.ESCAPE,
 615                                 false, false, false, false));
 616             assertEquals(0, keyEventCounter.getValue());
 617 
 618             popup.setConsumeAutoHidingEvents(false);
 619 
 620             popup.show(stage);
 621             Event.fireEvent(stage,
 622                             mouseEventGenerator.generateMouseEvent(
 623                                 MouseEvent.MOUSE_PRESSED, 0, 0));
 624             assertEquals(1, mouseEventCounter.getValue());
 625 
 626             popup.show(stage);
 627             Event.fireEvent(stage,
 628                             new KeyEvent(null, stage,
 629                                 KeyEvent.KEY_PRESSED,
 630                                 KeyEvent.CHAR_UNDEFINED,
 631                                 KeyCode.ESCAPE.getName(),
 632                                 KeyCode.ESCAPE,
 633                                 false, false, false, false));
 634             assertEquals(1, keyEventCounter.getValue());
 635 
 636         } finally {
 637             stage.removeEventHandler(MouseEvent.MOUSE_PRESSED,
 638                                      mouseEventCounter);
 639             stage.removeEventHandler(KeyEvent.KEY_PRESSED, keyEventCounter);
 640         }
 641     }
 642 
 643     @Test(expected=NullPointerException.class)
 644     public void testShowWithNullOwner() {
 645         final Popup popup = new Popup();
 646         popup.show(null);
 647     }
 648 
 649     @Test(expected=NullPointerException.class)
 650     public void testShowXYWithNullOwner() {
 651         final Popup popup = new Popup();
 652         popup.show((Window) null, 10, 10);
 653     }
 654 
 655     @Test(expected=IllegalArgumentException.class)
 656     public void testShowWithOwnerThatWouldCreateCycle1() {
 657         final Popup popup = new Popup();
 658         popup.show(popup);
 659     }
 660 
 661     @Test(expected=IllegalArgumentException.class)
 662     public void testShowWithOwnerThatWouldCreateCycle2() {
 663         final Popup popup1 = new Popup();
 664         final Popup popup2 = new Popup();
 665 
 666         popup1.show(stage);
 667         popup2.show(popup1);
 668         popup1.hide();
 669         popup1.show(popup2);
 670     }
 671 
 672     @Test(expected=IllegalArgumentException.class)
 673     public void testShowXYWithOwnerThatWouldCreateCycle1() {
 674         final Popup popup = new Popup();
 675         popup.show(popup, 10, 20);
 676     }
 677 
 678     @Test(expected=IllegalArgumentException.class)
 679     public void testShowXYWithOwnerThatWouldCreateCycle2() {
 680         final Popup popup1 = new Popup();
 681         final Popup popup2 = new Popup();
 682 
 683         popup1.show(stage);
 684         popup2.show(popup1);
 685         popup1.hide();
 686         popup1.show(popup2, 10, 20);
 687     }
 688 
 689     @Test
 690     public void testFocusGrabbedWhenNecessary() {
 691         final Popup popup = new Popup();
 692 
 693         popup.show(stage);
 694         stage.requestFocus();
 695 
 696         final StubStage peer = (StubStage) WindowHelper.getPeer(stage);
 697         assertFalse(peer.isFocusGrabbed());
 698 
 699         popup.setAutoHide(true);
 700         assertTrue(peer.isFocusGrabbed());
 701 
 702         popup.hide();
 703         assertFalse(peer.isFocusGrabbed());
 704     }
 705 
 706     @Test
 707     public void testPopupRootStyle() {
 708         final Popup popup = new Popup();
 709 
 710         final Parent oldRoot = popup.getScene().getRoot();
 711         Assert.assertTrue(oldRoot.getStyleClass().contains("popup"));
 712 
 713         final Group newRoot = new Group(new Rectangle(0, 0, 200, 300));
 714         popup.getScene().setRoot(newRoot);
 715 
 716         Assert.assertTrue(newRoot.getStyleClass().contains("popup"));
 717         Assert.assertFalse(oldRoot.getStyleClass().contains("popup"));
 718 
 719         System.out.println(javafx.scene.shape.Sphere.class.getResource("Sphere.class"));
 720     }
 721 
 722     @Test
 723     public void testCursorInheritance() {
 724         stage.getScene().setCursor(Cursor.CLOSED_HAND);
 725 
 726         final Popup popup = new Popup();
 727 
 728         popup.show(stage);
 729         assertEquals(Cursor.CLOSED_HAND, popup.getScene().getCursor());
 730 
 731     }
 732 
 733     private static final class EventCounter implements EventHandler<Event> {
 734         private int counter;
 735 
 736         public int getValue() {
 737             return counter;
 738         }
 739 
 740         public void handle(final Event event) {
 741             ++counter;
 742         }
 743     }
 744 }