Problem with PopupMenus in plugins on OS X


#1

The bug report I got is: popup menus disappear before the user has a chance to make a selection, but only the first time they are launched. This happens in AU Lab and Logic on at least OS X 10.8 and up. 

To reproduce this issue, take some code that makes a popup menu with submenus and plop it into JuceDemoPlugin. I used the menu with all the submenus from the Juce Demo and attached it to a new button on the JuceDemoPlugin.  Then, pull up the plugin in Au Lab or Logic. What happens is that the first submenu appears when the mouse moves down to it, but then when the mouse moves farther down the main menu the entire PopupMenu is dismissed. Because this only happens once after an editor is made, for a long time I assumed it was my fault for moving the mouse off the menu accidentally! But no.

The root of the problem is with how hosts and juce_mac_NSViewComponentPeer::isFocused() interact here:

 return isSharedWindow ? this == currentlyFocusedPeer : [window isKeyWindow];

When popup menu windows call this method, [window isKeyWindow] is often returning false, even after [window makeKeyWindow] is called in grabFocus(). To complicate things, it doesn't return false all of the time. Whether [window makeKeyWindow] is able to make [window isKeyWindow] return true depends on the host. JUCE plugin host and Ableton Live always return false. Au Lab and Logic return true sometimes. 

This problem is obscured by the code in PopupMenu::doesAnyJuceCompHaveFocus(). In a host where isFocused() always returns false, like the JUCE host or Live, doesAnyJuceCompHaveFocus() always returns true. This is the wrong answer, but does not lead to any visible problems. In Au Lab and Logic, where [window isKeyWindow] returns true sometimes, doesAnyJuceCompHaveFocus() returns false the first time only, which leads to the weird behavior described above. 

Workaround:

In the line of code above, "this == currentlyFocusedPeer" always does have the expected value for menu windows. So as a workaround I'm just returning that, which works for my plugins as far as I can tell. Another workaround may be needed in the case where something else is depending on the behavior with isSharedWindow = 0.

 

 

 

 


#2

That's really annoying - it does seem that when you call makeKeyWindow, it works but isKeyWindow mysteriously returns false at first!

Doing a bit of investigation, it does seem like it's probably ok to ignore isKeyWindow and just use the status of currentlyFocusedPeer.. I'll figure out a fix and check something in shortly..


#3

Looks good, thanks!