From 79b8ffa007e3ce12d712da72b038a5f65a3cab9d Mon Sep 17 00:00:00 2001 From: Julian Storer Date: Fri, 18 Jun 2010 11:33:53 +0100 Subject: [PATCH] Made ResizableWindow slightly more resilient. Added a method to OwnedArray. --- .../wrapper/VST/juce_VST_Wrapper.cpp | 1 - juce_amalgamated.cpp | 66 ++++++++----------- juce_amalgamated.h | 45 ++++++++++--- src/containers/juce_OwnedArray.h | 39 +++++++++-- src/core/juce_StandardHeader.h | 2 +- src/events/juce_MessageManager.cpp | 14 ++-- src/events/juce_MessageManager.h | 2 +- .../windows/juce_ResizableWindow.cpp | 9 +-- .../components/windows/juce_ResizableWindow.h | 2 +- src/native/linux/juce_linux_Messaging.cpp | 8 +-- src/native/mac/juce_iphone_MessageManager.mm | 17 ++--- src/native/mac/juce_mac_MessageManager.mm | 11 ++-- src/native/windows/juce_win32_Messaging.cpp | 6 +- 13 files changed, 127 insertions(+), 95 deletions(-) diff --git a/extras/audio plugins/wrapper/VST/juce_VST_Wrapper.cpp b/extras/audio plugins/wrapper/VST/juce_VST_Wrapper.cpp index 7b092dfa2c..7a31fd9f7d 100644 --- a/extras/audio plugins/wrapper/VST/juce_VST_Wrapper.cpp +++ b/extras/audio plugins/wrapper/VST/juce_VST_Wrapper.cpp @@ -160,7 +160,6 @@ BEGIN_JUCE_NAMESPACE #if JUCE_LINUX extern Display* display; - extern bool juce_postMessageToSystemQueue (void* message); #endif END_JUCE_NAMESPACE diff --git a/juce_amalgamated.cpp b/juce_amalgamated.cpp index 94c18ee2a3..14cb8ed3ff 100644 --- a/juce_amalgamated.cpp +++ b/juce_amalgamated.cpp @@ -17293,6 +17293,7 @@ bool JUCEApplication::initialiseApp (String& commandLine) if (! appLock->enter(0)) { + appLock = 0; MessageManager::broadcastMessage (getApplicationName() + "/" + commandLineParameters); delete appInstance; @@ -37732,7 +37733,7 @@ BEGIN_JUCE_NAMESPACE // platform-specific functions.. bool juce_dispatchNextMessageOnSystemQueue (bool returnIfNoPendingMessages); -bool juce_postMessageToSystemQueue (void* message); +bool juce_postMessageToSystemQueue (Message* message); MessageManager* MessageManager::instance = 0; @@ -37789,26 +37790,26 @@ void MessageManager::postCallbackMessage (Message* const message) } // not for public use.. -void MessageManager::deliverMessage (void* const message) +void MessageManager::deliverMessage (Message* const message) { - const ScopedPointer m (static_cast (message)); - MessageListener* const recipient = m->messageRecipient; + const ScopedPointer messageDeleter (message); + MessageListener* const recipient = message->messageRecipient; JUCE_TRY { if (messageListeners.contains (recipient)) { - recipient->handleMessage (*m); + recipient->handleMessage (*message); } else if (recipient == 0) { - if (m->intParameter1 == quitMessageId) + if (message->intParameter1 == quitMessageId) { quitMessageReceived = true; } else { - CallbackMessage* const cm = dynamic_cast (static_cast (m)); + CallbackMessage* const cm = dynamic_cast (message); if (cm != 0) cm->messageCallback(); @@ -77611,7 +77612,8 @@ ResizableWindow::~ResizableWindow() { resizableCorner = 0; resizableBorder = 0; - contentComponent = 0; + deleteAndZero (contentComponent); // (avoid using a scoped pointer for this, so that it survives + // external deletion of the content comp) // have you been adding your own components directly to this window..? tut tut tut. // Read the instructions for using a ResizableWindow! @@ -77636,9 +77638,9 @@ void ResizableWindow::setContentComponent (Component* const newContentComponent, if (newContentComponent != static_cast (contentComponent)) { - if (! deleteOldOne) - removeChildComponent (contentComponent.release()); - + if (deleteOldOne) + delete static_cast (contentComponent); // (avoid using a scoped pointer for this, so that it survives + // external deletion of the content comp) contentComponent = newContentComponent; Component::addAndMakeVisible (contentComponent); @@ -238585,7 +238587,7 @@ static LRESULT CALLBACK juce_MessageWndProc (HWND h, // here in case there are windows modal dialog boxes doing their own // dispatch loop and not calling our version - MessageManager::getInstance()->deliverMessage ((void*) lParam); + MessageManager::getInstance()->deliverMessage ((Message*) lParam); return 0; } else if (message == broadcastId) @@ -238673,7 +238675,7 @@ bool juce_dispatchNextMessageOnSystemQueue (const bool returnIfNoPendingMessages { if (m.message == specialId && m.hwnd == juce_messageWindowHandle) { - MessageManager::getInstance()->deliverMessage ((void*) m.lParam); + MessageManager::getInstance()->deliverMessage ((Message*) (void*) m.lParam); } else if (m.message == WM_QUIT) { @@ -238701,7 +238703,7 @@ bool juce_dispatchNextMessageOnSystemQueue (const bool returnIfNoPendingMessages return true; } -bool juce_postMessageToSystemQueue (void* message) +bool juce_postMessageToSystemQueue (Message* message) { return PostMessage (juce_messageWindowHandle, specialId, 0, (LPARAM) message) != 0; } @@ -254754,9 +254756,7 @@ private: (void) numBytes; } - Message* m = queue[0]; - queue.remove (0, false /* deleteObject */); - return m; + return queue.removeAndReturn (0); } bool dispatchNextInternalMessage() @@ -254922,12 +254922,12 @@ void MessageManager::doPlatformSpecificShutdown() } } -bool juce_postMessageToSystemQueue (void* message) +bool juce_postMessageToSystemQueue (Message* message) { if (LinuxErrorHandling::errorOccurred) return false; - InternalMessageQueue::getInstanceWithoutCreating()->postMessage ((Message*) message); + InternalMessageQueue::getInstanceWithoutCreating()->postMessage (message); return true; } @@ -265979,7 +265979,7 @@ bool MessageManager::runDispatchLoopUntil (int millisecondsToRunFor) static CFRunLoopRef runLoop = 0; static CFRunLoopSourceRef runLoopSource = 0; -static Array * pendingMessages = 0; +static OwnedArray * pendingMessages = 0; static JuceCustomMessageHandler* juceCustomMessageHandler = 0; static void runLoopSourceCallback (void*) @@ -265990,7 +265990,7 @@ static void runLoopSourceCallback (void*) do { - void* const nextMessage = pendingMessages->remove (0); + Message* const nextMessage = pendingMessages->removeAndReturn (0); if (nextMessage == 0) return; @@ -266007,7 +266007,7 @@ static void runLoopSourceCallback (void*) void MessageManager::doPlatformSpecificInitialisation() { - pendingMessages = new Array (); + pendingMessages = new OwnedArray (); runLoop = CFRunLoopGetCurrent(); CFRunLoopSourceContext sourceContext; @@ -266025,14 +266025,7 @@ void MessageManager::doPlatformSpecificShutdown() CFRunLoopSourceInvalidate (runLoopSource); CFRelease (runLoopSource); runLoopSource = 0; - - if (pendingMessages != 0) - { - while (pendingMessages->size() > 0) - delete ((Message*) pendingMessages->remove(0)); - - deleteAndZero (pendingMessages); - } + deleteAndZero (pendingMessages); if (juceCustomMessageHandler != 0) { @@ -266042,7 +266035,7 @@ void MessageManager::doPlatformSpecificShutdown() } } -bool juce_postMessageToSystemQueue (void* message) +bool juce_postMessageToSystemQueue (Message* message) { if (pendingMessages != 0) { @@ -274114,9 +274107,6 @@ public: CFRunLoopRemoveSource (runLoop, runLoopSource, kCFRunLoopCommonModes); CFRunLoopSourceInvalidate (runLoopSource); CFRelease (runLoopSource); - - while (messages.size() > 0) - delete static_cast (messages.remove(0)); } virtual NSApplicationTerminateReply shouldTerminate() @@ -274183,7 +274173,7 @@ public: delete this; } - void postMessage (void* m) + void postMessage (Message* const m) { messages.add (m); CFRunLoopSourceSignal (runLoopSource); @@ -274193,7 +274183,7 @@ public: private: CFRunLoopRef runLoop; CFRunLoopSourceRef runLoopSource; - Array messages; + OwnedArray messages; void runLoopCallback() { @@ -274201,7 +274191,7 @@ private: do { - void* const nextMessage = messages.remove (0); + Message* const nextMessage = messages.removeAndReturn (0); if (nextMessage == 0) return; @@ -274519,7 +274509,7 @@ void MessageManager::doPlatformSpecificShutdown() } } -bool juce_postMessageToSystemQueue (void* message) +bool juce_postMessageToSystemQueue (Message* message) { juceAppDelegate->redirector->postMessage (message); return true; diff --git a/juce_amalgamated.h b/juce_amalgamated.h index bcc483047b..dde123a88c 100644 --- a/juce_amalgamated.h +++ b/juce_amalgamated.h @@ -64,7 +64,7 @@ */ #define JUCE_MAJOR_VERSION 1 #define JUCE_MINOR_VERSION 52 -#define JUCE_BUILDNUMBER 23 +#define JUCE_BUILDNUMBER 24 /** Current Juce version number. @@ -6993,6 +6993,38 @@ public: } } + /** Removes and returns an object from the array without deleting it. + + This will remove the object at a given index and return it, moving back all + the subsequent objects to close the gap. If the index passed in is out-of-range, + nothing will happen. + + @param indexToRemove the index of the element to remove + @see remove, removeObject, removeRange + */ + ObjectClass* removeAndReturn (const int indexToRemove) + { + ObjectClass* removedItem = 0; + const ScopedLockType lock (getLock()); + + if (((unsigned int) indexToRemove) < (unsigned int) numUsed) + { + ObjectClass** const e = data.elements + indexToRemove; + removedItem = *e; + + --numUsed; + const int numToShift = numUsed - indexToRemove; + + if (numToShift > 0) + memmove (e, e + 1, numToShift * sizeof (ObjectClass*)); + + if ((numUsed << 1) < data.numAllocated) + minimiseStorageOverheads(); + } + + return removedItem; + } + /** Removes a specified object from the array. If the item isn't found, no action is taken. @@ -7079,14 +7111,9 @@ public: const ScopedLockType lock (getLock()); if (howManyToRemove >= numUsed) - { clear (deleteObjects); - } else - { - while (--howManyToRemove >= 0) - remove (numUsed - 1, deleteObjects); - } + removeRange (numUsed - howManyToRemove, howManyToRemove, deleteObjects); } /** Swaps a pair of objects in the array. @@ -42183,7 +42210,7 @@ public: void deregisterBroadcastListener (ActionListener* listener) throw(); /** @internal */ - void deliverMessage (void*); + void deliverMessage (Message*); /** @internal */ void deliverBroadcastMessage (const String&); /** @internal */ @@ -49874,7 +49901,7 @@ protected: ScopedPointer resizableBorder; private: - ScopedPointer contentComponent; + Component::SafePointer contentComponent; bool resizeToFitContent, fullscreen; ComponentDragger dragger; Rectangle lastNonFullScreenPos; diff --git a/src/containers/juce_OwnedArray.h b/src/containers/juce_OwnedArray.h index 44fbcb8c84..d98c013626 100644 --- a/src/containers/juce_OwnedArray.h +++ b/src/containers/juce_OwnedArray.h @@ -502,6 +502,38 @@ public: } } + /** Removes and returns an object from the array without deleting it. + + This will remove the object at a given index and return it, moving back all + the subsequent objects to close the gap. If the index passed in is out-of-range, + nothing will happen. + + @param indexToRemove the index of the element to remove + @see remove, removeObject, removeRange + */ + ObjectClass* removeAndReturn (const int indexToRemove) + { + ObjectClass* removedItem = 0; + const ScopedLockType lock (getLock()); + + if (((unsigned int) indexToRemove) < (unsigned int) numUsed) + { + ObjectClass** const e = data.elements + indexToRemove; + removedItem = *e; + + --numUsed; + const int numToShift = numUsed - indexToRemove; + + if (numToShift > 0) + memmove (e, e + 1, numToShift * sizeof (ObjectClass*)); + + if ((numUsed << 1) < data.numAllocated) + minimiseStorageOverheads(); + } + + return removedItem; + } + /** Removes a specified object from the array. If the item isn't found, no action is taken. @@ -588,14 +620,9 @@ public: const ScopedLockType lock (getLock()); if (howManyToRemove >= numUsed) - { clear (deleteObjects); - } else - { - while (--howManyToRemove >= 0) - remove (numUsed - 1, deleteObjects); - } + removeRange (numUsed - howManyToRemove, howManyToRemove, deleteObjects); } /** Swaps a pair of objects in the array. diff --git a/src/core/juce_StandardHeader.h b/src/core/juce_StandardHeader.h index 29e61e4ee3..289207c3c0 100644 --- a/src/core/juce_StandardHeader.h +++ b/src/core/juce_StandardHeader.h @@ -33,7 +33,7 @@ */ #define JUCE_MAJOR_VERSION 1 #define JUCE_MINOR_VERSION 52 -#define JUCE_BUILDNUMBER 23 +#define JUCE_BUILDNUMBER 24 /** Current Juce version number. diff --git a/src/events/juce_MessageManager.cpp b/src/events/juce_MessageManager.cpp index c5c69f9357..cced9ca31b 100644 --- a/src/events/juce_MessageManager.cpp +++ b/src/events/juce_MessageManager.cpp @@ -39,7 +39,7 @@ BEGIN_JUCE_NAMESPACE //============================================================================== // platform-specific functions.. bool juce_dispatchNextMessageOnSystemQueue (bool returnIfNoPendingMessages); -bool juce_postMessageToSystemQueue (void* message); +bool juce_postMessageToSystemQueue (Message* message); //============================================================================== MessageManager* MessageManager::instance = 0; @@ -99,26 +99,26 @@ void MessageManager::postCallbackMessage (Message* const message) //============================================================================== // not for public use.. -void MessageManager::deliverMessage (void* const message) +void MessageManager::deliverMessage (Message* const message) { - const ScopedPointer m (static_cast (message)); - MessageListener* const recipient = m->messageRecipient; + const ScopedPointer messageDeleter (message); + MessageListener* const recipient = message->messageRecipient; JUCE_TRY { if (messageListeners.contains (recipient)) { - recipient->handleMessage (*m); + recipient->handleMessage (*message); } else if (recipient == 0) { - if (m->intParameter1 == quitMessageId) + if (message->intParameter1 == quitMessageId) { quitMessageReceived = true; } else { - CallbackMessage* const cm = dynamic_cast (static_cast (m)); + CallbackMessage* const cm = dynamic_cast (message); if (cm != 0) cm->messageCallback(); diff --git a/src/events/juce_MessageManager.h b/src/events/juce_MessageManager.h index 869110bb5a..14e799440e 100644 --- a/src/events/juce_MessageManager.h +++ b/src/events/juce_MessageManager.h @@ -156,7 +156,7 @@ public: //============================================================================== /** @internal */ - void deliverMessage (void*); + void deliverMessage (Message*); /** @internal */ void deliverBroadcastMessage (const String&); /** @internal */ diff --git a/src/gui/components/windows/juce_ResizableWindow.cpp b/src/gui/components/windows/juce_ResizableWindow.cpp index 544f3dbbc5..c5c461e183 100644 --- a/src/gui/components/windows/juce_ResizableWindow.cpp +++ b/src/gui/components/windows/juce_ResizableWindow.cpp @@ -78,7 +78,8 @@ ResizableWindow::~ResizableWindow() { resizableCorner = 0; resizableBorder = 0; - contentComponent = 0; + deleteAndZero (contentComponent); // (avoid using a scoped pointer for this, so that it survives + // external deletion of the content comp) // have you been adding your own components directly to this window..? tut tut tut. // Read the instructions for using a ResizableWindow! @@ -104,9 +105,9 @@ void ResizableWindow::setContentComponent (Component* const newContentComponent, if (newContentComponent != static_cast (contentComponent)) { - if (! deleteOldOne) - removeChildComponent (contentComponent.release()); - + if (deleteOldOne) + delete static_cast (contentComponent); // (avoid using a scoped pointer for this, so that it survives + // external deletion of the content comp) contentComponent = newContentComponent; Component::addAndMakeVisible (contentComponent); diff --git a/src/gui/components/windows/juce_ResizableWindow.h b/src/gui/components/windows/juce_ResizableWindow.h index dbbcf7e273..d8207a2438 100644 --- a/src/gui/components/windows/juce_ResizableWindow.h +++ b/src/gui/components/windows/juce_ResizableWindow.h @@ -342,7 +342,7 @@ protected: ScopedPointer resizableBorder; private: - ScopedPointer contentComponent; + Component::SafePointer contentComponent; bool resizeToFitContent, fullscreen; ComponentDragger dragger; Rectangle lastNonFullScreenPos; diff --git a/src/native/linux/juce_linux_Messaging.cpp b/src/native/linux/juce_linux_Messaging.cpp index f5420d9d98..622ba5161d 100644 --- a/src/native/linux/juce_linux_Messaging.cpp +++ b/src/native/linux/juce_linux_Messaging.cpp @@ -207,9 +207,7 @@ private: (void) numBytes; } - Message* m = queue[0]; - queue.remove (0, false /* deleteObject */); - return m; + return queue.removeAndReturn (0); } bool dispatchNextInternalMessage() @@ -380,12 +378,12 @@ void MessageManager::doPlatformSpecificShutdown() } } -bool juce_postMessageToSystemQueue (void* message) +bool juce_postMessageToSystemQueue (Message* message) { if (LinuxErrorHandling::errorOccurred) return false; - InternalMessageQueue::getInstanceWithoutCreating()->postMessage ((Message*) message); + InternalMessageQueue::getInstanceWithoutCreating()->postMessage (message); return true; } diff --git a/src/native/mac/juce_iphone_MessageManager.mm b/src/native/mac/juce_iphone_MessageManager.mm index b2e3d54df1..93113eb683 100644 --- a/src/native/mac/juce_iphone_MessageManager.mm +++ b/src/native/mac/juce_iphone_MessageManager.mm @@ -108,7 +108,7 @@ bool MessageManager::runDispatchLoopUntil (int millisecondsToRunFor) //============================================================================== static CFRunLoopRef runLoop = 0; static CFRunLoopSourceRef runLoopSource = 0; -static Array * pendingMessages = 0; +static OwnedArray * pendingMessages = 0; static JuceCustomMessageHandler* juceCustomMessageHandler = 0; static void runLoopSourceCallback (void*) @@ -119,7 +119,7 @@ static void runLoopSourceCallback (void*) do { - void* const nextMessage = pendingMessages->remove (0); + Message* const nextMessage = pendingMessages->removeAndReturn (0); if (nextMessage == 0) return; @@ -136,7 +136,7 @@ static void runLoopSourceCallback (void*) void MessageManager::doPlatformSpecificInitialisation() { - pendingMessages = new Array (); + pendingMessages = new OwnedArray (); runLoop = CFRunLoopGetCurrent(); CFRunLoopSourceContext sourceContext; @@ -154,14 +154,7 @@ void MessageManager::doPlatformSpecificShutdown() CFRunLoopSourceInvalidate (runLoopSource); CFRelease (runLoopSource); runLoopSource = 0; - - if (pendingMessages != 0) - { - while (pendingMessages->size() > 0) - delete ((Message*) pendingMessages->remove(0)); - - deleteAndZero (pendingMessages); - } + deleteAndZero (pendingMessages); if (juceCustomMessageHandler != 0) { @@ -171,7 +164,7 @@ void MessageManager::doPlatformSpecificShutdown() } } -bool juce_postMessageToSystemQueue (void* message) +bool juce_postMessageToSystemQueue (Message* message) { if (pendingMessages != 0) { diff --git a/src/native/mac/juce_mac_MessageManager.mm b/src/native/mac/juce_mac_MessageManager.mm index acd74df46f..92d3a3f6e3 100644 --- a/src/native/mac/juce_mac_MessageManager.mm +++ b/src/native/mac/juce_mac_MessageManager.mm @@ -60,9 +60,6 @@ public: CFRunLoopRemoveSource (runLoop, runLoopSource, kCFRunLoopCommonModes); CFRunLoopSourceInvalidate (runLoopSource); CFRelease (runLoopSource); - - while (messages.size() > 0) - delete static_cast (messages.remove(0)); } virtual NSApplicationTerminateReply shouldTerminate() @@ -129,7 +126,7 @@ public: delete this; } - void postMessage (void* m) + void postMessage (Message* const m) { messages.add (m); CFRunLoopSourceSignal (runLoopSource); @@ -139,7 +136,7 @@ public: private: CFRunLoopRef runLoop; CFRunLoopSourceRef runLoopSource; - Array messages; + OwnedArray messages; void runLoopCallback() { @@ -147,7 +144,7 @@ private: do { - void* const nextMessage = messages.remove (0); + Message* const nextMessage = messages.removeAndReturn (0); if (nextMessage == 0) return; @@ -467,7 +464,7 @@ void MessageManager::doPlatformSpecificShutdown() } } -bool juce_postMessageToSystemQueue (void* message) +bool juce_postMessageToSystemQueue (Message* message) { juceAppDelegate->redirector->postMessage (message); return true; diff --git a/src/native/windows/juce_win32_Messaging.cpp b/src/native/windows/juce_win32_Messaging.cpp index aba2eb3444..eb16a9ded6 100644 --- a/src/native/windows/juce_win32_Messaging.cpp +++ b/src/native/windows/juce_win32_Messaging.cpp @@ -65,7 +65,7 @@ static LRESULT CALLBACK juce_MessageWndProc (HWND h, // here in case there are windows modal dialog boxes doing their own // dispatch loop and not calling our version - MessageManager::getInstance()->deliverMessage ((void*) lParam); + MessageManager::getInstance()->deliverMessage ((Message*) lParam); return 0; } else if (message == broadcastId) @@ -153,7 +153,7 @@ bool juce_dispatchNextMessageOnSystemQueue (const bool returnIfNoPendingMessages { if (m.message == specialId && m.hwnd == juce_messageWindowHandle) { - MessageManager::getInstance()->deliverMessage ((void*) m.lParam); + MessageManager::getInstance()->deliverMessage ((Message*) (void*) m.lParam); } else if (m.message == WM_QUIT) { @@ -182,7 +182,7 @@ bool juce_dispatchNextMessageOnSystemQueue (const bool returnIfNoPendingMessages } //============================================================================== -bool juce_postMessageToSystemQueue (void* message) +bool juce_postMessageToSystemQueue (Message* message) { return PostMessage (juce_messageWindowHandle, specialId, 0, (LPARAM) message) != 0; }