void (@NotNull Runnable init, @NotNull CompletableFuture<?> stopCondition) { ApplicationEx app = ApplicationManagerEx.getApplicationEx(); ThreadingAssertions.assertEventDispatchThread(); synchronized (getLock()) { LOG.assertTrue(!isRunning()); LOG.assertTrue(!myStoppedAlready); } try { executeInModalContext(() -> { init.run(); app.runUnlockingIntendedWrite(() -> { initializeOnEdtIfNeeded(); // guarantee AWT event after the future is done will be pumped and loop exited stopCondition.thenRun(() -> SwingUtilities.invokeLater(EmptyRunnable.INSTANCE)); try (AccessToken ignored = ThreadContext.resetThreadContext()) { IdeEventQueue.getInstance().pumpEventsForHierarchy(myDialog.getPanel(), stopCondition, event -> { if (isCancellationEvent(event)) { cancel(); } }); } return null; }); }); } finally { // make sure focus returns to the original component (at least requested to do so) // before other code is executed after showing modal progress myDialog.hideImmediately(); } }