From 45698e40b2e891a92b4dc0cc10e999dc2d146cad Mon Sep 17 00:00:00 2001 From: ed Date: Thu, 12 Apr 2018 11:05:29 +0100 Subject: [PATCH] Make Viewport::DragToScrollListener more robust and able to cope with the deletion of the original mouseDown event component --- .../juce_gui_basics/layout/juce_Viewport.cpp | 41 +++++++++++++------ 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/modules/juce_gui_basics/layout/juce_Viewport.cpp b/modules/juce_gui_basics/layout/juce_Viewport.cpp index 7e04b3152f..ab7b89ba3b 100644 --- a/modules/juce_gui_basics/layout/juce_Viewport.cpp +++ b/modules/juce_gui_basics/layout/juce_Viewport.cpp @@ -217,6 +217,7 @@ struct Viewport::DragToScrollListener : private MouseListener, ~DragToScrollListener() { viewport.contentHolder.removeMouseListener (this); + Desktop::getInstance().removeGlobalMouseListener (this); } void positionChanged (ViewportDragPosition&, double) override @@ -227,14 +228,23 @@ struct Viewport::DragToScrollListener : private MouseListener, void mouseDown (const MouseEvent&) override { - offsetX.setPosition (offsetX.getPosition()); - offsetY.setPosition (offsetY.getPosition()); - ++numTouches; + if (! isGlobalMouseListener) + { + offsetX.setPosition (offsetX.getPosition()); + offsetY.setPosition (offsetY.getPosition()); + + // switch to a global mouse listener so we still receive mouseUp events + // if the original event component is deleted + viewport.contentHolder.removeMouseListener (this); + Desktop::getInstance().addGlobalMouseListener (this); + + isGlobalMouseListener = true; + } } void mouseDrag (const MouseEvent& e) override { - if (numTouches == 1 && ! doesMouseEventComponentBlockViewportDrag (e.eventComponent)) + if (Desktop::getInstance().getNumDraggingMouseSources() == 1 && ! doesMouseEventComponentBlockViewportDrag (e.eventComponent)) { auto totalOffset = e.getOffsetFromDragStart().toFloat(); @@ -259,13 +269,20 @@ struct Viewport::DragToScrollListener : private MouseListener, void mouseUp (const MouseEvent&) override { - if (--numTouches <= 0) - { - offsetX.endDrag(); - offsetY.endDrag(); - isDragging = false; - numTouches = 0; - } + if (isGlobalMouseListener && Desktop::getInstance().getNumDraggingMouseSources() == 0) + endDragAndClearGlobalMouseListener(); + } + + void endDragAndClearGlobalMouseListener() + { + offsetX.endDrag(); + offsetY.endDrag(); + isDragging = false; + + viewport.contentHolder.addMouseListener (this, true); + Desktop::getInstance().removeGlobalMouseListener (this); + + isGlobalMouseListener = false; } bool doesMouseEventComponentBlockViewportDrag (const Component* eventComp) @@ -280,8 +297,8 @@ struct Viewport::DragToScrollListener : private MouseListener, Viewport& viewport; ViewportDragPosition offsetX, offsetY; Point originalViewPos; - int numTouches = 0; bool isDragging = false; + bool isGlobalMouseListener = false; JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DragToScrollListener) };