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

concurrent windows (stages) modifications

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Duplicate
    • Icon: P4 P4
    • None
    • 8u51
    • javafx
    • x86
    • windows_7

      FULL PRODUCT VERSION :
      java version "1.8.0_51"
      Java(TM) SE Runtime Environment (build 1.8.0_51-b16)
      Java HotSpot(TM) Client VM (build 25.51-b03, mixed mode, sharing)

      ADDITIONAL OS VERSION INFORMATION :
      Microsoft Windows [Version 6.1.7601]

      A DESCRIPTION OF THE PROBLEM :
      Multiple stages try to update the windows list in GlassStage class. This is particularly related to the enabled virtual keyboard.

      In the demo code, there are two dialogs (stages). One dialog A contains a textfield which holds the focus once the dialog pops up. There is another dialog B pops up 2 seconds after A pops up. When the dialog A pops up, a virtual keyboard shows up because the text field has the focus. The exception occurs when the dialog B pops up as seen in the stack trace below.

      As the result, user lost the control to dialog B. Dialog B won't respond.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Run the attached example code. Click on the 'Click Me' button.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Be able to close the dialogs.
      ACTUAL -
      user lost the control to dialog B. Dialog B won't respond. Can't close the dialog B.

      ERROR MESSAGES/STACK TRACES THAT OCCUR :
      Exception in thread "JavaFX Application Thread" java.util.ConcurrentModificationException
      at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
      at java.util.ArrayList$Itr.next(ArrayList.java:851)
      at com.sun.javafx.tk.quantum.GlassStage.windowsSetEnabled(GlassStage.java:166)
      at com.sun.javafx.tk.quantum.WindowStage.setVisible(WindowStage.java:441)
      at javafx.stage.Window$9.invalidated(Window.java:860)
      at javafx.beans.property.BooleanPropertyBase.markInvalid(BooleanPropertyBase.java:109)
      at javafx.beans.property.BooleanPropertyBase.set(BooleanPropertyBase.java:144)
      at javafx.stage.Window.setShowing(Window.java:910)
      at javafx.stage.Window.hide(Window.java:935)
      at fx.table.demo.FxDialog.popUp(DialogBugDemo.java:101)
      at fx.table.demo.DialogBugDemo.lambda$2(DialogBugDemo.java:42)
      at fx.table.demo.DialogBugDemo$$Lambda$168/4445380.run(Unknown Source)
      at com.sun.javafx.application.PlatformImpl.lambda$null$170(PlatformImpl.java:295)
      at com.sun.javafx.application.PlatformImpl$$Lambda$48/13613528.run(Unknown Source)
      at java.security.AccessController.doPrivileged(Native Method)
      at com.sun.javafx.application.PlatformImpl.lambda$runLater$171(PlatformImpl.java:294)
      at com.sun.javafx.application.PlatformImpl$$Lambda$47/24237394.run(Unknown Source)
      at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
      at com.sun.glass.ui.win.WinApplication._enterNestedEventLoopImpl(Native Method)
      at com.sun.glass.ui.win.WinApplication._enterNestedEventLoop(WinApplication.java:128)
      at com.sun.glass.ui.Application.enterNestedEventLoop(Application.java:511)
      at com.sun.glass.ui.EventLoop.enter(EventLoop.java:107)
      at com.sun.javafx.tk.quantum.QuantumToolkit.enterNestedEventLoop(QuantumToolkit.java:593)
      at javafx.stage.Stage.showAndWait(Stage.java:463)
      at fx.table.demo.FxDialog.popUp(DialogBugDemo.java:104)
      at fx.table.demo.DialogBugDemo.lambda$0(DialogBugDemo.java:54)
      at fx.table.demo.DialogBugDemo$$Lambda$68/14025593.handle(Unknown Source)
      at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
      at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
      at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
      at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
      at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
      at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
      at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
      at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
      at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
      at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
      at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
      at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49)
      at javafx.event.Event.fireEvent(Event.java:198)
      at javafx.scene.Node.fireEvent(Node.java:8390)
      at javafx.scene.control.Button.fire(Button.java:185)
      at com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(ButtonBehavior.java:182)
      at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:96)
      at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:89)
      at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218)
      at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
      at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
      at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
      at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
      at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
      at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
      at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
      at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
      at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
      at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
      at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
      at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
      at javafx.event.Event.fireEvent(Event.java:198)
      at javafx.scene.Scene$MouseHandler.process(Scene.java:3758)
      at javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3486)
      at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1762)
      at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2495)
      at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:350)
      at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:275)
      at java.security.AccessController.doPrivileged(Native Method)
      at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$350(GlassViewEventHandler.java:385)
      at com.sun.javafx.tk.quantum.GlassViewEventHandler$$Lambda$113/29964557.get(Unknown Source)
      at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:404)
      at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:384)
      at com.sun.glass.ui.View.handleMouseEvent(View.java:555)
      at com.sun.glass.ui.View.notifyMouse(View.java:927)
      at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
      at com.sun.glass.ui.win.WinApplication.lambda$null$145(WinApplication.java:101)
      at com.sun.glass.ui.win.WinApplication$$Lambda$36/24408301.run(Unknown Source)
      at java.lang.Thread.run(Thread.java:745)

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------

      package fx.table.demo;

      import javafx.application.Application;
      import javafx.application.Platform;
      import javafx.scene.Node;
      import javafx.scene.Scene;
      import javafx.scene.control.Button;
      import javafx.scene.control.Label;
      import javafx.scene.control.TextField;
      import javafx.scene.layout.BorderPane;
      import javafx.scene.layout.StackPane;
      import javafx.scene.layout.VBox;
      import javafx.stage.Modality;
      import javafx.stage.Stage;
      import javafx.stage.StageStyle;
      import javafx.stage.Window;

      /**
       *
       *
       */
      public class DialogBugDemo extends Application {

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

          @Override
          public void start(Stage stage) throws Exception {

             Button button = new Button("Click Me");
             button.setOnAction( e -> {
                //sleep for 10 sec, pop up another dialog
                new Thread( () -> {
                      try {
                          Thread.sleep(2000);
                          Platform.runLater( () -> {
                              FxDialog dialog = new FxDialog(stage, "Error!");

                              dialog.setContent( new Label("Some meesage!"));
                              dialog.popUp();
                          });
                      }
                      catch( Exception ex) {
                          ex.printStackTrace();
                      }
                  }).start();

                FxDialog dialog = new FxDialog(stage, "text input");
                TextField textField = new TextField("Some input");
                dialog.setContent( textField );
                textField.requestFocus();
                dialog.popUp();

             });
             StackPane pane = new StackPane();
             pane.getChildren().add( button );
             Scene scene = new Scene( pane );
             stage.setScene( scene );
             stage.show();
          }

      }

      class FxDialog extends Stage {

          /** the dialog pane */
          private BorderPane pane;

          public FxDialog(Window owner, String title) {
              initOwner( owner );
              initModality( Modality.APPLICATION_MODAL );
              initStyle( StageStyle.TRANSPARENT );
              setTitle(title);

              StackPane root = new StackPane();
              pane = new BorderPane();

              Button exitButton = new Button("Exit");
              exitButton.setOnAction( e -> { close(); } );
              pane.setBottom( exitButton );

              root.getChildren().setAll( pane );
              Scene scene = new Scene( root );
              setScene( scene );
              setAlwaysOnTop(true);
          }

          public void setContent( Node...content ) {
              VBox contentPane = new VBox();
              contentPane.getChildren().clear();
              contentPane.getChildren().addAll( content );
              pane.setCenter( contentPane );
          }

          public void popUp() {
              show();
              pane.requestLayout();
              sizeToScene();
              hide(); //so, we can do blocking showAndWait(), and allow centerOnOwner().
              centerOnOwner();
              toFront();
              showAndWait();
          }

          /**
           * put the dialog on the center of the owner window.
           * <p>
           * If the dialog has no owner, then put the dialog on the center of the
           * screen.
           */
          private void centerOnOwner() {

              if (getOwner() == null ) {
                  centerOnScreen();
                  return;
              }

              //center based on the ownder's location
              Window owner = getOwner();
              double oX = owner.getX();
              double oY = owner.getY();
              double oW = owner.getWidth();
              double oH = owner.getHeight();
              double dW = getWidth();
              double dH = getHeight();
              double dX = oX + oW/2 - dW/2;
              double dY = oY + oH/2 - dH/2;

              setX(dX);
              setY(dY);
          }
      }

      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      Not known.

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

              Created:
              Updated:
              Resolved: