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

11 Likes

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