Bring desktop dialogs to the foreground#18
Merged
lanceewing merged 1 commit intoJun 20, 2026
Conversation
The desktop Swing dialogs (file open, settings, About, and the quit/exit confirmations) could open behind the application window on Windows. This was a behaviour regression introduced by the macOS dialog deadlock fix (lanceewing#9) which moved the dialog calls onto the AWT event dispatch thread. On Windows a thread that does not own the foreground window cannot bring a new window to the front, so a dialog created on the EDT opens behind the application. Each dialog is now given a temporary, effectively invisible, owner window that is brought to the foreground and disposed as soon as the dialog closes, so the dialog appears in front. By default the code uses a gentle toFront()/requestFocus() to bring this window to the foreground. But a DIALOG_ALWAYS_ON_TOP static flag is included to switch to setting the owner window to always-on-top, which foregrounds more reliably but pins the dialog above all other windows while open, even when switching to ther applications. The correct choise for this static flag needs to be chosen after testing on Windows. The owner window is created on the EDT inside the existing dispatch, so the macOS deadlock fix is preserved.
Contributor
Author
|
By the way, if there's something you would like me to be doing differently relating to the CI failures, let me know. I'm happy to use whatever workflow you would prefer. |
Owner
|
This is working for me when running the desktop version on Windows, so I will merge it in a few minutes. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Following the macOS dialog deadlock fix (#9), on (at least some versions of) Windows the Swing dialogs (file open, the settings/ROM chooser, the About box, and the quit/exit confirmations) can open behind the JOric main window instead of in front of it.
The cause is the macOS deadlock fix moved the Swing dialog calls onto the AWT event dispatch thread (EDT). On Windows, the OS only allows the thread that owns the current foreground window to bring a new window to the front. As the EDT does not own the GLFW main application window, so a dialog created by the EDT opens behind the main application window. Before the deadlock fix the dialogs ran on the main thread (which owns the GLFW window) and came to the front normally.
Candidate Fix
For each dialog we now create a temporary, effectively invisible, owner window that is brought to the foreground, and disposed of as soon as the dialog is closed. The owner window is a 1x1, undecorated, UTILITY-type frame (the UTILITY type is meant to keep it out of the taskbar and the alt-tab list), created on the EDT inside the existing dispatch so the deadlock fix is preserved.
By default the code uses a gentle toFront()/requestFocus() to bring the dialog to the front without pinning it above other windows (so you can still switch away to, say, check a filename). A single DIALOG_ALWAYS_ON_TOP static flag switches the owner window to always-on-top for all the dialogs, which would foreground more reliably but keeps the dialog pinned above everything while it's open, even when switching away to other applications. Which mode should be set as the default behaviour will depend on the outcome of Windows testing. (See Testing section below.)
Scope
Desktop (lwjgl3) only - one file (DesktopDialogHandler). No changes to core, web or Android. All the dialog methods route through a single shared owner-creating helper, so the behaviour and the toggle are uniform across them.
Testing
Tested on macOS only. All the reachable dialogs open in front and dismiss correctly, with both the default gentle approach and the always-on-top toggle, and no visible stray window appears. (Note that the
promptForTextInputappears to be unused currently, so is untested.)I don't have a Windows machine, so I can't verify the actual fix there - that's the part that needs checking to see if the candidate fix works as is, or if it needs toggling to use the always-on-top mode.