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

FXCanvas should properly forward consumption state of key events from SWT to embedded scene

    Details

    • Subcomponent:
    • CPU:
      x86
    • OS:
      other

      Description

      FULL PRODUCT VERSION :


      A DESCRIPTION OF THE PROBLEM :
      org.eclipse.swt.events.KeyEvent provides a boolean doit flag, which can be set to false to indicate the event should be ignored by key handlers.

       /**
        * A flag indicating whether the operation should be allowed.
        * Setting this field to <code>false</code> will cancel the operation.
        */
      public boolean doit;

      In the context of FXCanvas this information is lost, as its not transferred to the embedded scene. As its functionality corresponds to that of javafx.event.Event.consumed the value could be transferred accordingly within FXCanvas.sendKeyEventToFX(KeyEvent, int).


      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      package canvas.bug;

      import org.eclipse.swt.SWT;
      import org.eclipse.swt.layout.FillLayout;
      import org.eclipse.swt.widgets.Display;
      import org.eclipse.swt.widgets.Shell;
      import org.junit.Test;

      import javafx.embed.swt.FXCanvas;
      import javafx.event.EventHandler;
      import javafx.scene.Group;
      import javafx.scene.Scene;
      import javafx.scene.input.KeyEvent;

      public class FXCanvasTests {

      @Test
      public void eventConsumption() {
      Display display = new Display();
      Shell shell = new Shell(display);
      shell.setLayout(new FillLayout());
      FXCanvas canvas = new FXCanvas(shell, SWT.NONE);

      Scene scene = new Scene(new Group(), 400, 400);
      canvas.setScene(scene);
      scene.addEventHandler(KeyEvent.KEY_PRESSED, new EventHandler<KeyEvent>() {
      public void handle(final KeyEvent keyEvent) {
      System.out.println("Handler: " + keyEvent);
      }
      });
      scene.addEventFilter(KeyEvent.KEY_PRESSED, new EventHandler<KeyEvent>() {
      public void handle(final KeyEvent keyEvent) {
      System.out.println("Filter: " + keyEvent);
      }
      });

      shell.setSize((int) scene.getWidth(), (int) scene.getHeight());
      shell.open();

      canvas.setFocus();
      org.eclipse.swt.widgets.Event event = new org.eclipse.swt.widgets.Event();
      event.widget = canvas;
      event.type = SWT.KeyDown;
      event.keyCode = SWT.DEL;
      event.doit = false;
      canvas.notifyListeners(SWT.KeyDown, event);

      while (!shell.isDisposed()) {
      if (!display.readAndDispatch()) {
      display.sleep();
      }
      }
      display.dispose();
      }
      }
      ---------- END SOURCE ----------

        Activity

        Hide
        anyssen Alexander Nyssen added a comment -
        While transferring the doit flag value from the SWT event to the JavaFX event is rather straightforward, there is one important thing to point out:

        As forwarding of key events to the embedded scene is performed through the SWT key listener mechanism (a key listener is registered by FXCanvas within registerEventListeners(), which is called from its constructor), and as the order in which key listeners get notified depends on the order in which they are registered, transferring the doit flag value alone will not be enough for a proper fix. It has to be ensured in addition that the key listener used by FXCanvas is the last one that gets notified, because manipulation of the doit flag by succeeding SWT listeners would otherwise not be recognized. As SWT offers two types of listeners, typed (KeyListener) as well as untyped ones (Listener), it needs to be ensured that the key listener used by FXCanvas is the last listener in the overall list of typed and untyped listeners. As both are kept in a single list (each typed listener is wrapped into a TypedListener, which wraps an untyped Event into a KeyEvent and properly transfers the doit flag value back), it will be sufficient to overwrite addListener(int, Listener) and removeListener(int, Listener) and to enforce this constraint within.
        Show
        anyssen Alexander Nyssen added a comment - While transferring the doit flag value from the SWT event to the JavaFX event is rather straightforward, there is one important thing to point out: As forwarding of key events to the embedded scene is performed through the SWT key listener mechanism (a key listener is registered by FXCanvas within registerEventListeners(), which is called from its constructor), and as the order in which key listeners get notified depends on the order in which they are registered, transferring the doit flag value alone will not be enough for a proper fix. It has to be ensured in addition that the key listener used by FXCanvas is the last one that gets notified, because manipulation of the doit flag by succeeding SWT listeners would otherwise not be recognized. As SWT offers two types of listeners, typed (KeyListener) as well as untyped ones (Listener), it needs to be ensured that the key listener used by FXCanvas is the last listener in the overall list of typed and untyped listeners. As both are kept in a single list (each typed listener is wrapped into a TypedListener, which wraps an untyped Event into a KeyEvent and properly transfers the doit flag value back), it will be sufficient to overwrite addListener(int, Listener) and removeListener(int, Listener) and to enforce this constraint within.

          People

          • Assignee:
            kcr Kevin Rushforth
            Reporter:
            webbuggrp Webbug Group
          • Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

            Dates

            • Created:
              Updated: