/* ============================================================================== This file is part of the JUCE library. Copyright (c) 2022 - Raw Material Software Limited JUCE is an open source library subject to commercial or open-source licensing. By using JUCE, you agree to the terms of both the JUCE 7 End-User License Agreement and JUCE Privacy Policy. End User License Agreement: www.juce.com/juce-7-licence Privacy Policy: www.juce.com/juce-privacy-policy Or: You may also use this code under the terms of the GPL v3 (see www.gnu.org/licenses). JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE DISCLAIMED. ============================================================================== */ namespace juce::detail { class MouseInputSourceList : public Timer { public: MouseInputSourceList() { #if JUCE_ANDROID || JUCE_IOS auto mainMouseInputType = MouseInputSource::InputSourceType::touch; #else auto mainMouseInputType = MouseInputSource::InputSourceType::mouse; #endif addSource (0, mainMouseInputType); } MouseInputSource* addSource (int index, MouseInputSource::InputSourceType type) { auto* s = new MouseInputSourceImpl (index, type); sources.add (s); sourceArray.add (MouseInputSource (s)); return &sourceArray.getReference (sourceArray.size() - 1); } MouseInputSource* getMouseSource (int index) noexcept { return isPositiveAndBelow (index, sourceArray.size()) ? &sourceArray.getReference (index) : nullptr; } MouseInputSource* getOrCreateMouseInputSource (MouseInputSource::InputSourceType type, int touchIndex = 0) { if (type == MouseInputSource::InputSourceType::mouse || type == MouseInputSource::InputSourceType::pen) { for (auto& m : sourceArray) if (type == m.getType()) return &m; addSource (0, type); } else if (type == MouseInputSource::InputSourceType::touch) { jassert (0 <= touchIndex && touchIndex < 100); // sanity-check on number of fingers for (auto& m : sourceArray) if (type == m.getType() && touchIndex == m.getIndex()) return &m; if (canUseTouch()) return addSource (touchIndex, type); } return nullptr; } int getNumDraggingMouseSources() const noexcept { int num = 0; for (auto* s : sources) if (s->isDragging()) ++num; return num; } MouseInputSource* getDraggingMouseSource (int index) noexcept { int num = 0; for (auto& s : sourceArray) { if (s.isDragging()) { if (index == num) return &s; ++num; } } return nullptr; } void beginDragAutoRepeat (int interval) { if (interval > 0) { if (getTimerInterval() != interval) startTimer (interval); } else { stopTimer(); } } void timerCallback() override { bool anyDragging = false; for (auto* s : sources) { // NB: when doing auto-repeat, we need to force an update of the current position and button state, // because on some OSes the queue can get overloaded with messages so that mouse-events don't get through.. if (s->isDragging() && ComponentPeer::getCurrentModifiersRealtime().isAnyMouseButtonDown()) { s->lastPointerState.position = s->getRawScreenPosition(); s->triggerFakeMove(); anyDragging = true; } } if (! anyDragging) stopTimer(); } OwnedArray sources; Array sourceArray; private: bool addSource(); bool canUseTouch() const; }; } // namespace juce::detail