Non-blocking (Popup)menu possible?

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
Remdul
Earned a small fee
Earned a small fee
Posts: 16
Joined: Tue Oct 27, 2009 10:14 pm
Location: Netherlands

Non-blocking (Popup)menu possible?

Post by Remdul »

I currently implement a context menu (wxMenu) with Popupmenu(), but that is a blocking function. It halts execution of the rest of the application. This is a problem for me, because the application is running a real-time simulation which should continue in the background regardless of UI events. Think of it like a video player, where you can right click to toggle options such as subtitles or aspect ratio, while the video keeps playing.

I noticed that when the same menu is shown by clicking via wxMenuBar on Linux/GTK, it doesn't block, so it seems it should be possible to prevent blocking. So why the difference?

On Windows, showing any menu via wxMenuBar does block, like Popupmenu, so it is consistent there (but not desirable). Is there a Windows specific workaround for this?

Does choosing the parent window of the wxMenu (via ::Popupmenu) influence anything?

Are there workarounds? It's fine if the solution is hacky or unsafe. I already implement a manual main loop in this application.
ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 7458
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Re: Non-blocking (Popup)menu possible?

Post by ONEEYEMAN »

Hi,
You best bet on implementing this - run the real-time simulation in a thread, posting the events to the main GUI.
Unfortunately GUI should be run only from the main thread, so you should make you simulation run from the thread.

Everything will work as expected.

Thank you.
User avatar
doublemax
Moderator
Moderator
Posts: 19114
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Non-blocking (Popup)menu possible?

Post by doublemax »

I think menus are always blocking under Windows. The only solution i could think of would be to build your own popup menu using wxPopupTransientWindow.
http://docs.wxwidgets.org/trunk/classwx ... indow.html

The "popup" sample shows how to use it.
Use the source, Luke!
Remdul
Earned a small fee
Earned a small fee
Posts: 16
Joined: Tue Oct 27, 2009 10:14 pm
Location: Netherlands

Re: Non-blocking (Popup)menu possible?

Post by Remdul »

Thanks doublemax, didn't know about that one yet, I will experiment with it and post the results here. It is kinda weird though that something as simple as showing a menu blocks things, while other more complex controls don't.

@ONEEYEMAN: I try to avoid threads at all cost, I've found they are rarely needed (even for real-time interactive applications), and usually a symptom of bad design, and often lead to a host of other problems. In the worst case, I'll try wrapping the menu itself in a thread rather than the other way around.
ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 7458
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Re: Non-blocking (Popup)menu possible?

Post by ONEEYEMAN »

Rendul,
Please don't do that.
The GUI has to be run from the main thread only.

Thank you.
meltphace
In need of some credit
In need of some credit
Posts: 2
Joined: Thu Apr 15, 2021 7:59 am

Re: Non-blocking (Popup)menu possible?

Post by meltphace »

Hi Remdul,

I'm facing the exact same problem (trying to display a popup menu in a non blocking manner).

Did you find a solution/workaround?

Thank you very much in advance.
catalin
Moderator
Moderator
Posts: 1618
Joined: Wed Nov 12, 2008 7:23 am
Location: Romania

Re: Non-blocking (Popup)menu possible?

Post by catalin »

When menus are shown (and scrollbars are active, and probably a few other cases), idle events were not sent on MSW (and this might have changed in 3.1.x versions). BTW, which version did you use? Your app is probably relying on the "next idle event". Otherwise, the menu should not be "blocking" anything.
One possible solution is to try with the latest version (i.e. the newly released 3.1.5).
Another one is to switch to timer-based triggering.
There may be others..
meltphace
In need of some credit
In need of some credit
Posts: 2
Joined: Thu Apr 15, 2021 7:59 am

Re: Non-blocking (Popup)menu possible?

Post by meltphace »

Dear Catalin,

Thank you very much for your extremely quick and precise response.
Even though I failed to mention which system I'm working on, which version of wxWidgets I'm using, and couldn't even formulate my question properly, you've got it all right.

(I'm working on MSW with wxWidgets 3.1.4)

As you explained, even though wxWindow::PopupMenu(...) is a blocking call (it doesn't return until the popup menu is closed), wxWidget's event system is still working behind the scenes, and events are still sent/received, in the main thread, during that period of time.

On MSW however, this excludes idle events, which are simply not sent. As you guessed, I was indeed relying on them to do updates on my underlying wxGLCanvas.

I can confirm that this behaviour is still in effect with 3.1.5, which I just tried.

+++

Following your suggestion, I'm now launching a wxTimer just before calling wxWindow::PopupMenu(...) and use it to trigger my updates while the menu is on.

As it's already been reported here:
viewtopic.php?t=43967

a wxTimer with zero interval on MSW has quite a poor granularity (~15ms tick interval on average, with frequent occurrences of the worst case at more that 20ms), so I experience frame drops while the context menu is on, but I can live with that.

As soon as the context menu is closed, updates can get triggered by idle events again, with a much better granularity, and we're back to silky smooth 60 fps.

+++

Again, thank you very much Catalin. Even though I'd really like to see idle events being sent when menus are shown in future versions of wxWidgets, your suggestion helped me a lot.

Thanks!
Big Muscle
Earned some good credits
Earned some good credits
Posts: 100
Joined: Sun Jun 27, 2010 6:18 pm

Re: Non-blocking (Popup)menu possible?

Post by Big Muscle »

meltphace wrote: Fri Apr 16, 2021 8:09 am As you explained, even though wxWindow::PopupMenu(...) is a blocking call (it doesn't return until the popup menu is closed), wxWidget's event system is still working behind the scenes, and events are still sent/received, in the main thread, during that period of time.

On MSW however, this excludes idle events, which are simply not sent. As you guessed, I was indeed relying on them to do updates on my underlying wxGLCanvas.
Is CallAfter considered to be idle event? I noticed that timer/mouse events are still processed on PopupMenu but CallAfter callback called in the separate thread is not.
catalin
Moderator
Moderator
Posts: 1618
Joined: Wed Nov 12, 2008 7:23 am
Location: Romania

Re: Non-blocking (Popup)menu possible?

Post by catalin »

AFAIR what you pass to CallAfter will be executed in the main thread at the next idle event. So CallAfter is not itself an idle event, but depends on an idle event.
Post Reply