diff --git a/src/surge-xt/gui/SurgeGUIUtils.cpp b/src/surge-xt/gui/SurgeGUIUtils.cpp index 452b5433d39..a1dc1cf9e53 100644 --- a/src/surge-xt/gui/SurgeGUIUtils.cpp +++ b/src/surge-xt/gui/SurgeGUIUtils.cpp @@ -38,6 +38,12 @@ bool showCursor(SurgeStorage *storage) return sc || tm; }; +bool isTouchMode(SurgeStorage *storage) +{ + bool tm = Surge::Storage::getUserDefaultValue(storage, Surge::Storage::TouchMouseMode, false); + return tm; +} + /* * We kinda want to know if we are standalone here, but don't have reference to the processor * but that's a constant for a process (you can't mix standalone and not) so make it a static diff --git a/src/surge-xt/gui/SurgeGUIUtils.h b/src/surge-xt/gui/SurgeGUIUtils.h index 80f985a0dba..f854b4f08d3 100644 --- a/src/surge-xt/gui/SurgeGUIUtils.h +++ b/src/surge-xt/gui/SurgeGUIUtils.h @@ -12,6 +12,7 @@ std::string toOSCaseForMenu(const std::string &menuName); extern bool showCursor(SurgeStorage *storage); extern bool allowKeyboardEdits(SurgeStorage *storage); +extern bool isTouchMode(SurgeStorage *storage); bool get_line_intersection(float p0_x, float p0_y, float p1_x, float p1_y, float p2_x, float p2_y, float p3_x, float p3_y, float *i_x, float *i_y); diff --git a/src/surge-xt/gui/widgets/ModulatableSlider.cpp b/src/surge-xt/gui/widgets/ModulatableSlider.cpp index 84f93971ca2..f8f16b21a61 100644 --- a/src/surge-xt/gui/widgets/ModulatableSlider.cpp +++ b/src/surge-xt/gui/widgets/ModulatableSlider.cpp @@ -387,6 +387,8 @@ void ModulatableSlider::mouseDrag(const juce::MouseEvent &event) return; } + mouseDragLongHold(event); + auto p = mouseDownFloatPosition; float distance = event.position.getX() - p.getX(); if (orientation == ParamConfig::kVertical) @@ -472,6 +474,7 @@ void ModulatableSlider::mouseDown(const juce::MouseEvent &event) return; } + mouseDownLongHold(event); valueOnMouseDown = value; modValueOnMouseDown = modValue; lastDistance = 0.f; @@ -481,6 +484,7 @@ void ModulatableSlider::mouseDown(const juce::MouseEvent &event) void ModulatableSlider::mouseMove(const juce::MouseEvent &event) { + mouseMoveLongHold(event); enqueueFutureInfowindow(SurgeGUIEditor::InfoQAction::START, event.position); } @@ -499,6 +503,8 @@ void ModulatableSlider::mouseUp(const juce::MouseEvent &event) hideInfowindowSoon(); } + mouseUpLongHold(event); + if (!Surge::GUI::showCursor(storage)) { juce::Desktop::getInstance().getMainMouseSource().enableUnboundedMouseMovement(false); diff --git a/src/surge-xt/gui/widgets/ModulatableSlider.h b/src/surge-xt/gui/widgets/ModulatableSlider.h index 8d25090b4ca..713486bbee0 100644 --- a/src/surge-xt/gui/widgets/ModulatableSlider.h +++ b/src/surge-xt/gui/widgets/ModulatableSlider.h @@ -31,6 +31,7 @@ namespace Widgets { struct ModulatableSlider : public juce::Component, public WidgetBaseMixin, + public LongHoldMixin, public ModulatableControlInterface { ModulatableSlider(); diff --git a/src/surge-xt/gui/widgets/WidgetBaseMixin.h b/src/surge-xt/gui/widgets/WidgetBaseMixin.h index a5ecac147c7..a5a8b8c921e 100644 --- a/src/surge-xt/gui/widgets/WidgetBaseMixin.h +++ b/src/surge-xt/gui/widgets/WidgetBaseMixin.h @@ -18,6 +18,7 @@ #include "SkinSupport.h" #include "SurgeGUICallbackInterfaces.h" +#include "SurgeGUIUtils.h" #include "juce_gui_basics/juce_gui_basics.h" @@ -185,6 +186,75 @@ struct WidgetBaseMixin : public Surge::GUI::SkinConsumingComponent, return firstListenerOfType() && e.mods.isMiddleButtonDown(); } }; + +template struct LongHoldMixin +{ + LongHoldMixin() {} + virtual ~LongHoldMixin() + { + if (timer && timer->isTimerRunning()) + timer->stopTimer(); + } + inline T *asT() { return static_cast(this); } + + static constexpr uint32_t holdDelayTimeInMS = 750; + void onLongHoldWrapper() + { + if (timer) + timer->stopTimer(); + onLongHold(); + } + + virtual void onLongHold() + { + juce::ModifierKeys k{0}; + asT()->notifyControlModifierClicked(k, true); + } + + bool shouldLongHold() + { + // return true; + return GUI::isTouchMode(asT()->storage); + } + + juce::Point startingHoldPosition; + virtual void mouseDownLongHold(const juce::MouseEvent &e) + { + if (!shouldLongHold()) + return; + + startingHoldPosition = e.position.toFloat(); + if (timer && timer->isTimerRunning()) + timer->stopTimer(); + timer = std::make_unique(this); + timer->startTimer(holdDelayTimeInMS); // ms + } + virtual void mouseMoveLongHold(const juce::MouseEvent &e) + { + if (e.position.getDistanceFrom(startingHoldPosition) > 4) + if (timer && timer->isTimerRunning()) + timer->stopTimer(); + } + virtual void mouseDragLongHold(const juce::MouseEvent &e) + { + if (e.position.getDistanceFrom(startingHoldPosition) > 1) + if (timer && timer->isTimerRunning()) + timer->stopTimer(); + } + virtual void mouseUpLongHold(const juce::MouseEvent &e) + { + if (timer && timer->isTimerRunning()) + timer->stopTimer(); + } + + struct LHCB : public juce::Timer + { + LongHoldMixin *that{nullptr}; + LHCB(LongHoldMixin *t) : that(t) {} + void timerCallback() override { that->onLongHoldWrapper(); } + }; + std::unique_ptr timer; +}; } // namespace Widgets } // namespace Surge #endif // SURGE_XT_WIDGETBASEMIXIN_H