Hi,
PopupMenu, especially when there are submenus involved , do not work well with touchscreens, either on iOS or on Windows: the submenus often fail to open, the menu is sometimes inadvertently closed. With long menus, the auto scroll does not work well (it is really designed for mouses, by depending on the current mouse position)
Here is an attempt at improving the situation for iOS – with this patch PopupMenu work much better on iOS – not perfect but really better. The first thing that I change is to remove MouseInputSource::offscreenMousePos from juce_iOS_UIViewComponentPeer:
if (isUp || isCancel)
{
handleMouseEvent (MouseInputSource::InputSourceType::touch, pos /* MouseInputSource::offscreenMousePos*/, modsToSend,
MouseInputSource::invalidPressure, MouseInputSource::invalidOrientation, time, {}, touchIndex);
It does not seem to break anything (appart from the auto-scroll of popupmenus, but it was already not working well). With this change the PopupMenu MouseInputSource will stop receiving fake mousemove events that prevent submenus from working. So this simple change improves a lot of things already.
Now, I what to also be able to scroll in the menu , just by dragging. I came up with this patch:
double scrollAcceleration = 0; uint32 lastScrollTime, lastMouseMoveTime = 0; bool isDown = false; bool isTouchDragging = false; Point<int> lastTouchDraggingPos; // ADD THIS void handleMousePosition (Point<int> globalMousePos) { auto localMousePos = window.getLocalPoint (nullptr, globalMousePos); auto timeNow = Time::getMillisecondCounter(); /// BEGIN ADD THIS if (source.isTouch()) { if (source.getIndex() > 0) return; // one finger only if (source.isDragging() && source.hasMovedSignificantlySincePressed()) { bool move = isTouchDragging && window.canScroll(); // using globalMousePos does not work well when scrolling (jumps) auto pos = source.getScreenPosition().roundToInt(); if (move) { auto delta_y = lastTouchDraggingPos.y - pos.y; if (delta_y) { window.alterChildYPos(delta_y); } } lastTouchDraggingPos = pos; isTouchDragging = true; } if (!source.isDragging() && isTouchDragging) { isTouchDragging = false; isDown = false; // prevent triggerCurrentlyHighlightedItem from being called after a drag } if (isTouchDragging) { if (window.activeSubMenu) window.activeSubMenu->hide (nullptr, true); return; // skip everything else (the auto-scroll, the submenu display..) } } // END ADD THIS if (timeNow > window.timeEnteredCurrentChildComp + 100 && window.reallyContains (localMousePos, true)
It’s still not working on windows, I assume that the situation where there is both a mouse and a touchscreen is causing specific issues.
I really would like the PopupMenu to be working better with touchscreens , this is a complicated but so useful component…