On Thu, 3 Sep 2026 13:10:59 GMT, Kevin Rushforth <[email protected]> wrote:

>> ### Description
>> 
>> The setup is the following:
>> Window1
>> Window2 owner Window1
>> FileChooser owner Window2
>> 
>> When Window2 is closed,
>> then Window2 and the FileChooser are closed,
>> but the nested event loop from the dialog never returns.
>> Even worse, Window1 is in a broken state: it can't ever get focus again.
>> 
>> ### The Fix
>> The fix has two parts.
>> 
>> ### Close FileChooser when owner is closed (GlassDialogs.m)
>> AppKit does not call the completionHandler of the dialog when the owner 
>> window is closed, so the nested event loop is never left.
>> We add a listener to the owner of the FileChooser, ensuring the FileChooser 
>> gets closed when the owner is closed.
>> showOpenDialog then returns null, as if the user had cancelled.
>> 
>> ### Refocus when disabled window becomes key/focused (GlassWindow.m)
>> When a window becomes focused while it is disabled, the focus isn't 
>> processed.
>> Therefore we resend the focus event when it gets re-enabled.
>> 
>> ### System test
>> A system test is included which tests both changes at once.
>> 
>> ### A note on platform differences
>> On Windows/Linux, closing the owner of a FileChooser currently doesn't close
>> the FileChooser at all. For that reason, the test only works on macOS.
>> But this difference is not introduced by the PR.
>> It probably would be possible to change that behavior and it would be a good
>> additional improvement, because in all other cases, closing the owner also 
>> closes the child windows.
>> 
>> From the Stage JavaDoc (class doc, showAndWait doc):
>>  > When a parent window is closed or iconified, then all owned windows will 
>> be affected as well
>>  > A Stage is hidden (closed) by one of the following means: ... this stage 
>> has a non-null owner window, and its owner is closed
>> 
>> ### Close API
>> A possible follow-up would be to provide an API to close the FileChooser 
>> programmatically.
>> This would also make it easier to write tests.
>> 
>> ---------
>> - [x] I confirm that I make this contribution in accordance with the 
>> [OpenJDK Interim AI Policy](https://openjdk.org/legal/ai).
>
> @FlorianKirmaier This PR is not `rfr` because you haven't checked the box 
> asserting your compliance with the OpenJDK AI policy, so it is not on 
> anyone's review queue.

(Note: as @kevinrushforth pointed out, you do need to check the box to confirm 
that there's no AI code in this PR).

Linux also behaves badly with the same test case.

Ugh. I didn't know there were cases where the OS hides a sheet without calling 
the completion handlers. Now we've found two; when the parent window is hidden 
and when the parent window is iconified.

By the time the WillClose notification is sent the sheets are already hidden 
and no longer associated with the window. This happens earlier when the parent 
window is hidden (the orderOut: call in MacWindow__1setVisible) and that is 
probably a better place to ensure the sheets are closed.

A suggestion: add a routine to GlassWindow that ends all the sheets attached to 
the NSWindow. It would look something like:

for (NSWindow* sheet in nsWindow.sheets) {
    [nsWindow endSheet: sheet returnCode: NSModalResponseCancel];
}

Then you can scatter calls to this routine around the code. One call should 
happen in windowWillMiniaturize:  and another before the orderOut: call inside 
MacWindow__1setVisible in GlassWindow.m. In theory a window will always be 
hidden before it's closed but just in case I would add a call in 
windowWillClose: as well. Then you won't need to mess with notifications.

-------------

PR Comment: https://git.openjdk.org/jfx/pull/2242#issuecomment-5705869474

Reply via email to