| @@ -853,11 +853,9 @@ void MidiKeyboardComponent::timerCallback() | |||||
| if (shouldCheckMousePos) | if (shouldCheckMousePos) | ||||
| { | { | ||||
| const Array<MouseInputSource>& 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()); | |||||
| } | } | ||||
| } | } | ||||
| @@ -393,14 +393,14 @@ public: | |||||
| /** Download the URL to a file. | /** 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, | DownloadTask* downloadToFile (const File& targetLocation, | ||||
| String extraHeaders = String(), | String extraHeaders = String(), | ||||
| DownloadTask::Listener* listener = nullptr); | DownloadTask::Listener* listener = nullptr); | ||||
| @@ -46,7 +46,10 @@ | |||||
| Always create a new instance of a CallbackMessage on the heap, as it will be | Always create a new instance of a CallbackMessage on the heap, as it will be | ||||
| deleted automatically after the message has been delivered. | 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 | class JUCE_API CallbackMessage : public MessageManager::MessageBase | ||||
| { | { | ||||
| @@ -29,10 +29,7 @@ | |||||
| */ | */ | ||||
| MessageManager::MessageManager() noexcept | MessageManager::MessageManager() noexcept | ||||
| : quitMessagePosted (false), | |||||
| quitMessageReceived (false), | |||||
| messageThreadId (Thread::getCurrentThreadId()), | |||||
| threadWithLock (0) | |||||
| : messageThreadId (Thread::getCurrentThreadId()) | |||||
| { | { | ||||
| if (JUCEApplicationBase::isStandaloneApp()) | if (JUCEApplicationBase::isStandaloneApp()) | ||||
| Thread::setCurrentThreadName ("Juce Message Thread"); | Thread::setCurrentThreadName ("Juce Message Thread"); | ||||
| @@ -74,7 +71,7 @@ void MessageManager::deleteInstance() | |||||
| //============================================================================== | //============================================================================== | ||||
| bool MessageManager::MessageBase::post() | bool MessageManager::MessageBase::post() | ||||
| { | { | ||||
| MessageManager* const mm = MessageManager::instance; | |||||
| auto* mm = MessageManager::instance; | |||||
| if (mm == nullptr || mm->quitMessagePosted || ! postMessageToSystemQueue (this)) | if (mm == nullptr || mm->quitMessagePosted || ! postMessageToSystemQueue (this)) | ||||
| { | { | ||||
| @@ -118,7 +115,7 @@ public: | |||||
| void messageCallback() override | void messageCallback() override | ||||
| { | { | ||||
| if (MessageManager* const mm = MessageManager::instance) | |||||
| if (auto* mm = MessageManager::instance) | |||||
| mm->quitMessageReceived = true; | mm->quitMessageReceived = true; | ||||
| } | } | ||||
| @@ -148,31 +145,12 @@ void MessageManager::stopDispatchLoop() | |||||
| #endif | #endif | ||||
| //============================================================================== | |||||
| #if JUCE_COMPILER_SUPPORTS_LAMBDAS | |||||
| struct AsyncFunction : private MessageManager::MessageBase | |||||
| { | |||||
| AsyncFunction (std::function<void(void)> f) : fn (f) { post(); } | |||||
| private: | |||||
| std::function<void(void)> fn; | |||||
| void messageCallback() override { fn(); } | |||||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AsyncFunction) | |||||
| }; | |||||
| void MessageManager::callAsync (std::function<void(void)> f) | |||||
| { | |||||
| new AsyncFunction (f); | |||||
| } | |||||
| #endif | |||||
| //============================================================================== | //============================================================================== | ||||
| class AsyncFunctionCallback : public MessageManager::MessageBase | class AsyncFunctionCallback : public MessageManager::MessageBase | ||||
| { | { | ||||
| public: | public: | ||||
| AsyncFunctionCallback (MessageCallbackFunction* const f, void* const param) | AsyncFunctionCallback (MessageCallbackFunction* const f, void* const param) | ||||
| : result (nullptr), func (f), parameter (param) | |||||
| : func (f), parameter (param) | |||||
| {} | {} | ||||
| void messageCallback() override | void messageCallback() override | ||||
| @@ -182,7 +160,7 @@ public: | |||||
| } | } | ||||
| WaitableEvent finished; | WaitableEvent finished; | ||||
| void* volatile result; | |||||
| void* volatile result = nullptr; | |||||
| private: | private: | ||||
| MessageCallbackFunction* const func; | MessageCallbackFunction* const func; | ||||
| @@ -306,7 +284,7 @@ MessageManagerLock::MessageManagerLock (BailOutChecker& bailOutChecker) | |||||
| bool MessageManagerLock::attemptLock (BailOutChecker* bailOutChecker) | bool MessageManagerLock::attemptLock (BailOutChecker* bailOutChecker) | ||||
| { | { | ||||
| MessageManager* const mm = MessageManager::instance; | |||||
| auto* mm = MessageManager::instance; | |||||
| if (mm == nullptr) | if (mm == nullptr) | ||||
| return false; | return false; | ||||
| @@ -358,7 +336,7 @@ MessageManagerLock::~MessageManagerLock() noexcept | |||||
| { | { | ||||
| if (blockingMessage != nullptr) | if (blockingMessage != nullptr) | ||||
| { | { | ||||
| MessageManager* const mm = MessageManager::instance; | |||||
| auto* mm = MessageManager::instance; | |||||
| jassert (mm == nullptr || mm->currentThreadHasLockedMessageManager()); | jassert (mm == nullptr || mm->currentThreadHasLockedMessageManager()); | ||||
| @@ -99,12 +99,12 @@ public: | |||||
| #endif | #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<void(void)>); | |||||
| #endif | |||||
| /** Asynchronously invokes a function or C++11 lambda on the message thread. */ | |||||
| template <typename FunctionType> | |||||
| static void callAsync (FunctionType functionToCall) | |||||
| { | |||||
| new AsyncCallInvoker<FunctionType> (functionToCall); | |||||
| } | |||||
| /** Calls a function using the message-thread. | /** Calls a function using the message-thread. | ||||
| @@ -211,9 +211,9 @@ private: | |||||
| friend class MessageManagerLock; | friend class MessageManagerLock; | ||||
| ScopedPointer<ActionBroadcaster> broadcaster; | ScopedPointer<ActionBroadcaster> broadcaster; | ||||
| bool quitMessagePosted, quitMessageReceived; | |||||
| bool quitMessagePosted = false, quitMessageReceived = false; | |||||
| Thread::ThreadID messageThreadId; | Thread::ThreadID messageThreadId; | ||||
| Thread::ThreadID volatile threadWithLock; | |||||
| Thread::ThreadID volatile threadWithLock = {}; | |||||
| CriticalSection lockingLock; | CriticalSection lockingLock; | ||||
| static bool postMessageToSystemQueue (MessageBase*); | static bool postMessageToSystemQueue (MessageBase*); | ||||
| @@ -222,6 +222,16 @@ private: | |||||
| static void doPlatformSpecificShutdown(); | static void doPlatformSpecificShutdown(); | ||||
| static bool dispatchNextMessageOnSystemQueue (bool returnIfNoPendingMessages); | static bool dispatchNextMessageOnSystemQueue (bool returnIfNoPendingMessages); | ||||
| template <typename FunctionType> | |||||
| 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) | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MessageManager) | ||||
| }; | }; | ||||
| @@ -1731,7 +1731,7 @@ void Component::enterModalState (const bool shouldTakeKeyboardFocus, | |||||
| if (! isCurrentlyModal (false)) | if (! isCurrentlyModal (false)) | ||||
| { | { | ||||
| ModalComponentManager& mcm = *ModalComponentManager::getInstance(); | |||||
| auto& mcm = *ModalComponentManager::getInstance(); | |||||
| mcm.startModal (this, deleteWhenDismissed); | mcm.startModal (this, deleteWhenDismissed); | ||||
| mcm.attachCallback (this, callback); | mcm.attachCallback (this, callback); | ||||
| @@ -1753,36 +1753,24 @@ void Component::exitModalState (const int returnValue) | |||||
| { | { | ||||
| if (MessageManager::getInstance()->isThisTheMessageThread()) | if (MessageManager::getInstance()->isThisTheMessageThread()) | ||||
| { | { | ||||
| ModalComponentManager& mcm = *ModalComponentManager::getInstance(); | |||||
| auto& mcm = *ModalComponentManager::getInstance(); | |||||
| mcm.endModal (this, returnValue); | mcm.endModal (this, returnValue); | ||||
| mcm.bringModalComponentsToFront(); | mcm.bringModalComponentsToFront(); | ||||
| // If any of the mouse sources are over another Component when we exit the modal state then send a mouse enter event | // If any of the mouse sources are over another Component when we exit the modal state then send a mouse enter event | ||||
| const Array<MouseInputSource>& 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 | else | ||||
| { | { | ||||
| struct ExitModalStateMessage : public CallbackMessage | |||||
| { | |||||
| ExitModalStateMessage (Component* c, int res) : target (c), result (res) {} | |||||
| WeakReference<Component> target (this); | |||||
| void messageCallback() override | |||||
| { | |||||
| if (Component* c = target) | |||||
| c->exitModalState (result); | |||||
| } | |||||
| WeakReference<Component> 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(); | const int n = onlyConsiderForemostModalComponent ? 1 : getNumCurrentlyModalComponents(); | ||||
| for (int i = 0; i < n; ++i) | for (int i = 0; i < n; ++i) | ||||
| if (getCurrentlyModalComponent (i) == this) | |||||
| if (getCurrentlyModalComponent(i) == this) | |||||
| return true; | return true; | ||||
| return false; | 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<Component> target (this); | |||||
| private: | |||||
| WeakReference<Component> target; | |||||
| int commandId; | |||||
| }; | |||||
| (new CustomCommandMessage (this, commandId))->post(); | |||||
| MessageManager::callAsync ([=]() | |||||
| { | |||||
| if (auto* c = target.get()) | |||||
| c->handleCommandMessage (commandID); | |||||
| }); | |||||
| } | } | ||||
| void Component::handleCommandMessage (int) | void Component::handleCommandMessage (int) | ||||
| @@ -40,8 +40,7 @@ public: | |||||
| : sourceDetails (desc, sourceComponent, Point<int>()), | : sourceDetails (desc, sourceComponent, Point<int>()), | ||||
| image (im), owner (ddc), | image (im), owner (ddc), | ||||
| mouseDragSource (mouseSource), | mouseDragSource (mouseSource), | ||||
| imageOffset (offset), | |||||
| hasCheckedForExternalDrag (false) | |||||
| imageOffset (offset) | |||||
| { | { | ||||
| updateSize(); | updateSize(); | ||||
| @@ -211,7 +210,7 @@ private: | |||||
| DragAndDropContainer& owner; | DragAndDropContainer& owner; | ||||
| WeakReference<Component> mouseDragSource, currentlyOverComp; | WeakReference<Component> mouseDragSource, currentlyOverComp; | ||||
| const Point<int> imageOffset; | const Point<int> imageOffset; | ||||
| bool hasCheckedForExternalDrag; | |||||
| bool hasCheckedForExternalDrag = false; | |||||
| Time lastTimeOverTarget; | Time lastTimeOverTarget; | ||||
| void updateSize() | void updateSize() | ||||
| @@ -294,27 +293,6 @@ private: | |||||
| target->itemDragMove (details); | 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<int> screenPos) | void checkForExternalDrag (DragAndDropTarget::SourceDetails& details, Point<int> screenPos) | ||||
| { | { | ||||
| if (! hasCheckedForExternalDrag) | if (! hasCheckedForExternalDrag) | ||||
| @@ -322,21 +300,26 @@ private: | |||||
| if (Desktop::getInstance().findComponentAt (screenPos) == nullptr) | if (Desktop::getInstance().findComponentAt (screenPos) == nullptr) | ||||
| { | { | ||||
| hasCheckedForExternalDrag = true; | hasCheckedForExternalDrag = true; | ||||
| StringArray files; | |||||
| String text; | |||||
| bool canMoveFiles = false; | |||||
| if (ModifierKeys::getCurrentModifiersRealtime().isAnyMouseButtonDown()) | if (ModifierKeys::getCurrentModifiersRealtime().isAnyMouseButtonDown()) | ||||
| { | { | ||||
| StringArray files; | |||||
| bool canMoveFiles = false; | |||||
| if (owner.shouldDropFilesWhenDraggedExternally (details, files, canMoveFiles) && ! files.isEmpty()) | if (owner.shouldDropFilesWhenDraggedExternally (details, files, canMoveFiles) && ! files.isEmpty()) | ||||
| { | { | ||||
| (new ExternalDragAndDropMessage (files, canMoveFiles))->post(); | |||||
| MessageManager::callAsync ([=]() { DragAndDropContainer::performExternalDragDropOfFiles (files, canMoveFiles); }); | |||||
| deleteSelf(); | 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(); | deleteSelf(); | ||||
| return; | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -367,15 +367,11 @@ private: | |||||
| static bool isMouseDraggingInChildCompOf (Component* const comp) | static bool isMouseDraggingInChildCompOf (Component* const comp) | ||||
| { | { | ||||
| const Array<MouseInputSource>& 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)) | if (comp == underMouse || comp->isParentOf (underMouse)) | ||||
| return true; | return true; | ||||
| } | |||||
| return false; | return false; | ||||
| } | } | ||||
| @@ -28,17 +28,14 @@ static uint32 lastUniquePeerID = 1; | |||||
| ComponentPeer::ComponentPeer (Component& comp, const int flags) | ComponentPeer::ComponentPeer (Component& comp, const int flags) | ||||
| : component (comp), | : component (comp), | ||||
| styleFlags (flags), | 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); | Desktop::getInstance().peers.add (this); | ||||
| } | } | ||||
| ComponentPeer::~ComponentPeer() | ComponentPeer::~ComponentPeer() | ||||
| { | { | ||||
| Desktop& desktop = Desktop::getInstance(); | |||||
| auto& desktop = Desktop::getInstance(); | |||||
| desktop.peers.removeFirstMatchingValue (this); | desktop.peers.removeFirstMatchingValue (this); | ||||
| desktop.triggerFocusCallback(); | desktop.triggerFocusCallback(); | ||||
| } | } | ||||
| @@ -56,15 +53,9 @@ ComponentPeer* ComponentPeer::getPeer (const int index) noexcept | |||||
| ComponentPeer* ComponentPeer::getPeerFor (const Component* const component) noexcept | ComponentPeer* ComponentPeer::getPeerFor (const Component* const component) noexcept | ||||
| { | { | ||||
| const Array<ComponentPeer*>& 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) | if (&(peer->getComponent()) == component) | ||||
| return peer; | return peer; | ||||
| } | |||||
| return nullptr; | return nullptr; | ||||
| } | } | ||||
| @@ -169,7 +160,7 @@ Component* ComponentPeer::getTargetForKeyPress() | |||||
| c = &component; | c = &component; | ||||
| if (c->isCurrentlyBlockedByAnotherModalComponent()) | if (c->isCurrentlyBlockedByAnotherModalComponent()) | ||||
| if (Component* const currentModalComp = Component::getCurrentlyModalComponent()) | |||||
| if (auto* currentModalComp = Component::getCurrentlyModalComponent()) | |||||
| c = currentModalComp; | c = currentModalComp; | ||||
| return c; | return c; | ||||
| @@ -193,7 +184,7 @@ bool ComponentPeer::handleKeyPress (const KeyPress& keyInfo) | |||||
| { | { | ||||
| const WeakReference<Component> deletionChecker (target); | const WeakReference<Component> deletionChecker (target); | ||||
| if (const Array<KeyListener*>* const keyListeners = target->keyListeners) | |||||
| if (auto* keyListeners = target->keyListeners.get()) | |||||
| { | { | ||||
| for (int i = keyListeners->size(); --i >= 0;) | for (int i = keyListeners->size(); --i >= 0;) | ||||
| { | { | ||||
| @@ -211,7 +202,7 @@ bool ComponentPeer::handleKeyPress (const KeyPress& keyInfo) | |||||
| if (keyWasUsed || deletionChecker == nullptr) | if (keyWasUsed || deletionChecker == nullptr) | ||||
| break; | break; | ||||
| if (Component* const currentlyFocused = Component::getCurrentlyFocusedComponent()) | |||||
| if (auto* currentlyFocused = Component::getCurrentlyFocusedComponent()) | |||||
| { | { | ||||
| const bool isTab = (keyInfo == KeyPress::tabKey); | const bool isTab = (keyInfo == KeyPress::tabKey); | ||||
| const bool isShiftTab = (keyInfo == KeyPress (KeyPress::tabKey, ModifierKeys::shiftModifier, 0)); | const bool isShiftTab = (keyInfo == KeyPress (KeyPress::tabKey, ModifierKeys::shiftModifier, 0)); | ||||
| @@ -265,7 +256,7 @@ void ComponentPeer::handleModifierKeysChange() | |||||
| { | { | ||||
| ModifierKeys::updateCurrentModifiers(); | ModifierKeys::updateCurrentModifiers(); | ||||
| Component* target = Desktop::getInstance().getMainMouseSource().getComponentUnderMouse(); | |||||
| auto* target = Desktop::getInstance().getMainMouseSource().getComponentUnderMouse(); | |||||
| if (target == nullptr) | if (target == nullptr) | ||||
| target = Component::getCurrentlyFocusedComponent(); | target = Component::getCurrentlyFocusedComponent(); | ||||
| @@ -279,7 +270,7 @@ void ComponentPeer::handleModifierKeysChange() | |||||
| TextInputTarget* ComponentPeer::findCurrentTextInputTarget() | TextInputTarget* ComponentPeer::findCurrentTextInputTarget() | ||||
| { | { | ||||
| Component* const c = Component::getCurrentlyFocusedComponent(); | |||||
| auto* c = Component::getCurrentlyFocusedComponent(); | |||||
| if (c == &component || component.isParentOf (c)) | if (c == &component || component.isParentOf (c)) | ||||
| if (TextInputTarget* const ti = dynamic_cast<TextInputTarget*> (c)) | if (TextInputTarget* const ti = dynamic_cast<TextInputTarget*> (c)) | ||||
| @@ -313,8 +304,8 @@ void ComponentPeer::handleMovedOrResized() | |||||
| { | { | ||||
| const WeakReference<Component> deletionChecker (&component); | const WeakReference<Component> deletionChecker (&component); | ||||
| Rectangle<int> newBounds (Component::ComponentHelpers::rawPeerPositionToLocal (component, getBounds())); | |||||
| Rectangle<int> oldBounds (component.getBounds()); | |||||
| auto newBounds = Component::ComponentHelpers::rawPeerPositionToLocal (component, getBounds()); | |||||
| auto oldBounds = component.getBounds(); | |||||
| const bool wasMoved = (oldBounds.getPosition() != newBounds.getPosition()); | const bool wasMoved = (oldBounds.getPosition() != newBounds.getPosition()); | ||||
| const bool wasResized = (oldBounds.getWidth() != newBounds.getWidth() || oldBounds.getHeight() != newBounds.getHeight()); | const bool wasResized = (oldBounds.getWidth() != newBounds.getWidth() || oldBounds.getHeight() != newBounds.getHeight()); | ||||
| @@ -452,31 +443,6 @@ namespace DragHelpers | |||||
| return nullptr; | 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<FileDragAndDropTarget*> (c)->filesDropped (info.files, info.position.x, info.position.y); | |||||
| else | |||||
| dynamic_cast<TextDragAndDropTarget*> (c)->textDropped (info.text, info.position.x, info.position.y); | |||||
| } | |||||
| } | |||||
| private: | |||||
| WeakReference<Component> target; | |||||
| const ComponentPeer::DragInfo info; | |||||
| JUCE_DECLARE_NON_COPYABLE (AsyncDropMessage) | |||||
| }; | |||||
| } | } | ||||
| bool ComponentPeer::handleDragMove (const ComponentPeer::DragInfo& info) | bool ComponentPeer::handleDragMove (const ComponentPeer::DragInfo& info) | ||||
| @@ -508,7 +474,7 @@ bool ComponentPeer::handleDragMove (const ComponentPeer::DragInfo& info) | |||||
| if (DragHelpers::isSuitableTarget (info, newTarget)) | if (DragHelpers::isSuitableTarget (info, newTarget)) | ||||
| { | { | ||||
| dragAndDropTargetComponent = newTarget; | dragAndDropTargetComponent = newTarget; | ||||
| const Point<int> pos (newTarget->getLocalPoint (&component, info.position)); | |||||
| auto pos = newTarget->getLocalPoint (&component, info.position); | |||||
| if (DragHelpers::isFileDrag (info)) | if (DragHelpers::isFileDrag (info)) | ||||
| dynamic_cast<FileDragAndDropTarget*> (newTarget)->fileDragEnter (info.files, pos.x, pos.y); | dynamic_cast<FileDragAndDropTarget*> (newTarget)->fileDragEnter (info.files, pos.x, pos.y); | ||||
| @@ -525,7 +491,7 @@ bool ComponentPeer::handleDragMove (const ComponentPeer::DragInfo& info) | |||||
| if (! DragHelpers::isSuitableTarget (info, newTarget)) | if (! DragHelpers::isSuitableTarget (info, newTarget)) | ||||
| return false; | return false; | ||||
| const Point<int> pos (newTarget->getLocalPoint (&component, info.position)); | |||||
| auto pos = newTarget->getLocalPoint (&component, info.position); | |||||
| if (DragHelpers::isFileDrag (info)) | if (DragHelpers::isFileDrag (info)) | ||||
| dynamic_cast<FileDragAndDropTarget*> (newTarget)->fileDragMove (info.files, pos.x, pos.y); | dynamic_cast<FileDragAndDropTarget*> (newTarget)->fileDragMove (info.files, pos.x, pos.y); | ||||
| @@ -550,7 +516,7 @@ bool ComponentPeer::handleDragDrop (const ComponentPeer::DragInfo& info) | |||||
| { | { | ||||
| handleDragMove (info); | handleDragMove (info); | ||||
| if (Component* const targetComp = dragAndDropTargetComponent) | |||||
| if (WeakReference<Component> targetComp = dragAndDropTargetComponent) | |||||
| { | { | ||||
| dragAndDropTargetComponent = nullptr; | dragAndDropTargetComponent = nullptr; | ||||
| lastDragAndDropCompUnderMouse = nullptr; | lastDragAndDropCompUnderMouse = nullptr; | ||||
| @@ -565,10 +531,22 @@ bool ComponentPeer::handleDragDrop (const ComponentPeer::DragInfo& info) | |||||
| return true; | 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<FileDragAndDropTarget*> (c)->filesDropped (infoCopy.files, infoCopy.position.x, infoCopy.position.y); | |||||
| else | |||||
| dynamic_cast<TextDragAndDropTarget*> (c)->textDropped (infoCopy.text, infoCopy.position.x, infoCopy.position.y); | |||||
| } | |||||
| }); | |||||
| (new DragHelpers::AsyncDropMessage (targetComp, info2))->post(); | |||||
| return true; | return true; | ||||
| } | } | ||||
| } | } | ||||
| @@ -364,14 +364,14 @@ protected: | |||||
| Component& component; | Component& component; | ||||
| const int styleFlags; | const int styleFlags; | ||||
| Rectangle<int> lastNonFullscreenBounds; | Rectangle<int> lastNonFullscreenBounds; | ||||
| ComponentBoundsConstrainer* constrainer; | |||||
| ComponentBoundsConstrainer* constrainer = nullptr; | |||||
| private: | private: | ||||
| //============================================================================== | //============================================================================== | ||||
| WeakReference<Component> lastFocusedComponent, dragAndDropTargetComponent; | WeakReference<Component> lastFocusedComponent, dragAndDropTargetComponent; | ||||
| Component* lastDragAndDropCompUnderMouse; | |||||
| Component* lastDragAndDropCompUnderMouse = nullptr; | |||||
| const uint32 uniqueID; | const uint32 uniqueID; | ||||
| bool isWindowMinimised; | |||||
| bool isWindowMinimised = false; | |||||
| Component* getTargetForKeyPress(); | Component* getTargetForKeyPress(); | ||||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ComponentPeer) | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ComponentPeer) | ||||