ComboBox ModalCallbackFunction


#1

Using the tip...

Anyone else see this issue: http://screencast.com/t/HpWUzXTSjNoz

If you create a plugin with a ComboBox and click on the parent title bar it doesn't dismiss the PopupMenu (popupMenuFinishedCallback isn't called)...  The video shows the issue using the JUCE Demo Plugin and a test ComboBox.

The video shows the code I'm using to display and populate the ComboBox, if I'm missing something.. let me know.

Thanks,

Rail


#2

Really... No-one else seeing this?

 

 

 

 


AudioProcessorEditor::broughtToFront() never called
#3

When you click on the parent window, the plugin doesn't get any kind of event that it could use to dismiss the box. Not sure what could be done about that.


#4

I'm looking at other JUCE based plugins which appear to use comboboxes and I'm not seeing this behaviour...  

I'll try subclassing ComboBox and see if I can come up with something to dismiss the popup on any click outside the Component.

The problem is if the popup isn't dismissed then you get the popup being disembodied from the edit box as in the image above (and in the video).. so this can't be right...  

 

BTW, I'm seeing this in both VST and RTAS on OSX (haven't checked Windows or AU yet).

Rail


#5

Okay… since I’ve seen other JUCE based commercial plugins handling this title bar click correctly… it looks like they must be showing the PopupMenu modally… so I changed:

void ComboBox::showPopup()
{
    if (! menuActive)
    {
        const int selectedId = getSelectedId();

        PopupMenu menu;
        menu.setLookAndFeel (&getLookAndFeel());

        for (int i = 0; i < items.size(); ++i)
        {
            const ItemInfo* const item = items.getUnchecked(i);

            if (item->isSeparator())
                menu.addSeparator();
            else if (item->isHeading)
                menu.addSectionHeader (item->name);
            else
                menu.addItem (item->itemId, item->name,
                              item->isEnabled, item->itemId == selectedId);
        }

        if (items.size() == 0)
            menu.addItem (1, noChoicesMessage, false);

        // Set menuActive to false and show the PopupMenu modally without a callback:

	menuActive = false;
    
    	menu.showMenu (PopupMenu::Options().withTargetComponent (this)
                        .withItemThatMustBeVisible (selectedId)
                        .withMinimumWidth (getWidth())
                        .withMaximumNumColumns (1)
                        .withStandardItemHeight (jlimit (12, 24, getHeight())));
    
    }
}[/code]

and in PopupMenu:

[code]PopupMenu::~PopupMenu()
{    
    dismissAllActiveMenus();
}

Testing so far this appears to be okay from a click point of view… But it’s not responding to menu selections (yet)… I have not found any issues with processing while the PopupMenu is visible… Will keep hacking…

Rail


#6

I'm getting tired of repeating this advice again and again, but here we go: 

NEVER use modal loops in plugins.


#7


I was expecting that :)

 

The problem is this needs a resolution…  And currently I've managed to make it work 100% using a modal PopupMenu -- Obviously I'll keep working on a non-modal solution.. if possible.. but in the meantime the modal hack is working and I haven't seen any crashes yet….

I sent you a PM showing a commercial JUCE based app where the functionality is correct.. Either they're using a similar hack to mine or they've created a delegate in OSX and a Hook in Windows to get around the problem.

Rail
 


#8

Jules,

In juce_ComponentPeer.cpp

Please add: PopupMenu::dismissAllActiveMenus();

void ComponentPeer::handleFocusLoss()
{
    ModifierKeys::updateCurrentModifiers();
    
    [b][color=red]PopupMenu::dismissAllActiveMenus();[/color][/b]

    if (component.hasKeyboardFocus (true))
    {
        lastFocusedComponent = Component::currentlyFocusedComponent;

        if (lastFocusedComponent != nullptr)
        {
            Component::currentlyFocusedComponent = nullptr;
            Desktop::getInstance().triggerFocusCallback();
            lastFocusedComponent->internalFocusLoss (Component::focusChangedByMouseClick);
        }
    }
}

Thanks,

Rail


#9

No chance!

PopupMenus themselves use ComponentPeers. So when there are submenus, and one of them loses focus, that'd dismiss the entire menu. Not great. And I'm sure it'd cause all kinds of other edge-case problems too.

If you're going to randomly request changes without even explaining why it would be a good idea, you're going to have to do better than that!