Skip to content

Commit edf20b5

Browse files
committed
8387119: Tests for ScrollEvent redirection
Reviewed-by: angorya, mfox
1 parent e84b145 commit edf20b5

1 file changed

Lines changed: 216 additions & 1 deletion

File tree

modules/javafx.graphics/src/test/java/test/javafx/scene/input/ScrollEventTest.java

Lines changed: 216 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -26,7 +26,12 @@
2626
package test.javafx.scene.input;
2727

2828
import com.sun.javafx.scene.SceneHelper;
29+
import com.sun.javafx.tk.Toolkit;
30+
import javafx.event.EventType;
31+
import org.junit.jupiter.api.AfterEach;
32+
import org.junit.jupiter.api.BeforeEach;
2933
import test.com.sun.javafx.pgstub.StubScene;
34+
import test.com.sun.javafx.pgstub.StubToolkit;
3035
import test.com.sun.javafx.test.MouseEventGenerator;
3136
import javafx.event.Event;
3237
import javafx.geometry.Point3D;
@@ -40,6 +45,10 @@
4045
import javafx.stage.Stage;
4146

4247
import org.junit.jupiter.api.Test;
48+
49+
import java.util.ArrayList;
50+
import java.util.List;
51+
4352
import static org.junit.jupiter.api.Assertions.assertEquals;
4453
import static org.junit.jupiter.api.Assertions.assertFalse;
4554
import static org.junit.jupiter.api.Assertions.assertNotNull;
@@ -51,6 +60,18 @@ public class ScrollEventTest {
5160
private boolean scrolled;
5261
private boolean scrolled2;
5362
private PickResult pickRes;
63+
private Stage stage;
64+
65+
@BeforeEach
66+
public void setUp() {
67+
stage = new Stage();
68+
stage.show();
69+
}
70+
71+
@AfterEach
72+
public void tearDown() {
73+
stage.hide();
74+
}
5475

5576
@Test public void testShortConstructor() {
5677
Rectangle node = new Rectangle();
@@ -821,6 +842,192 @@ public void unknownLocalShouldBeFixedByMousePosition() {
821842
assertFalse(s.isEmpty());
822843
}
823844

845+
/**
846+
* Verifies that scroll inertia events are retargeted to the picked node when the original gesture target node
847+
* has been removed from the scene graph.
848+
*/
849+
@Test
850+
public void testInertiaScrollRetargetedToPickedNodeWhenTargetRemovedFromScene() {
851+
final StubToolkit toolkit = (StubToolkit) Toolkit.getToolkit();
852+
853+
Rectangle background = new Rectangle(0, 0, 400, 400);
854+
Rectangle scrollTarget = new Rectangle(100, 100, 200, 200);
855+
Group root = new Group(background, scrollTarget);
856+
Scene scene = new Scene(root, 400, 400);
857+
stage.setScene(scene);
858+
toolkit.firePulse();
859+
860+
List<ScrollEvent> receivedScrollEvents = new ArrayList<>();
861+
scene.addEventFilter(ScrollEvent.SCROLL, receivedScrollEvents::add);
862+
863+
StubScene stub = (StubScene) SceneHelper.getPeer(scene);
864+
865+
// 1. Start a scroll gesture over scrollTarget.
866+
scrollEvent(stub, ScrollEvent.SCROLL_STARTED, 200, 200, false);
867+
868+
// 2. Send a normal scroll event.
869+
scrollEvent(stub, ScrollEvent.SCROLL, 200, 200, false);
870+
871+
assertEquals(1, receivedScrollEvents.size());
872+
assertSame(scrollTarget, receivedScrollEvents.getFirst().getTarget());
873+
874+
// 3. Finish the scroll event.
875+
scrollEvent(stub, ScrollEvent.SCROLL_FINISHED, 200, 200, false);
876+
877+
// 4. Remove the target.
878+
root.getChildren().remove(scrollTarget);
879+
toolkit.firePulse();
880+
receivedScrollEvents.clear();
881+
882+
// 5. Inertia scroll arrives after the target has been removed.
883+
scrollEvent(stub, ScrollEvent.SCROLL, 200, 200, true);
884+
885+
assertEquals(1, receivedScrollEvents.size(),
886+
"Inertia Scroll must be delivered after the original target is removed from the Scene");
887+
assertSame(background, receivedScrollEvents.getFirst().getTarget(),
888+
"Inertia Scroll should be retargeted to the Node that was picked at the event coordinates");
889+
assertTrue(receivedScrollEvents.getFirst().isInertia());
890+
}
891+
892+
/**
893+
* Verifies that scroll inertia events are retargeted to the Scene when the original gesture target node
894+
* has been removed from the scene graph and there is no other node to pick underneath.
895+
*/
896+
@Test
897+
public void testInertiaScrollRetargetedToSceneWhenTargetRemovedFromScene() {
898+
final StubToolkit toolkit = (StubToolkit) Toolkit.getToolkit();
899+
900+
Rectangle background = new Rectangle(0, 0, 400, 400);
901+
Group root = new Group(background);
902+
Scene scene = new Scene(root, 400, 400);
903+
stage.setScene(scene);
904+
toolkit.firePulse();
905+
906+
List<ScrollEvent> receivedScrollEvents = new ArrayList<>();
907+
scene.addEventFilter(ScrollEvent.SCROLL, receivedScrollEvents::add);
908+
909+
StubScene stub = (StubScene) SceneHelper.getPeer(scene);
910+
911+
// 1. Start a scroll gesture over background.
912+
scrollEvent(stub, ScrollEvent.SCROLL_STARTED, 200, 200, false);
913+
914+
// 2. Send a normal scroll event.
915+
scrollEvent(stub, ScrollEvent.SCROLL, 200, 200, false);
916+
917+
assertEquals(1, receivedScrollEvents.size());
918+
assertSame(background, receivedScrollEvents.getFirst().getTarget());
919+
920+
// 3. Finish the scroll event.
921+
scrollEvent(stub, ScrollEvent.SCROLL_FINISHED, 200, 200, false);
922+
923+
// 4. Remove the target.
924+
root.getChildren().remove(background);
925+
toolkit.firePulse();
926+
receivedScrollEvents.clear();
927+
928+
// 5. Inertia scroll arrives after the target has been removed.
929+
scrollEvent(stub, ScrollEvent.SCROLL, 200, 200, true);
930+
931+
assertEquals(1, receivedScrollEvents.size(),
932+
"Inertia Scroll must be delivered after the original target is removed from the Scene");
933+
assertSame(scene, receivedScrollEvents.getFirst().getTarget(),
934+
"Inertia Scroll should be retargeted to the Scene as there is no Node to pick");
935+
assertTrue(receivedScrollEvents.getFirst().isInertia());
936+
}
937+
938+
/**
939+
* Verifies that scroll events are retargeted to the picked node when the original gesture target node
940+
* has been removed from the scene graph.
941+
*/
942+
@Test
943+
public void testScrollRetargetedToPickedNodeWhenTargetRemovedFromScene() {
944+
final StubToolkit toolkit = (StubToolkit) Toolkit.getToolkit();
945+
946+
Rectangle background = new Rectangle(0, 0, 400, 400);
947+
Rectangle scrollTarget = new Rectangle(100, 100, 200, 200);
948+
Group root = new Group(background, scrollTarget);
949+
Scene scene = new Scene(root, 400, 400);
950+
stage.setScene(scene);
951+
toolkit.firePulse();
952+
953+
List<ScrollEvent> receivedScrollEvents = new ArrayList<>();
954+
scene.addEventFilter(ScrollEvent.SCROLL, receivedScrollEvents::add);
955+
956+
StubScene stub = (StubScene) SceneHelper.getPeer(scene);
957+
958+
// 1. Start a scroll gesture over scrollTarget.
959+
scrollEvent(stub, ScrollEvent.SCROLL_STARTED, 200, 200, false);
960+
961+
// 2. Send a normal scroll event.
962+
scrollEvent(stub, ScrollEvent.SCROLL, 200, 200, false);
963+
964+
assertEquals(1, receivedScrollEvents.size());
965+
assertSame(scrollTarget, receivedScrollEvents.getFirst().getTarget());
966+
967+
// 3. Remove the target.
968+
root.getChildren().remove(scrollTarget);
969+
toolkit.firePulse();
970+
receivedScrollEvents.clear();
971+
972+
// 4. Send another normal scroll event.
973+
scrollEvent(stub, ScrollEvent.SCROLL, 200, 200, false);
974+
975+
// 3. Finish the scroll event.
976+
scrollEvent(stub, ScrollEvent.SCROLL_FINISHED, 200, 200, false);
977+
978+
assertEquals(1, receivedScrollEvents.size(),
979+
"Scroll must be delivered after the original target is removed from the Scene");
980+
assertSame(background, receivedScrollEvents.getFirst().getTarget(),
981+
"Scroll should be retargeted to the Node that was picked at the event coordinates");
982+
assertFalse(receivedScrollEvents.getFirst().isInertia());
983+
}
984+
985+
/**
986+
* Verifies that scroll events are retargeted to the Scene when the original gesture target node
987+
* has been removed from the scene graph and there is no other node to pick underneath.
988+
*/
989+
@Test
990+
public void testScrollRetargetedToSceneWhenTargetRemovedFromScene() {
991+
final StubToolkit toolkit = (StubToolkit) Toolkit.getToolkit();
992+
993+
Rectangle background = new Rectangle(0, 0, 400, 400);
994+
Group root = new Group(background);
995+
Scene scene = new Scene(root, 400, 400);
996+
stage.setScene(scene);
997+
toolkit.firePulse();
998+
999+
List<ScrollEvent> receivedScrollEvents = new ArrayList<>();
1000+
scene.addEventFilter(ScrollEvent.SCROLL, receivedScrollEvents::add);
1001+
1002+
StubScene stub = (StubScene) SceneHelper.getPeer(scene);
1003+
1004+
// 1. Start a scroll gesture over background.
1005+
scrollEvent(stub, ScrollEvent.SCROLL_STARTED, 200, 200, false);
1006+
1007+
// 2. Send a normal scroll event.
1008+
scrollEvent(stub, ScrollEvent.SCROLL, 200, 200, false);
1009+
1010+
assertEquals(1, receivedScrollEvents.size());
1011+
assertSame(background, receivedScrollEvents.getFirst().getTarget());
1012+
1013+
// 3. Remove the target.
1014+
root.getChildren().remove(background);
1015+
toolkit.firePulse();
1016+
receivedScrollEvents.clear();
1017+
1018+
// 4. Send another normal scroll event.
1019+
scrollEvent(stub, ScrollEvent.SCROLL, 200, 200, false);
1020+
1021+
// 3. Finish the scroll event.
1022+
scrollEvent(stub, ScrollEvent.SCROLL_FINISHED, 200, 200, false);
1023+
1024+
assertEquals(1, receivedScrollEvents.size(),
1025+
"Scroll must be delivered after the original target is removed from the Scene");
1026+
assertSame(scene, receivedScrollEvents.getFirst().getTarget(),
1027+
"Scroll should be retargeted to the Scene as there is no Node to pick");
1028+
assertFalse(receivedScrollEvents.getFirst().isInertia());
1029+
}
1030+
8241031
private Scene createScene() {
8251032
final Group root = new Group();
8261033

@@ -837,4 +1044,12 @@ private Scene createScene() {
8371044

8381045
return scene;
8391046
}
1047+
1048+
private void scrollEvent(StubScene stub, EventType<ScrollEvent> event, double x, double y, boolean inertia) {
1049+
stub.getListener().scrollEvent(
1050+
event,
1051+
0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0,
1052+
x, y, x, y,
1053+
false, false, false, false, false, inertia);
1054+
}
8401055
}

0 commit comments

Comments
 (0)