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
This commit is contained in:
Karl Tauber
2026-01-11 17:40:47 +01:00
parent 82759c2472
commit d0b01e4937
2 changed files with 32 additions and 0 deletions

View File

@@ -6,6 +6,8 @@ FlatLaf Change Log
- System File Chooser:
- Update current filter before invoking approve callback and after closing
dialog. (issue #1065)
- Fixed: System and Swing file dialogs were shown at the same time if
application has no other displayable window. (issue #1078)
- On Linux: Check whether required GSettings schemas are installed to avoid
application crash (occurred on NixOS with Plasma/KDE desktop). (issue #1069)
- ComboBox: Added UI property `ComboBox.buttonFocusedEditableBackground`. (issue

View File

@@ -18,6 +18,8 @@ package com.formdev.flatlaf.util;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Frame;
import java.awt.KeyboardFocusManager;
import java.awt.SecondaryLoop;
import java.awt.Toolkit;
@@ -743,6 +745,9 @@ public class SystemFileChooser
}
private int showDialogImpl( Component parent ) {
if( !EventQueue.isDispatchThread() )
throw new IllegalStateException( "Must be invoked from the AWT/Swing event dispatch thread" );
Window owner = (parent instanceof Window)
? (Window) parent
: (parent != null) ? SwingUtilities.windowForComponent( parent ) : null;
@@ -791,6 +796,16 @@ public class SystemFileChooser
{
@Override
public File[] showDialog( Window owner, SystemFileChooser fc ) {
// if there is no displayable window, then AWT's auto-shutdown feature
// quits our secondary event loop (see below) immediately
// https://docs.oracle.com/en/java/javase/25/docs/api/java.desktop/java/awt/doc-files/AWTThreadIssues.html#Autoshutdown
Window dummyWindow = null;
if( !hasDisplayableWindow( owner ) ) {
// create a (not visible) displayable window to avoid AWT auto-shutdown
dummyWindow = new Window( (Frame) null );
dummyWindow.addNotify();
}
AtomicReference<String[]> filenamesRef = new AtomicReference<>();
// create secondary event look and invoke system file dialog on a new thread
@@ -801,6 +816,10 @@ public class SystemFileChooser
}, "FlatLaf SystemFileChooser" ).start();
secondaryLoop.enter();
// dispose dummy window to allow AWT to auto-shutdown
if( dummyWindow != null )
dummyWindow.dispose();
String[] filenames = filenamesRef.get();
// fallback to Swing file chooser if system file dialog failed or is not available
@@ -837,6 +856,17 @@ public class SystemFileChooser
files[i] = fsv.createFileObject( filenames[i] );
return files;
}
private static boolean hasDisplayableWindow( Window owner ) {
if( owner != null && owner.isDisplayable() )
return true;
for( Window window : Window.getWindows() ) {
if( window.isDisplayable() )
return true;
}
return false;
}
}
//---- class WindowsFileChooserProvider -----------------------------------