From c38909386a757df4d076025f3ea9b464ff92480d Mon Sep 17 00:00:00 2001 From: deekshithaby Date: Tue, 17 Feb 2026 07:14:59 +0530 Subject: [PATCH] Fix modal dialogs freezing all IDE windows (#1375) - Change FileDialog modality from APPLICATION_MODAL to DOCUMENT_MODAL in Base.java, Sketch.java, and ShimAWT.java so file dialogs only block their parent window on Linux/Windows. - Replace orphan Frame() parents in Messages.kt with a helper that uses KeyboardFocusManager to find the active window and creates DOCUMENT_MODAL dialogs, preventing message popups from freezing all IDE windows. Note: Native macOS file dialogs ignore Java modality settings (Apple limitation), but all JOptionPane-based messages are now fixed across all platforms. --- app/src/processing/app/Base.java | 1 + app/src/processing/app/Messages.kt | 38 +++++++++++++--------------- app/src/processing/app/Sketch.java | 3 +++ core/src/processing/awt/ShimAWT.java | 2 ++ 4 files changed, 24 insertions(+), 20 deletions(-) diff --git a/app/src/processing/app/Base.java b/app/src/processing/app/Base.java index 49a8625e51..839eb68891 100644 --- a/app/src/processing/app/Base.java +++ b/app/src/processing/app/Base.java @@ -1155,6 +1155,7 @@ public void handleOpenPrompt() { // use the front-most window frame for placing file dialog FileDialog openDialog = new FileDialog(activeEditor, prompt, FileDialog.LOAD); + openDialog.setModalityType(Dialog.ModalityType.DOCUMENT_MODAL); // Only show .pde files as eligible bachelors openDialog.setFilenameFilter((dir, name) -> { diff --git a/app/src/processing/app/Messages.kt b/app/src/processing/app/Messages.kt index 9b4ac7cd00..76e9368955 100644 --- a/app/src/processing/app/Messages.kt +++ b/app/src/processing/app/Messages.kt @@ -48,6 +48,19 @@ import javax.swing.UIManager class Messages { companion object { + + /** + * Shows a modal dialog that only blocks its parent window, + * not all windows in the application. + */ + private fun showModalDialog(message: Any, title: String, messageType: Int) { + val activeWindow = java.awt.KeyboardFocusManager + .getCurrentKeyboardFocusManager().activeWindow + val pane = JOptionPane(message, messageType) + val dialog = pane.createDialog(activeWindow, title) + dialog.modalityType = java.awt.Dialog.ModalityType.DOCUMENT_MODAL + dialog.isVisible = true + } /** * "No cookie for you" type messages. Nothing fatal or all that * much of a bummer, but something to notify the user about. @@ -57,10 +70,7 @@ class Messages { if (Base.isCommandLine()) { println("$title: $message") } else { - JOptionPane.showMessageDialog( - Frame(), message, title, - JOptionPane.INFORMATION_MESSAGE - ) + showModalDialog(message, title, JOptionPane.INFORMATION_MESSAGE) } } @@ -77,10 +87,7 @@ class Messages { if (Base.isCommandLine()) { println("$title: $message") } else { - JOptionPane.showMessageDialog( - Frame(), message, title, - JOptionPane.WARNING_MESSAGE - ) + showModalDialog(message, title, JOptionPane.WARNING_MESSAGE) } e?.printStackTrace() } @@ -101,11 +108,7 @@ class Messages { println("$title: $primary\n$secondary") } else { EventQueue.invokeLater { - JOptionPane.showMessageDialog( - JFrame(), - Toolkit.formatMessage(primary, secondary), - title, JOptionPane.WARNING_MESSAGE - ) + showModalDialog(Toolkit.formatMessage(primary, secondary), title, JOptionPane.WARNING_MESSAGE) } } e?.printStackTrace() @@ -122,10 +125,7 @@ class Messages { if (Base.isCommandLine()) { System.err.println("$title: $message") } else { - JOptionPane.showMessageDialog( - Frame(), message, title, - JOptionPane.ERROR_MESSAGE - ) + showModalDialog(message, title, JOptionPane.ERROR_MESSAGE) } e?.printStackTrace() System.exit(1) @@ -151,9 +151,7 @@ class Messages { val sw = StringWriter() t!!.printStackTrace(PrintWriter(sw)) - JOptionPane.showMessageDialog( - Frame(), // first
clears to the next line - // second
is a shorter height blank space before the trace + showModalDialog( Toolkit.formatMessage("$message

$sw
"), title, if (fatal) JOptionPane.ERROR_MESSAGE else JOptionPane.WARNING_MESSAGE diff --git a/app/src/processing/app/Sketch.java b/app/src/processing/app/Sketch.java index 8bb50352b0..124adac861 100644 --- a/app/src/processing/app/Sketch.java +++ b/app/src/processing/app/Sketch.java @@ -34,6 +34,7 @@ import java.awt.Container; import java.awt.EventQueue; import java.awt.FileDialog; +import java.awt.Dialog; import java.awt.event.ActionListener; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; @@ -866,6 +867,7 @@ public boolean saveAs() throws IOException { if (useNative) { // get new name for folder FileDialog fd = new FileDialog(editor, PROMPT, FileDialog.SAVE); + fd.setModalityType(Dialog.ModalityType.DOCUMENT_MODAL); if (isReadOnly() || isUntitled()) { // default to the sketchbook folder fd.setDirectory(Preferences.getSketchbookPath()); @@ -1387,6 +1389,7 @@ public void handleAddFile() { String prompt = Language.text("file"); //FileDialog fd = new FileDialog(new Frame(), prompt, FileDialog.LOAD); FileDialog fd = new FileDialog(editor, prompt, FileDialog.LOAD); + fd.setModalityType(Dialog.ModalityType.DOCUMENT_MODAL); fd.setVisible(true); String directory = fd.getDirectory(); diff --git a/core/src/processing/awt/ShimAWT.java b/core/src/processing/awt/ShimAWT.java index 304b8dd2ac..5c6c061b7c 100644 --- a/core/src/processing/awt/ShimAWT.java +++ b/core/src/processing/awt/ShimAWT.java @@ -818,6 +818,7 @@ static public void selectImpl(final String prompt, if (PApplet.useNativeSelect) { FileDialog dialog = new FileDialog(parentFrame, prompt, mode); + dialog.setModalityType(Dialog.ModalityType.DOCUMENT_MODAL); if (defaultSelection != null) { dialog.setDirectory(defaultSelection.getParent()); dialog.setFile(defaultSelection.getName()); @@ -910,6 +911,7 @@ static public void selectFolderImpl(final String prompt, if (PApplet.platform == PConstants.MACOS && PApplet.useNativeSelect) { FileDialog fileDialog = new FileDialog(parentFrame, prompt, FileDialog.LOAD); + fileDialog.setModalityType(Dialog.ModalityType.DOCUMENT_MODAL); if (defaultSelection != null) { fileDialog.setDirectory(defaultSelection.getAbsolutePath()); }