1818
1919import java .awt .Component ;
2020import java .awt .Dimension ;
21+ import java .awt .EventQueue ;
22+ import java .awt .Frame ;
2123import java .awt .KeyboardFocusManager ;
2224import java .awt .SecondaryLoop ;
2325import java .awt .Toolkit ;
@@ -743,6 +745,9 @@ private String buildStateKey( String key ) {
743745 }
744746
745747 private int showDialogImpl ( Component parent ) {
748+ if ( !EventQueue .isDispatchThread () )
749+ throw new IllegalStateException ( "Must be invoked from the AWT/Swing event dispatch thread" );
750+
746751 Window owner = (parent instanceof Window )
747752 ? (Window ) parent
748753 : (parent != null ) ? SwingUtilities .windowForComponent ( parent ) : null ;
@@ -791,6 +796,16 @@ private static abstract class SystemFileChooserProvider
791796 {
792797 @ Override
793798 public File [] showDialog ( Window owner , SystemFileChooser fc ) {
799+ // if there is no displayable window, then AWT's auto-shutdown feature
800+ // quits our secondary event loop (see below) immediately
801+ // https://docs.oracle.com/en/java/javase/25/docs/api/java.desktop/java/awt/doc-files/AWTThreadIssues.html#Autoshutdown
802+ Window dummyWindow = null ;
803+ if ( !hasDisplayableWindow ( owner ) ) {
804+ // create a (not visible) displayable window to avoid AWT auto-shutdown
805+ dummyWindow = new Window ( (Frame ) null );
806+ dummyWindow .addNotify ();
807+ }
808+
794809 AtomicReference <String []> filenamesRef = new AtomicReference <>();
795810
796811 // create secondary event look and invoke system file dialog on a new thread
@@ -801,6 +816,10 @@ public File[] showDialog( Window owner, SystemFileChooser fc ) {
801816 }, "FlatLaf SystemFileChooser" ).start ();
802817 secondaryLoop .enter ();
803818
819+ // dispose dummy window to allow AWT to auto-shutdown
820+ if ( dummyWindow != null )
821+ dummyWindow .dispose ();
822+
804823 String [] filenames = filenamesRef .get ();
805824
806825 // fallback to Swing file chooser if system file dialog failed or is not available
@@ -837,6 +856,17 @@ private static File[] filenames2files( String[] filenames ) {
837856 files [i ] = fsv .createFileObject ( filenames [i ] );
838857 return files ;
839858 }
859+
860+ private static boolean hasDisplayableWindow ( Window owner ) {
861+ if ( owner != null && owner .isDisplayable () )
862+ return true ;
863+
864+ for ( Window window : Window .getWindows () ) {
865+ if ( window .isDisplayable () )
866+ return true ;
867+ }
868+ return false ;
869+ }
840870 }
841871
842872 //---- class WindowsFileChooserProvider -----------------------------------
0 commit comments