JUCE 6.1. broke NativeMessageBox

After updating to JUCE 6.1 (from 6.0.8), I have multiple issues with NativeMessageBox on both Mac and Windows.

  1. The messagebox started to return immediately with zero without waiting for the user to press any buttons. I noticed this was caused by the added JUCE_MODAL_LOOPS_PERMITTED check in ShowDialog. I had to add JUCE_MODAL_LOOPS_PERMITTED=1 to the preprosessor definitions to get it working like before. Is this intended and the correct way to fix this? I did not see an option in Projucer anywhere for specifying this, which would have been nice if this is indeed the required way to restore old behaviour.

  2. The return values have swapped and the documentation is wrong. Pressing “yes” / “ok” now returns zero instead of one like before. OkCancelBox will now return false when OK was pressed.

  3. The message box does not block the GUI anymore like I need it to. I am showing an update message to the user (“update available, do you want to download?”), and I need the MessageBox to block the main GUI while this popup is shown. This no longer works on Windows (10), but it does on Mac.

We had a similar thing - we were previously using the non-async methods to launch native dialog boxes, but those were removed in 6.1 so we had to switch to the async methods instead.

IMO, these were some good changes which stopped us being lazy and forced us to implement the dialog boxes properly.

As @ImJimmi mentioned the default value for JUCE_MODAL_LOOPS_PERMITTED is now 0 so you’ll need to enable that preprocessor flag if you want to use the old, modal methods in NativeMessageBox.

The return values have swapped and the documentation is wrong. Pressing “yes” / “ok” now returns zero instead of one like before. OkCancelBox will now return false when OK was pressed.

Thanks for reporting, that was an error in some recent changes to the dialog window classes and has been fixed now on develop here:

This has also been fixed on develop now with the following commit where we fall back to the old-style dialog for modal alerts on Windows as the updated TaskDialog class does not support blocking, modal alerts:

Again, thanks for reporting these and let us know if you run into any more issues!

1 Like

Thank you for the fixes, I will try the develop branch out :slight_smile:

Regarding 1.), sorry I missed the info in the breaking-changes doc, I was not familiar with the modal loops term / flag and did not realise it would affect the MessageBox usage…

I’m having a possibly related issue in Windows with modal dialogs, first noticed it with JUCE 6.1.2 and still having it now with 6.1.4.

This is in a standalone app on Windows 10. In different places, I’m using both NativeMessageBox::showYesNoBox and NativeMessageBox::showMessageBox, and have JUCE_MODAL_LOOPS_PERMITTED=1 in my preprocessor definitions.

What happens is, when one of these is triggered, the spinning blue circle cursor appears, and the main window de-focuses and becomes unresponsive. But the dialog box does not appear. If I wiggle the mouse, the cursor reverts to the regular pointer, but the app remains unresponsive. At first I thought it had crashed…

But actually, pressing the Alt-Tab keyboard shortcut (to show the system’s “switcher” view of all open windows) reveals the missing dialog box in its preview window, and then when when exiting the switcher, the missing dialog suddenly appears where it was supposed to be in the first place. From there, the dialog box and the app function normally (and the dialog box behaves modally, blocking input to the rest of the app until dismissed).

Can anyone else reproduce this on Windows with a standalone app?

Further details: when calling showMessageBox, I’m leaving the associatedComponent parameter as nullptr. And when calling showYesNoBox, the ModalComponentManager::Callback parameter is left as nullptr as well, so it is being called synchronously/modally.

I had a quick go at reproducing this on Windows 11 with the DialogsDemo. I added the modal loops definition, then modified the relevant functions to use the modal versions. In all cases I tried (both alert window types, with and without a native titlebar) the dialog opened on top of the application window.

Can you provide any more details, or a minimal code example that reliably triggers the problem? Is there anything special about your app that might affect window order?

OK, thank you @reuk – I will try a build of DialogsDemo and see if I can reproduce the issue.

Off the top of my head, one difference from that demo is that in my app, neither alert window type is being triggered by a mouse click – one is triggered by a keypress, and the other automatically from a constructor (conditionally in case of an error).

Also, to be clear: the dialogs aren’t opening behind the application window, they aren’t opening at all. (The application window itself is fairly small, so it’s easy to see that difference when a dialog pops up.)

Besides that, I’ll have to comb through the code and see how I might reduce it to an example to post here.

PS: Forgot to mention that this issue isn’t happening at all on macOS.

Although we couldn’t reproduce the exact issue you are seeing, we have pushed a change to develop that might affect what you are experiencing.

Thanks for the suggestion. I got to try that patch today, but it didn’t fix the issue. (First just cherry picked this commit against JUCE 6.1.4 master, then tried the whole develop branch.)

I did try DialogsDemo, and the disappearing window is not happening with that (even when modifying it to use the modal versions, as @reuk had mentioned).

There are a couple things that my app does with window order, so I’ll have to start whittling that down and see where the trouble is happening.

I have been working on tracking this bug down, and so far it has been elusive. Here is the test code I’m calling, in MainComponent::keyPressed, in response to pressing the “t” key. So this should open a native Yes/No dialog box, modally:

    int result = NativeMessageBox::showYesNoBox (AlertWindow::NoIcon, "Coffee Break", "Do you take sugar?", nullptr, nullptr);
    
    if (result == 1) DBG ("OK, adding sugar");
    else             DBG ("OK, no sugar");

The current behavior is: the dialog window is not visually appearing, but after triggering the test code above, I can use the return key or the spacebar to answer the dialog’s yes/no question, and then I see the DBG output happen and the modal status of the dialog is released (the main app window is responsive again). So it’s like the dialog window was there, but visually it never appears at any point.

Alternately, to get the dialog window to appear, I can press the Alt key (this is a correction of what I said above: I don’t actually have to press Alt-Tab combo to cycle through open windows to get the dialog window to appear, I just need to tap the Alt key once.)

I have been going through the code (more or less in the order that the constructors run) and commenting different parts out, or doing early returns from the ctors, and sometimes I’ll hit a spot where omitting a part causes the dialog box to be visible as expected. But the weird thing is, I cannot correlate the connection between those spots and dialog behavior. For example, the first line I found where commenting it out affected the dialog visibility was a ValueTree::addListener call in a constructor.

I’m going to try a few more things today, and I’m still trying to recreate the bug in a simpler DialogsDemo type example.

PS: I don’t think I ever mentioned the system setup here – I’m building on Windows 10, with Visual Studio 2017 (so that’s with Platform Toolset v141). And it’s running as a virtual machine in VMware Fusion.

I have been using juce::AlertWindow, which has been working well on Windows. Just need to set setUsingNativeAlertWindows(true); for the LookAndFeel.

I tried adding that @AkseliYS, but I’m already calling NativeMessageBox directly and not leaving it up to LookAndFeel (as happens when using an AlertWindow method), so it did not make a difference.

Also tried changing my test calls to async message boxes, and the problem persists – so it’s not isolated to the modal behavior per-se.

NativeMessageBox::showMessageBoxAsync (AlertWindow::NoIcon, "Coffee Break", "Will you want sugar later?", this);

At last, I found the cause of the NativeMessageBox not appearing correctly onscreen.

At the end of a LookAndFeel method (drawPropertyComponentBackground) where I was conditionally setting some colors for a PropertyComponent, I had put this:

component.repaint();

And that causes an endless (though asynchronous) loop! Since that marks the Component as dirty, and then the next time the graphics scheduler fires PropertyComponent::paint, the paint method in turn calls drawPropertyComponentBackground again.

So, that part was my bad. (I had left myself a comment there claiming that the call was necessary, or else the background color wouldn’t be updated - although that doesn’t actually seem to be true, so no idea what I had previously observed about that.)

For whatever reasons, this loop did not prevent the NativeMessageBox from appearing on macOS, but on Windows 10 it did. As mentioned above here, I had to tap the Alt key on Windows to get the native dialog box to appear onscreen.

JUCE Devs: is there something that should be tweaked (in how repaints are queued?) so that they don’t block dialog window drawing like this? In this case, it was a benefit for me (i.e. leading me to fix some bad code), but I wonder if during times of justifiably heavy repaint activity, that blocking the dialog window might happen then too.