JDK-8207774 : TextField: must not forward ENTER if actionHandler consumed the actionEvent
  • Type: Bug
  • Component: javafx
  • Sub-Component: controls
  • Affected Version: 8,9,10.0.1,openjfx13
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2018-07-18
  • Updated: 2019-09-10
  • Resolved: 2019-09-10
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
openjfx14Fixed
Related Reports
Relates :  
Relates :  
Relates :  
Description
happens if the actionHandler is registered via addEventHandler(ActionEvent), does not happen if registered via setOnAction

To reproduce, compile and run the example 
- focus the textField
- press Enter
- expected: neither accelerator nor keyHandler on parent must execute
- actual: both execute

Example code:

public class TextFieldActionHandler extends Application {

    private TextField textField;

    private Parent createContent() {
        textField = new TextField("added handler: ");
        textField.addEventHandler(ActionEvent.ACTION, e -> {
            System.out.println("in added: " + e);
            e.consume();
        });
        
        VBox pane = new VBox(10, textField);
        
        pane.addEventHandler(KeyEvent.KEY_PRESSED, e -> {
            System.out.println("in parent: " + e);
        });
        
        return pane;
    }

    @Override
    public void start(Stage stage) throws Exception {
        Scene scene = new Scene(createContent());
        scene.getAccelerators().put(KeyCombination.keyCombination("ENTER"),
                () -> System.out.println("in accelerator"));
        stage.setScene(scene);
       // stage.setTitle(FXUtils.version());
        stage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }

}

I think the reason for the misbehaviour is in TextFieldBehaviour.fire:

    @Override protected void fire(KeyEvent event) {
        TextField textField = getNode();
        EventHandler<ActionEvent> onAction = textField.getOnAction();
        ActionEvent actionEvent = new ActionEvent(textField, null);

        textField.commitValue();
        textField.fireEvent(actionEvent);
        // ---> intention not met
        if (onAction == null && !actionEvent.isConsumed()) {
            forwardToParent(event);
        }
    }

the intention seems to be to not forward if either the field has an onAction handler or any other handler consumed the event. The latter never happens, because node.fireEvent (ultimately) sends around copies of an event if target != node, that is handlers consuming the event do so on a copy, not on the original.

A tentative solution might be to construct the actionEvent with both source and target set the field (working but not formally tested), that's what menuItem does in its fire method.

set priority to p3 because this seems to play a role in other recently reported issues, like JDK-8207385 (acts as exposer of the bug in MenuItemContaine) and maybe JDK-8207759 (though that's slightly different, registering a keyhandler directly)




Comments
Changeset: 5e4bf30f8b26 Author: fastegal Date: 2019-09-10 08:43 -0700 URL: https://hg.openjdk.java.net/openjfx/jfx-dev/rt/rev/5e4bf30f8b26 8207774: TextField: must not forward ENTER if actionHandler consumed the actionEvent Reviewed-by: kcr, aghaisas
10-09-2019