Weird slowdown with popupmenus


#1

Hello,

I have a class I've created, and in the mouseDown method, I create a popup menu via the .show() method, like shown in the example in the API.

I have a few of these classes on the screen.

If I hover over one of these components and right click, I can keep popping up this menu, and selecting different things as many times as I want, no problem.

Now if I go over to another one afterwards and try to pop up a menu, the menu loads really slowly and sluggishly. It lets me hover over the different items, which change colour, but it won't let me select an item or dismiss the menu (or do anything else on the GUI - I have to kill the program).

It's weird as it doesn't matter which one I start with, but going to a second one will always lock up. Should I be using the showMenuAsync() method rather than just the show() or something?


#2

You're probably creating some recursive modal loops. Yes: always use the async versions - show() is really just there for legacy support, it's a really bad idea to run modal loops unless there's absolutely no alternative.


#3

Thanks Jules,

I've tried setting it up but I'm getting an assertion error.

So my class inherits ModalComponentManager::Callback, and I've implemented the void modalStateFinished (int returnValue); function, and implemented the following in MouseDown();...


PopupMenu m;
m.addItem (1, "Menu item");
m.showMenuAsync(PopupMenu::Options(), this);

When modalStateFinished() is called, the function executes as normal, but it throws a Microsoft Debug assertion... BLOCK_TYPE_IS_VALID(pHead->nBlockUse) and a JUCE assertion... *** Leaked objects detected: 1 instance(s) of class OwnedArray - I'm not using an OwnedArray. Is this the internal data for the popup menu?

Should I be cleaning something up in the popupmenu during the callback?


#4

You're probably leaking one of your own objects which contains an OwnedArray. If you add the JUCE_LEAK_DETECTOR to all your classes you should be able to find out where it came from.


#5

OK. So after debugging and looking at the JUCE code/API, I've worked out the assert is because the callback is deleting my class. I've been using the callback like a regular listener. I got it working with...

m.showMenuAsync(PopupMenu::Options(), ModalCallbackFunction::create <int>(this->myClassCallbackFunction, 3));

But as the myClassCallbackFunction has to be static, I can't call any of my other member methods from the callback function...

In any case, the original problem still persists, however, I've narrowed it down to submenus in debug mode. Release mode doesn't appear to have the problem.

 


#6

The whole PopUp functionality is a bit of a pain in the  *** to use. You can use a combination of templates, function pointers and object pointers to get rid off the callback object idea. 

This small PopUpCallback class just takes everything that is needed to call an unknown member function from an unkown class. The only constriant is that you have to specify the argument list of the function. But you could pass aditional info through the PopUpCallback constructor.

template<typename T>
    class PopUpCallback : public ModalComponentManager::Callback
    {
    public:
        PopUpCallback(T *owner, void(T::*function)(int)) : mOwner(owner), mFunction(function) {};
        void modalStateFinished(int result)
        {
            if (mOwner != NULL)
            {
                (mOwner->*mFunction)(result);
            }
        }
    private:
        T *mOwner;
        void(T::*mFunction)(int);
    };

This leaves you with a call like this:

m.showMenuAsync(PopupMenu::Options(), new PopUpCallback<AUIEditor>(this, &AUIEditor::popUpClosed));

 


#7

I'm having a similar issue, on Windows. My popups were getting stuck in the modal loop and not returning from show(). I finally tracked it down to some debug code that was enabling the MS CRT heap checking:

    _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_CHECK_ALWAYS_DF );

This of course checks the heap on every alloc and slows things down considerably.

I created a simple test based on the demo plugin example. I added a text button that creates a popup menu. It works fine. Then add the above and it gets stuck. I've also discovered that disabling the menu drop shadows fixes the issue.

 


#8

For me dropdown menus of the combo box and the menu that appears when a tabbed component is to small responds very slow when hovering the items or clicking them.

OS: OS X, latest master (6f7f976)

The weird thing is, that it disappears after a a few seconds.

I was on pre-4 juce version before. The slowdown appeared just after updating - none of my code has changed.

best,
-- Benjamin

Update: I'm starting to think, that it is connected to resizing the main window in my case. I enabled repaint debugging, and if I resize the window, it looks like the resizing messages are slowing coming in from a queue and each triggers a repaint. When I'm wildly resizing the window for two seconds, it will take a few seconds until the last repaint is done - even though I'm on a pretty fast machine.

Update 2: Everything works fine if I use the OpenGL Renderer. But unfortunately then the fonts look weird - so this is not really an option for us.


#9

We'd like to help, but I think we'd need some example code to reproduce this, it's not something we've noticed ourselves.


#10

I've sent you a minimal example to you rawmaterial email address.

It appears only to happen, if you use a non native-titlebar and resize/reposition child components in the resized() callback. if repaint debugging is enabled, you can get an idea of what's going on.

 


#11

I emailed a zip of my test project. I'm building 32-bit target using VC 2013. I tried both Juce v3 and v4 code, and on two machines, same behavior. I also notice the drop shadows are getting continuously repainted, which of course slows way down when the heap checking is enabled.