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

JavaFX Drag & Drop often hangs on Linux

XMLWordPrintable

      ADDITIONAL SYSTEM INFORMATION :
      openjdk version "11.0.13" 2021-10-19 LTS
      OpenJDK Runtime Environment 18.9 (build 11.0.13+8-LTS)
      OpenJDK 64-Bit Server VM 18.9 (build 11.0.13+8-LTS, mixed mode, sharing)

      Linux 4.18.0-305.19.1.el8_4.x86_64 #1 SMP Wed Sep 15 19:12:32 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux

      OpenJFX 17.0.1

      A DESCRIPTION OF THE PROBLEM :
      When we try to use D&D in our application, the drag often stops working: We can still move the mouse cursor around, but the cursor is not a drag cursor anymore, the drag view (which apparently now has a default drag view enabled by default that cannot be disabled) stops moving, reactions to drag over etc. are not triggered, etc.

      We have adapted the demo code from JDK-8211302 , which reproduces the problem very reliably for us (at least 9 out of 10 times, it happens on the first try).
      Things we have noticed:
      When the bug has occurred (D&D hangs):
      * It seems like no drag events occur anymore or are not properly propagated, as there are no sysouts.
      * When we move the mouse cursor out of the Fx window and back in, D&D sometimes (but not always) starts working again, at least for an instant (= drag view moved to the reentry point of the mouse cursor into the window, sysouts for DRAG_OVER printed).
      * When we move the move cursor into and out of the area of where the drag view "hangs" on the screen, there are some reactions (drag view moves a bit, sysouts for DRAG_OVER printed)
      * When we move the mouse cursor out of the window (easiest at the top) and quickly onto the green area that is the possible drop target, D&D starts/keeps working (correct drag cursor, drag view moves around, expected sysouts printed, dropping works, etc.).

      We can provide a video of the bug occurring if desired.

      We assume that the problem has something to do with the drag view for two reasons:
      First, D&D starts working for a short amount of time when we move the mouse over the are of the hanging drag view.
      Secondly, we already had similar problems using D&D with OpenJFX 13.0.1 and using a custom drag view. With that version, we could just NOT set the custom drag view, and D&D then worked reliably. OpenJFX 17 however has a default drag view that is displayed when no custom drag view is set, and we cannot work around the issue anymore.
      Under Windows 10, we could not reproduce the problem. When no drag view is explicitly specified, there IS no drag view ( = no default drag view), and D&D works as expected.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Run the test program.
      Drag the source label (yellow/left) around for a bit. Maybe several tries are needed until the bug occurs.


      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Drag cursor should be moved, default drag view should follow the mouse cursor. Sysouts for drag events should be printed. Mouse cursor should change when over the drop target (green label/right).
      ACTUAL -
      When the bug occurs, the mouse cursor becomes the default cursor instead of the drag cursor, the default drag view stops moving (= "hangs" somewhere on the screen), and there are no more sysouts for drag events. The mouse cursor does not change when over the drop target (green label/right).

      ---------- BEGIN SOURCE ----------
      public static class DndDemoApp extends Application {

              @Override
              public void start(Stage stage) {
                  HBox root = new HBox();
                  root.setPadding(new Insets(5));
                  root.setSpacing(25);

                  Scene scene = new Scene(root, 400, 200);

                  final Label source = new Label("DRAG ME");
                  source.setCursor(Cursor.HAND);
                  source.setBackground(new Background(new BackgroundFill(Color.YELLOW, CornerRadii.EMPTY, Insets.EMPTY)));

                  final Label target = new Label("DROP HERE");
                  target.setBackground(new Background(new BackgroundFill(Color.GREEN, CornerRadii.EMPTY, Insets.EMPTY)));

                  root.addEventHandler(DragEvent.ANY, evt -> {
                      System.out.println("drag event: " + evt.getEventType());
                  });

                  source.setOnDragDetected((event) -> {
                      System.out.println("onDragDetected");

                      Dragboard db = source.startDragAndDrop(TransferMode.MOVE);
                      ClipboardContent content = new ClipboardContent();
                      content.putString("DRAGGED CONTENT");
                      db.setContent(content);

                      // not setting drag view made D&D work reliably with JFX 11, but under JFX 18 it's broken anyway
                      // db.setDragView(...);

                      event.consume();
                  });

                  source.setOnDragDone((event) -> {
                      System.out.println("onDragDone");

                      event.consume();
                  });

                  target.setOnDragOver((event) -> {
                      System.out.println("onDragOver");

                      if (event.getGestureSource() != target && event.getDragboard().hasString()) {
                          event.acceptTransferModes(TransferMode.MOVE);
                      }

                      event.consume();
                  });

                  target.setOnDragEntered((event) -> {
                      System.out.println("onDragEntered");

                      event.consume();
                  });

                  target.setOnDragExited((event) -> {
                      System.out.println("onDragExited");

                      event.consume();
                  });

                  target.setOnDragDropped((event) -> {
                      System.out.println("onDragDropped");

                      Dragboard db = event.getDragboard();
                      boolean hasString = db.hasString();
                      if (hasString) target.setText(db.getString());

                      event.setDropCompleted(hasString);

                      event.consume();
                  });

                  root.getChildren().add(source);
                  root.getChildren().add(target);
                  stage.setScene(scene);
                  stage.show();
              }

              public static void main(String[] args) {
                  Application.launch(args);
              }
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      None found.

      FREQUENCY : always


        1. DndDemoApp.java
          3 kB
        2. jfx13.mp4
          575 kB
        3. jfx17.mp4
          898 kB

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

              Created:
              Updated: