Modal dialogs in macOS Tahoe

I have updated to Tahoe and latest Xcode and I’m running into issues with modal windows and dialogs. Showing the window just using enterModalState with an asynchronous callback works fine but waiting for the result causes all sorts of UI issues.

Currently on JUCE 8.0.10 master.

What’s the correct way to show a modal dialog and wait for its result in a standalone macOS/Windows application? Is that broken with Tahoe?

Interestingly, when I build the same code on an older OS it works just fine in Tahoe but when I build it from Tahoe the event loop appears to get stuck.

EDIT: this only happens with Xcode 26 on Tahoe. Building the app from Xcode 16.4 on Tahoe doesn’t show this. However, this also builds against an older macOS SDK so it’s likely the current Tahoe SDK causes this.

Running modal-loops can create all kind of issues, especially in plugins.

I recommend always using asynchronous callbacks.

The Juce team didn’t disable modal loops by default for no reason many years ago. AFAIK they originally did that because Android apparently doesn’t have that feature available at all, but it was predictable modal loops would start causing problems on other operating systems too. And it hasn’t been a good idea to have those in plugins in any case, regardless of platform.

Thanks.

Should’ve made this clear: we’re talking about standalone apps here, not plugins.

1 Like

Can’t confirm/deny yet, but I will say this:
Scrapping modal dialogs entirely is a really big deal for those of us building standalone apps with really large complex functions. The refactor necessary for us will be huge and the result will be the most awful spaghetti code of nested dialogs with lambdas inside dialogs with lambdas… etc.

There are some actions which absolutely require user input at several stages, dependent on the inputs received from previous stages. Modal dialogs just make a lot of sense (assuming they work), when I definitely know I do not want anyone messing with the UI and data model.

If modal dialogs are not supported, kill them completely. Otherwise, an effort ought to be made to fix any bugs.

Maybe you could describe it what kind of UI issues are happing, that helps the juce team move forward. Did you try to debug this issue? It is quite possible that there is a bug or other issue with newer SDKs, in which case it should be fixed. Does it also happen when you run a very simple example program?

Using modal loops has been deprecated for some time.

We noticed it two iOS versions ago, that Apple quietly started breaking programs with modal loops, even though according to their documentation some uses of it should still work.

We filed a bug report, and made a good case pointing to their own documentation, but we only received a blanket rejection telling us not to use modal loops. In light of this it’s not likely that we can keep modal loop behaviour working well, when the underlying OS doesn’t support this.

1 Like

I think that “modal dialogs” can be a bit confusing. It might seem that “modal dialog” refers to placing a dialog in a modal state by using enterModalState(). This blocks all other UI interaction but, unlike modal loops, not the message thread, so they are fine.

We should probably refer to displaying dialogs using a modal loop as “synchronous dialogs” instead of “modal dialogs”.

Wouldn’t displaying dialogs using enterModalState() work just as well for that?

A big refactor using callbacks would still be necessary though…

I made a video to illustrate the issue:

Video

The main issue is that the event loop appears to be stuck. You click a ToggleButton and it doesn’t show the updated state until you move the mouse over it. Same for keyboard events. You usually have to click a button multiple times for it to do anything…

I tried all sorts of different options to show the modal window and wait for the result, but the behavior is always the same.

And to stress that again: this is only with Xcode 26 building against the Tahoe SDK. Building with Xcode 16.4 on the same machine and building against the Sequoia 15.5 SDK, everything behaves just fine.

Of course it is somehow possible to work around this and make everything async but it’s a lot of work… and would likely lead to nested lambdas instead of a clear, linear control flow.

@nonlethalapplications I can’t actually seem to view your video.

Regardless I managed to reproduce the same issue.

It seems we just don’t receive any of the OS callbacks for mouse or keyboard events until the mouse moves in this scenario. It’s not clear to me exactly why this would be but this strongly suggests an OS issue. One that it’s completely possible we won’t be able to overcome. I believe someone in the team reported an issue regarding modal dialogs to Apple a little while ago and the response from them was “don’t use modal dialogs”. So I’m not too hopeful that reporting this issue will be that helpful either.

I did however quickly test native dialogs and they seem to work. Would it maybe be less work for you to migrate to native dialogs? You can enable them on AlertWindow by calling setUsingNativeAlertWindows (true) on your LookAndFeel instance, or for a simple OK/Cancel dialog you can call AlertWindow::showNativeDialogBox().

1 Like

Fixed the video link now.

Thanks for testing. Good to know you can reproduce it. I hope this is a but that will be fixed on Apple’s end.

As you can see in the video we’re using modal dialogs not only for simple message boxes but also for custom windows where using native alert windows are too limited.

For now I’ll use Xcode 16.4 on Tahoe and stick with Ventura on the build server.

In the long run, we’ll try to move modal dialogs over to async handlers where we can.