Skip to content

Commit d0b01e4

Browse files
committed
System File Chooser: Fixed: system and Swing file dialogs were shown at the same time if application has no other displayable window (issue #1078)
also require that `SystemFileChooser.show*Dialog()` methods are invoked on AWT thread
1 parent 82759c2 commit d0b01e4

File tree

2 files changed

+32
-0
lines changed

2 files changed

+32
-0
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ FlatLaf Change Log
66
- System File Chooser:
77
- Update current filter before invoking approve callback and after closing
88
dialog. (issue #1065)
9+
- Fixed: System and Swing file dialogs were shown at the same time if
10+
application has no other displayable window. (issue #1078)
911
- On Linux: Check whether required GSettings schemas are installed to avoid
1012
application crash (occurred on NixOS with Plasma/KDE desktop). (issue #1069)
1113
- ComboBox: Added UI property `ComboBox.buttonFocusedEditableBackground`. (issue

flatlaf-core/src/main/java/com/formdev/flatlaf/util/SystemFileChooser.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818

1919
import java.awt.Component;
2020
import java.awt.Dimension;
21+
import java.awt.EventQueue;
22+
import java.awt.Frame;
2123
import java.awt.KeyboardFocusManager;
2224
import java.awt.SecondaryLoop;
2325
import 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

Comments
 (0)