Issue | Fix Version | Assignee | Priority | Status | Resolution | Resolved In Build |
---|---|---|---|---|---|---|
JDK-8228724 | 8u241 | Kevin Rushforth | P4 | Resolved | Fixed | b01 |
JDK-8237091 | jfx11.0.6 | Kevin Rushforth | P4 | Closed | Fixed |
ADDITIONAL SYSTEM INFORMATION :
Problem was reproduced on OpenJFX master.
A DESCRIPTION OF THE PROBLEM :
For SVG renderings the developer can specify, which graphics elements should receive
mouse events. For example:
.clickable {
pointer-events: stroke;
}
configures all elements with the class "clickable" to receive pointer events. This was found
while evaluating if using bpmn.js (https://github.com/bpmn-io/bpmn-js) via JavaFX
WebView would be viable option for BPMN integration.
It was noticed, that hovering over normal elements works, but hovering/selecting connectors
did not. The problem was not reproducible in other webkit based browsers.
Analysis lead to the call sequence:
RenderSVGShape::nodeAtFloatPoint
calls into RenderSVGShape::strokeContains
calls into RenderSVGShape::shapeDependentStrokeContains
calls into Path::strokeContains
at that point the call sequence fails. The current implementation in JavaFX reads (TemporaryLinkStubsJava.cpp):
bool Path::strokeContains(StrokeStyleApplier*, const FloatPoint&) const
{
notImplemented();
return false;
}
As this method always reports false, strokes are never considered as targets for mouse events.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Open index.html in a normal web browser, click on the strokes of the shapes, they will turn green
2. Run the attached TestBrwoser3.java, it will open a JavaFX Stage with a WebView, that loads the index.html
3. Click on the strokes of the shapes in the WebView
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
All shapes should react to the clicks by turning green.
ACTUAL -
Only the basic shapes (lower row): rect, circle and ellipse work, the complex shapes (upper row) path, polyline and polygon don't react.
---------- BEGIN SOURCE ----------
======================== TestBrowser3.java ==============
package eu.doppel_helix.dev.jdk.reproducecrash;
import com.sun.javafx.webkit.WebConsoleListener;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
public class TestBrowser3 implements Runnable {
public static void main(String[] args) {
Platform.startup(new TestBrowser3());
}
public void run() {
final Stage primaryStage = new Stage();
primaryStage.setTitle("Hello World!");
final WebView view = new WebView();
BorderPane bp = new BorderPane();
bp.setCenter(view);
primaryStage.setScene(new Scene(bp, 800, 600));
primaryStage.show();
WebConsoleListener.setDefaultListener((webView, message, lineNumber, sourceId) -> {
System.out.println(message + "[at " + lineNumber + "]");
});
view.getEngine().load(TestBrowser3.class.getResource("index.html").toExternalForm());
}
}
======================== index.html ==================
<!DOCTYPE html>
<html>
<head>
<title>Test pointer events on stroke</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style type="text/css">
rect, path, polyline, line, circle, ellipse, polygon {
pointer-events: stroke;
stroke: gray;
stroke-opacity: 1;
stroke-width: 10px;
fill: transparent;
}
rect.clicked, path.clicked, polyline.clicked, line.clicked, circle.clicked, ellipse.clicked, polygon.clicked {
stroke: green;
}
</style>
<script>
var testElements = [ "polyline", "path", "rect", "circle", "ellipse", "polygon" ];
window.addEventListener( 'DOMContentLoaded', ( event ) => {
for ( var el of testElements ) {
document.getElementById( el ).addEventListener( "mousedown", function ( evt ) {
this.classList.add( "clicked" );
console.log( "mousedown(" + evt.pageX + ", " + evt.pageY + ")" );
} );
}
} );
function clearState() {
for ( var el of testElements ) {
document.getElementById( el ).addEventListener( "mousedown", function ( evt ) {
this.classList.remove( "clicked" );
} );
}
}
function isActivated( id ) {
return document.getElementById( id ).classList.contains( "clicked" );
}
</script>
</head>
<body>
<svg
xmlns="http://www.w3.org/2000/svg"
id="svg8"
version="1.1"
viewBox="0 0 300 200"
height="400px"
width="600px">
<polyline points="10,10 60,10 60,60 10,60 " id="polyline" />
<path d="M110 10 H 160 V 60 H 110" id="path"/>
<polygon points="210,10 260,10 260,60 210,60 " id="polygon" />
<rect x="10" y="110" width="50" height="50" id="rect"/>
<circle cx="135" cy="135" r="25" id="circle"/>
<ellipse cx="235" cy="135" rx="25" ry="25" id="ellipse"/>
</svg>
<p>
It is expected, that a click on each of the shapes is recorded.
In an interactive test a successful record is reflected by the
shape turning green.
</p>
</body>
</html>
---------- END SOURCE ----------
FREQUENCY : always
Problem was reproduced on OpenJFX master.
A DESCRIPTION OF THE PROBLEM :
For SVG renderings the developer can specify, which graphics elements should receive
mouse events. For example:
.clickable {
pointer-events: stroke;
}
configures all elements with the class "clickable" to receive pointer events. This was found
while evaluating if using bpmn.js (https://github.com/bpmn-io/bpmn-js) via JavaFX
WebView would be viable option for BPMN integration.
It was noticed, that hovering over normal elements works, but hovering/selecting connectors
did not. The problem was not reproducible in other webkit based browsers.
Analysis lead to the call sequence:
RenderSVGShape::nodeAtFloatPoint
calls into RenderSVGShape::strokeContains
calls into RenderSVGShape::shapeDependentStrokeContains
calls into Path::strokeContains
at that point the call sequence fails. The current implementation in JavaFX reads (TemporaryLinkStubsJava.cpp):
bool Path::strokeContains(StrokeStyleApplier*, const FloatPoint&) const
{
notImplemented();
return false;
}
As this method always reports false, strokes are never considered as targets for mouse events.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Open index.html in a normal web browser, click on the strokes of the shapes, they will turn green
2. Run the attached TestBrwoser3.java, it will open a JavaFX Stage with a WebView, that loads the index.html
3. Click on the strokes of the shapes in the WebView
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
All shapes should react to the clicks by turning green.
ACTUAL -
Only the basic shapes (lower row): rect, circle and ellipse work, the complex shapes (upper row) path, polyline and polygon don't react.
---------- BEGIN SOURCE ----------
======================== TestBrowser3.java ==============
package eu.doppel_helix.dev.jdk.reproducecrash;
import com.sun.javafx.webkit.WebConsoleListener;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
public class TestBrowser3 implements Runnable {
public static void main(String[] args) {
Platform.startup(new TestBrowser3());
}
public void run() {
final Stage primaryStage = new Stage();
primaryStage.setTitle("Hello World!");
final WebView view = new WebView();
BorderPane bp = new BorderPane();
bp.setCenter(view);
primaryStage.setScene(new Scene(bp, 800, 600));
primaryStage.show();
WebConsoleListener.setDefaultListener((webView, message, lineNumber, sourceId) -> {
System.out.println(message + "[at " + lineNumber + "]");
});
view.getEngine().load(TestBrowser3.class.getResource("index.html").toExternalForm());
}
}
======================== index.html ==================
<!DOCTYPE html>
<html>
<head>
<title>Test pointer events on stroke</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style type="text/css">
rect, path, polyline, line, circle, ellipse, polygon {
pointer-events: stroke;
stroke: gray;
stroke-opacity: 1;
stroke-width: 10px;
fill: transparent;
}
rect.clicked, path.clicked, polyline.clicked, line.clicked, circle.clicked, ellipse.clicked, polygon.clicked {
stroke: green;
}
</style>
<script>
var testElements = [ "polyline", "path", "rect", "circle", "ellipse", "polygon" ];
window.addEventListener( 'DOMContentLoaded', ( event ) => {
for ( var el of testElements ) {
document.getElementById( el ).addEventListener( "mousedown", function ( evt ) {
this.classList.add( "clicked" );
console.log( "mousedown(" + evt.pageX + ", " + evt.pageY + ")" );
} );
}
} );
function clearState() {
for ( var el of testElements ) {
document.getElementById( el ).addEventListener( "mousedown", function ( evt ) {
this.classList.remove( "clicked" );
} );
}
}
function isActivated( id ) {
return document.getElementById( id ).classList.contains( "clicked" );
}
</script>
</head>
<body>
<svg
xmlns="http://www.w3.org/2000/svg"
id="svg8"
version="1.1"
viewBox="0 0 300 200"
height="400px"
width="600px">
<polyline points="10,10 60,10 60,60 10,60 " id="polyline" />
<path d="M110 10 H 160 V 60 H 110" id="path"/>
<polygon points="210,10 260,10 260,60 210,60 " id="polygon" />
<rect x="10" y="110" width="50" height="50" id="rect"/>
<circle cx="135" cy="135" r="25" id="circle"/>
<ellipse cx="235" cy="135" rx="25" ry="25" id="ellipse"/>
</svg>
<p>
It is expected, that a click on each of the shapes is recorded.
In an interactive test a successful record is reflected by the
shape turning green.
</p>
</body>
</html>
---------- END SOURCE ----------
FREQUENCY : always
- backported by
-
JDK-8228724 CSS "pointer-events" property "stroke" is not respected for SVG renderings
- Resolved
-
JDK-8237091 CSS "pointer-events" property "stroke" is not respected for SVG renderings
- Closed
- links to