PopupMenu with a rewritten mouse handling code

Hi,

I’m a heavy user of juce PopupMenu, and have a complicated relation with it. I love it because it is super convenient, and I hate it because it has a lot of annoying issues that are sometimes platform dependent, that depend on the input (touch and / or mouse), that may depend on the fact that submenus are used, or if the menu window appears over the mouse pointer or not, or if the popupmenu has a parent component or not.

After spending way too much time (weeks…) trying to fix the issues I had with the juce PopupMenu (with touchscreen, especially when submenus are involved), I have finally taken the time to rewrite the part of the juce_PopupMenu.cpp that have been bothering me for a long time.

Why rewriting instead of fixing ? because each time I have fixed something (like making it work correctly for touchscreen on windows) it broke somewhere else. The current mouse handling stuff of the popup menus is too intricate.

The part handling mouse input was obviously written at a time where JUCE was not handling touch screens, so its behavior is centered around the fact that the mouse can “hover” over a menu item. Also there are many mouse events that are received by the MenuWindow, most of them redundant: each MenuWindow (the main menu, its submenus…) listens to its own mouse events, and is also a global mouse listener where is pointer position is polled by a timer. The fact that these events are being sent while windows (the submenus) appear and disappear, make their sequence a bit platform-dependent: for the same gesture you won’t always get the same event sequence if you are on windows with a touchscreen , or if you are on iOS. The PopupMenu also handles each event source separately, so when you have a mouse and a touchscreen, even if the mouse does not do anything, it still has an effect on the PopupMenu (its position is polled, and the item below the mouse pointer is highlighted).

The replacement juce_PopupMenu.cpp that I attach here is basically the same as the original one, except for the multiple MouseSourceState instances (one instance per window and per MouseInputSource in the original popupmenu code) that have been replaced that a single MouseManager (one instance shared for all windows of the current menu, and that handles input from all input sources, listening only to the last one that has sent events). All the code that handles the popupmenu layout, the MenuWindow placement etc, is still the same.

I have been running this new version only for a few days, so there might be still some edge case that don’t work fine (the PopupMenu behaviour is quite rich, and there are many complicated situations that may arise), but it still works much better in my opinion than the original version, and I have spent a lot less time writing it than the time I have spent trying to fix the original.

My changes are under the WTFPL, in case the JUCE team wants to use them. I’ll be happy if it helps to improve the official juce PopupMenu.

https://bitbucket.org/jpommier/juce-stuff/src/master/juce_PopupMenu.cpp

15 Likes

That’s impressive! I’ll definitely test your modified version. Thank you very much!

I have pushed a small update to the code (backporting recent changes from the juce team).

1 Like

I’m still wondering if the JUCE team is considering adopting your version of the PopupMenu? The one in JUCE8 is still problematic for touch screens when using sub menus unfortunately.

1 Like

Bumping this… the standard JUCE popup menu is still barely useable on a touch screen (iOS) especially in combination with sub menus (tried the develop version and doesn’t work properly). @jpo has created a version that does seem to work really well; I want to reiterate on the suggestion for the JUCE team to have a look at it…

Just noticed the JUCE 8.0.9 update; the usability of PopupMenus on mobile screens is still cumbersome.

There seems to be a new issue however: popup menus do not appear at all anymore on iOS / AUv3 when using the editor as parent component in the PopupMenu::Options struct, while they do work on iOS standalone. Anyone else also seeing this?

A quick debugging session seemed to reveal that the size of the MenuWindow instance is set to negative values in AUv3, but not in iOS stand alone, and I can reproduce this in an empty project. I’ll create a new thread with a BR and sample code.