Skip to content

Commit 3ce3af0

Browse files
author
Andy Goryachev
committed
8348100: Tooltips cannot be instantiated on background thread
Reviewed-by: kcr, mstrauss
1 parent 2cf9779 commit 3ce3af0

File tree

2 files changed

+71
-26
lines changed

2 files changed

+71
-26
lines changed

modules/javafx.controls/src/main/java/javafx/scene/control/Tooltip.java

Lines changed: 28 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2010, 2024, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2010, 2025, 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
@@ -25,50 +25,53 @@
2525

2626
package javafx.scene.control;
2727

28-
import com.sun.javafx.beans.IDProperty;
29-
import com.sun.javafx.css.StyleManager;
30-
import com.sun.javafx.scene.NodeHelper;
31-
import com.sun.javafx.stage.PopupWindowHelper;
32-
33-
import javafx.css.SimpleStyleableBooleanProperty;
34-
import javafx.css.SimpleStyleableDoubleProperty;
35-
import javafx.css.SimpleStyleableObjectProperty;
36-
import javafx.css.StyleOrigin;
37-
import javafx.css.StyleableObjectProperty;
38-
import javafx.css.StyleableStringProperty;
39-
40-
import javafx.css.converter.BooleanConverter;
41-
import javafx.css.converter.EnumConverter;
42-
import javafx.css.converter.SizeConverter;
43-
import javafx.css.converter.StringConverter;
44-
import javafx.css.converter.DurationConverter;
45-
import javafx.scene.control.skin.TooltipSkin;
46-
4728
import java.util.ArrayList;
4829
import java.util.Collections;
4930
import java.util.List;
50-
5131
import javafx.animation.KeyFrame;
5232
import javafx.animation.Timeline;
53-
import javafx.beans.property.*;
33+
import javafx.application.Platform;
34+
import javafx.beans.property.BooleanProperty;
35+
import javafx.beans.property.DoubleProperty;
36+
import javafx.beans.property.ObjectProperty;
37+
import javafx.beans.property.ReadOnlyBooleanProperty;
38+
import javafx.beans.property.ReadOnlyBooleanWrapper;
39+
import javafx.beans.property.SimpleStringProperty;
40+
import javafx.beans.property.StringProperty;
5441
import javafx.beans.value.WritableValue;
5542
import javafx.css.CssMetaData;
5643
import javafx.css.FontCssMetaData;
44+
import javafx.css.SimpleStyleableBooleanProperty;
45+
import javafx.css.SimpleStyleableDoubleProperty;
46+
import javafx.css.SimpleStyleableObjectProperty;
47+
import javafx.css.StyleOrigin;
5748
import javafx.css.Styleable;
49+
import javafx.css.StyleableObjectProperty;
5850
import javafx.css.StyleableProperty;
51+
import javafx.css.StyleableStringProperty;
52+
import javafx.css.converter.BooleanConverter;
53+
import javafx.css.converter.DurationConverter;
54+
import javafx.css.converter.EnumConverter;
55+
import javafx.css.converter.SizeConverter;
56+
import javafx.css.converter.StringConverter;
5957
import javafx.event.EventHandler;
6058
import javafx.geometry.NodeOrientation;
6159
import javafx.scene.AccessibleRole;
6260
import javafx.scene.Node;
6361
import javafx.scene.Parent;
6462
import javafx.scene.Scene;
63+
import javafx.scene.control.skin.TooltipSkin;
6564
import javafx.scene.image.Image;
6665
import javafx.scene.image.ImageView;
6766
import javafx.scene.input.MouseEvent;
6867
import javafx.scene.text.Font;
6968
import javafx.scene.text.TextAlignment;
7069
import javafx.stage.Window;
7170
import javafx.util.Duration;
71+
import com.sun.javafx.beans.IDProperty;
72+
import com.sun.javafx.css.StyleManager;
73+
import com.sun.javafx.scene.NodeHelper;
74+
import com.sun.javafx.stage.PopupWindowHelper;
7275

7376
/**
7477
* Tooltips are common UI elements which are typically used for showing
@@ -769,8 +772,9 @@ public StyleableProperty<Duration> getStyleableProperty(Tooltip.CSSBridge cssBri
769772
return getClassCssMetaData();
770773
}
771774

772-
@Override public Styleable getStyleableParent() {
773-
if (BEHAVIOR.hoveredNode == null) {
775+
@Override
776+
public Styleable getStyleableParent() {
777+
if (!Platform.isFxApplicationThread() || (BEHAVIOR.hoveredNode == null)) {
774778
return super.getStyleableParent();
775779
}
776780
return BEHAVIOR.hoveredNode;

tests/system/src/test/java/test/robot/javafx/scene/NodeInitializationStressTest.java

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,9 @@
3737
import java.util.concurrent.atomic.AtomicReference;
3838
import java.util.function.Consumer;
3939
import java.util.function.Supplier;
40+
import javafx.application.Platform;
4041
import javafx.beans.property.SimpleObjectProperty;
42+
import javafx.geometry.Point2D;
4143
import javafx.geometry.Pos;
4244
import javafx.geometry.Side;
4345
import javafx.scene.Node;
@@ -87,6 +89,7 @@
8789
import javafx.scene.control.TitledPane;
8890
import javafx.scene.control.ToggleButton;
8991
import javafx.scene.control.ToolBar;
92+
import javafx.scene.control.Tooltip;
9093
import javafx.scene.control.TreeItem;
9194
import javafx.scene.control.TreeTableColumn;
9295
import javafx.scene.control.TreeTableView;
@@ -116,11 +119,14 @@
116119
import javafx.scene.control.skin.ToolBarSkin;
117120
import javafx.scene.control.skin.TreeTableViewSkin;
118121
import javafx.scene.control.skin.TreeViewSkin;
122+
import javafx.scene.layout.Border;
119123
import javafx.scene.layout.BorderPane;
120124
import javafx.scene.layout.Region;
125+
import javafx.scene.layout.VBox;
121126
import javafx.scene.paint.Color;
122127
import javafx.scene.text.Text;
123128
import javafx.scene.text.TextFlow;
129+
import javafx.util.Duration;
124130
import org.junit.jupiter.api.AfterEach;
125131
import org.junit.jupiter.api.BeforeAll;
126132
import org.junit.jupiter.api.BeforeEach;
@@ -669,11 +675,46 @@ public void toolBar() {
669675
});
670676
}
671677

672-
@Disabled("JDK-8348100") // FIX
673678
@Test
674679
public void tooltip() {
675680
assumeFalse(SKIP_TEST);
676-
// TODO will have a better test in JDK-8348100
681+
AtomicBoolean phase = new AtomicBoolean();
682+
test(() -> {
683+
Tooltip t = new Tooltip("tooltip");
684+
t.setStyle("-fx-background-color:red; -fx-min-width:100px; -fx-min-height:100px; -fx-wrap-text:true; -fx-show-delay:0ms; -fx-hide-delay:0ms;");
685+
t.setShowDelay(Duration.ZERO);
686+
t.setHideDelay(Duration.ZERO);
687+
Label c = new Label("Tooltip");
688+
c.setSkin(new LabelSkin(c));
689+
c.setTooltip(t);
690+
c.setBorder(Border.stroke(Color.BLACK));
691+
c.setPrefHeight(500);
692+
c.setPrefWidth(500);
693+
VBox b = new VBox();
694+
b.getChildren().add(c);
695+
b.setId("Tooltip");
696+
return b;
697+
}, (c) -> {
698+
Tooltip t = new Tooltip();
699+
if (Platform.isFxApplicationThread()) {
700+
Label label = (Label)c.getChildren().get(0);
701+
Point2D p;
702+
if (phase.get()) {
703+
p = c.localToScreen(c.getWidth() / 2.0, c.getHeight() / 2.0);
704+
} else {
705+
p = c.localToScreen(c.getWidth() + 2, c.getHeight() + 2);
706+
}
707+
robot.mouseMove(p);
708+
double h = STAGE_HEIGHT;
709+
if (phase.get()) {
710+
h += 10;
711+
}
712+
label.setMinHeight(h);
713+
label.setMaxHeight(h);
714+
stage.setHeight(h);
715+
phase.set(!phase.get());
716+
}
717+
});
677718
}
678719

679720
@Test

0 commit comments

Comments
 (0)