Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8224636

CSS "pointer-events" property "stroke" is not respected for SVG renderings

XMLWordPrintable

    • web
    • x86_64
    • linux_ubuntu

        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


              kcr Kevin Rushforth
              webbuggrp Webbug Group
              Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

                Created:
                Updated:
                Resolved: