RFR: 8268225: Support :focus-visible and :focus-within CSS pseudoclasses [v7]

Jeanette Winzenburg fastegal at openjdk.java.net
Tue Dec 7 12:25:12 UTC 2021


On Fri, 20 Aug 2021 05:15:49 GMT, Michael Strauß <mstrauss at openjdk.org> wrote:

>> This PR adds the `Node.focusVisible` and `Node.focusWithin` properties, as well as the corresponding `:focus-visible` and `:focus-within` CSS pseudo-classes.
>
> Michael Strauß has updated the pull request incrementally with one additional commit since the last revision:
> 
>   fixed undeterministic test failures

thanks for taking a closer look :) 

> > might also need a test that verifies the focusWithin of a parent added somewhere above the focused node? hmm .. or maybe not, that would require to re-arrange a complete subtree ..
> 
> Inserting a parent into a scene graph such that the existing subtree at that position becomes a subtree of the newly inserted parent can't be done as an atomic operation. First, you'll need to remove the subtree at the insertion point from the existing scene graph (otherwise you'll get an exception saying that a node can only appear once in a scene graph). Then you can add the new parent with the removed subtree as its child.

yeah that's true, but might happen behind the scenes - we can move a focused node from one parent to another by simply adding it the new. 

So I'm not sure I would agree: 

> I'm inclined to think that this behavior is a bug.

arguable, though :) Below is an example of moving a focused node (button "Moving", the other is just for having something else that might get the focus) between 2 parents by F1: the button keeps its focused state in its new parent (and scene's focusOwner doesn't change) - I think that's what a user would expect also when dragging a focused node around (s/he might not even be aware of the hierarchy). I suspect that changing the behavior would break existing applications - except if it could be done completely transparently.

The example:

    private Parent createContent() {
        first = new VBox();
        first.setBackground(new Background(new BackgroundFill(Color.ALICEBLUE, null, null)));
        first.getChildren().add(new Label("label on first"));
        second = new VBox();
        second.setBackground(new Background(new BackgroundFill(Color.LAVENDER, null, null)));
        second.getChildren().add(new Label("label on second"));

        moving = new Button("moving");
        first.getChildren().add(moving);
        Button move = new Button("move");
        move.setOnAction(e -> {
            move();
        });
        move.setDefaultButton(true);
        HBox content = new HBox(10, first, second, move);
        content.addEventFilter(KeyEvent.KEY_PRESSED, e -> {
            if (e.getCode() == KeyCode.F1) {
                move();
            }
        });
        return content;
    }

    private void move() {
        Parent parent = moving.getParent();
        Pane target = parent == first ? second : first;
        target.getChildren().add(moving);
    }

    @Override
    public void start(Stage stage) throws Exception {
        Scene scene = new Scene(createContent(), 300, 300);
        scene.focusOwnerProperty().addListener((scr, ov, nv) -> {
            System.out.println("focusOwner: " + nv);
        });
        stage.setScene(scene);
        stage.show();
    }

    private VBox first;
    private VBox second;
    private Button moving;

-------------

PR: https://git.openjdk.java.net/jfx/pull/475


More information about the openjfx-dev mailing list