From 60e9231fb118e888b255d51ba6cea852fa374807 Mon Sep 17 00:00:00 2001 From: jules Date: Wed, 29 Mar 2017 15:31:26 +0100 Subject: [PATCH] Removed need for std::function in order to use MessageManager::callAsync(). Used it to modernise a few bits of old code. --- .../gui/juce_MidiKeyboardComponent.cpp | 8 +- modules/juce_core/network/juce_URL.h | 14 ++-- .../messages/juce_CallbackMessage.h | 5 +- .../messages/juce_MessageManager.cpp | 36 ++------- .../messages/juce_MessageManager.h | 26 +++++-- .../components/juce_Component.cpp | 60 +++++--------- .../mouse/juce_DragAndDropContainer.cpp | 43 ++++------ .../juce_gui_basics/widgets/juce_TreeView.cpp | 10 +-- .../windows/juce_ComponentPeer.cpp | 78 +++++++------------ .../windows/juce_ComponentPeer.h | 6 +- 10 files changed, 105 insertions(+), 181 deletions(-) diff --git a/modules/juce_audio_utils/gui/juce_MidiKeyboardComponent.cpp b/modules/juce_audio_utils/gui/juce_MidiKeyboardComponent.cpp index c8e5e6d99e..2ff33f20b2 100644 --- a/modules/juce_audio_utils/gui/juce_MidiKeyboardComponent.cpp +++ b/modules/juce_audio_utils/gui/juce_MidiKeyboardComponent.cpp @@ -853,11 +853,9 @@ void MidiKeyboardComponent::timerCallback() if (shouldCheckMousePos) { - const Array& mouseSources = Desktop::getInstance().getMouseSources(); - - for (MouseInputSource* mi = mouseSources.begin(), * const e = mouseSources.end(); mi != e; ++mi) - if (mi->getComponentUnderMouse() == this || isParentOf (mi->getComponentUnderMouse())) - updateNoteUnderMouse (getLocalPoint (nullptr, mi->getScreenPosition()).roundToInt(), mi->isDragging(), mi->getIndex()); + for (auto& ms : Desktop::getInstance().getMouseSources()) + if (ms.getComponentUnderMouse() == this || isParentOf (ms.getComponentUnderMouse())) + updateNoteUnderMouse (getLocalPoint (nullptr, ms.getScreenPosition()).roundToInt(), ms.isDragging(), ms.getIndex()); } } diff --git a/modules/juce_core/network/juce_URL.h b/modules/juce_core/network/juce_URL.h index 6ff00093ac..a0b35056e5 100644 --- a/modules/juce_core/network/juce_URL.h +++ b/modules/juce_core/network/juce_URL.h @@ -393,14 +393,14 @@ public: /** Download the URL to a file. - This method attempts to download the URL to a given file location. + This method attempts to download the URL to a given file location. - Using this method to download files on mobile is less flexible but more reliable - than using createInputStream or WebInputStreams as it will attempt to download the file - using a native OS background network task. Such tasks automatically deal with - network re-connections and continuing your download while your app is suspended but are - limited to simple GET requests. - */ + Using this method to download files on mobile is less flexible but more reliable + than using createInputStream or WebInputStreams as it will attempt to download the file + using a native OS background network task. Such tasks automatically deal with + network re-connections and continuing your download while your app is suspended but are + limited to simple GET requests. + */ DownloadTask* downloadToFile (const File& targetLocation, String extraHeaders = String(), DownloadTask::Listener* listener = nullptr); diff --git a/modules/juce_events/messages/juce_CallbackMessage.h b/modules/juce_events/messages/juce_CallbackMessage.h index fc9099d298..3de88b0184 100644 --- a/modules/juce_events/messages/juce_CallbackMessage.h +++ b/modules/juce_events/messages/juce_CallbackMessage.h @@ -46,7 +46,10 @@ Always create a new instance of a CallbackMessage on the heap, as it will be deleted automatically after the message has been delivered. - @see MessageManager, MessageListener, ActionListener, ChangeListener + Note that this class was essential back in the days before C++11, but in modern + times you may prefer to use MessageManager::callAsync() with a lambda. + + @see MessageManager::callAsync, MessageListener, ActionListener, ChangeListener */ class JUCE_API CallbackMessage : public MessageManager::MessageBase { diff --git a/modules/juce_events/messages/juce_MessageManager.cpp b/modules/juce_events/messages/juce_MessageManager.cpp index afaf570cae..12940aca9d 100644 --- a/modules/juce_events/messages/juce_MessageManager.cpp +++ b/modules/juce_events/messages/juce_MessageManager.cpp @@ -29,10 +29,7 @@ */ MessageManager::MessageManager() noexcept - : quitMessagePosted (false), - quitMessageReceived (false), - messageThreadId (Thread::getCurrentThreadId()), - threadWithLock (0) + : messageThreadId (Thread::getCurrentThreadId()) { if (JUCEApplicationBase::isStandaloneApp()) Thread::setCurrentThreadName ("Juce Message Thread"); @@ -74,7 +71,7 @@ void MessageManager::deleteInstance() //============================================================================== bool MessageManager::MessageBase::post() { - MessageManager* const mm = MessageManager::instance; + auto* mm = MessageManager::instance; if (mm == nullptr || mm->quitMessagePosted || ! postMessageToSystemQueue (this)) { @@ -118,7 +115,7 @@ public: void messageCallback() override { - if (MessageManager* const mm = MessageManager::instance) + if (auto* mm = MessageManager::instance) mm->quitMessageReceived = true; } @@ -148,31 +145,12 @@ void MessageManager::stopDispatchLoop() #endif -//============================================================================== -#if JUCE_COMPILER_SUPPORTS_LAMBDAS -struct AsyncFunction : private MessageManager::MessageBase -{ - AsyncFunction (std::function f) : fn (f) { post(); } - -private: - std::function fn; - void messageCallback() override { fn(); } - - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AsyncFunction) -}; - -void MessageManager::callAsync (std::function f) -{ - new AsyncFunction (f); -} -#endif - //============================================================================== class AsyncFunctionCallback : public MessageManager::MessageBase { public: AsyncFunctionCallback (MessageCallbackFunction* const f, void* const param) - : result (nullptr), func (f), parameter (param) + : func (f), parameter (param) {} void messageCallback() override @@ -182,7 +160,7 @@ public: } WaitableEvent finished; - void* volatile result; + void* volatile result = nullptr; private: MessageCallbackFunction* const func; @@ -306,7 +284,7 @@ MessageManagerLock::MessageManagerLock (BailOutChecker& bailOutChecker) bool MessageManagerLock::attemptLock (BailOutChecker* bailOutChecker) { - MessageManager* const mm = MessageManager::instance; + auto* mm = MessageManager::instance; if (mm == nullptr) return false; @@ -358,7 +336,7 @@ MessageManagerLock::~MessageManagerLock() noexcept { if (blockingMessage != nullptr) { - MessageManager* const mm = MessageManager::instance; + auto* mm = MessageManager::instance; jassert (mm == nullptr || mm->currentThreadHasLockedMessageManager()); diff --git a/modules/juce_events/messages/juce_MessageManager.h b/modules/juce_events/messages/juce_MessageManager.h index f83c2c2a5d..4ebc6d2f12 100644 --- a/modules/juce_events/messages/juce_MessageManager.h +++ b/modules/juce_events/messages/juce_MessageManager.h @@ -99,12 +99,12 @@ public: #endif //============================================================================== - #if JUCE_COMPILER_SUPPORTS_LAMBDAS - /** Asynchronously invokes a function or C++11 lambda on the message thread. - Internally this uses the CallbackMessage class to invoke the callback. - */ - static void callAsync (std::function); - #endif + /** Asynchronously invokes a function or C++11 lambda on the message thread. */ + template + static void callAsync (FunctionType functionToCall) + { + new AsyncCallInvoker (functionToCall); + } /** Calls a function using the message-thread. @@ -211,9 +211,9 @@ private: friend class MessageManagerLock; ScopedPointer broadcaster; - bool quitMessagePosted, quitMessageReceived; + bool quitMessagePosted = false, quitMessageReceived = false; Thread::ThreadID messageThreadId; - Thread::ThreadID volatile threadWithLock; + Thread::ThreadID volatile threadWithLock = {}; CriticalSection lockingLock; static bool postMessageToSystemQueue (MessageBase*); @@ -222,6 +222,16 @@ private: static void doPlatformSpecificShutdown(); static bool dispatchNextMessageOnSystemQueue (bool returnIfNoPendingMessages); + template + struct AsyncCallInvoker : public MessageBase + { + AsyncCallInvoker (FunctionType f) : callback (f) { post(); } + void messageCallback() override { callback(); } + FunctionType callback; + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AsyncCallInvoker) + }; + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MessageManager) }; diff --git a/modules/juce_gui_basics/components/juce_Component.cpp b/modules/juce_gui_basics/components/juce_Component.cpp index 5c54f79074..b35cb9a1c5 100644 --- a/modules/juce_gui_basics/components/juce_Component.cpp +++ b/modules/juce_gui_basics/components/juce_Component.cpp @@ -1731,7 +1731,7 @@ void Component::enterModalState (const bool shouldTakeKeyboardFocus, if (! isCurrentlyModal (false)) { - ModalComponentManager& mcm = *ModalComponentManager::getInstance(); + auto& mcm = *ModalComponentManager::getInstance(); mcm.startModal (this, deleteWhenDismissed); mcm.attachCallback (this, callback); @@ -1753,36 +1753,24 @@ void Component::exitModalState (const int returnValue) { if (MessageManager::getInstance()->isThisTheMessageThread()) { - ModalComponentManager& mcm = *ModalComponentManager::getInstance(); + auto& mcm = *ModalComponentManager::getInstance(); mcm.endModal (this, returnValue); mcm.bringModalComponentsToFront(); // If any of the mouse sources are over another Component when we exit the modal state then send a mouse enter event - const Array& mouseSources = Desktop::getInstance().getMouseSources(); - - for (MouseInputSource* mi = mouseSources.begin(), * const e = mouseSources.end(); mi != e; ++mi) - { - if (Component* c = mi->getComponentUnderMouse()) - c->internalMouseEnter (*mi, mi->getScreenPosition(), Time::getCurrentTime()); - } + for (auto& ms : Desktop::getInstance().getMouseSources()) + if (auto* c = ms.getComponentUnderMouse()) + c->internalMouseEnter (ms, ms.getScreenPosition(), Time::getCurrentTime()); } else { - struct ExitModalStateMessage : public CallbackMessage - { - ExitModalStateMessage (Component* c, int res) : target (c), result (res) {} + WeakReference target (this); - void messageCallback() override - { - if (Component* c = target) - c->exitModalState (result); - } - - WeakReference target; - int result; - }; - - (new ExitModalStateMessage (this, returnValue))->post(); + MessageManager::callAsync ([=]() + { + if (auto* c = target.get()) + c->exitModalState (returnValue); + }); } } } @@ -1792,7 +1780,7 @@ bool Component::isCurrentlyModal (bool onlyConsiderForemostModalComponent) const const int n = onlyConsiderForemostModalComponent ? 1 : getNumCurrentlyModalComponents(); for (int i = 0; i < n; ++i) - if (getCurrentlyModalComponent (i) == this) + if (getCurrentlyModalComponent(i) == this) return true; return false; @@ -2333,25 +2321,15 @@ void Component::internalModalInputAttempt() } //============================================================================== -void Component::postCommandMessage (const int commandId) +void Component::postCommandMessage (const int commandID) { - struct CustomCommandMessage : public CallbackMessage - { - CustomCommandMessage (Component* const c, const int command) - : target (c), commandId (command) {} - - void messageCallback() override - { - if (auto* c = target.get()) - c->handleCommandMessage (commandId); - } + WeakReference target (this); - private: - WeakReference target; - int commandId; - }; - - (new CustomCommandMessage (this, commandId))->post(); + MessageManager::callAsync ([=]() + { + if (auto* c = target.get()) + c->handleCommandMessage (commandID); + }); } void Component::handleCommandMessage (int) diff --git a/modules/juce_gui_basics/mouse/juce_DragAndDropContainer.cpp b/modules/juce_gui_basics/mouse/juce_DragAndDropContainer.cpp index 527c8ea8a5..adef3c930c 100644 --- a/modules/juce_gui_basics/mouse/juce_DragAndDropContainer.cpp +++ b/modules/juce_gui_basics/mouse/juce_DragAndDropContainer.cpp @@ -40,8 +40,7 @@ public: : sourceDetails (desc, sourceComponent, Point()), image (im), owner (ddc), mouseDragSource (mouseSource), - imageOffset (offset), - hasCheckedForExternalDrag (false) + imageOffset (offset) { updateSize(); @@ -211,7 +210,7 @@ private: DragAndDropContainer& owner; WeakReference mouseDragSource, currentlyOverComp; const Point imageOffset; - bool hasCheckedForExternalDrag; + bool hasCheckedForExternalDrag = false; Time lastTimeOverTarget; void updateSize() @@ -294,27 +293,6 @@ private: target->itemDragMove (details); } - struct ExternalDragAndDropMessage : public CallbackMessage - { - ExternalDragAndDropMessage (const StringArray& f, bool canMove) - : files (f), canMoveFiles (canMove) - {} - - ExternalDragAndDropMessage (const String& t) : text (t), canMoveFiles() {} - - void messageCallback() override - { - if (text.isEmpty()) - DragAndDropContainer::performExternalDragDropOfFiles (files, canMoveFiles); - else - DragAndDropContainer::performExternalDragDropOfText (text); - } - - String text; - StringArray files; - bool canMoveFiles; - }; - void checkForExternalDrag (DragAndDropTarget::SourceDetails& details, Point screenPos) { if (! hasCheckedForExternalDrag) @@ -322,21 +300,26 @@ private: if (Desktop::getInstance().findComponentAt (screenPos) == nullptr) { hasCheckedForExternalDrag = true; - StringArray files; - String text; - bool canMoveFiles = false; if (ModifierKeys::getCurrentModifiersRealtime().isAnyMouseButtonDown()) { + StringArray files; + bool canMoveFiles = false; + if (owner.shouldDropFilesWhenDraggedExternally (details, files, canMoveFiles) && ! files.isEmpty()) { - (new ExternalDragAndDropMessage (files, canMoveFiles))->post(); + MessageManager::callAsync ([=]() { DragAndDropContainer::performExternalDragDropOfFiles (files, canMoveFiles); }); deleteSelf(); + return; } - else if (owner.shouldDropTextWhenDraggedExternally (details, text) && text.isNotEmpty()) + + String text; + + if (owner.shouldDropTextWhenDraggedExternally (details, text) && text.isNotEmpty()) { - (new ExternalDragAndDropMessage (text))->post(); + MessageManager::callAsync ([=]() { DragAndDropContainer::performExternalDragDropOfText (text); }); deleteSelf(); + return; } } } diff --git a/modules/juce_gui_basics/widgets/juce_TreeView.cpp b/modules/juce_gui_basics/widgets/juce_TreeView.cpp index 8d320bb0bc..4e67828a95 100644 --- a/modules/juce_gui_basics/widgets/juce_TreeView.cpp +++ b/modules/juce_gui_basics/widgets/juce_TreeView.cpp @@ -367,15 +367,11 @@ private: static bool isMouseDraggingInChildCompOf (Component* const comp) { - const Array& mouseSources = Desktop::getInstance().getMouseSources(); - - for (MouseInputSource* mi = mouseSources.begin(), * const e = mouseSources.end(); mi != e; ++mi) - { - if (mi->isDragging()) - if (Component* const underMouse = mi->getComponentUnderMouse()) + for (auto& ms : Desktop::getInstance().getMouseSources()) + if (ms.isDragging()) + if (auto* underMouse = ms.getComponentUnderMouse()) if (comp == underMouse || comp->isParentOf (underMouse)) return true; - } return false; } diff --git a/modules/juce_gui_basics/windows/juce_ComponentPeer.cpp b/modules/juce_gui_basics/windows/juce_ComponentPeer.cpp index 4aceb08779..c9615f8da2 100644 --- a/modules/juce_gui_basics/windows/juce_ComponentPeer.cpp +++ b/modules/juce_gui_basics/windows/juce_ComponentPeer.cpp @@ -28,17 +28,14 @@ static uint32 lastUniquePeerID = 1; ComponentPeer::ComponentPeer (Component& comp, const int flags) : component (comp), styleFlags (flags), - constrainer (nullptr), - lastDragAndDropCompUnderMouse (nullptr), - uniqueID (lastUniquePeerID += 2), // increment by 2 so that this can never hit 0 - isWindowMinimised (false) + uniqueID (lastUniquePeerID += 2) // increment by 2 so that this can never hit 0 { Desktop::getInstance().peers.add (this); } ComponentPeer::~ComponentPeer() { - Desktop& desktop = Desktop::getInstance(); + auto& desktop = Desktop::getInstance(); desktop.peers.removeFirstMatchingValue (this); desktop.triggerFocusCallback(); } @@ -56,15 +53,9 @@ ComponentPeer* ComponentPeer::getPeer (const int index) noexcept ComponentPeer* ComponentPeer::getPeerFor (const Component* const component) noexcept { - const Array& peers = Desktop::getInstance().peers; - - for (int i = peers.size(); --i >= 0;) - { - ComponentPeer* const peer = peers.getUnchecked(i); - + for (auto* peer : Desktop::getInstance().peers) if (&(peer->getComponent()) == component) return peer; - } return nullptr; } @@ -169,7 +160,7 @@ Component* ComponentPeer::getTargetForKeyPress() c = &component; if (c->isCurrentlyBlockedByAnotherModalComponent()) - if (Component* const currentModalComp = Component::getCurrentlyModalComponent()) + if (auto* currentModalComp = Component::getCurrentlyModalComponent()) c = currentModalComp; return c; @@ -193,7 +184,7 @@ bool ComponentPeer::handleKeyPress (const KeyPress& keyInfo) { const WeakReference deletionChecker (target); - if (const Array* const keyListeners = target->keyListeners) + if (auto* keyListeners = target->keyListeners.get()) { for (int i = keyListeners->size(); --i >= 0;) { @@ -211,7 +202,7 @@ bool ComponentPeer::handleKeyPress (const KeyPress& keyInfo) if (keyWasUsed || deletionChecker == nullptr) break; - if (Component* const currentlyFocused = Component::getCurrentlyFocusedComponent()) + if (auto* currentlyFocused = Component::getCurrentlyFocusedComponent()) { const bool isTab = (keyInfo == KeyPress::tabKey); const bool isShiftTab = (keyInfo == KeyPress (KeyPress::tabKey, ModifierKeys::shiftModifier, 0)); @@ -265,7 +256,7 @@ void ComponentPeer::handleModifierKeysChange() { ModifierKeys::updateCurrentModifiers(); - Component* target = Desktop::getInstance().getMainMouseSource().getComponentUnderMouse(); + auto* target = Desktop::getInstance().getMainMouseSource().getComponentUnderMouse(); if (target == nullptr) target = Component::getCurrentlyFocusedComponent(); @@ -279,7 +270,7 @@ void ComponentPeer::handleModifierKeysChange() TextInputTarget* ComponentPeer::findCurrentTextInputTarget() { - Component* const c = Component::getCurrentlyFocusedComponent(); + auto* c = Component::getCurrentlyFocusedComponent(); if (c == &component || component.isParentOf (c)) if (TextInputTarget* const ti = dynamic_cast (c)) @@ -313,8 +304,8 @@ void ComponentPeer::handleMovedOrResized() { const WeakReference deletionChecker (&component); - Rectangle newBounds (Component::ComponentHelpers::rawPeerPositionToLocal (component, getBounds())); - Rectangle oldBounds (component.getBounds()); + auto newBounds = Component::ComponentHelpers::rawPeerPositionToLocal (component, getBounds()); + auto oldBounds = component.getBounds(); const bool wasMoved = (oldBounds.getPosition() != newBounds.getPosition()); const bool wasResized = (oldBounds.getWidth() != newBounds.getWidth() || oldBounds.getHeight() != newBounds.getHeight()); @@ -452,31 +443,6 @@ namespace DragHelpers return nullptr; } - - // We'll use an async message to deliver the drop, because if the target decides - // to run a modal loop, it can gum-up the operating system.. - class AsyncDropMessage : public CallbackMessage - { - public: - AsyncDropMessage (Component* c, const ComponentPeer::DragInfo& d) : target (c), info (d) {} - - void messageCallback() override - { - if (Component* const c = target.get()) - { - if (isFileDrag (info)) - dynamic_cast (c)->filesDropped (info.files, info.position.x, info.position.y); - else - dynamic_cast (c)->textDropped (info.text, info.position.x, info.position.y); - } - } - - private: - WeakReference target; - const ComponentPeer::DragInfo info; - - JUCE_DECLARE_NON_COPYABLE (AsyncDropMessage) - }; } bool ComponentPeer::handleDragMove (const ComponentPeer::DragInfo& info) @@ -508,7 +474,7 @@ bool ComponentPeer::handleDragMove (const ComponentPeer::DragInfo& info) if (DragHelpers::isSuitableTarget (info, newTarget)) { dragAndDropTargetComponent = newTarget; - const Point pos (newTarget->getLocalPoint (&component, info.position)); + auto pos = newTarget->getLocalPoint (&component, info.position); if (DragHelpers::isFileDrag (info)) dynamic_cast (newTarget)->fileDragEnter (info.files, pos.x, pos.y); @@ -525,7 +491,7 @@ bool ComponentPeer::handleDragMove (const ComponentPeer::DragInfo& info) if (! DragHelpers::isSuitableTarget (info, newTarget)) return false; - const Point pos (newTarget->getLocalPoint (&component, info.position)); + auto pos = newTarget->getLocalPoint (&component, info.position); if (DragHelpers::isFileDrag (info)) dynamic_cast (newTarget)->fileDragMove (info.files, pos.x, pos.y); @@ -550,7 +516,7 @@ bool ComponentPeer::handleDragDrop (const ComponentPeer::DragInfo& info) { handleDragMove (info); - if (Component* const targetComp = dragAndDropTargetComponent) + if (WeakReference targetComp = dragAndDropTargetComponent) { dragAndDropTargetComponent = nullptr; lastDragAndDropCompUnderMouse = nullptr; @@ -565,10 +531,22 @@ bool ComponentPeer::handleDragDrop (const ComponentPeer::DragInfo& info) return true; } - ComponentPeer::DragInfo info2 (info); - info2.position = targetComp->getLocalPoint (&component, info.position); + ComponentPeer::DragInfo infoCopy (info); + infoCopy.position = targetComp->getLocalPoint (&component, info.position); + + // We'll use an async message to deliver the drop, because if the target decides + // to run a modal loop, it can gum-up the operating system.. + MessageManager::callAsync ([=]() + { + if (auto* c = targetComp.get()) + { + if (DragHelpers::isFileDrag (info)) + dynamic_cast (c)->filesDropped (infoCopy.files, infoCopy.position.x, infoCopy.position.y); + else + dynamic_cast (c)->textDropped (infoCopy.text, infoCopy.position.x, infoCopy.position.y); + } + }); - (new DragHelpers::AsyncDropMessage (targetComp, info2))->post(); return true; } } diff --git a/modules/juce_gui_basics/windows/juce_ComponentPeer.h b/modules/juce_gui_basics/windows/juce_ComponentPeer.h index d4458fb3ec..1d39219b64 100644 --- a/modules/juce_gui_basics/windows/juce_ComponentPeer.h +++ b/modules/juce_gui_basics/windows/juce_ComponentPeer.h @@ -364,14 +364,14 @@ protected: Component& component; const int styleFlags; Rectangle lastNonFullscreenBounds; - ComponentBoundsConstrainer* constrainer; + ComponentBoundsConstrainer* constrainer = nullptr; private: //============================================================================== WeakReference lastFocusedComponent, dragAndDropTargetComponent; - Component* lastDragAndDropCompUnderMouse; + Component* lastDragAndDropCompUnderMouse = nullptr; const uint32 uniqueID; - bool isWindowMinimised; + bool isWindowMinimised = false; Component* getTargetForKeyPress(); JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ComponentPeer)